feat: 입고/자재현황/분석리포트 컨트롤러 및 프론트엔드 개선
- receivingController: 헤더-디테일 JOIN 구조로 변경, 검색/조회 로직 개선 - materialStatusController: work_instruction 테이블 기반으로 쿼리 수정 - analyticsReportController: 구매 리포트 company_code 필터링 로직 개선 - material-status 페이지: COMPANY_29/COMPANY_7 프론트엔드 업데이트 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -218,37 +218,84 @@ export async function getPurchaseReportData(req: any, res: Response): Promise<vo
|
||||
if (!companyCode) { res.status(401).json({ success: false, message: "인증 정보가 없습니다" }); return; }
|
||||
|
||||
const { startDate, endDate } = req.query;
|
||||
const conditions: string[] = [];
|
||||
const params: any[] = [];
|
||||
let idx = 1;
|
||||
|
||||
// company_code 필터 파라미터 ($1 또는 없음)
|
||||
const cf = buildCompanyFilter(companyCode, "po", idx);
|
||||
if (cf.condition) { conditions.push(cf.condition); params.push(...cf.params); idx = cf.nextIdx; }
|
||||
let companyConditionDetail = "";
|
||||
let companyConditionLegacy = "";
|
||||
if (cf.condition) {
|
||||
// purchase_detail 쪽: pd.company_code
|
||||
companyConditionDetail = `pd.company_code = $${idx}`;
|
||||
// purchase_order_mng 쪽: po.company_code
|
||||
companyConditionLegacy = `po.company_code = $${idx}`;
|
||||
// NOT EXISTS 내부에서도 동일 파라미터 재사용
|
||||
params.push(...cf.params);
|
||||
idx = cf.nextIdx;
|
||||
}
|
||||
|
||||
const df = buildDateFilter(startDate, endDate, "COALESCE(po.order_date, po.created_date::date::text)", idx);
|
||||
conditions.push(...df.conditions); params.push(...df.params); idx = df.nextIdx;
|
||||
// 날짜 필터는 외부 쿼리에서 적용
|
||||
const outerConditions: string[] = [];
|
||||
const df = buildDateFilter(startDate, endDate, "date", idx);
|
||||
outerConditions.push(...df.conditions);
|
||||
params.push(...df.params);
|
||||
idx = df.nextIdx;
|
||||
|
||||
const whereClause = buildWhereClause(conditions);
|
||||
const outerWhereClause = buildWhereClause(outerConditions);
|
||||
|
||||
const dataQuery = `
|
||||
SELECT
|
||||
COALESCE(po.order_date, po.created_date::date::text) as date,
|
||||
po.purchase_no,
|
||||
COALESCE(po.supplier_name, po.supplier_code, '미지정') as supplier,
|
||||
COALESCE(po.item_name, po.item_code, '미지정') as item,
|
||||
po.item_code,
|
||||
COALESCE(po.manager, '미지정') as manager,
|
||||
po.status,
|
||||
CAST(COALESCE(NULLIF(po.order_qty, ''), '0') AS numeric) as "orderQty",
|
||||
CAST(COALESCE(NULLIF(po.received_qty, ''), '0') AS numeric) as "receiveQty",
|
||||
CAST(COALESCE(NULLIF(po.unit_price, ''), '0') AS numeric) as "unitPrice",
|
||||
CAST(COALESCE(NULLIF(po.amount, ''), '0') AS numeric) as "orderAmt",
|
||||
CAST(COALESCE(NULLIF(po.received_qty, ''), '0') AS numeric)
|
||||
* CAST(COALESCE(NULLIF(po.unit_price, ''), '0') AS numeric) as "receiveAmt",
|
||||
1 as "orderCnt",
|
||||
po.company_code
|
||||
FROM purchase_order_mng po
|
||||
${whereClause}
|
||||
WITH combined AS (
|
||||
-- 신규: purchase_detail 기반 (헤더는 purchase_order_mng LEFT JOIN)
|
||||
SELECT
|
||||
COALESCE(po.order_date, po.created_date::date::text, pd.created_date::date::text) as date,
|
||||
COALESCE(po.purchase_no, pd.purchase_no) as purchase_no,
|
||||
COALESCE(pd.supplier_name, pd.supplier_code, po.supplier_name, po.supplier_code, '미지정') as supplier,
|
||||
COALESCE(NULLIF(pd.item_name, ''), po.item_name, NULLIF(pd.item_code, ''), po.item_code, '미지정') as item,
|
||||
COALESCE(NULLIF(pd.item_code, ''), po.item_code) as item_code,
|
||||
COALESCE(po.manager, '미지정') as manager,
|
||||
COALESCE(po.status, '') as status,
|
||||
CAST(COALESCE(NULLIF(pd.order_qty, ''), '0') AS numeric) as "orderQty",
|
||||
CAST(COALESCE(NULLIF(po.received_qty, ''), '0') AS numeric) as "receiveQty",
|
||||
CAST(COALESCE(NULLIF(pd.unit_price, ''), '0') AS numeric) as "unitPrice",
|
||||
CAST(COALESCE(NULLIF(pd.order_qty, ''), '0') AS numeric)
|
||||
* CAST(COALESCE(NULLIF(pd.unit_price, ''), '0') AS numeric) as "orderAmt",
|
||||
CAST(COALESCE(NULLIF(po.received_qty, ''), '0') AS numeric)
|
||||
* CAST(COALESCE(NULLIF(pd.unit_price, ''), '0') AS numeric) as "receiveAmt",
|
||||
1 as "orderCnt",
|
||||
pd.company_code
|
||||
FROM purchase_detail pd
|
||||
LEFT JOIN purchase_order_mng po
|
||||
ON pd.purchase_no = po.purchase_no AND pd.company_code = po.company_code
|
||||
${companyConditionDetail ? `WHERE ${companyConditionDetail}` : ""}
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 레거시: purchase_detail에 없는 purchase_order_mng 데이터
|
||||
SELECT
|
||||
COALESCE(po.order_date, po.created_date::date::text) as date,
|
||||
po.purchase_no,
|
||||
COALESCE(po.supplier_name, po.supplier_code, '미지정') as supplier,
|
||||
COALESCE(po.item_name, po.item_code, '미지정') as item,
|
||||
po.item_code,
|
||||
COALESCE(po.manager, '미지정') as manager,
|
||||
po.status,
|
||||
CAST(COALESCE(NULLIF(po.order_qty, ''), '0') AS numeric) as "orderQty",
|
||||
CAST(COALESCE(NULLIF(po.received_qty, ''), '0') AS numeric) as "receiveQty",
|
||||
CAST(COALESCE(NULLIF(po.unit_price, ''), '0') AS numeric) as "unitPrice",
|
||||
CAST(COALESCE(NULLIF(po.amount, ''), '0') AS numeric) as "orderAmt",
|
||||
CAST(COALESCE(NULLIF(po.received_qty, ''), '0') AS numeric)
|
||||
* CAST(COALESCE(NULLIF(po.unit_price, ''), '0') AS numeric) as "receiveAmt",
|
||||
1 as "orderCnt",
|
||||
po.company_code
|
||||
FROM purchase_order_mng po
|
||||
WHERE ${companyConditionLegacy ? `${companyConditionLegacy} AND ` : ""}NOT EXISTS (
|
||||
SELECT 1 FROM purchase_detail pd
|
||||
WHERE pd.purchase_no = po.purchase_no AND pd.company_code = po.company_code
|
||||
)
|
||||
)
|
||||
SELECT * FROM combined
|
||||
${outerWhereClause}
|
||||
ORDER BY date DESC NULLS LAST
|
||||
`;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user