/** * POP 입출고관리 디테일 단건 조회 컨트롤러 * * inout-history 카드 클릭 시 모달용 단건 조회 API 3종 (read-only). * 라우트는 popInventoryRoutes.ts 에서 source 별로 분리: * GET /api/pop/inventory/inout-detail/inbound/:id (+ ?detail_id=...) * GET /api/pop/inventory/inout-detail/outbound/:id * GET /api/pop/inventory/inout-detail/history/:id */ import type { Response } from "express"; import { getPool } from "../database/db"; import type { AuthenticatedRequest } from "../types/auth"; import { logger } from "../utils/logger"; // ===== inbound: inbound_mng (헤더) + inbound_detail (1행, optional) ===== export async function getInboundDetail( req: AuthenticatedRequest, res: Response, ) { try { const companyCode = req.user!.companyCode; const { id } = req.params; const { detail_id } = req.query as Record; const pool = getPool(); const headerSql = ` SELECT im.*, wh.warehouse_name, u.user_name AS writer_name FROM inbound_mng im LEFT JOIN warehouse_info wh ON wh.warehouse_code = im.warehouse_code AND wh.company_code = im.company_code LEFT JOIN user_info u ON u.user_id = im.writer AND u.company_code = im.company_code WHERE im.id = $1 AND ($2::text = '*' OR im.company_code = $2) `; const headerResult = await pool.query(headerSql, [id, companyCode]); if (headerResult.rowCount === 0) { return res .status(404) .json({ success: false, message: "입고 데이터를 찾을 수 없습니다." }); } const header = headerResult.rows[0]; let detail: Record | null = null; if (detail_id) { const detailResult = await pool.query( `SELECT * FROM inbound_detail WHERE id = $1 AND ($2::text = '*' OR company_code = $2)`, [detail_id, companyCode], ); detail = detailResult.rows[0] ?? null; } return res.json({ success: true, data: { header, detail } }); } catch (error: unknown) { const msg = error instanceof Error ? error.message : "조회 실패"; logger.error("입고 디테일 단건 조회 실패", { error: msg }); return res.status(500).json({ success: false, message: msg }); } } // ===== outbound: outbound_mng (단건) ===== export async function getOutboundDetail( req: AuthenticatedRequest, res: Response, ) { try { const companyCode = req.user!.companyCode; const { id } = req.params; const pool = getPool(); const sql = ` SELECT om.*, wh.warehouse_name, u.user_name AS writer_name FROM outbound_mng om LEFT JOIN warehouse_info wh ON wh.warehouse_code = om.warehouse_code AND wh.company_code = om.company_code LEFT JOIN user_info u ON u.user_id = om.writer AND u.company_code = om.company_code WHERE om.id = $1 AND ($2::text = '*' OR om.company_code = $2) `; const result = await pool.query(sql, [id, companyCode]); if (result.rowCount === 0) { return res .status(404) .json({ success: false, message: "출고 데이터를 찾을 수 없습니다." }); } return res.json({ success: true, data: { row: result.rows[0] } }); } catch (error: unknown) { const msg = error instanceof Error ? error.message : "조회 실패"; logger.error("출고 디테일 단건 조회 실패", { error: msg }); return res.status(500).json({ success: false, message: msg }); } } // ===== history: inventory_history (단건) + warehouse + item_info JOIN ===== export async function getHistoryDetail( req: AuthenticatedRequest, res: Response, ) { try { const companyCode = req.user!.companyCode; const { id } = req.params; const pool = getPool(); const sql = ` SELECT ih.*, wh.warehouse_name, ii.item_name AS joined_item_name, ii.unit AS joined_unit FROM inventory_history ih LEFT JOIN warehouse_info wh ON wh.warehouse_code = ih.warehouse_code AND wh.company_code = ih.company_code LEFT JOIN ( SELECT DISTINCT ON (item_number, company_code) item_number, item_name, unit, company_code FROM item_info ORDER BY item_number, company_code, created_date DESC ) ii ON ih.item_code = ii.item_number AND ih.company_code = ii.company_code WHERE ih.id = $1 AND ($2::text = '*' OR ih.company_code = $2) `; const result = await pool.query(sql, [id, companyCode]); if (result.rowCount === 0) { return res.status(404).json({ success: false, message: "재고이력 데이터를 찾을 수 없습니다.", }); } return res.json({ success: true, data: { row: result.rows[0] } }); } catch (error: unknown) { const msg = error instanceof Error ? error.message : "조회 실패"; logger.error("재고이력 디테일 단건 조회 실패", { error: msg }); return res.status(500).json({ success: false, message: msg }); } }