feat: POP 시연 준비 — 5개 화면 + 버그 수정 + 재고검증

This commit is contained in:
SeongHyun Kim
2026-04-09 14:28:57 +09:00
parent 0d62af8c8b
commit bfac350ed4
25 changed files with 2804 additions and 284 deletions

View File

@@ -1157,21 +1157,30 @@ export const saveResult = async (
}
if (shouldActivateNext) {
// 다음 seq 활성화 (completed도 재활성화 — 새 양품이 들어오면 추가 접수 가능)
const nextSeq = String(seqNum + 1);
const nextUpdate = await pool.query(
`UPDATE work_order_process
SET status = 'acceptable',
updated_date = NOW()
WHERE wo_id = $1 AND seq_no = $2 AND company_code = $3
AND parent_process_id IS NULL
RETURNING id, process_name, status`,
[wo_id, nextSeq, companyCode]
// 다음 seq 활성화 (seq_no 비순차 대응: seqNum+1이 아니라 "현재보다 큰 가장 작은 seq_no")
const nextSeqQuery = await pool.query(
`SELECT MIN(CAST(seq_no AS int)) as next_seq
FROM work_order_process
WHERE wo_id = $1 AND company_code = $2 AND parent_process_id IS NULL
AND CAST(seq_no AS int) > $3`,
[wo_id, companyCode, seqNum]
);
if (nextUpdate.rowCount > 0) {
logger.info("[pop/production] 다음 공정 상태 전환", {
nextProcess: nextUpdate.rows[0],
});
const actualNextSeq = nextSeqQuery.rows[0]?.next_seq;
if (actualNextSeq != null) {
const nextUpdate = await pool.query(
`UPDATE work_order_process
SET status = 'acceptable',
updated_date = NOW()
WHERE wo_id = $1 AND seq_no = $2 AND company_code = $3
AND parent_process_id IS NULL
RETURNING id, process_name, status`,
[wo_id, String(actualNextSeq), companyCode]
);
if (nextUpdate.rowCount > 0) {
logger.info("[pop/production] 다음 공정 상태 전환", {
nextProcess: nextUpdate.rows[0],
});
}
}
}
}
@@ -1672,17 +1681,37 @@ export const getAvailableQty = async (req: AuthenticatedRequest, res: Response)
myInputQty = parseInt(totalAccepted.rows[0].total_input, 10) || 0;
prevGoodQty = instrQty;
if (seqNum > 1) {
const prevSeq = String(seqNum - 1);
const prevProcess = await pool.query(
`SELECT COALESCE(SUM(good_qty::int), 0) + COALESCE(SUM(concession_qty::int), 0) as total_good
// 첫 공정 여부를 seq_no==1이 아니라 "이 공정보다 작은 seq_no가 있는지"로 판단
// (라우팅 seq_no가 1, 2, 3이 아니라 10, 20, 30 같은 비순차여도 정상 동작)
const minSeqCheck = await pool.query(
`SELECT MIN(CAST(seq_no AS int)) as min_seq
FROM work_order_process
WHERE wo_id = $1 AND company_code = $2 AND parent_process_id IS NULL`,
[wo_id, companyCode]
);
const minSeq = parseInt(minSeqCheck.rows[0]?.min_seq, 10) || seqNum;
const isFirstProcess = seqNum <= minSeq;
if (!isFirstProcess) {
// 이전 공정 찾기 (seq_no가 더 작은 가장 가까운 공정)
const prevProcessSeq = await pool.query(
`SELECT MAX(CAST(seq_no AS int)) as prev_seq
FROM work_order_process
WHERE wo_id = $1 AND seq_no = $2 AND company_code = $3
AND parent_process_id IS NOT NULL`,
[wo_id, prevSeq, companyCode]
WHERE wo_id = $1 AND company_code = $2 AND parent_process_id IS NULL
AND CAST(seq_no AS int) < $3`,
[wo_id, companyCode, seqNum]
);
if (prevProcess.rowCount > 0) {
prevGoodQty = parseInt(prevProcess.rows[0].total_good, 10) || 0;
const actualPrevSeq = prevProcessSeq.rows[0]?.prev_seq;
if (actualPrevSeq != null) {
const prevProcess = await pool.query(
`SELECT COALESCE(SUM(good_qty::int), 0) + COALESCE(SUM(concession_qty::int), 0) as total_good
FROM work_order_process
WHERE wo_id = $1 AND seq_no = $2 AND company_code = $3
AND parent_process_id IS NOT NULL`,
[wo_id, String(actualPrevSeq), companyCode]
);
if (prevProcess.rowCount > 0) {
prevGoodQty = parseInt(prevProcess.rows[0].total_good, 10) || 0;
}
}
}
availableQty = Math.max(0, prevGoodQty - myInputQty);
@@ -1848,8 +1877,26 @@ export const acceptProcess = async (req: AuthenticatedRequest, res: Response) =>
currentTotalInput = parseInt(totalAccepted.rows[0].total_input, 10) || 0;
prevGoodQty = instrQty;
if (seqNum > 1) {
const prevSeq = String(seqNum - 1);
// 첫 공정 여부를 seq_no==1이 아니라 "이 공정보다 작은 seq_no가 있는지"로 판단
const minSeqCheck = await client.query(
`SELECT MIN(CAST(seq_no AS int)) as min_seq
FROM work_order_process
WHERE wo_id = $1 AND company_code = $2 AND parent_process_id IS NULL`,
[row.wo_id, companyCode]
);
const minSeq = parseInt(minSeqCheck.rows[0]?.min_seq, 10) || seqNum;
const isFirstProcess = seqNum <= minSeq;
if (!isFirstProcess) {
// 이전 공정 = 이 공정보다 작은 seq_no 중 가장 큰 값
const prevProcessSeq = await client.query(
`SELECT MAX(CAST(seq_no AS int)) as prev_seq
FROM work_order_process
WHERE wo_id = $1 AND company_code = $2 AND parent_process_id IS NULL
AND CAST(seq_no AS int) < $3`,
[row.wo_id, companyCode, seqNum]
);
const actualPrevSeq = prevProcessSeq.rows[0]?.prev_seq;
const prevSeq = actualPrevSeq != null ? String(actualPrevSeq) : String(seqNum - 1);
const prevProcess = await client.query(
`SELECT COALESCE(SUM(good_qty::int), 0) + COALESCE(SUM(concession_qty::int), 0) as total_good
FROM work_order_process