import { apiClient } from "@/lib/api/client"; export interface PaginatedResponse { success: boolean; data: any[]; totalCount: number; page: number; pageSize: number; } export async function getWorkInstructionList(params?: Record) { const res = await apiClient.get("/work-instruction/list", { params }); return res.data as { success: boolean; data: any[]; totalCount?: number; page?: number; pageSize?: number }; } export async function previewWorkInstructionNo() { const res = await apiClient.get("/work-instruction/preview-no"); return res.data as { success: boolean; instructionNo: string }; } export async function saveWorkInstruction(data: any) { const res = await apiClient.post("/work-instruction/save", data); return res.data as { success: boolean; data?: any; message?: string }; } export async function deleteWorkInstructions(ids: string[]) { const res = await apiClient.post("/work-instruction/delete", { ids }); return res.data as { success: boolean; deletedCount?: number; message?: string }; } export async function getWIItemSource(params?: Record) { const res = await apiClient.get("/work-instruction/source/item", { params }); return res.data as PaginatedResponse; } export async function getWISalesOrderSource(params?: Record) { const res = await apiClient.get("/work-instruction/source/sales-order", { params }); return res.data as PaginatedResponse; } export async function getWIProductionPlanSource(params?: Record) { const res = await apiClient.get("/work-instruction/source/production-plan", { params }); return res.data as PaginatedResponse; } export async function getEquipmentList() { const res = await apiClient.get("/work-instruction/equipment"); return res.data as { success: boolean; data: { id: string; equipment_code: string; equipment_name: string }[] }; } export async function getEmployeeList() { const res = await apiClient.get("/work-instruction/employees"); return res.data as { success: boolean; data: { user_id: string; user_name: string; dept_name: string | null }[] }; } // BOM 기준수(0레벨 base_qty) 일괄 조회 — 작업지시 등록 모달의 기준수/배치수 산출용 export async function getBomBaseQtyMap(itemCodes: string[]) { const res = await apiClient.post("/work-instruction/bom-base-qty", { itemCodes }); // batchUse: 품목별 배치사용여부 (Y=사용/N=미사용). 미포함 시 'Y' 간주 (하위호환) return res.data as { success: boolean; data: Record; batchUse?: Record }; } // ─── 라우팅 & 공정작업기준 API ─── export interface RoutingProcess { routing_detail_id: string; seq_no: string; process_code: string; process_name: string; is_required?: string; work_type?: string; } export interface RoutingVersionData { id: string; version_name: string; description?: string; is_default: boolean; processes: RoutingProcess[]; } export interface WIWorkItemDetail { id?: string; work_item_id?: string; detail_type?: string; content?: string; is_required?: string; sort_order?: number; remark?: string; // 검사항목(inspection) 전용 process_inspection_apply?: string; // "apply" | "none" inspection_code?: string; inspection_method?: string; unit?: string; lower_limit?: string; upper_limit?: string; base_value?: string; tolerance?: string; auto_collect?: string; // "Y" | "N" plc_data?: string; // 작업절차(procedure) 전용 duration_minutes?: number; // 직접입력(input) 전용 input_type?: string; // 문서참조(lookup) 전용 lookup_target?: string; display_fields?: string; // 설비점검(equip_inspection) 전용 equip_inspection_apply?: string; // "apply" | "none" // 설비조건(equip_condition) 전용 condition_name?: string; condition_unit?: string; condition_base_value?: string; condition_tolerance?: string; condition_auto_collect?: string; condition_plc_data?: string; // 실적등록(production_result) 전용 work_qty_auto_collect?: string; work_qty_plc_data?: string; defect_qty_auto_collect?: string; defect_qty_plc_data?: string; good_qty_auto_collect?: string; good_qty_plc_data?: string; loss_qty_auto_collect?: string; loss_qty_plc_data?: string; // 자재투입(material_input) 전용 - BOM 자동연동 material_code?: string; material_name?: string; quantity?: string; material_unit?: string; selected_bom_items?: string[] | string; bom_item_id?: string; bom_item_name?: string; bom_qty?: string; bom_unit?: string; material_input_type?: string; // "auto"(자동투입, 기본) | "manual"(수동투입) } export interface WIWorkItem { id?: string; routing_detail_id?: string; work_phase: string; title: string; is_required: string; sort_order: number; description?: string; detail_count?: number; details?: WIWorkItemDetail[]; source_work_item_id?: string; } export interface WIWorkStandardProcess { routing_detail_id: string; seq_no: string; process_code: string; process_name: string; workItems: WIWorkItem[]; } export async function getRoutingVersions(wiNo: string, itemCode: string) { const res = await apiClient.get(`/work-instruction/${wiNo}/routing-versions/${encodeURIComponent(itemCode)}`); return res.data as { success: boolean; data: RoutingVersionData[] }; } export async function updateWIRouting(wiNo: string, routingVersionId: string) { const res = await apiClient.put(`/work-instruction/${wiNo}/routing`, { routingVersionId }); return res.data as { success: boolean }; } export async function getWIWorkStandard(wiNo: string, routingVersionId: string) { const res = await apiClient.get(`/work-instruction/${wiNo}/work-standard`, { params: { routingVersionId } }); return res.data as { success: boolean; data: { processes: WIWorkStandardProcess[]; isCustom: boolean } }; } export async function copyWorkStandard(wiNo: string, routingVersionId: string) { const res = await apiClient.post(`/work-instruction/${wiNo}/work-standard/copy`, { routingVersionId }); return res.data as { success: boolean }; } export async function saveWIWorkStandard(wiNo: string, routingDetailId: string, workItems: WIWorkItem[]) { const res = await apiClient.put(`/work-instruction/${wiNo}/work-standard/save`, { routingDetailId, workItems }); return res.data as { success: boolean }; } export async function resetWIWorkStandard(wiNo: string) { const res = await apiClient.delete(`/work-instruction/${wiNo}/work-standard/reset`); return res.data as { success: boolean }; } // ─── BOM 대체품 / 작업지시 단위 자재투입 매핑 (TASK:ERP-node-090) ─── // BOM 자재 행 (작업지시 등록 모달에서 펼침) export interface WIBomMaterial { id: string; // bom_detail.id child_item_id: string | null; // item_info.id (자재 품목 id) child_item_code?: string | null; child_item_name?: string | null; quantity?: string | number | null; detail_unit?: string | null; item_unit?: string | null; process_type?: string | null; } // 품목 코드(item_code)로 그 품목의 BOM 자재 목록을 조회 (단일 레벨) // process-info의 /process-info/bom-materials/:itemCode 라우트 재활용 export async function getWIBomMaterials(itemCode: string) { const res = await apiClient.get(`/process-info/bom-materials/${encodeURIComponent(itemCode)}`); return res.data as { success: boolean; data: WIBomMaterial[] }; } // BOM 트리 조회 — 다중 레벨 자재를 재귀 트리로 반환 (TASK:ERP-node-090 트리화) // 활성 버전(current_version_id) 기준. 미초기화 BOM은 version_id IS NULL 폴백. export interface WIBomTreeNode { id: string; // bom_detail.id bom_id: string; parent_detail_id: string | null; child_item_id: string | null; child_item_code?: string | null; child_item_name?: string | null; quantity?: string | number | null; detail_unit?: string | null; item_unit?: string | null; process_type?: string | null; level?: number | string | null; seq_no?: string | null; children: WIBomTreeNode[]; } // 루트 노드(품목 자체) 정보 — BomTreeComponent와 동일하게 0레벨로 표시 export interface WIBomTreeRootItem { itemId: string | null; itemCode: string; itemName: string; baseQty: string | number | null; unit: string; } export async function getWIBomTree(itemCode: string) { const res = await apiClient.get(`/work-instruction/bom-tree/${encodeURIComponent(itemCode)}`); return res.data as { success: boolean; hasBom: boolean; treeRoots: WIBomTreeNode[]; rootItem: WIBomTreeRootItem | null; }; } // bom_detail.id 단위 대체품 후보 조회 (마스터 bom_detail_substitute) export interface WIBomSubstitute { id: string; bom_detail_id: string; substitute_item_id: string; substitute_item_name?: string | null; substitute_item_number?: string | null; substitute_unit?: string | null; priority?: number | string | null; ratio?: number | string | null; status?: string | null; } export async function getWIBomSubstitutes(detailId: string) { const res = await apiClient.get(`/bom/details/${encodeURIComponent(detailId)}/substitutes`); return res.data as { success: boolean; data: WIBomSubstitute[] }; } // 작업지시별 자재투입 매핑 조회 (편집 복원용) export interface WIMaterialOverrideMaterial { detailId: string; bomItemId: string; bomItemName: string; bomQty: string; bomUnit: string; content: string; isOverride: boolean; originalBomItemId: string | null; } export interface WIMaterialOverrideRouting { routingDetailId: string; processCode: string; processName: string; materials: WIMaterialOverrideMaterial[]; } export async function getWIMaterialOverrides(wiNo: string) { const res = await apiClient.get(`/work-instruction/${encodeURIComponent(wiNo)}/material-overrides`); return res.data as { success: boolean; data: WIMaterialOverrideRouting[] }; } // ─── 작업지시 인포(메모) 조회 — 편집 모달 복원용 (TASK:ERP-node-095) ─── export interface WIInfo { id: string; content: string; sort_order: number; } export async function getWIInfos(wiNo: string) { const res = await apiClient.get(`/work-instruction/${encodeURIComponent(wiNo)}/infos`); return res.data as { success: boolean; data: WIInfo[] }; } // 품목 검색 (대체품 SmartSelect 옵션 — 마스터에 등록 안 된 임의 자재로 교체할 때 사용) // 작업지시 등록 모달의 source/item 라우트를 재활용 (이미 keyword 검색 지원) // → getWIItemSource(params={ keyword, page, pageSize })