/** * 생산계획 API 클라이언트 */ import apiClient from "./client"; // ─── 타입 정의 ─── export interface OrderSummaryItem { item_code: string; item_name: string; total_order_qty: number; total_ship_qty: number; total_balance_qty: number; order_count: number; earliest_due_date: string | null; current_stock: number; safety_stock: number; existing_plan_qty: number; in_progress_qty: number; required_plan_qty: number; orders: OrderDetail[]; } export interface OrderDetail { id: string; order_no: string; part_code: string; part_name: string; order_qty: number; ship_qty: number; balance_qty: number; due_date: string | null; status: string; customer_name: string | null; } export interface StockShortageItem { item_code: string; item_name: string; current_qty: number; safety_qty: number; shortage_qty: number; recommended_qty: number; last_in_date: string | null; } export interface ProductionPlan { id: number; company_code: string; plan_no: string; plan_date: string; item_code: string; item_name: string; product_type: string; plan_qty: number; completed_qty: number; progress_rate: number; start_date: string; end_date: string; due_date: string | null; equipment_id: number | null; equipment_code: string | null; equipment_name: string | null; status: string; priority: string | null; order_no: string | null; parent_plan_id: number | null; remarks: string | null; } export interface GenerateScheduleRequest { items: { item_code: string; item_name: string; required_qty: number; earliest_due_date: string; hourly_capacity?: number; daily_capacity?: number; lead_time?: number; }[]; options?: { safety_lead_time?: number; recalculate_unstarted?: boolean; product_type?: string; }; } export interface GenerateScheduleResponse { summary: { total: number; new_count: number; kept_count: number; deleted_count: number; }; schedules: ProductionPlan[]; } // ─── API 함수 ─── /** 수주 데이터 조회 (품목별 그룹핑) */ export async function getOrderSummary(params?: { excludePlanned?: boolean; itemCode?: string; itemName?: string; }) { const queryParams = new URLSearchParams(); if (params?.excludePlanned) queryParams.set("excludePlanned", "true"); if (params?.itemCode) queryParams.set("itemCode", params.itemCode); if (params?.itemName) queryParams.set("itemName", params.itemName); const qs = queryParams.toString(); const url = `/api/production/order-summary${qs ? `?${qs}` : ""}`; const response = await apiClient.get(url); return response.data as { success: boolean; data: OrderSummaryItem[] }; } /** 안전재고 부족분 조회 */ export async function getStockShortage() { const response = await apiClient.get("/api/production/stock-shortage"); return response.data as { success: boolean; data: StockShortageItem[] }; } /** 생산계획 상세 조회 */ export async function getPlanById(planId: number) { const response = await apiClient.get(`/api/production/plan/${planId}`); return response.data as { success: boolean; data: ProductionPlan }; } /** 생산계획 수정 */ export async function updatePlan(planId: number, data: Partial) { const response = await apiClient.put(`/api/production/plan/${planId}`, data); return response.data as { success: boolean; data: ProductionPlan }; } /** 생산계획 삭제 */ export async function deletePlan(planId: number) { const response = await apiClient.delete(`/api/production/plan/${planId}`); return response.data as { success: boolean; message: string }; } /** 자동 스케줄 생성 */ export async function generateSchedule(request: GenerateScheduleRequest) { const response = await apiClient.post("/api/production/generate-schedule", request); return response.data as { success: boolean; data: GenerateScheduleResponse }; } /** 스케줄 병합 */ export async function mergeSchedules(scheduleIds: number[], productType?: string) { const response = await apiClient.post("/api/production/merge-schedules", { schedule_ids: scheduleIds, product_type: productType || "완제품", }); return response.data as { success: boolean; data: ProductionPlan }; } /** 반제품 계획 자동 생성 */ export async function generateSemiSchedule( planIds: number[], options?: { considerStock?: boolean; excludeUsed?: boolean } ) { const response = await apiClient.post("/api/production/generate-semi-schedule", { plan_ids: planIds, options: options || {}, }); return response.data as { success: boolean; data: { count: number; schedules: ProductionPlan[] } }; } /** 스케줄 분할 */ export async function splitSchedule(planId: number, splitQty: number) { const response = await apiClient.post(`/api/production/plan/${planId}/split`, { split_qty: splitQty, }); return response.data as { success: boolean; data: { original: { id: number; plan_qty: number }; split: ProductionPlan }; }; }