bd47ca80df
운영판 mBomEbomSelectPopup.jsp (324 lines) 1:1 레이아웃:
· 헤더 — "E-BOM 선택" / "E-BOM 상세 및 변경" 토글 제목 + 우측 [E-BOM 변경] 버튼
· 현재 할당된 E-BOM 정보 카드 — 2×3 table (제품구분/품번/품명/Ver/등록일/작성자)
· 리스트 토글 — 할당된 경우 변경 모드 ON 시에만 노출
· 검색폼 운영판 매칭 — 제품구분(SmartSelect) + 품번 + 품명 + 등록일(범위)
· 리스트 헤더 우측 [조회][E-BOM 할당] 버튼 (footer 제거)
· 선택 시 하단 미리보기 트리 자동 로드 (read-only, 동적 LEVEL + 폴더아이콘)
신규 백엔드:
· mbomService.previewEbomTree(bomReportObjid) — EBOM_WORKING_TREE_SQL 재사용
· GET /api/production/mbom/ebom-preview/:bomReportObjid
· searchAssignableEboms 필터: material/supplier → product_cd/from_date/to_date 운영판 매칭
· objid 단건 필터 추가 — 현재 할당 E-BOM 카드 정보 자체 로드용
프론트:
· MbomAssignDialog 완전 재작성 (full layout, SmartSelect, 미리보기 PreviewTree 컴포넌트)
· MbomDetailDialog: currentEbomObjid prop 으로 단순화 (다이얼로그 내부에서 상세 fetch)
· mbomApi.previewEbomTree + AssignableEbomFilter 타입 매칭
이전 b38f5957 의 PR-B5 베이스(검색/할당) 위에 운영판 UX 정합 강화.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
326 lines
11 KiB
TypeScript
326 lines
11 KiB
TypeScript
import { apiClient } from "./client";
|
|
|
|
// ============================================================
|
|
// 생산관리 > M-BOM 관리 — wace productionplanning.xml 1:1
|
|
// 라우트:
|
|
// GET /api/production/mbom/list (PR-A1, 그리드)
|
|
// GET /api/production/mbom/detail/:objid (PR-A2, 단건 상세)
|
|
// GET /api/production/mbom/tree/:objid (PR-A2, read-only 트리 4분기)
|
|
// ============================================================
|
|
|
|
export interface MbomListFilter {
|
|
search_category_cd?: string;
|
|
search_product_cd?: string;
|
|
search_area_cd?: string;
|
|
search_customer_objid?: string;
|
|
search_paid_type?: string;
|
|
search_serial_no?: string;
|
|
search_part_no?: string;
|
|
search_part_name?: string;
|
|
search_receipt_date_from?: string;
|
|
search_receipt_date_to?: string;
|
|
search_req_del_date_from?: string;
|
|
search_req_del_date_to?: string;
|
|
page?: number;
|
|
page_size?: number;
|
|
}
|
|
|
|
export interface MbomRow {
|
|
objid: string;
|
|
contract_objid: string | null;
|
|
project_no: string | null;
|
|
category_cd: string | null;
|
|
category_name: string | null;
|
|
product: string | null;
|
|
product_name: string | null;
|
|
area_cd: string | null;
|
|
area_name: string | null;
|
|
receipt_date: string | null;
|
|
writer_name: string | null;
|
|
customer_objid: string | null;
|
|
customer_name: string | null;
|
|
paid_type: string | null;
|
|
paid_type_name: string | null;
|
|
part_no: string | null;
|
|
part_name: string | null;
|
|
part_objid: string | null;
|
|
serial_no: string | null;
|
|
serial_no_list: string | null;
|
|
quantity: string | number | null;
|
|
req_del_date: string | null;
|
|
customer_request: string | null;
|
|
bom_report_objid: string | null;
|
|
ebom_status: string | null;
|
|
ebom_regdate: string | null;
|
|
mbom_header_objid: string | null;
|
|
purchase_list_objid: string | null;
|
|
purchase_list_date: string | null;
|
|
mbom_status: string | null;
|
|
mbom_part_no: string | null;
|
|
mbom_regdate: string | null;
|
|
mbom_editor: string | null;
|
|
mbom_version: number | null;
|
|
}
|
|
|
|
export interface MbomListResponse {
|
|
rows: MbomRow[];
|
|
totalCount: number;
|
|
page: number;
|
|
pageSize: number;
|
|
}
|
|
|
|
// ─── 단건 상세 (PR-A2) ──────────────────────────────────────
|
|
|
|
export interface MbomDetail {
|
|
objid: string;
|
|
contract_objid: string | null;
|
|
project_no: string | null;
|
|
bom_report_objid: string | null;
|
|
part_objid: string | null;
|
|
part_no: string | null;
|
|
part_name: string | null;
|
|
source_bom_type: string | null;
|
|
source_ebom_objid: string | null;
|
|
source_mbom_objid: string | null;
|
|
quantity: string | number | null;
|
|
total_prod_qty: string | number | null;
|
|
mbom_part_no: string | null;
|
|
category_cd: string | null;
|
|
category_name: string | null;
|
|
product: string | null;
|
|
product_code: string | null;
|
|
product_name: string | null;
|
|
area_cd: string | null;
|
|
area_name: string | null;
|
|
customer_objid: string | null;
|
|
customer_name: string | null;
|
|
paid_type: string | null;
|
|
req_del_date: string | null;
|
|
receipt_date: string | null;
|
|
mbom_regdate: string | null;
|
|
}
|
|
|
|
// ─── read-only 트리 (PR-A2) ─────────────────────────────────
|
|
// 운영판 mBomPopupLeft.do 4분기 자동 판별:
|
|
// SAVED — mbom_header.status='Y' 최신
|
|
// ASSIGNED_EBOM — source_bom_type='EBOM' + source_ebom_objid
|
|
// ASSIGNED_MBOM — source_bom_type='MBOM' + source_mbom_objid
|
|
// TEMPLATE — Machine 이외 + 동일 part_no 의 mbom_header
|
|
// NONE — 빈 트리
|
|
|
|
export type MbomBomDataType = "SAVED" | "ASSIGNED_EBOM" | "ASSIGNED_MBOM" | "TEMPLATE" | "NONE";
|
|
|
|
export interface MbomTreeRow {
|
|
objid: string;
|
|
parent_objid: string | null;
|
|
child_objid: string | null;
|
|
part_objid: string | null;
|
|
part_no: string | null;
|
|
part_name: string | null;
|
|
qty: string | number | null;
|
|
item_qty: string | number | null;
|
|
qty_temp: string | number | null;
|
|
level: number;
|
|
sub_part_cnt: number;
|
|
seq: number;
|
|
status: string | null;
|
|
unit: string | null;
|
|
unit_title: string | null;
|
|
supply_type: string | null;
|
|
make_or_buy: string | null;
|
|
raw_material_no: string | null;
|
|
raw_material_spec: string | null;
|
|
raw_material: string | null;
|
|
size: string | null;
|
|
processing_vendor: string | null;
|
|
processing_vendor_name: string | null;
|
|
processing_deadline: string | null;
|
|
grinding_deadline: string | null;
|
|
required_qty: string | number | null;
|
|
order_qty: string | number | null;
|
|
production_qty: string | number | null;
|
|
vendor: string | null;
|
|
vendor_name: string | null;
|
|
unit_price: string | number | null;
|
|
total_price: string | number | null;
|
|
currency: string | null;
|
|
writer: string | null;
|
|
regdate: string | null;
|
|
editer: string | null;
|
|
edit_date: string | null;
|
|
remark: string | null;
|
|
spec: string | null;
|
|
material: string | null;
|
|
weight: string | number | null;
|
|
revision: string | null;
|
|
cu01_cnt: number;
|
|
cu02_cnt: number;
|
|
cu03_cnt: number;
|
|
[key: string]: any;
|
|
}
|
|
|
|
export interface MbomTreeResponse {
|
|
bom_data_type: MbomBomDataType;
|
|
bom_report_objid: string | null;
|
|
max_level: number;
|
|
rows: MbomTreeRow[];
|
|
}
|
|
|
|
// ─── 저장 (PR-B1) ───────────────────────────────────────────
|
|
// 운영판 saveMbom.do 1:1 — 신규/수정 통합 엔드포인트.
|
|
// is_update=false → 새 mbom_header + child_objid 재매핑 후 detail 일괄 insert
|
|
// is_update=true → 기존 mbom_header.objid 조회 → UPSERT + 누락 행 delete
|
|
|
|
export interface MbomSaveRow {
|
|
objid?: string | null;
|
|
parent_objid?: string | null;
|
|
child_objid?: string | null;
|
|
seq?: number | string | null;
|
|
level?: number | string | null;
|
|
part_objid?: string | number | null;
|
|
part_no?: string | null;
|
|
part_name?: string | null;
|
|
qty?: number | string | null;
|
|
item_qty?: number | string | null;
|
|
unit?: string | null;
|
|
supply_type?: string | null;
|
|
make_or_buy?: string | null;
|
|
raw_material_no?: string | null;
|
|
raw_material_spec?: string | null;
|
|
raw_material?: string | null;
|
|
size?: string | null;
|
|
raw_material_size?: string | null;
|
|
processing_vendor?: string | null;
|
|
processing_deadline?: string | null;
|
|
grinding_deadline?: string | null;
|
|
required_qty?: number | string | null;
|
|
order_qty?: number | string | null;
|
|
production_qty?: number | string | null;
|
|
remark?: string | null;
|
|
}
|
|
|
|
export interface MbomSavePayload {
|
|
project_obj_id: string;
|
|
is_update: boolean;
|
|
mbom_part_no?: string | null;
|
|
rows: MbomSaveRow[];
|
|
}
|
|
|
|
export interface MbomSaveResult {
|
|
mode: "CREATE" | "UPDATE";
|
|
mbom_header_objid: string;
|
|
mbom_no: string;
|
|
inserted: number;
|
|
updated: number;
|
|
deleted: number;
|
|
}
|
|
|
|
// ─── 구매리스트 생성 (PR-B3) ────────────────────────────────
|
|
// 운영판 createPurchaseListFromMBom.do 1:1. SALES_REQUEST_MASTER 단건 생성.
|
|
// 동일 mbom_header_objid 로 이미 생성된 SRM 있으면 400 에러.
|
|
|
|
export interface CreateSalesRequestPayload {
|
|
mbom_header_objid: string;
|
|
project_mgmt_objid: string;
|
|
}
|
|
|
|
export interface CreateSalesRequestResult {
|
|
objid: string;
|
|
request_mng_no: string;
|
|
mbom_header_objid: string;
|
|
}
|
|
|
|
export const mbomApi = {
|
|
async list(filter: MbomListFilter = {}): Promise<MbomListResponse> {
|
|
const res = await apiClient.get("/production/mbom/list", { params: filter });
|
|
return res.data?.data as MbomListResponse;
|
|
},
|
|
async getDetail(objid: string): Promise<MbomDetail> {
|
|
const res = await apiClient.get(`/production/mbom/detail/${encodeURIComponent(objid)}`);
|
|
return res.data?.data as MbomDetail;
|
|
},
|
|
async getTree(objid: string): Promise<MbomTreeResponse> {
|
|
const res = await apiClient.get(`/production/mbom/tree/${encodeURIComponent(objid)}`);
|
|
return res.data?.data as MbomTreeResponse;
|
|
},
|
|
async save(payload: MbomSavePayload): Promise<MbomSaveResult> {
|
|
const res = await apiClient.post("/production/mbom/save", payload);
|
|
return res.data?.data as MbomSaveResult;
|
|
},
|
|
async getHistory(projectObjid: string): Promise<MbomHistoryRow[]> {
|
|
const res = await apiClient.get(`/production/mbom/history/${encodeURIComponent(projectObjid)}`);
|
|
return (res.data?.data ?? []) as MbomHistoryRow[];
|
|
},
|
|
async createSalesRequest(payload: CreateSalesRequestPayload): Promise<CreateSalesRequestResult> {
|
|
const res = await apiClient.post("/production/mbom/sales-request", payload);
|
|
return res.data?.data as CreateSalesRequestResult;
|
|
},
|
|
async searchAssignableEboms(filter: AssignableEbomFilter = {}): Promise<AssignableEbomRow[]> {
|
|
const res = await apiClient.get("/production/mbom/assignable-eboms", { params: filter });
|
|
return (res.data?.data ?? []) as AssignableEbomRow[];
|
|
},
|
|
async previewEbomTree(bomReportObjid: string): Promise<MbomTreeResponse> {
|
|
const res = await apiClient.get(`/production/mbom/ebom-preview/${encodeURIComponent(bomReportObjid)}`);
|
|
return res.data?.data as MbomTreeResponse;
|
|
},
|
|
async assignBom(payload: AssignBomPayload): Promise<AssignBomResult> {
|
|
const res = await apiClient.post("/production/mbom/assign", payload);
|
|
return res.data?.data as AssignBomResult;
|
|
},
|
|
};
|
|
|
|
// ─── BOM 할당 (PR-B5) ───────────────────────────────────────
|
|
// 운영판 mBomEbomSelectPopup.do + saveBomAssignment.do 1:1.
|
|
// project_mgmt.source_bom_type='EBOM' + source_ebom_objid 만 우선 지원.
|
|
|
|
export interface AssignableEbomFilter {
|
|
objid?: string;
|
|
product_cd?: string;
|
|
search_part_no?: string;
|
|
search_part_name?: string;
|
|
search_from_date?: string;
|
|
search_to_date?: string;
|
|
limit?: number;
|
|
}
|
|
|
|
export interface AssignableEbomRow {
|
|
objid: string;
|
|
product_cd: string | null;
|
|
product_name: string | null;
|
|
part_no: string | null;
|
|
part_name: string | null;
|
|
status: string | null;
|
|
revision: string | null;
|
|
reg_date: string | null;
|
|
writer_name: string | null;
|
|
dept_name: string | null;
|
|
material: string | null;
|
|
supplier: string | null;
|
|
}
|
|
|
|
export interface AssignBomPayload {
|
|
project_obj_id: string;
|
|
source_bom_type: "EBOM" | "MBOM";
|
|
source_bom_obj_id: string;
|
|
}
|
|
|
|
export interface AssignBomResult {
|
|
success: boolean;
|
|
source_bom_type: string;
|
|
source_obj_id: string;
|
|
}
|
|
|
|
// ─── 변경이력 (PR-B4) ───────────────────────────────────────
|
|
|
|
export interface MbomHistoryRow {
|
|
objid: string;
|
|
mbom_header_objid: string;
|
|
change_type: string; // CREATE | UPDATE
|
|
change_description: string | null;
|
|
change_user: string | null;
|
|
change_user_name: string | null;
|
|
change_date: string;
|
|
mbom_part_no: string | null;
|
|
mbom_regdate: string | null;
|
|
}
|