Refactor analytics report data retrieval and improve logistics info page loading logic

- Updated the analytics report controller to correctly join work_order_process and work_order_process_result for accurate production data retrieval.
- Enhanced the logistics info page to load all tabs on mount for immediate count accuracy, while ensuring only the active tab is reloaded on subsequent changes to prevent race conditions.

This refactor improves data accuracy and user experience in the logistics module.
This commit is contained in:
kjs
2026-04-28 18:15:22 +09:00
parent bf8d99ccf5
commit 0b7c967f56
9 changed files with 84 additions and 69 deletions

View File

@@ -59,37 +59,39 @@ export async function getProductionReportData(req: any, res: Response): Promise<
const cf = buildCompanyFilter(companyCode, "wop", idx);
if (cf.condition) { conditions.push(cf.condition); params.push(...cf.params); idx = cf.nextIdx; }
const dateExpr = "COALESCE(NULLIF(wop.started_at, ''), wop.created_date::date::text)";
const dateExpr = "COALESCE(NULLIF(wopr.started_at, ''), wop.created_date::date::text)";
const df = buildDateFilter(startDate, endDate, dateExpr, idx);
conditions.push(...df.conditions); params.push(...df.params); idx = df.nextIdx;
const whereClause = buildWhereClause(conditions);
// 실제 공정별 생산 데이터는 work_order_process에 있음
// (work_instruction.routing은 routing_version_id UUID일 뿐이라 공정명이 아님)
// 공정 메타(process_code/name/plan_qty)는 work_order_process,
// 실적(started_at/completed_at/good_qty/defect_qty/equipment_code 등)은 work_order_process_result에 있음
const dataQuery = `
SELECT
COALESCE(NULLIF(wop.started_at, ''), wop.created_date::date::text) as date,
COALESCE(NULLIF(wopr.started_at, ''), wop.created_date::date::text) as date,
COALESCE(NULLIF(wop.process_name, ''), NULLIF(wop.process_code, ''), '미지정') as process,
COALESCE(NULLIF(em.equipment_name, ''), NULLIF(em.equipment_code, ''), '미지정') as equipment,
COALESCE(NULLIF(ii.item_name, ''), NULLIF(ii.item_number, ''), '미지정') as item,
COALESCE(NULLIF(wi.worker, ''), '미지정') as worker,
CAST(COALESCE(NULLIF(wop.plan_qty, ''), '0') AS numeric) as "planQty",
CAST(COALESCE(NULLIF(wop.good_qty, ''), '0') AS numeric) as "prodQty",
CAST(COALESCE(NULLIF(wop.defect_qty, ''), '0') AS numeric) as "defectQty",
CAST(COALESCE(NULLIF(wopr.good_qty, ''), '0') AS numeric) as "prodQty",
CAST(COALESCE(NULLIF(wopr.defect_qty, ''), '0') AS numeric) as "defectQty",
CASE
WHEN NULLIF(wop.started_at, '') IS NOT NULL
AND NULLIF(wop.completed_at, '') IS NOT NULL
WHEN NULLIF(wopr.started_at, '') IS NOT NULL
AND NULLIF(wopr.completed_at, '') IS NOT NULL
THEN GREATEST(
EXTRACT(EPOCH FROM (wop.completed_at::timestamp - wop.started_at::timestamp)) / 3600.0,
EXTRACT(EPOCH FROM (wopr.completed_at::timestamp - wopr.started_at::timestamp)) / 3600.0,
0
)
ELSE 0
END as "runTime",
CAST(COALESCE(NULLIF(wop.total_paused_time, ''), '0') AS numeric) / 3600.0 as "downTime",
wop.status,
CAST(COALESCE(NULLIF(wopr.total_paused_time, ''), '0') AS numeric) / 3600.0 as "downTime",
wopr.status,
wop.company_code
FROM work_order_process wop
LEFT JOIN work_order_process_result wopr
ON wopr.wop_id = wop.id AND wopr.company_code = wop.company_code
LEFT JOIN work_instruction wi
ON wop.wo_id = wi.id AND wop.company_code = wi.company_code
LEFT JOIN LATERAL (
@@ -97,8 +99,8 @@ export async function getProductionReportData(req: any, res: Response): Promise<
FROM equipment_mng
WHERE company_code = wi.company_code
AND (id = wi.equipment_id OR equipment_code = wi.equipment_id
OR id = wop.equipment_code OR equipment_code = wop.equipment_code)
ORDER BY (id = wi.equipment_id OR id = wop.equipment_code) DESC, created_date DESC
OR id = wopr.equipment_code OR equipment_code = wopr.equipment_code)
ORDER BY (id = wi.equipment_id OR id = wopr.equipment_code) DESC, created_date DESC
LIMIT 1
) em ON true
LEFT JOIN LATERAL (