diff --git a/src/components/production/WorkerScreen/MaterialInputModal.tsx b/src/components/production/WorkerScreen/MaterialInputModal.tsx index fd945ddc..e2a15e26 100644 --- a/src/components/production/WorkerScreen/MaterialInputModal.tsx +++ b/src/components/production/WorkerScreen/MaterialInputModal.tsx @@ -34,7 +34,7 @@ import { } from '@/components/ui/table'; import { toast } from 'sonner'; import { isNextRedirectError } from '@/lib/utils/redirect-error'; -import { getMaterialsForWorkOrder, registerMaterialInput, getMaterialsForItem, registerMaterialInputForItem, searchStockByCode, type MaterialForInput, type MaterialForItemInput, type StockSearchResult } from './actions'; +import { getMaterialsForWorkOrder, registerMaterialInput, getMaterialsForItem, registerMaterialInputForItem, searchStockByCode, forceCreateReceiving, type MaterialForInput, type MaterialForItemInput, type StockSearchResult } from './actions'; import type { WorkOrder } from '../ProductionDashboard/types'; import type { MaterialInput } from './types'; import { formatNumber } from '@/lib/utils/amount'; @@ -103,6 +103,8 @@ export function MaterialInputModal({ setIsSearching(false); }, []); + const [isForceCreating, setIsForceCreating] = useState(false); + // 목업 자재 데이터 (개발용) const MOCK_MATERIALS: MaterialForInput[] = Array.from({ length: 5 }, (_, i) => ({ stockLotId: 100 + i, @@ -346,6 +348,20 @@ export function MaterialInputModal({ } }, [order, workOrderItemId, workOrderItemIds]); + // [개발전용] 입고 강제생성 핸들러 + const handleForceReceiving = useCallback(async (itemId: number, itemCode: string) => { + setIsForceCreating(true); + const result = await forceCreateReceiving(itemId, 100); + if (result.success && result.data) { + toast.success(`${result.data.item_code} 입고 생성 완료 (LOT: ${result.data.lot_no}, ${result.data.qty}EA)`); + handleStockSearch(itemCode); + loadMaterials(); + } else { + toast.error(result.error || '입고 생성 실패'); + } + setIsForceCreating(false); + }, [handleStockSearch, loadMaterials]); + // 모달이 열릴 때 데이터 로드 + 선택 초기화 useEffect(() => { if (open && order) { @@ -823,6 +839,19 @@ export function MaterialInputModal({ ) : searchQuery && (
검색 결과 없음 — 해당 품목의 입고 처리가 필요합니다
)} + {/* [개발전용] 입고 강제생성 버튼 */} + {group.lots[0]?.itemId && ( + + )} )} diff --git a/src/components/production/WorkerScreen/actions.ts b/src/components/production/WorkerScreen/actions.ts index aefa0683..a71e0948 100644 --- a/src/components/production/WorkerScreen/actions.ts +++ b/src/components/production/WorkerScreen/actions.ts @@ -886,6 +886,22 @@ export interface StockSearchResult { lots: Array<{ lotNo: string; availableQty: number; fifoOrder: number }>; } +// ===== [개발전용] 입고 강제 생성 ===== +export async function forceCreateReceiving( + itemId: number, + qty: number = 100 +): Promise<{ success: boolean; data?: { receiving_number: string; lot_no: string; item_code: string; item_name: string; qty: number; available_qty: number }; error?: string }> { + const result = await executeServerAction<{ + receiving_number: string; lot_no: string; item_code: string; item_name: string; qty: number; available_qty: number; + }>({ + url: buildApiUrl('/api/v1/dev/force-receiving'), + method: 'POST', + body: { item_id: itemId, qty }, + errorMessage: '입고 강제 생성에 실패했습니다.', + }); + return { success: result.success, data: result.data, error: result.error }; +} + export async function searchStockByCode( search: string ): Promise<{ success: boolean; data: StockSearchResult[]; error?: string }> {