생산관리 M-BOM PR-B5+ — BOM 할당 다이얼로그 운영판 1:1 재구성 + 미리보기 트리
운영판 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>
This commit is contained in:
@@ -58,10 +58,12 @@ export async function searchAssignableEboms(req: AuthenticatedRequest, res: Resp
|
||||
try {
|
||||
const q = req.query as Record<string, any>;
|
||||
const data = await svc.searchAssignableEboms({
|
||||
objid: String(q.objid ?? "").trim() || undefined,
|
||||
product_cd: String(q.product_cd ?? "").trim() || undefined,
|
||||
search_part_no: String(q.search_part_no ?? "").trim() || undefined,
|
||||
search_part_name: String(q.search_part_name ?? "").trim() || undefined,
|
||||
search_material: String(q.search_material ?? "").trim() || undefined,
|
||||
search_supplier: String(q.search_supplier ?? "").trim() || undefined,
|
||||
search_from_date: String(q.search_from_date ?? "").trim() || undefined,
|
||||
search_to_date: String(q.search_to_date ?? "").trim() || undefined,
|
||||
limit: q.limit ? Number(q.limit) : undefined,
|
||||
});
|
||||
return res.json({ success: true, data });
|
||||
@@ -71,6 +73,19 @@ export async function searchAssignableEboms(req: AuthenticatedRequest, res: Resp
|
||||
}
|
||||
}
|
||||
|
||||
// PR-B5 — E-BOM 미리보기 트리 (운영 mBomEbomSelectPopup.jsp iframe 대체)
|
||||
export async function previewEbomTree(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
const bomReportObjid = String(req.params.bomReportObjid ?? "").trim();
|
||||
if (!bomReportObjid) return res.status(400).json({ success: false, message: "bomReportObjid 누락" });
|
||||
const data = await svc.previewEbomTree(bomReportObjid);
|
||||
return res.json({ success: true, data });
|
||||
} catch (e: any) {
|
||||
logger.error("E-BOM 미리보기 조회 실패", { error: e.message });
|
||||
return res.status(500).json({ success: false, message: e.message });
|
||||
}
|
||||
}
|
||||
|
||||
// PR-B5 — BOM 할당 (운영 saveBomAssignment.do 1:1)
|
||||
export async function assignBom(req: AuthenticatedRequest, res: Response) {
|
||||
try {
|
||||
|
||||
@@ -17,6 +17,7 @@ router.post("/save", ctrl.save); // PR-B1 본 편집 저장
|
||||
router.get("/history/:projectObjid", ctrl.getHistory); // PR-B4 변경이력 조회
|
||||
router.post("/sales-request", ctrl.createSalesRequest); // PR-B3 구매리스트 생성
|
||||
router.get("/assignable-eboms", ctrl.searchAssignableEboms); // PR-B5 할당 가능 E-BOM 검색
|
||||
router.get("/ebom-preview/:bomReportObjid", ctrl.previewEbomTree); // PR-B5 E-BOM 미리보기
|
||||
router.post("/assign", ctrl.assignBom); // PR-B5 BOM 할당
|
||||
|
||||
export default router;
|
||||
|
||||
@@ -1241,10 +1241,12 @@ export async function save(payload: MbomSavePayload, sessionUserId: string): Pro
|
||||
// (M-BOM 할당은 PR-B5 v2 — 우선 E-BOM 만)
|
||||
|
||||
export interface AssignableEbomFilter {
|
||||
objid?: string; // 단건 정확매칭 (현재 할당 E-BOM 정보 조회용)
|
||||
product_cd?: string;
|
||||
search_part_no?: string;
|
||||
search_part_name?: string;
|
||||
search_material?: string;
|
||||
search_supplier?: string;
|
||||
search_from_date?: string; // YYYY-MM-DD
|
||||
search_to_date?: string;
|
||||
limit?: number;
|
||||
}
|
||||
|
||||
@@ -1268,6 +1270,14 @@ export async function searchAssignableEboms(filter: AssignableEbomFilter): Promi
|
||||
const conds: string[] = [];
|
||||
const params: any[] = [];
|
||||
let idx = 1;
|
||||
if (filter.objid) {
|
||||
conds.push(`T.OBJID::VARCHAR = $${idx++}`);
|
||||
params.push(filter.objid);
|
||||
}
|
||||
if (filter.product_cd) {
|
||||
conds.push(`T.PRODUCT_CD = $${idx++}`);
|
||||
params.push(filter.product_cd);
|
||||
}
|
||||
if (filter.search_part_no) {
|
||||
conds.push(`UPPER(T.PART_NO) LIKE '%' || UPPER($${idx++}) || '%'`);
|
||||
params.push(filter.search_part_no);
|
||||
@@ -1276,13 +1286,13 @@ export async function searchAssignableEboms(filter: AssignableEbomFilter): Promi
|
||||
conds.push(`UPPER(T.PART_NAME) LIKE '%' || UPPER($${idx++}) || '%'`);
|
||||
params.push(filter.search_part_name);
|
||||
}
|
||||
if (filter.search_material) {
|
||||
conds.push(`UPPER(PM.MATERIAL) LIKE '%' || UPPER($${idx++}) || '%'`);
|
||||
params.push(filter.search_material);
|
||||
if (filter.search_from_date) {
|
||||
conds.push(`T.REGDATE >= TO_DATE($${idx++}, 'YYYY-MM-DD')`);
|
||||
params.push(filter.search_from_date);
|
||||
}
|
||||
if (filter.search_supplier) {
|
||||
conds.push(`UPPER(PM.MAKER) LIKE '%' || UPPER($${idx++}) || '%'`);
|
||||
params.push(filter.search_supplier);
|
||||
if (filter.search_to_date) {
|
||||
conds.push(`T.REGDATE < TO_DATE($${idx++}, 'YYYY-MM-DD') + INTERVAL '1 day'`);
|
||||
params.push(filter.search_to_date);
|
||||
}
|
||||
const limit = Math.min(500, Math.max(1, Number(filter.limit) || 100));
|
||||
const sql = `
|
||||
@@ -1314,6 +1324,16 @@ export async function searchAssignableEboms(filter: AssignableEbomFilter): Promi
|
||||
return r.rows;
|
||||
}
|
||||
|
||||
// E-BOM 미리보기 트리 — bom_report_objid 만으로 EBOM_WORKING_TREE_SQL 호출.
|
||||
// 운영판 mBomEbomSelectPopup.jsp 의 iframe 미리보기 대체.
|
||||
export async function previewEbomTree(bomReportObjid: string): Promise<MbomTreeResult> {
|
||||
if (!bomReportObjid) {
|
||||
return { bom_data_type: "NONE", bom_report_objid: null, max_level: 1, rows: [] };
|
||||
}
|
||||
const rows = await getEbomWorkingTree(bomReportObjid);
|
||||
return finalize("ASSIGNED_EBOM", bomReportObjid, rows);
|
||||
}
|
||||
|
||||
export type AssignSourceType = "EBOM" | "MBOM";
|
||||
|
||||
export async function assignBom(
|
||||
|
||||
Reference in New Issue
Block a user