WIP: preset + inspection (임시, 나중에 squash)

This commit is contained in:
SeongHyun Kim
2026-03-27 17:05:36 +09:00
parent f10946ae5b
commit eacfe60f89
9 changed files with 2454 additions and 7 deletions

View File

@@ -127,6 +127,7 @@ import screenEmbeddingRoutes from "./routes/screenEmbeddingRoutes"; // 화면
import screenGroupRoutes from "./routes/screenGroupRoutes"; // 화면 그룹 관리
import popActionRoutes from "./routes/popActionRoutes"; // POP 액션 실행
import popProductionRoutes from "./routes/popProductionRoutes"; // POP 생산 관리 (공정 생성/타이머)
import inspectionResultRoutes from "./routes/inspectionResultRoutes"; // POP 검사 결과 관리
import vehicleTripRoutes from "./routes/vehicleTripRoutes"; // 차량 운행 이력 관리
import approvalRoutes from "./routes/approvalRoutes"; // 결재 시스템
import driverRoutes from "./routes/driverRoutes"; // 공차중계 운전자 관리
@@ -287,6 +288,7 @@ app.use("/api/screen-management", screenManagementRoutes);
app.use("/api/screen-groups", screenGroupRoutes); // 화면 그룹 관리
app.use("/api/pop", popActionRoutes); // POP 액션 실행
app.use("/api/pop/production", popProductionRoutes); // POP 생산 관리
app.use("/api/pop/inspection-result", inspectionResultRoutes); // POP 검사 결과 관리
app.use("/api/common-codes", commonCodeRoutes);
app.use("/api/dynamic-form", dynamicFormRoutes);
app.use("/api/files", fileRoutes);

View File

@@ -0,0 +1,191 @@
import { Router, Request, Response } from "express";
import { getPool } from "../database/db";
import { authenticateToken } from "../middleware/authMiddleware";
const router = Router();
router.use(authenticateToken);
// ---- 검사 기준 조회 (item_inspection_info) ----
// GET /api/pop/inspection-result/info?itemCode=ITEM-001&inspectionType=입고검사
router.get("/info", async (req: Request, res: Response) => {
const pool = getPool();
const companyCode = (req as any).user?.companyCode;
const { itemCode, itemId, inspectionType } = req.query;
if (!companyCode) {
return res.status(401).json({ success: false, message: "인증 정보 없음" });
}
const conditions: string[] = ["company_code = $1", "is_active = 'Y'"];
const params: unknown[] = [companyCode];
let idx = 2;
if (itemCode) {
conditions.push(`item_code = $${idx++}`);
params.push(itemCode);
}
if (itemId) {
conditions.push(`item_id = $${idx++}`);
params.push(itemId);
}
if (inspectionType) {
conditions.push(`inspection_type = $${idx++}`);
params.push(inspectionType);
}
const sql = `
SELECT id, item_id, item_code, item_name,
inspection_type, inspection_item_name, inspection_standard,
inspection_method, pass_criteria, is_required, sort_order, memo
FROM item_inspection_info
WHERE ${conditions.join(" AND ")}
ORDER BY sort_order, inspection_item_name
`;
try {
const result = await pool.query(sql, params);
return res.json({ success: true, data: result.rows });
} catch (err: any) {
return res.status(500).json({ success: false, message: err.message });
}
});
// ---- 검사 결과 조회 ----
// GET /api/pop/inspection-result?referenceId=xxx&referenceTable=yyy&screenId=zzz
router.get("/", async (req: Request, res: Response) => {
const pool = getPool();
const companyCode = (req as any).user?.companyCode;
const { referenceId, referenceTable, screenId } = req.query;
if (!companyCode) {
return res.status(401).json({ success: false, message: "인증 정보 없음" });
}
const conditions: string[] = ["company_code = $1"];
const params: unknown[] = [companyCode];
let idx = 2;
if (referenceId) {
conditions.push(`reference_id = $${idx++}`);
params.push(referenceId);
}
if (referenceTable) {
conditions.push(`reference_table = $${idx++}`);
params.push(referenceTable);
}
if (screenId) {
conditions.push(`screen_id = $${idx++}`);
params.push(screenId);
}
const sql = `
SELECT *
FROM inspection_result
WHERE ${conditions.join(" AND ")}
ORDER BY created_date DESC
`;
try {
const result = await pool.query(sql, params);
return res.json({ success: true, data: result.rows });
} catch (err: any) {
return res.status(500).json({ success: false, message: err.message });
}
});
// ---- 검사 결과 저장 (INSERT or UPDATE) ----
// POST /api/pop/inspection-result
router.post("/", async (req: Request, res: Response) => {
const pool = getPool();
const companyCode = (req as any).user?.companyCode;
const writer = (req as any).user?.userId;
if (!companyCode) {
return res.status(401).json({ success: false, message: "인증 정보 없음" });
}
const {
referenceTable,
referenceId,
screenId,
itemId,
itemCode,
itemName,
inspectionType,
items, // 검사 항목별 결과 배열
overallJudgment,
memo,
isCompleted,
} = req.body;
if (!items || !Array.isArray(items) || items.length === 0) {
return res.status(400).json({ success: false, message: "검사 항목이 없습니다" });
}
const client = await pool.connect();
try {
await client.query("BEGIN");
// 기존 결과 삭제 (동일 referenceId + referenceTable 기준 덮어쓰기)
if (referenceId && referenceTable) {
await client.query(
`DELETE FROM inspection_result
WHERE company_code = $1 AND reference_id = $2 AND reference_table = $3`,
[companyCode, referenceId, referenceTable]
);
}
const insertedIds: string[] = [];
for (const item of items) {
const completedFlag = isCompleted ? "Y" : "N";
const completedDate = isCompleted ? new Date() : null;
const insertSql = `
INSERT INTO inspection_result (
company_code, writer,
reference_table, reference_id, screen_id,
inspection_info_id, item_id, item_code, item_name,
inspection_type, inspection_item_name, inspection_standard, pass_criteria, is_required,
measured_value, judgment, overall_judgment, memo,
is_completed, completed_date
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20
)
RETURNING id
`;
const result = await client.query(insertSql, [
companyCode,
writer,
referenceTable || null,
referenceId || null,
screenId || null,
item.inspectionInfoId || null,
itemId || item.itemId || null,
itemCode || item.itemCode || null,
itemName || item.itemName || null,
inspectionType || item.inspectionType || null,
item.inspectionItemName || null,
item.inspectionStandard || null,
item.passCriteria || null,
item.isRequired || "Y",
item.measuredValue || null,
item.judgment || null,
overallJudgment || null,
memo || null,
completedFlag,
completedDate,
]);
insertedIds.push(result.rows[0].id);
}
await client.query("COMMIT");
return res.json({ success: true, data: { ids: insertedIds } });
} catch (err: any) {
await client.query("ROLLBACK");
return res.status(500).json({ success: false, message: err.message });
} finally {
client.release();
}
});
export default router;