Bundle POP sales outbound + inspection wiring
- outbound: wire 판매출고 to shipment_instruction with customer_mng JOIN, add customer filter, auto-transition shipment_instruction.status to COMPLETED/IN_PROGRESS based on remaining qty
- inspection: fix is_active filter ('Y' -> '사용') and JOIN inspection_standard to expose judgment_criteria
- POP InspectionModal (7 companies): hide measured-value input when judgment_criteria == CAT_JC_03 (O/X)
- POP SalesOutbound (7 companies): connect to /outbound/source/shipment-instructions, fix stale-closure bug in saveToDb via ref
- COMPANY_16/30 main: temporarily comment out 품질/안전관리 menu entries
This commit is contained in:
@@ -180,7 +180,7 @@ export async function create(req: AuthenticatedRequest, res: Response) {
|
||||
item.outbound_status || "대기",
|
||||
manager_id || item.manager_id || null,
|
||||
memo || item.memo || null,
|
||||
item.source_type || null,
|
||||
item.source_type || item.source_table || null,
|
||||
item.sales_order_id || null,
|
||||
item.shipment_plan_id || null,
|
||||
item.item_info_id || null,
|
||||
@@ -275,11 +275,12 @@ export async function create(req: AuthenticatedRequest, res: Response) {
|
||||
);
|
||||
}
|
||||
|
||||
// 판매출고인 경우 출하지시의 ship_qty 업데이트 + 수주상세 ship_qty 반영
|
||||
// 판매출고인 경우 출하지시의 ship_qty 업데이트 + 수주상세 ship_qty 반영 + master status 자동 전환
|
||||
const itemSourceTable = item.source_type || item.source_table;
|
||||
if (
|
||||
item.outbound_type === "판매출고" &&
|
||||
item.source_id &&
|
||||
item.source_type === "shipment_instruction_detail"
|
||||
itemSourceTable === "shipment_instruction_detail"
|
||||
) {
|
||||
const outQtyNum = Number(item.outbound_qty) || 0;
|
||||
await client.query(
|
||||
@@ -292,9 +293,12 @@ export async function create(req: AuthenticatedRequest, res: Response) {
|
||||
|
||||
// 출하지시 상세의 detail_id로 수주상세(sales_order_detail) ship_qty도 업데이트
|
||||
const sidRes = await client.query(
|
||||
`SELECT detail_id FROM shipment_instruction_detail WHERE id = $1 AND company_code = $2`,
|
||||
`SELECT instruction_id, detail_id
|
||||
FROM shipment_instruction_detail
|
||||
WHERE id = $1 AND company_code = $2`,
|
||||
[item.source_id, companyCode],
|
||||
);
|
||||
const instructionId = sidRes.rows[0]?.instruction_id;
|
||||
const detailId = sidRes.rows[0]?.detail_id;
|
||||
if (detailId) {
|
||||
await client.query(
|
||||
@@ -306,6 +310,27 @@ export async function create(req: AuthenticatedRequest, res: Response) {
|
||||
[outQtyNum, detailId, companyCode],
|
||||
);
|
||||
}
|
||||
|
||||
// shipment_instruction master status 자동 전환 (입고의 purchase_detail → purchase_order_mng 패턴)
|
||||
// 모든 detail 의 잔량이 0 이면 COMPLETED, 아니면 IN_PROGRESS
|
||||
if (instructionId) {
|
||||
const unshippedRes = await client.query(
|
||||
`SELECT COUNT(*)::int AS unshipped
|
||||
FROM shipment_instruction_detail
|
||||
WHERE instruction_id = $1 AND company_code = $2
|
||||
AND COALESCE(plan_qty, 0) > COALESCE(ship_qty, 0)`,
|
||||
[instructionId, companyCode],
|
||||
);
|
||||
const unshipped = unshippedRes.rows[0]?.unshipped ?? 0;
|
||||
const newStatus = unshipped === 0 ? "COMPLETED" : "IN_PROGRESS";
|
||||
await client.query(
|
||||
`UPDATE shipment_instruction
|
||||
SET status = $1,
|
||||
updated_date = NOW()
|
||||
WHERE id = $2 AND company_code = $3`,
|
||||
[newStatus, instructionId, companyCode],
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -569,12 +594,18 @@ export async function getShipmentInstructions(
|
||||
) {
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const { keyword } = req.query;
|
||||
const { keyword, customer } = req.query;
|
||||
|
||||
const conditions: string[] = ["si.company_code = $1"];
|
||||
const params: any[] = [companyCode];
|
||||
let paramIdx = 2;
|
||||
|
||||
if (customer) {
|
||||
conditions.push(`si.partner_id = $${paramIdx}`);
|
||||
params.push(customer);
|
||||
paramIdx++;
|
||||
}
|
||||
|
||||
if (keyword) {
|
||||
conditions.push(
|
||||
`(si.instruction_no ILIKE $${paramIdx} OR sid.item_name ILIKE $${paramIdx} OR sid.item_code ILIKE $${paramIdx})`,
|
||||
@@ -591,6 +622,7 @@ export async function getShipmentInstructions(
|
||||
si.instruction_no,
|
||||
si.instruction_date,
|
||||
si.partner_id,
|
||||
COALESCE(c.customer_name, si.partner_id, '') AS customer_name,
|
||||
si.status AS instruction_status,
|
||||
sid.item_code,
|
||||
sid.item_name,
|
||||
@@ -605,6 +637,9 @@ export async function getShipmentInstructions(
|
||||
JOIN shipment_instruction_detail sid
|
||||
ON si.id = sid.instruction_id
|
||||
AND si.company_code = sid.company_code
|
||||
LEFT JOIN customer_mng c
|
||||
ON si.partner_id = c.customer_code
|
||||
AND si.company_code = c.company_code
|
||||
WHERE ${conditions.join(" AND ")}
|
||||
AND COALESCE(sid.plan_qty, 0) > COALESCE(sid.ship_qty, 0)
|
||||
ORDER BY si.instruction_date DESC, si.instruction_no`,
|
||||
|
||||
@@ -17,30 +17,32 @@ router.get("/info", async (req: Request, res: Response) => {
|
||||
return res.status(401).json({ success: false, message: "인증 정보 없음" });
|
||||
}
|
||||
|
||||
const conditions: string[] = ["company_code = $1", "is_active = 'Y'"];
|
||||
const conditions: string[] = ["iii.company_code = $1", "iii.is_active = '사용'"];
|
||||
const params: unknown[] = [companyCode];
|
||||
let idx = 2;
|
||||
|
||||
if (itemCode) {
|
||||
conditions.push(`item_code = $${idx++}`);
|
||||
conditions.push(`iii.item_code = $${idx++}`);
|
||||
params.push(itemCode);
|
||||
}
|
||||
if (itemId) {
|
||||
conditions.push(`item_id = $${idx++}`);
|
||||
conditions.push(`iii.item_id = $${idx++}`);
|
||||
params.push(itemId);
|
||||
}
|
||||
if (inspectionType) {
|
||||
conditions.push(`inspection_type = $${idx++}`);
|
||||
conditions.push(`iii.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
|
||||
SELECT iii.id, iii.item_id, iii.item_code, iii.item_name,
|
||||
iii.inspection_type, iii.inspection_item_name, iii.inspection_standard,
|
||||
iii.inspection_method, iii.pass_criteria, iii.is_required, iii.sort_order, iii.memo,
|
||||
ist.judgment_criteria
|
||||
FROM item_inspection_info iii
|
||||
LEFT JOIN inspection_standard ist ON ist.id = iii.inspection_standard_id
|
||||
WHERE ${conditions.join(" AND ")}
|
||||
ORDER BY sort_order, inspection_item_name
|
||||
ORDER BY iii.sort_order, iii.inspection_item_name
|
||||
`;
|
||||
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user