From cc6786d791435e03dbbbff50a01cb20917bc15ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B9=80=EB=B3=B4=EA=B3=A4?= Date: Sun, 22 Mar 2026 17:33:41 +0900 Subject: [PATCH] =?UTF-8?q?fix:=20[=EC=9E=90=EC=9E=AC=ED=88=AC=EC=9E=85]?= =?UTF-8?q?=20=EC=9E=90=EB=8F=99=EC=9E=85=EB=A0=A5=20=EB=B0=B0=EC=A0=95?= =?UTF-8?q?=EC=88=98=EB=9F=89=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=E2=80=94=20=EA=B7=B8=EB=A3=B9=EB=B3=84=20=EB=8F=85=EB=A6=BD=20?= =?UTF-8?q?=EA=B3=84=EC=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - physicalUsed 교차그룹 추적 제거: 같은 물리 LOT가 다른 BOM 그룹에서 사용될 때 lotInputtedQty가 그룹마다 달라 부정확한 차감 발생 - 각 그룹의 LOT 가용량을 독립적으로 계산 (lotAvailableQty + lotInputtedQty) - allocations useMemo도 동일하게 수정 --- .../WorkerScreen/MaterialInputModal.tsx | 22 +++++-------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/src/components/production/WorkerScreen/MaterialInputModal.tsx b/src/components/production/WorkerScreen/MaterialInputModal.tsx index 64d3ce49..2b1d4131 100644 --- a/src/components/production/WorkerScreen/MaterialInputModal.tsx +++ b/src/components/production/WorkerScreen/MaterialInputModal.tsx @@ -199,10 +199,9 @@ export function MaterialInputModal({ return group.alreadyInputted > 0 ? group.requiredQty : group.effectiveRequiredQty; }, []); - // 배정 수량 계산 (manual 우선 → 나머지 FIFO 자동배분, 물리LOT 교차그룹 추적) + // 배정 수량 계산 (manual 우선 → 나머지 FIFO 자동배분, 그룹별 독립) const allocations = useMemo(() => { const result = new Map(); - const physicalUsed = new Map(); // stockLotId → 그룹 간 누적 사용량 for (const group of materialGroups) { const targetQty = getGroupTargetQty(group); @@ -215,24 +214,18 @@ export function MaterialInputModal({ const val = manualAllocations.get(lotKey)!; result.set(lotKey, val); remaining -= val; - physicalUsed.set(lot.stockLotId, (physicalUsed.get(lot.stockLotId) || 0) + val); } } - // 2차: non-manual 선택 로트 FIFO 자동배분 (물리LOT 가용량 고려) + // 2차: non-manual 선택 로트 FIFO 자동배분 (그룹 내 독립 계산) for (const lot of group.lots) { const lotKey = getLotKey(lot, group.groupKey); if (selectedLotKeys.has(lotKey) && lot.stockLotId && !manualAllocations.has(lotKey)) { const itemInput = lot as unknown as MaterialForItemInput; const maxAvail = lot.lotAvailableQty + (itemInput.lotInputtedQty ?? 0); - const used = physicalUsed.get(lot.stockLotId) || 0; - const effectiveAvail = Math.max(0, maxAvail - used); - const alloc = remaining > 0 ? Math.min(effectiveAvail, remaining) : 0; + const alloc = remaining > 0 ? Math.min(maxAvail, remaining) : 0; result.set(lotKey, alloc); remaining -= alloc; - if (alloc > 0) { - physicalUsed.set(lot.stockLotId, used + alloc); - } } } } @@ -286,11 +279,10 @@ export function MaterialInputModal({ }); }, []); - // FIFO 자동입력 (물리LOT 교차그룹 가용량 추적) + // FIFO 자동입력 (그룹별 독립 배정 — 각 그룹의 LOT 가용량 독립 계산) const handleAutoFill = useCallback(() => { const newSelected = new Set(); const newAllocations = new Map(); - const physicalUsed = new Map(); // stockLotId → 그룹 간 누적 사용량 for (const group of materialGroups) { const targetQty = getGroupTargetQty(group); @@ -301,15 +293,13 @@ export function MaterialInputModal({ if (!lot.stockLotId || remaining <= 0) continue; const lotKey = getLotKey(lot, group.groupKey); const itemInput = lot as unknown as MaterialForItemInput; + // 해당 그룹에서의 LOT 가용량 = 현재 가용 + 이 그룹에서 기투입된 수량 const maxAvail = lot.lotAvailableQty + (itemInput.lotInputtedQty ?? 0); - const used = physicalUsed.get(lot.stockLotId) || 0; - const effectiveAvail = Math.max(0, maxAvail - used); - const alloc = Math.min(effectiveAvail, remaining); + const alloc = Math.min(maxAvail, remaining); if (alloc > 0) { newSelected.add(lotKey); newAllocations.set(lotKey, alloc); remaining -= alloc; - physicalUsed.set(lot.stockLotId, used + alloc); } } }