import { apiClient } from "./client"; // ============================================================ // 개발관리 PART (M1 등록 / M2 조회) — wace partMng.xml 1:1 // 라우트: /api/development/part-temp/*, /api/development/part/* // ============================================================ export interface PartListFilter { search_part_no?: string; search_part_name?: string; search_material?: string; search_spec?: string; search_part_type?: string; writer?: string; status?: string; status_arr?: string[]; product_code?: string; upg_no?: string; page?: number; page_size?: number; // M2 추가 필터 search_year?: string; search_design_date_from?: string; search_design_date_to?: string; customer_objid?: string; customer_cd?: string; project_name?: string; unit_code?: string; is_last?: string; eo?: string; } /** partMngBaseSimple + M1/M2 추가 컬럼 평탄화 — Postgres는 컬럼명을 소문자로 반환 */ export interface PartRow { objid: string; part_no: string | null; part_name: string | null; product_mgmt_objid: string | null; upg_no: string | null; unit: string | null; unit_title: string | null; qty: string | null; spec: string | null; post_processing: string | null; material: string | null; weight: string | null; part_type: string | null; part_type_title: string | null; remark: string | null; es_spec: string | null; ms_spec: string | null; change_type: string | null; design_apply_point: string | null; change_option: string | null; change_option_name: string | null; management_flag: string | null; revision: string | null; status: string | null; reg_date: string | null; part_regdate_title: string | null; edit_date: string | null; writer: string | null; is_last: string | null; is_longd: string | null; eo_date: string | null; eo_no: string | null; eo_temp: string | null; maker: string | null; contract_objid: string | null; thickness: string | null; width: string | null; height: string | null; out_diameter: string | null; in_diameter: string | null; length: string | null; sourcing_code: string | null; supply_code: string | null; supply_name: string | null; sub_material: string | null; parent_part_no: string | null; design_date: string | null; deploy_date: string | null; excel_upload_seq: string | number | null; cu01_cnt: number | string | null; cu02_cnt: number | string | null; cu03_cnt: number | string | null; cu_total_cnt: number | string | null; // 추가 15컬럼 + 라벨 heat_treatment_hardness: string | null; heat_treatment_method: string | null; surface_treatment: string | null; acctfg: string | null; acctfg_nm: string | null; odrfg: string | null; odrfg_nm: string | null; unit_dc: string | null; unit_dc_nm: string | null; unitmang_dc: string | null; unitmang_dc_nm: string | null; unitchng_nb: string | number | null; lot_fg: string | null; lot_fg_nm: string | null; use_yn: string | null; use_yn_nm: string | null; qc_fg: string | null; qc_fg_nm: string | null; setitem_fg: string | null; setitem_fg_nm: string | null; req_fg: string | null; req_fg_nm: string | null; unit_length: string | null; unit_qty: string | null; // M1 전용 부속 partner_title?: string | null; parent_part_info?: string | null; bom_report_objid?: string | null; objid_qty?: string | null; child_objid?: string | null; q_qty?: string | null; q_qty_raw?: string | null; qty_temp?: string | null; sort?: string | null; // M2 전용 부속 num?: number | null; bom_qty?: string | null; } export interface PartListResponse { rows: PartRow[]; total: number; page: number; pageSize: number; } export interface PartCreateBody { part_objid?: string; part_no: string; part_name: string; unit?: string; qty?: string; spec?: string; material?: string; thickness?: string; width?: string; height?: string; out_diameter?: string; in_diameter?: string; length?: string; remark?: string; part_type: string; product_mgmt_objid?: string; supply_code?: string; maker?: string; contract_objid?: string; post_processing?: string; heat_treatment_hardness?: string; heat_treatment_method?: string; surface_treatment?: string; acctfg?: string; odrfg?: string; unit_dc?: string; unitmang_dc?: string; unitchng_nb?: string; lot_fg?: string; use_yn?: string; qc_fg?: string; setitem_fg?: string; req_fg?: string; unit_length?: string; unit_qty?: string; } export interface PartUpdateBody { part_name?: string; material?: string; heat_treatment_hardness?: string; heat_treatment_method?: string; surface_treatment?: string; maker?: string; part_type?: string; acctfg?: string; odrfg?: string; spec?: string; unit_dc?: string; unitmang_dc?: string; unitchng_nb?: string; lot_fg?: string; use_yn?: string; qc_fg?: string; setitem_fg?: string; req_fg?: string; unit_length?: string; unit_qty?: string; remark?: string; } export interface DeployResult { deployed: number; eo_nos: Record; } // ─── Excel Import ──────────────────────────────────────────── export interface PartExcelRow { NOTE: string; PART_NO: string; PART_NAME: string; MATERIAL: string; HEAT_TREATMENT_HARDNESS: string; HEAT_TREATMENT_METHOD: string; SURFACE_TREATMENT: string; MAKER: string; PART_TYPE: string; PART_TYPE_NAME?: string; SPEC: string; ACCTFG: string; ACCTFG_NAME?: string; ODRFG: string; ODRFG_NAME?: string; UNIT_DC: string; UNIT_DC_NAME?: string; UNITMANG_DC: string; UNITMANG_DC_NAME?: string; UNITCHNG_NB: string; LOT_FG: string; USE_YN: string; QC_FG: string; SETITEM_FG: string; REQ_FG: string; UNIT_LENGTH: string; UNIT_QTY: string; REMARK: string; } export interface ExcelParseResponse { rows: PartExcelRow[]; hasError: boolean; } export interface ExcelSaveResponse { inserted: number; skipped: number; skippedPartNos: string[]; } // ─── API ──────────────────────────────────────────────────── export const devPartApi = { // M1 그리드 async listTemp(filter: PartListFilter = {}): Promise { const res = await apiClient.get("/development/part-temp/list", { params: filter }); return res.data?.data as PartListResponse; }, // M2 그리드 async list(filter: PartListFilter = {}): Promise { const res = await apiClient.get("/development/part/list", { params: filter }); return res.data?.data as PartListResponse; }, // 단건 상세 async detail(objid: string): Promise { const res = await apiClient.get(`/development/part/${objid}`); return res.data?.data ?? null; }, // 신규 등록 (38 컬럼) async create(body: PartCreateBody): Promise<{ objid: string }> { const res = await apiClient.post("/development/part", body); return res.data?.data; }, // 상세 수정 (21 컬럼) async update(objid: string, body: PartUpdateBody) { return (await apiClient.put(`/development/part/${objid}`, body)).data; }, // 확정 (M1→M2): EO_NO 채번 + part_mng_history 이력 async deploy(objids: string[]): Promise { const res = await apiClient.post("/development/part-temp/deploy", { objids }); return res.data?.data as DeployResult; }, // 다중 삭제 async remove(objids: string[]) { const res = await apiClient.delete("/development/part", { data: { objids } }); return res.data; }, // Excel Import — 파싱 + 검증 async excelParse(file: File): Promise { const fd = new FormData(); fd.append("file", file); const res = await apiClient.post("/development/part/excel-parse", fd, { headers: { "Content-Type": "multipart/form-data" }, }); return res.data?.data as ExcelParseResponse; }, // Excel Import — 저장 (신규 PART_NO 만 INSERT) async excelSave(rows: PartExcelRow[]): Promise { const res = await apiClient.post("/development/part/excel-save", { rows }); return res.data?.data as ExcelSaveResponse; }, // 도면 다중 업로드 (wace btnDrawingUpload 1:1) // 확장자 stp/step → 3D_CAD, dwg/dxf → 2D_DRAWING_CAD, pdf → 2D_PDF_CAD // 파일명 ↔ part_no 자동 매칭 (정확 일치 → longest prefix) // partNoList 지정 → 그 목록만 매칭 후보 (M1) // partNoList null/undefined → IS_LAST='1' 전체 매칭 (M2) async drawingMultiUpload( files: File[], partNoList?: string[] | null ): Promise { const fd = new FormData(); for (const f of files) fd.append("files", f); if (Array.isArray(partNoList) && partNoList.length > 0) { fd.append("partNoList", JSON.stringify(partNoList)); } const res = await apiClient.post( "/development/part/drawing-multi-upload", fd, { headers: { "Content-Type": "multipart/form-data" } } ); return res.data?.data as DrawingMultiUploadResult; }, }; // ─── 도면 다중 업로드 결과 타입 ────────────────────────────── export interface DrawingMultiUploadDetail { fileName: string; partNo?: string; docType?: string; status: "success" | "fail" | "notFound" | "unsupported"; reason?: string; } export interface DrawingMultiUploadResult { successCount: number; failCount: number; notFoundCount: number; details: DrawingMultiUploadDetail[]; }