Refactor analytics report and production plan services for improved data handling

- Updated the `getQualityReportData` function to utilize `inspection_result_mng` for quality report generation, enhancing data accuracy by aggregating inspection results.
- Refined date handling in the `getOrderSummary` function to improve filtering logic and ensure accurate stock calculations.
- Implemented virtual scrolling in the `TimelineScheduler` component to optimize performance when rendering large datasets.

These changes enhance data retrieval efficiency and user experience across analytics and production planning modules.
This commit is contained in:
kjs
2026-04-29 21:05:38 +09:00
parent 5f9c876f9e
commit d549947fac
6 changed files with 150 additions and 93 deletions

View File

@@ -131,7 +131,13 @@ export async function getOrderSummary(
LEFT JOIN stock_info si ON os.item_code = si.item_code
LEFT JOIN plan_info pi ON os.item_code = pi.item_code
LEFT JOIN item_info_dedup ilt ON os.item_code = ilt.item_number
${options?.excludePlanned ? "WHERE COALESCE(pi.existing_plan_qty, 0) + COALESCE(pi.in_progress_qty, 0) = 0" : ""}
${options?.excludePlanned
? ""
: `WHERE GREATEST(
os.total_balance_qty + COALESCE(si.safety_stock, 0) - COALESCE(si.current_stock, 0)
- COALESCE(pi.existing_plan_qty, 0) - COALESCE(pi.in_progress_qty, 0),
0
) > 0`}
ORDER BY os.item_code
`;
@@ -141,10 +147,11 @@ export async function getOrderSummary(
let pagedParams: any[] = params;
if (usePaging) {
// total: 그룹 수 = order_summary CTE의 행
// total: excludePlanned 필터까지 적용한 그룹
// order_summary + plan_info CTE만 다시 만들어서 동일 필터로 COUNT
const countQuery = `
WITH all_orders AS (
SELECT so.part_code, so.company_code
SELECT so.part_code, so.company_code, COALESCE(so.balance_qty::numeric, 0) AS balance_qty
FROM sales_order_mng so
WHERE ${whereClause}
AND so.part_code IS NOT NULL AND so.part_code != ''
@@ -153,15 +160,43 @@ export async function getOrderSummary(
WHERE sd.order_no = so.order_no AND sd.company_code = so.company_code
)
UNION ALL
SELECT sd.part_code, sd.company_code
SELECT sd.part_code, sd.company_code, COALESCE(sd.balance_qty::numeric, sd.qty::numeric - COALESCE(sd.ship_qty::numeric, 0), 0)
FROM sales_order_detail sd
INNER JOIN sales_order_mng so ON sd.order_no = so.order_no AND sd.company_code = so.company_code
WHERE sd.company_code = $1
AND sd.part_code IS NOT NULL AND sd.part_code != ''
),
os AS (
SELECT part_code AS item_code, SUM(balance_qty) AS total_balance_qty
FROM all_orders GROUP BY part_code
),
si AS (
SELECT item_code,
SUM(COALESCE(current_qty::numeric, 0)) AS current_stock,
MAX(COALESCE(safety_qty::numeric, 0)) AS safety_stock
FROM inventory_stock WHERE company_code = $1 GROUP BY item_code
),
pi AS (
SELECT item_code,
SUM(CASE WHEN status = 'planned' THEN COALESCE(plan_qty, 0) ELSE 0 END) AS existing_plan_qty,
SUM(CASE WHEN status = 'in_progress' THEN COALESCE(plan_qty, 0) ELSE 0 END) AS in_progress_qty
FROM production_plan_mng
WHERE company_code = $1
AND COALESCE(product_type, '완제품') = '완제품'
AND status NOT IN ('completed', 'cancelled')
GROUP BY item_code
)
SELECT COUNT(*)::int AS total FROM (
SELECT DISTINCT part_code FROM all_orders
) g;
SELECT COUNT(*)::int AS total
FROM os
LEFT JOIN si ON os.item_code = si.item_code
LEFT JOIN pi ON os.item_code = pi.item_code
${options?.excludePlanned
? ""
: `WHERE GREATEST(
os.total_balance_qty + COALESCE(si.safety_stock, 0) - COALESCE(si.current_stock, 0)
- COALESCE(pi.existing_plan_qty, 0) - COALESCE(pi.in_progress_qty, 0),
0
) > 0`};
`;
const countRes = await pool.query(countQuery, params);
total = countRes.rows[0]?.total ?? 0;