Merge branch 'main' of https://g.wace.me/jskim/vexplor_dev into jskim-node
This commit is contained in:
@@ -118,7 +118,7 @@ export async function create(req: AuthenticatedRequest, res: Response) {
|
||||
for (const item of items) {
|
||||
const result = await client.query(
|
||||
`INSERT INTO outbound_mng (
|
||||
company_code, outbound_number, outbound_type, outbound_date,
|
||||
id, company_code, outbound_number, outbound_type, outbound_date,
|
||||
reference_number, customer_code, customer_name,
|
||||
item_code, item_name, specification, material, unit,
|
||||
outbound_qty, unit_price, total_amount,
|
||||
@@ -128,7 +128,7 @@ export async function create(req: AuthenticatedRequest, res: Response) {
|
||||
destination_code, delivery_destination, delivery_address,
|
||||
created_date, created_by, writer, status
|
||||
) VALUES (
|
||||
$1, $2, $3, $4,
|
||||
gen_random_uuid()::text, $1, $2, $3, $4,
|
||||
$5, $6, $7,
|
||||
$8, $9, $10, $11, $12,
|
||||
$13, $14, $15,
|
||||
|
||||
@@ -29,7 +29,7 @@ async function copyChecklistToSplit(
|
||||
if (routingDetailId) {
|
||||
const result = await client.query(
|
||||
`INSERT INTO process_work_result (
|
||||
company_code, work_order_process_id,
|
||||
id, company_code, work_order_process_id,
|
||||
source_work_item_id, source_detail_id,
|
||||
work_phase, item_title, item_sort_order,
|
||||
detail_content, detail_type, detail_sort_order, is_required,
|
||||
@@ -38,7 +38,7 @@ async function copyChecklistToSplit(
|
||||
status, writer
|
||||
)
|
||||
SELECT
|
||||
pwi.company_code, $1,
|
||||
gen_random_uuid()::text, pwi.company_code, $1,
|
||||
pwi.id, pwd.id,
|
||||
pwi.work_phase, pwi.title, pwi.sort_order::text,
|
||||
pwd.content, pwd.detail_type, pwd.sort_order::text, pwd.is_required,
|
||||
@@ -59,7 +59,7 @@ async function copyChecklistToSplit(
|
||||
// B. routing_detail_id가 없으면 마스터 행의 process_work_result에서 구조만 복사 (타이머/결과값 초기화)
|
||||
const result = await client.query(
|
||||
`INSERT INTO process_work_result (
|
||||
company_code, work_order_process_id,
|
||||
id, company_code, work_order_process_id,
|
||||
source_work_item_id, source_detail_id,
|
||||
work_phase, item_title, item_sort_order,
|
||||
detail_content, detail_type, detail_sort_order, is_required,
|
||||
@@ -68,7 +68,7 @@ async function copyChecklistToSplit(
|
||||
status, writer
|
||||
)
|
||||
SELECT
|
||||
company_code, $1,
|
||||
gen_random_uuid()::text, company_code, $1,
|
||||
source_work_item_id, source_detail_id,
|
||||
work_phase, item_title, item_sort_order,
|
||||
detail_content, detail_type, detail_sort_order, is_required,
|
||||
@@ -168,10 +168,10 @@ export const createWorkProcesses = async (
|
||||
// 2. work_order_process INSERT
|
||||
const wopResult = await client.query(
|
||||
`INSERT INTO work_order_process (
|
||||
company_code, wo_id, seq_no, process_code, process_name,
|
||||
id, company_code, wo_id, seq_no, process_code, process_name,
|
||||
is_required, is_fixed_order, standard_time, plan_qty,
|
||||
status, routing_detail_id, writer
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
) VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
RETURNING id`,
|
||||
[
|
||||
companyCode,
|
||||
@@ -778,13 +778,13 @@ export const saveResult = async (
|
||||
const masterId = proc.parent_process_id || work_order_process_id;
|
||||
const reworkInsert = await pool.query(
|
||||
`INSERT INTO work_order_process (
|
||||
wo_id, seq_no, process_code, process_name, is_required, is_fixed_order,
|
||||
id, wo_id, seq_no, process_code, process_name, is_required, is_fixed_order,
|
||||
standard_time, equipment_code, routing_detail_id,
|
||||
status, input_qty, good_qty, defect_qty, concession_qty, total_production_qty,
|
||||
result_status, is_rework, rework_source_id,
|
||||
parent_process_id, company_code, writer
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9,
|
||||
gen_random_uuid()::text, $1, $2, $3, $4, $5, $6, $7, $8, $9,
|
||||
'acceptable', $10, '0', '0', '0', '0',
|
||||
'draft', 'Y', $11,
|
||||
$12, $13, $14
|
||||
@@ -1444,13 +1444,13 @@ export const acceptProcess = async (req: AuthenticatedRequest, res: Response) =>
|
||||
// 분할 행 INSERT (원본 행에서 공정 정보 복사)
|
||||
const result = await pool.query(
|
||||
`INSERT INTO work_order_process (
|
||||
wo_id, seq_no, process_code, process_name, is_required, is_fixed_order,
|
||||
id, wo_id, seq_no, process_code, process_name, is_required, is_fixed_order,
|
||||
standard_time, equipment_code, routing_detail_id,
|
||||
status, input_qty, good_qty, defect_qty, total_production_qty,
|
||||
result_status, accepted_by, accepted_at, started_at,
|
||||
parent_process_id, company_code, writer
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7, $8, $9,
|
||||
gen_random_uuid()::text, $1, $2, $3, $4, $5, $6, $7, $8, $9,
|
||||
'in_progress', $10, '0', '0', '0',
|
||||
'draft', $11, NOW()::text, NOW()::text,
|
||||
$12, $13, $11
|
||||
@@ -1607,3 +1607,355 @@ export const cancelAccept = async (
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ========================================
|
||||
// POP 전용 함수 (PC 코드와 분리)
|
||||
// ========================================
|
||||
|
||||
/**
|
||||
* 내부 헬퍼: 단일 작업지시에 대해 work_order_process + process_work_result 일괄 생성
|
||||
* syncWorkInstructions에서 사용한다.
|
||||
*/
|
||||
async function generateWorkProcessesForInstruction(
|
||||
client: { query: (text: string, values?: any[]) => Promise<any> },
|
||||
workInstructionId: string,
|
||||
routingVersionId: string,
|
||||
planQty: string | null,
|
||||
companyCode: string,
|
||||
userId: string
|
||||
): Promise<{
|
||||
processes: Array<{ id: string; seq_no: string; process_name: string; checklist_count: number }>;
|
||||
total_checklists: number;
|
||||
} | null> {
|
||||
const existCheck = await client.query(
|
||||
`SELECT COUNT(*) as cnt FROM work_order_process
|
||||
WHERE wo_id = $1 AND company_code = $2`,
|
||||
[workInstructionId, companyCode]
|
||||
);
|
||||
if (parseInt(existCheck.rows[0].cnt, 10) > 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const routingDetails = await client.query(
|
||||
`SELECT rd.id, rd.seq_no, rd.process_code,
|
||||
COALESCE(pm.process_name, rd.process_code) as process_name,
|
||||
rd.is_required, rd.is_fixed_order, rd.standard_time
|
||||
FROM item_routing_detail rd
|
||||
LEFT JOIN process_mng pm ON pm.process_code = rd.process_code
|
||||
AND pm.company_code = rd.company_code
|
||||
WHERE rd.routing_version_id = $1 AND rd.company_code = $2
|
||||
ORDER BY CAST(rd.seq_no AS int) NULLS LAST`,
|
||||
[routingVersionId, companyCode]
|
||||
);
|
||||
|
||||
if (routingDetails.rows.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const processes: Array<{
|
||||
id: string; seq_no: string; process_name: string; checklist_count: number;
|
||||
}> = [];
|
||||
let totalChecklists = 0;
|
||||
|
||||
for (const rd of routingDetails.rows) {
|
||||
const wopResult = await client.query(
|
||||
`INSERT INTO work_order_process (
|
||||
id, company_code, wo_id, seq_no, process_code, process_name,
|
||||
is_required, is_fixed_order, standard_time, plan_qty,
|
||||
status, routing_detail_id, writer
|
||||
) VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
||||
RETURNING id`,
|
||||
[
|
||||
companyCode, workInstructionId, rd.seq_no, rd.process_code, rd.process_name,
|
||||
rd.is_required, rd.is_fixed_order, rd.standard_time, planQty || null,
|
||||
parseInt(rd.seq_no, 10) === 1 ? "acceptable" : "waiting", rd.id, userId,
|
||||
]
|
||||
);
|
||||
const wopId = wopResult.rows[0].id;
|
||||
|
||||
const checklistCount = await copyChecklistToSplit(
|
||||
client, wopId, wopId, rd.id, companyCode, userId
|
||||
);
|
||||
totalChecklists += checklistCount;
|
||||
|
||||
processes.push({
|
||||
id: wopId, seq_no: rd.seq_no, process_name: rd.process_name, checklist_count: checklistCount,
|
||||
});
|
||||
}
|
||||
|
||||
return { processes, total_checklists: totalChecklists };
|
||||
}
|
||||
|
||||
/**
|
||||
* POP: 미동기화 작업지시 일괄 동기화
|
||||
*/
|
||||
export const syncWorkInstructions = async (
|
||||
req: AuthenticatedRequest,
|
||||
res: Response
|
||||
) => {
|
||||
const pool = getPool();
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const userId = req.user!.userId;
|
||||
const unsyncedResult = await pool.query(
|
||||
`SELECT wi.id, wi.work_instruction_no, wi.routing, wi.qty
|
||||
FROM work_instruction wi
|
||||
WHERE wi.company_code = $1
|
||||
AND wi.routing IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM work_order_process wop
|
||||
WHERE wop.wo_id = wi.id AND wop.company_code = $1
|
||||
)`,
|
||||
[companyCode]
|
||||
);
|
||||
const unsynced = unsyncedResult.rows;
|
||||
if (unsynced.length === 0) {
|
||||
return res.json({ success: true, data: { synced: 0, skipped: 0, errors: 0, details: [] } });
|
||||
}
|
||||
let synced = 0, skipped = 0, errors = 0;
|
||||
const details: Array<{
|
||||
work_instruction_id: string; work_instruction_no: string;
|
||||
status: "synced" | "skipped" | "error"; process_count?: number; error?: string;
|
||||
}> = [];
|
||||
for (const wi of unsynced) {
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
await client.query("BEGIN");
|
||||
const result = await generateWorkProcessesForInstruction(
|
||||
client, wi.id, wi.routing, wi.qty || null, companyCode, userId
|
||||
);
|
||||
if (!result) {
|
||||
await client.query("ROLLBACK");
|
||||
skipped++;
|
||||
details.push({ work_instruction_id: wi.id, work_instruction_no: wi.work_instruction_no, status: "skipped" });
|
||||
continue;
|
||||
}
|
||||
await client.query("COMMIT");
|
||||
synced++;
|
||||
details.push({
|
||||
work_instruction_id: wi.id, work_instruction_no: wi.work_instruction_no,
|
||||
status: "synced", process_count: result.processes.length,
|
||||
});
|
||||
} catch (err: any) {
|
||||
await client.query("ROLLBACK");
|
||||
errors++;
|
||||
details.push({
|
||||
work_instruction_id: wi.id, work_instruction_no: wi.work_instruction_no,
|
||||
status: "error", error: err.message || "알 수 없는 오류",
|
||||
});
|
||||
} finally {
|
||||
client.release();
|
||||
}
|
||||
}
|
||||
return res.json({ success: true, data: { synced, skipped, errors, details } });
|
||||
} catch (error: any) {
|
||||
logger.error("[pop/production] sync-work-instructions 오류:", error);
|
||||
return res.status(500).json({ success: false, message: error.message || "동기화 오류" });
|
||||
}
|
||||
};
|
||||
|
||||
export const getWarehouses = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const pool = getPool();
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const result = await pool.query(
|
||||
`SELECT id, warehouse_code, warehouse_name, warehouse_type
|
||||
FROM warehouse_info WHERE company_code = $1 AND COALESCE(status, '') != '삭제' ORDER BY warehouse_name`,
|
||||
[companyCode]
|
||||
);
|
||||
return res.json({ success: true, data: result.rows });
|
||||
} catch (error: any) {
|
||||
return res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
export const getWarehouseLocations = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const pool = getPool();
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const { warehouseId } = req.params;
|
||||
if (!warehouseId) return res.status(400).json({ success: false, message: "warehouseId 필수" });
|
||||
const whInfo = await pool.query(
|
||||
`SELECT warehouse_code FROM warehouse_info WHERE id = $1 AND company_code = $2`,
|
||||
[warehouseId, companyCode]
|
||||
);
|
||||
if (whInfo.rowCount === 0) return res.json({ success: true, data: [] });
|
||||
const result = await pool.query(
|
||||
`SELECT id, location_code, location_name FROM warehouse_location
|
||||
WHERE warehouse_code = $1 AND company_code = $2 ORDER BY location_name`,
|
||||
[whInfo.rows[0].warehouse_code, companyCode]
|
||||
);
|
||||
return res.json({ success: true, data: result.rows });
|
||||
} catch (error: any) {
|
||||
return res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
export const isLastProcess = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const pool = getPool();
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const { processId } = req.params;
|
||||
if (!processId) return res.json({ success: true, data: { isLast: false } });
|
||||
const process = await pool.query(
|
||||
`SELECT wo_id, seq_no, parent_process_id FROM work_order_process WHERE id = $1 AND company_code = $2`,
|
||||
[processId, companyCode]
|
||||
);
|
||||
if (process.rowCount === 0) return res.json({ success: true, data: { isLast: false } });
|
||||
const { wo_id, seq_no, parent_process_id } = process.rows[0];
|
||||
let effectiveSeqNo = seq_no;
|
||||
if (parent_process_id) {
|
||||
const master = await pool.query(
|
||||
`SELECT seq_no FROM work_order_process WHERE id = $1 AND company_code = $2`,
|
||||
[parent_process_id, companyCode]
|
||||
);
|
||||
if (master.rowCount > 0) effectiveSeqNo = master.rows[0].seq_no;
|
||||
}
|
||||
const next = await pool.query(
|
||||
`SELECT id FROM work_order_process
|
||||
WHERE wo_id = $1 AND company_code = $2 AND CAST(seq_no AS int) > CAST($3 AS int) AND parent_process_id IS NULL LIMIT 1`,
|
||||
[wo_id, companyCode, effectiveSeqNo]
|
||||
);
|
||||
const warehouseInfo = await pool.query(
|
||||
`SELECT target_warehouse_id, target_location_code FROM work_order_process WHERE id = $1 AND company_code = $2`,
|
||||
[processId, companyCode]
|
||||
);
|
||||
return res.json({
|
||||
success: true,
|
||||
data: {
|
||||
isLast: next.rowCount === 0, woId: wo_id, seqNo: effectiveSeqNo,
|
||||
targetWarehouseId: warehouseInfo.rows[0]?.target_warehouse_id || null,
|
||||
targetLocationCode: warehouseInfo.rows[0]?.target_location_code || null,
|
||||
},
|
||||
});
|
||||
} catch (error: any) {
|
||||
return res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
export const updateTargetWarehouse = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const pool = getPool();
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const userId = req.user!.userId;
|
||||
const { work_order_process_id, target_warehouse_id, target_location_code } = req.body;
|
||||
if (!work_order_process_id || !target_warehouse_id)
|
||||
return res.status(400).json({ success: false, message: "work_order_process_id와 target_warehouse_id 필수" });
|
||||
const procInfo = await pool.query(
|
||||
`SELECT parent_process_id FROM work_order_process WHERE id = $1 AND company_code = $2`,
|
||||
[work_order_process_id, companyCode]
|
||||
);
|
||||
const idsToUpdate = [work_order_process_id];
|
||||
if (procInfo.rowCount > 0 && procInfo.rows[0].parent_process_id) idsToUpdate.push(procInfo.rows[0].parent_process_id);
|
||||
for (const id of idsToUpdate) {
|
||||
await pool.query(
|
||||
`UPDATE work_order_process SET target_warehouse_id = $3, target_location_code = $4, writer = $5, updated_date = NOW()
|
||||
WHERE id = $1 AND company_code = $2`,
|
||||
[id, companyCode, target_warehouse_id, target_location_code || null, userId]
|
||||
);
|
||||
}
|
||||
return res.json({ success: true, data: { target_warehouse_id, target_location_code } });
|
||||
} catch (error: any) {
|
||||
return res.status(500).json({ success: false, message: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
export const inventoryInbound = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const userId = req.user!.userId;
|
||||
const { work_order_process_id, warehouse_code, location_code } = req.body;
|
||||
if (!work_order_process_id || !warehouse_code)
|
||||
return res.status(400).json({ success: false, message: "work_order_process_id와 warehouse_code 필수" });
|
||||
await client.query("BEGIN");
|
||||
const procResult = await client.query(
|
||||
`SELECT wo_id, good_qty, concession_qty, parent_process_id, target_warehouse_id FROM work_order_process WHERE id = $1 AND company_code = $2`,
|
||||
[work_order_process_id, companyCode]
|
||||
);
|
||||
if (procResult.rowCount === 0) { await client.query("ROLLBACK"); return res.status(404).json({ success: false, message: "공정 없음" }); }
|
||||
const proc = procResult.rows[0];
|
||||
if (proc.target_warehouse_id) { await client.query("ROLLBACK"); return res.status(409).json({ success: false, message: "이미 입고 완료" }); }
|
||||
const goodQty = parseInt(proc.good_qty || "0", 10) + parseInt(proc.concession_qty || "0", 10);
|
||||
if (goodQty <= 0) { await client.query("ROLLBACK"); return res.status(400).json({ success: false, message: "양품 0" }); }
|
||||
const wiResult = await client.query(`SELECT item_id FROM work_instruction WHERE id = $1 AND company_code = $2`, [proc.wo_id, companyCode]);
|
||||
if (wiResult.rowCount === 0) { await client.query("ROLLBACK"); return res.status(404).json({ success: false, message: "작업지시 없음" }); }
|
||||
const itemResult = await client.query(`SELECT item_number FROM item_info WHERE id = $1 AND company_code = $2`, [wiResult.rows[0].item_id, companyCode]);
|
||||
if (itemResult.rowCount === 0) { await client.query("ROLLBACK"); return res.status(404).json({ success: false, message: "품목 없음" }); }
|
||||
const itemCode = itemResult.rows[0].item_number;
|
||||
const locCode = location_code || warehouse_code;
|
||||
await client.query(
|
||||
`INSERT INTO inventory_stock (id, company_code, item_code, warehouse_code, location_code, current_qty, last_in_date, created_date, updated_date, writer)
|
||||
VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, NOW(), NOW(), NOW(), $6)
|
||||
ON CONFLICT (company_code, item_code, warehouse_code, location_code)
|
||||
DO UPDATE SET current_qty = (COALESCE(inventory_stock.current_qty::numeric, 0) + $5::numeric)::text,
|
||||
last_in_date = NOW(), updated_date = NOW(), writer = $6`,
|
||||
[companyCode, itemCode, warehouse_code, locCode, String(goodQty), userId]
|
||||
);
|
||||
const idsToUpdate = [work_order_process_id];
|
||||
if (proc.parent_process_id) idsToUpdate.push(proc.parent_process_id);
|
||||
for (const id of idsToUpdate) {
|
||||
await client.query(
|
||||
`UPDATE work_order_process SET target_warehouse_id = $3, target_location_code = $4, writer = $5, updated_date = NOW() WHERE id = $1 AND company_code = $2`,
|
||||
[id, companyCode, warehouse_code, location_code || null, userId]
|
||||
);
|
||||
}
|
||||
await client.query("COMMIT");
|
||||
return res.json({ success: true, message: "재고 입고 완료", data: { item_code: itemCode, warehouse_code, location_code: locCode, qty: goodQty } });
|
||||
} catch (error: any) {
|
||||
await client.query("ROLLBACK").catch(() => {});
|
||||
return res.status(500).json({ success: false, message: error.message });
|
||||
} finally { client.release(); }
|
||||
};
|
||||
|
||||
export const quickInventoryInbound = async (req: AuthenticatedRequest, res: Response) => {
|
||||
const pool = getPool();
|
||||
const client = await pool.connect();
|
||||
try {
|
||||
const companyCode = req.user!.companyCode;
|
||||
const userId = req.user!.userId;
|
||||
const { item_id, qty, warehouse_code, location_code, remark } = req.body;
|
||||
if (!item_id || !qty || !warehouse_code)
|
||||
return res.status(400).json({ success: false, message: "item_id, qty, warehouse_code 필수" });
|
||||
const parsedQty = parseInt(String(qty), 10);
|
||||
if (isNaN(parsedQty) || parsedQty <= 0)
|
||||
return res.status(400).json({ success: false, message: "수량은 1 이상" });
|
||||
await client.query("BEGIN");
|
||||
const itemResult = await client.query(
|
||||
`SELECT item_number, item_name, size, material, unit FROM item_info WHERE id = $1 AND company_code = $2`, [item_id, companyCode]
|
||||
);
|
||||
if (itemResult.rowCount === 0) { await client.query("ROLLBACK"); return res.status(404).json({ success: false, message: "품목 없음" }); }
|
||||
const item = itemResult.rows[0];
|
||||
const locCode = location_code || warehouse_code;
|
||||
await client.query(
|
||||
`INSERT INTO inventory_stock (id, company_code, item_code, warehouse_code, location_code, current_qty, last_in_date, created_date, updated_date, writer)
|
||||
VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, NOW(), NOW(), NOW(), $6)
|
||||
ON CONFLICT (company_code, item_code, warehouse_code, location_code)
|
||||
DO UPDATE SET current_qty = (COALESCE(inventory_stock.current_qty::numeric, 0) + $5::numeric)::text,
|
||||
last_in_date = NOW(), updated_date = NOW(), writer = $6`,
|
||||
[companyCode, item.item_number, warehouse_code, locCode, String(parsedQty), userId]
|
||||
);
|
||||
const seqResult = await client.query(
|
||||
`SELECT COALESCE(MAX(CASE WHEN inbound_number ~ '^QIB-[0-9]{4}-[0-9]+$'
|
||||
THEN CAST(SUBSTRING(inbound_number FROM '[0-9]+$') AS INTEGER) ELSE 0 END), 0) + 1 AS next_seq
|
||||
FROM inbound_mng WHERE company_code = $1`, [companyCode]
|
||||
);
|
||||
const inboundNumber = `QIB-${new Date().getFullYear()}-${String(seqResult.rows[0].next_seq).padStart(4, "0")}`;
|
||||
await client.query(
|
||||
`INSERT INTO inbound_mng (id, company_code, inbound_number, inbound_type, inbound_date,
|
||||
item_number, item_name, spec, material, unit, inbound_qty, warehouse_code, location_code,
|
||||
inbound_status, memo, remark, created_date, updated_date, writer, created_by, updated_by
|
||||
) VALUES (gen_random_uuid()::text, $1, $2, '간이입고', CURRENT_DATE,
|
||||
$3, $4, $5, $6, $7, $8, $9, $10, '완료', $11, $12, NOW(), NOW(), $13, $13, $13)`,
|
||||
[companyCode, inboundNumber, item.item_number, item.item_name, item.size, item.material, item.unit,
|
||||
parsedQty, warehouse_code, locCode, remark || "POP 간이입고", remark || null, userId]
|
||||
);
|
||||
await client.query("COMMIT");
|
||||
return res.json({ success: true, message: "간이 입고 완료",
|
||||
data: { inbound_number: inboundNumber, item_code: item.item_number, item_name: item.item_name, warehouse_code, location_code: locCode, qty: parsedQty } });
|
||||
} catch (error: any) {
|
||||
await client.query("ROLLBACK").catch(() => {});
|
||||
return res.status(500).json({ success: false, message: error.message });
|
||||
} finally { client.release(); }
|
||||
};
|
||||
|
||||
@@ -246,10 +246,10 @@ export async function create(req: AuthenticatedRequest, res: Response) {
|
||||
} else {
|
||||
await client.query(
|
||||
`INSERT INTO inventory_stock (
|
||||
company_code, item_code, warehouse_code, location_code,
|
||||
id, company_code, item_code, warehouse_code, location_code,
|
||||
current_qty, safety_qty, last_in_date,
|
||||
created_date, updated_date, writer
|
||||
) VALUES ($1, $2, $3, $4, $5, '0', NOW(), NOW(), NOW(), $6)`,
|
||||
) VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, '0', NOW(), NOW(), NOW(), $6)`,
|
||||
[companyCode, itemCode, whCode, locCode, String(inQty), userId]
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user