Implement KPI daily production feature
- Added a new KPI controller to handle daily production data retrieval. - Created routes for accessing KPI data, specifically for daily production. - Developed frontend components for displaying daily production metrics, including charts and summary cards. - Implemented data fetching logic with date range filtering for production data. - Ensured proper loading states and error handling in the UI. This feature is part of TASK:ERP-022.
This commit is contained in:
48
backend-node/src/controllers/kpiController.ts
Normal file
48
backend-node/src/controllers/kpiController.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/**
|
||||
* KPI 컨트롤러 — TASK:ERP-022
|
||||
* 일별 생산량 등 KPI 지표 조회 전담
|
||||
*/
|
||||
import { Response } from "express";
|
||||
import { AuthenticatedRequest } from "../types/auth";
|
||||
import { getPool } from "../database/db";
|
||||
import { logger } from "../utils/logger";
|
||||
|
||||
/**
|
||||
* GET /api/kpi/daily-production?from=YYYY-MM-DD&to=YYYY-MM-DD
|
||||
* 회사별 일별 생산량 조회
|
||||
*/
|
||||
export async function getDailyProduction(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const companyCode = req.user?.companyCode;
|
||||
if (!companyCode) {
|
||||
return res.status(401).json({ success: false, message: "인증 필요" });
|
||||
}
|
||||
|
||||
const from = (req.query.from as string) || "";
|
||||
const to = (req.query.to as string) || "";
|
||||
|
||||
const params: any[] = [companyCode];
|
||||
let where = "company_code = $1";
|
||||
if (from) {
|
||||
params.push(from);
|
||||
where += ` AND prod_date >= $${params.length}`;
|
||||
}
|
||||
if (to) {
|
||||
params.push(to);
|
||||
where += ` AND prod_date <= $${params.length}`;
|
||||
}
|
||||
|
||||
const result = await getPool().query(
|
||||
`SELECT prod_date, production_qty, defect_qty, work_hours, remark
|
||||
FROM kpi_daily_production
|
||||
WHERE ${where}
|
||||
ORDER BY prod_date`,
|
||||
params
|
||||
);
|
||||
|
||||
return res.json({ success: true, data: result.rows });
|
||||
} catch (error: any) {
|
||||
logger.error("KPI 일별 생산량 조회 실패", { error: error.message });
|
||||
return res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
}
|
||||
@@ -468,10 +468,10 @@ export async function saveRoutingDetails(req: AuthenticatedRequest, res: Respons
|
||||
}
|
||||
|
||||
const insertRes = await client.query(
|
||||
`INSERT INTO item_routing_detail (id, company_code, routing_version_id, seq_no, process_code, is_required, is_fixed_order, work_type, standard_time, outsource_supplier, writer)
|
||||
VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||
`INSERT INTO item_routing_detail (id, company_code, routing_version_id, seq_no, process_code, is_required, is_fixed_order, work_type, standard_time, outsource_supplier, execution_type, writer)
|
||||
VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)
|
||||
RETURNING id`,
|
||||
[companyCode, versionId, d.seq_no, d.process_code, d.is_required || "Y", d.is_fixed_order || "Y", d.work_type || "내부", d.standard_time || "0", legacyCode, writer]
|
||||
[companyCode, versionId, d.seq_no, d.process_code, d.is_required || "Y", d.is_fixed_order || "Y", d.work_type || "내부", d.standard_time || "0", legacyCode, d.execution_type || null, writer]
|
||||
);
|
||||
const newDetailId = insertRes.rows[0].id;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user