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>
310 lines
8.2 KiB
TypeScript
310 lines
8.2 KiB
TypeScript
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<string, string>;
|
|
}
|
|
|
|
// ─── 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<PartListResponse> {
|
|
const res = await apiClient.get("/development/part-temp/list", { params: filter });
|
|
return res.data?.data as PartListResponse;
|
|
},
|
|
|
|
// M2 그리드
|
|
async list(filter: PartListFilter = {}): Promise<PartListResponse> {
|
|
const res = await apiClient.get("/development/part/list", { params: filter });
|
|
return res.data?.data as PartListResponse;
|
|
},
|
|
|
|
// 단건 상세
|
|
async detail(objid: string): Promise<PartRow | null> {
|
|
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<DeployResult> {
|
|
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<ExcelParseResponse> {
|
|
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<ExcelSaveResponse> {
|
|
const res = await apiClient.post("/development/part/excel-save", { rows });
|
|
return res.data?.data as ExcelSaveResponse;
|
|
},
|
|
};
|