7779f37c17
PART Excel Import (M1·M2 공용):
- /partMng/openPartExcelImportPopUp.do + partParsingExcelFile.do + partUploadSave.do 1:1
- 22컬럼 파싱 + NOTE 누적 검증 (품번 필수/중복, PART_TYPE/ACCTFG/UNIT_DC commCode 매핑,
ODRFG/LOT_FG/USE_YN/QC_FG/SETITEM_FG/REQ_FG 한글 → 코드값)
- 저장은 신규 PART_NO 만 mergePartMng INSERT (기존 IS_LAST='1' 행은 skip)
- part-regist + part-search 페이지에 Excel Upload 버튼 + 다이얼로그 연결
BOM Report Excel Import (M3 = openBomReportExcelImportPopUp = "PART 및 구조등록 Excel upload"):
- /partMng/parsingExcelFile.do + checkDuplicatePartNo.do + getBomDataForCopy.do
+ partBomApplySave.do (savePartBomMaster) 1:1
- 10컬럼 파싱 + 자품번/모품번/품명/수량 필수 검증, 모품번이 자품번 목록(Set)에 존재 검증,
수량 숫자+>0 검증, PART_TYPE='0001788'(구매품표준) part_mng 존재 검증
- 1레벨(모품번 없는 첫 행) → 헤더 PART_NO/PART_NAME 자동 채움
- 저장 트랜잭션 (wace 1:1):
헤더 part_bom_report INSERT(신규) / DELETE 자식트리+UPDATE(수정)
자식 PART: part_mng IS_LAST='1' 존재 시 updatePartInfoFromCsv UPDATE, 없으면 insertpartInfo INSERT
부모 PART: 존재 시 lookup, 없으면 "" (절대 INSERT 안 함 — wace 5359-5361)
bom_part_qty INSERT (relatePartInfo) — 부모행 CHILD_OBJID 를 PARENT_OBJID 로 체인
- 헤더 PART_NO 중복 검사 (편집 중인 자신 제외)
- E-BOM 복사 기능 (기존 BOM → 그리드 행) + Template Download
- ebom-regist 페이지에 "E-BOM 등록(Excel)" 버튼 + 다이얼로그 연결
운영 템플릿 정적 자산:
- frontend/public/templates/PART_EXCEL_IMPORT_TEMPLATE.xlsx
- frontend/public/templates/BOM_REPORT_EXCEL_IMPORT_TEMPLATE.xlsx (.gitignore 우회 git add -f)
wace structureExcelImportPopup.jsp 는 옛 차종/제품군/사양 도메인 화면으로 운영 메뉴 트리에
서 더이상 호출되지 않아 이식 대상 제외.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
231 lines
6.4 KiB
TypeScript
231 lines
6.4 KiB
TypeScript
import { apiClient } from "./client";
|
|
|
|
// ============================================================
|
|
// 개발관리 E-BOM (M3 등록 / M4 조회) — wace partMng.xml 1:1
|
|
// 라우트: /api/development/ebom/*, /api/development/ebom-tree/*
|
|
// ============================================================
|
|
|
|
export interface BomReportListFilter {
|
|
customer_cd?: string;
|
|
project_name?: string;
|
|
unit_code?: string;
|
|
search_unit_name?: string;
|
|
search_writer?: string;
|
|
product_cd?: string;
|
|
search_part_no?: string;
|
|
search_part_name?: string;
|
|
search_from_date?: string;
|
|
search_to_date?: string;
|
|
status?: string;
|
|
page?: number;
|
|
page_size?: number;
|
|
}
|
|
|
|
export interface BomReportRow {
|
|
num: number | string;
|
|
objid: string;
|
|
customer_objid: string | null;
|
|
customer_name: string | null;
|
|
contract_objid: string | null;
|
|
customer_project_name: string | null;
|
|
project_no: string | null;
|
|
unit_code: string | null;
|
|
unit_name: string | null;
|
|
status: string | null;
|
|
status_title: string | null;
|
|
writer: string | null;
|
|
dept_name: string | null;
|
|
user_name: string | null;
|
|
dept_user_name: string | null;
|
|
regdate: string | null;
|
|
reg_date: string | null;
|
|
deploy_date: string | null;
|
|
revision: string | null;
|
|
eo_no: string | null;
|
|
eo_date: string | null;
|
|
note: string | null;
|
|
multi_yn: string | null;
|
|
multi_master_yn: string | null;
|
|
multi_break_yn: string | null;
|
|
multi_master_objid: string | null;
|
|
bom_cnt: number | string | null;
|
|
product_cd: string | null;
|
|
product_name: string | null;
|
|
part_no: string | null;
|
|
part_name: string | null;
|
|
}
|
|
|
|
export interface BomReportListResponse {
|
|
rows: BomReportRow[];
|
|
total: number;
|
|
page: number;
|
|
pageSize: number;
|
|
}
|
|
|
|
export interface BomReportStatusBody {
|
|
product_cd?: string;
|
|
part_no?: string;
|
|
part_name?: string;
|
|
version?: string;
|
|
status: string;
|
|
}
|
|
|
|
export interface BomTreeFilter {
|
|
bom_report_objid?: string;
|
|
project_name?: string;
|
|
unit_code?: string;
|
|
search_part_no?: string;
|
|
search_part_name?: string;
|
|
}
|
|
|
|
export interface BomTreeRow {
|
|
bom_report_objid: string | null;
|
|
objid: string;
|
|
parent_objid: string | null;
|
|
child_objid: string | null;
|
|
part_no: string | null; // bom_part_qty.part_no (= part_mng.objid)
|
|
qty: string | null;
|
|
seq: number | string | null;
|
|
status: string | null;
|
|
lev: number;
|
|
path: string[] | null;
|
|
// part_mng JOIN
|
|
pm_part_no: string | null;
|
|
pm_part_name: string | null;
|
|
spec: string | null;
|
|
material: string | null;
|
|
weight: string | null;
|
|
remark: string | null;
|
|
edit_date: string | null;
|
|
eo_no: string | null;
|
|
revision: string | null;
|
|
cu01_cnt: number | string | null;
|
|
cu02_cnt: number | string | null;
|
|
cu03_cnt: number | string | null;
|
|
max_level: number | string | null;
|
|
}
|
|
|
|
export interface BomTreeResponse {
|
|
rows: BomTreeRow[];
|
|
max_level: number;
|
|
}
|
|
|
|
// ─── API ─────────────────────────────────────────────────
|
|
|
|
export const devBomApi = {
|
|
// M3 그리드
|
|
async list(filter: BomReportListFilter = {}): Promise<BomReportListResponse> {
|
|
const res = await apiClient.get("/development/ebom/list", { params: filter });
|
|
return res.data?.data as BomReportListResponse;
|
|
},
|
|
|
|
async detail(objid: string): Promise<BomReportRow | null> {
|
|
const res = await apiClient.get(`/development/ebom/${objid}`);
|
|
return res.data?.data ?? null;
|
|
},
|
|
|
|
async updateStatus(objid: string, body: BomReportStatusBody) {
|
|
return (await apiClient.put(`/development/ebom/${objid}/status`, body)).data;
|
|
},
|
|
|
|
async remove(objids: string[]) {
|
|
const res = await apiClient.delete("/development/ebom", { data: { objids } });
|
|
return res.data;
|
|
},
|
|
|
|
// M4
|
|
async ascending(filter: BomTreeFilter): Promise<BomTreeResponse> {
|
|
const res = await apiClient.get("/development/ebom-tree/ascending", { params: filter });
|
|
return res.data?.data as BomTreeResponse;
|
|
},
|
|
|
|
async descending(filter: BomTreeFilter): Promise<BomTreeResponse> {
|
|
const res = await apiClient.get("/development/ebom-tree/descending", { params: filter });
|
|
return res.data?.data as BomTreeResponse;
|
|
},
|
|
|
|
// Excel Import
|
|
async excelParse(file: File): Promise<BomExcelParseResponse> {
|
|
const fd = new FormData();
|
|
fd.append("file", file);
|
|
const res = await apiClient.post("/development/ebom/excel-parse", fd, {
|
|
headers: { "Content-Type": "multipart/form-data" },
|
|
});
|
|
return res.data?.data as BomExcelParseResponse;
|
|
},
|
|
|
|
async excelCheckDuplicate(partNo: string, exclude?: string): Promise<boolean> {
|
|
const res = await apiClient.get("/development/ebom/excel-check-duplicate", {
|
|
params: { partNo, exclude },
|
|
});
|
|
return !!res.data?.data?.isDuplicate;
|
|
},
|
|
|
|
async excelCopySource(productCd?: string): Promise<BomCopySourceRow[]> {
|
|
const res = await apiClient.get("/development/ebom/excel-copy-source", {
|
|
params: productCd ? { productCd } : undefined,
|
|
});
|
|
return (res.data?.data as BomCopySourceRow[]) ?? [];
|
|
},
|
|
|
|
async excelCopy(objid: string): Promise<BomExcelRow[]> {
|
|
const res = await apiClient.get(`/development/ebom/excel-copy/${objid}`);
|
|
return ((res.data?.data?.rows as BomExcelRow[]) ?? []);
|
|
},
|
|
|
|
async excelSave(input: BomExcelSaveInput): Promise<BomExcelSaveResult> {
|
|
const res = await apiClient.post("/development/ebom/excel-save", input);
|
|
return res.data?.data as BomExcelSaveResult;
|
|
},
|
|
};
|
|
|
|
// ─── Excel Import 타입 ─────────────────────────────────────
|
|
|
|
export interface BomExcelRow {
|
|
NOTE: string;
|
|
PARENT_PART_NO: string;
|
|
PART_NO: string;
|
|
PART_NAME: string;
|
|
QTY: string;
|
|
ITEM_QTY: string;
|
|
MATERIAL: string;
|
|
SPEC: string;
|
|
POST_PROCESSING: string;
|
|
MAKER: string;
|
|
PART_TYPE: string;
|
|
PART_TYPE_NAME?: string;
|
|
REMARK: string;
|
|
}
|
|
|
|
export interface BomExcelParseResponse {
|
|
rows: BomExcelRow[];
|
|
hasError: boolean;
|
|
firstLevel: { part_no: string; part_name: string } | null;
|
|
}
|
|
|
|
export interface BomCopySourceRow {
|
|
objid: string;
|
|
part_no: string;
|
|
part_name: string;
|
|
revision: string | null;
|
|
product_cd: string | null;
|
|
regdate: string | null;
|
|
}
|
|
|
|
export interface BomExcelSaveInput {
|
|
bomReportObjid?: string;
|
|
productCd: string;
|
|
partNo: string;
|
|
partName: string;
|
|
version?: string;
|
|
rows: BomExcelRow[];
|
|
}
|
|
|
|
export interface BomExcelSaveResult {
|
|
bomReportObjid: string;
|
|
insertedParts: number;
|
|
updatedParts: number;
|
|
bomRows: number;
|
|
mode: "create" | "update";
|
|
}
|