feat: POP 작업상세 체크리스트 UI를 judgment_criteria 기반으로 매핑

- 백엔드: /api/pop/production/checklist-items/:processId 신규 추가
  process_work_result ⟕ inspection_standard(judgment_criteria) LEFT JOIN으로
  한 번에 반환 (inspection_code 미설정 시 null로 안전)

- 프론트: resolveInputType + normalizeByJudgmentCriteria + normalizeByDetailType
  1순위: judgment_criteria (CAT_JC_01~04) → inspect/numeric_range/ox/select/text
  2순위: detail_type 폴백
    - checklist/equip_inspection → check(토글)
    - inspection/equip_condition/production_result → inspect(숫자 키패드)
    - lookup → input(텍스트)
    - material_input → material(BOM 자재)
  기존 canonical 값은 건드리지 않아 회귀 없음

- fetchData는 전용 API 사용 + 실패 시 기존 dataApi.getTableData로 폴백
This commit is contained in:
SeongHyun Kim
2026-04-07 12:06:01 +09:00
parent 9361b2484a
commit 450247026c
3 changed files with 238 additions and 7 deletions

View File

@@ -2969,3 +2969,84 @@ export const getMaterialInputs = async (req: AuthenticatedRequest, res: Response
return res.status(500).json({ success: false, message: error.message });
}
};
/**
* 체크리스트 조회 (judgment_criteria 조인 포함)
*
* process_work_result를 조회하면서 inspection_standard.judgment_criteria를
* LEFT JOIN으로 같이 반환한다.
*
* UI는 프론트의 resolveInputType()에서
* 1순위: judgment_criteria (CAT_JC_01~04)
* 2순위: detail_type 폴백
* 으로 입력 UI를 결정한다.
*/
export const getChecklistItems = async (
req: AuthenticatedRequest,
res: Response
) => {
const pool = getPool();
try {
const companyCode = req.user!.companyCode;
const { processId } = req.params;
if (!processId) {
return res
.status(400)
.json({ success: false, message: "processId 필수" });
}
const result = await pool.query(
`SELECT
pwr.id,
pwr.company_code,
pwr.work_order_process_id,
pwr.source_work_item_id,
pwr.source_detail_id,
pwr.work_phase,
pwr.item_title,
pwr.item_sort_order,
pwr.detail_content,
pwr.detail_type,
pwr.detail_sort_order,
pwr.is_required,
pwr.inspection_code,
pwr.inspection_method,
pwr.unit,
pwr.lower_limit,
pwr.upper_limit,
pwr.input_type,
pwr.lookup_target,
pwr.display_fields,
pwr.duration_minutes,
pwr.status,
pwr.result_value,
pwr.is_passed,
pwr.remark,
pwr.recorded_by,
pwr.recorded_at,
pwr.started_at,
pwr.group_started_at,
pwr.group_paused_at,
pwr.group_total_paused_time,
pwr.group_completed_at,
ist.judgment_criteria
FROM process_work_result pwr
LEFT JOIN inspection_standard ist
ON pwr.inspection_code = ist.inspection_code
AND pwr.company_code = ist.company_code
WHERE pwr.work_order_process_id = $1
AND pwr.company_code = $2
ORDER BY
COALESCE(NULLIF(pwr.item_sort_order, '')::int, 0),
COALESCE(NULLIF(pwr.detail_sort_order, '')::int, 0)`,
[processId, companyCode]
);
return res.json({ success: true, data: result.rows });
} catch (error: any) {
logger.error("[pop/production] checklist-items 조회 오류:", error);
return res
.status(500)
.json({ success: false, message: error.message });
}
};

View File

@@ -22,6 +22,7 @@ import {
getBomMaterials,
saveMaterialInput,
getMaterialInputs,
getChecklistItems,
} from "../controllers/popProductionController";
const router = Router();
@@ -49,5 +50,6 @@ router.get("/rework-history/:woId", getReworkHistory);
router.get("/bom-materials/:processId", getBomMaterials);
router.post("/material-input", saveMaterialInput);
router.get("/material-inputs/:processId", getMaterialInputs);
router.get("/checklist-items/:processId", getChecklistItems);
export default router;