5개 메뉴 1:1 검증(Agent 5병렬) 후 발견된 mbom 메인 그리드 [BOM 복사] 누락 보완.
저장 매퍼는 PR-B5 saveBomAssignment 재사용 — 백엔드는 EBOM/MBOM 분기 이미 지원,
이번에 MBOM UI 진입점도 첫 노출.
신규 컴포넌트:
- BomCopyDialog.tsx — 품번/품명 readonly + E-BOM/M-BOM 셀렉트 상호배타 +
트리 미리보기 + AttachFileDropZone (docType=MBOM_DRAWING, accept=.stp,.step,.dwg,.dxf,.pdf)
- 메인 page.tsx [BOM 복사] 버튼 추가 + 체크 단건 검증 +
Machine(0000928) 외 동일 partNo 최신 M-BOM 자동 추천
신규 백엔드 (mbomService/Controller/Routes):
- searchAssignableMboms — 매퍼 productionplanning.getMbomListForSelect2 (4007~4014) 1:1
- previewMbomTree — getStructureOnly + finalize("ASSIGNED_MBOM")
- getLatestMbomByPartNo — 매퍼 getLatestMbomByPartNo (3426~3445) 1:1, Machine 외 자동 검색
- 라우트: GET /assignable-mboms, GET /mbom-preview/:objid, GET /latest-mbom-by-partno/:partNo
도면 업로드 차이: 운영 fn_uploadDrawingFiles 는 placeholder("구현 예정"). RPS 는
공용 AttachFileDropZone 재사용해 실구현 (target_objid=projectObjid).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
신규 4개 메뉴 (PageHeader + CompactFilterBar + DataGrid 통일):
- 품질관리/수입검사 요청 (/quality/incoming-request)
- 품질관리/수입검사 관리 (/quality/incoming-mgmt)
- 품질관리/공정검사 관리 (/quality/process-inspection)
- 품질관리/반제품검사 관리 (/quality/semi-product-inspection)
DB 마이그레이션 (docs/migration/quality/):
- 01_quality_tables_from_ilshin.sql — ilshin 운영 5개 테이블 vexplor_rps 정합
(customer_service_mgmt/part/workingtime, inspection_mgmt, delivery_history_defect)
+ ecr_mng 7개 컬럼 동기화 (project_no, customer_cd, equip_name,
design_dept, unit_cd, memo, check_result)
- 02_wace_plm_quality_tables.sql — wace_plm quality.xml 매퍼 호환 신규 5개 테이블
(incoming_inspection_detail/defect, process_inspection_master/detail,
pms_quality_semi_product_inspection) + 인덱스 정의
백엔드:
- qualityRoutes.ts — 4개 메뉴 list 엔드포인트 (실 테이블 조회)
- ecrMngService SELECT_BASE 에 ilshin 신규 7컬럼 노출
- app.ts 라우팅 등록 (/api/quality/*)
프론트:
- DataGrid 4개 신규 페이지 + 그리드 툴바 (차트/엑셀/새로고침/컬럼설정/페이지사이즈)
- customer-cs/cs, ecr/ecr — 견적관리와 동일한 PageHeader + CompactFilterBar
+ DataGrid 패턴으로 리팩토링 (다이얼로그/기존 API 유지)
- ECR 그리드에 신규 6개 컬럼 추가 (설비명/프로젝트번호/고객사/설계부서/조치결과 등)
- AdminPageRenderer 4개 라우트 등록
데이터 복사: ilshin → vexplor_rps (workingtime 5건, inspection_mgmt 1건,
ecr_mng 1건). 나머지 ilshin 운영 테이블은 0건이므로 스키마만 정합.
운영 productionplanning.getMbomHistory (3448~3470) 1:1 이식:
· backend mbomService.getHistory(projectObjid) — project 단위 mbom_header 변경이력
시간순 최신 우선, USER_INFO join 으로 변경자명 함께
· GET /api/production/mbom/history/:projectObjid
· frontend MbomHistoryDialog — 5컬럼 그리드(변경일시/유형/내용/변경자/M-BOM품번)
CREATE=파란 뱃지, UPDATE=황색 뱃지, max-w-900px
· MbomDetailDialog toolbar 에 "변경이력" 버튼 (편집 모드 아닐 때만 노출)
PR-B1 의 history 저장 결과를 사용자가 직접 확인할 수 있도록 보는 화면 마무리.
부수: production/mbom/page 그리드 컬럼 폭 정돈 + summaryStats(전체/페이지/수주합/M-BOM 비율).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- /auth/login 401 응답은 인터셉터에서 리다이렉트하지 않고 그대로 반환해 호출부에서 에러 메시지를 표시하도록 수정
- apiCall에서 errorCode 추출 시 error.code 경로도 지원
- useLogin: errorCode === "LOGIN_FAILED"면 INVALID_CREDENTIALS 메시지 노출
(1) 정전개 트리 화면 운영판 wace structureAscendingList.jsp 1:1 정정:
- L1..LMaxLevel 컬럼 — row.lev 와 일치하는 컬럼에만 "*" 표시 (이전엔 품번 표시)
- 별도 품번 컬럼 1개 (모든 행 part_no)
- 3D/2D/PDF — renderType: "folder" (wace fnc_getFolderIcon 1:1)
- 컬럼 운영판 1:1 : 품번/품명/수량/항목수량/3D/2D/PDF/재료/열처리경도/열처리방법/표면처리/메이커/범주이름/비고
- 제거 : 변경일/REV/규격/중량 (운영판 미사용)
(2) 토글 -/+ 버튼 추가 (wace 트리 1:1):
- 첫 컬럼 __toggle — 자식 있는 행만 − / + 표시, 클릭 시 자식 숨김/표시
- collapsedChildIds Set<string> 상태로 접힘 관리
- ancestor 체인: parent_objid → 부모 행 child_objid 추적 (cycle guard)
- 가시 행 필터: ancestor 중 하나라도 collapsed Set 에 있으면 hide → 자손 전체 숨김
- 새 조회 시 collapsed Set 초기화 (모두 펼침)
(3) 품번 셀 클릭 → PartDetailDialog (wace partMngDetailPopUp 1:1):
- row.part_no = part_mng.objid::varchar 이므로 그대로 detail dialog 의 objid 로 전달
- ebom-search 페이지에 PartDetailDialog 임포트 + state
(4) 검색 필터 anchor 정정 (사용자 검증: 1행만 나오고 자식 안 풀림):
- 이전: search_part_no/search_part_name 을 결과 단계 WHERE PM.part_no LIKE ... 로 적용
→ 매칭 행 1개만 살아남고 자식 잘림
- 정정: anchor 단계에서 매칭된 PART 가 들어있는 bom_report_objid 전체를 startWhere 로
→ 재귀 CTE 가 자식 모두 풀어냄 (운영판 1:1)
- search_level (1~5) 은 결과 단계 유지 (트리 깊이 제한)
- ascending / ascendingForExcel 양쪽 동일 패턴
(5) ascending SELECT 풀 컬럼 보강:
- 추가 : item_qty(p_qty), heat_treatment_hardness/method, surface_treatment,
maker, part_type, part_type_title (comm_code.code_name)
- TREE CTE 컬럼에 item_qty 추가
- BomTreeRow 타입 동기 (lib/api/devBom.ts)
(6) 상태변경 시 확정일(DEPLOY_DATE) 처리 — 사용자 요청:
- status = 'Y' 변경 시 DEPLOY_DATE = TO_CHAR(NOW(), 'YYYY-MM-DD') 채움 (varchar)
- 'N' 변경 시 기존 DEPLOY_DATE 보존
- $5 prepared statement 타입 추론 충돌 (varchar vs unknown) → $5::varchar 명시 캐스팅
- STATUS_TITLE 매핑은 운영판 1:1 — CREATE/CHANGEDESIGN/DEPLOY 만 라벨, Y/N 등은 raw 표시
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
사용자 검증으로 발견된 5가지 함정 일괄 정정.
(1) ebom-search 검색폼 운영판 1:1 — wace structureAscendingList.jsp 노출 필드만:
- 제거: 프로젝트 OBJID (raw input), UNIT_CODE (raw input)
운영판도 고객사/프로젝트번호/유닛명 모두 주석 처리되어 노출 안 됨
- 유지: 품번 / 품명 / 표시 레벨 (1~5 select)
- BomTreeFilter.search_level 추가 + ascending/descending CTE 에 T.lev <= $search_level::int
(2) 품번/품명 자동완성 (wace select2-part 1:1):
- 영업관리 PartSelect 는 item_info 마스터 기반 → 개발관리(part_mng)용 별도 컴포넌트 신설
- backend GET /api/development/part/options : IS_LAST='1' part_mng 전체 (영업관리 sales/parts 패턴)
- frontend DevPartSelect.tsx : SmartSelect 캐시 + mode partNo/partName 분리
- ebom-search 페이지 단순 Input → DevPartSelect 교체
- 품번 선택 시 품명 자동 채움 / 품명 선택 시 품번 자동 채움 (운영판 select2-part 1:1)
(3) BomReportStatusDialog 운영판 1:1 재작성 — wace structureStatusChangePopup.jsp:
- 잘못된 점: read-only 박스 + 상태 select(create/changeDesign/deploy 3옵션)
- 정정: 5필드 모두 편집 가능 (CommCodeSelect 제품구분 / 품번 input / 품명 input /
Version input / 상태 Y/N 라디오) — 운영 매퍼 updateStructureStatus 5컬럼 UPDATE 1:1
- 헤더 파란 바 + 4컬럼 테이블(25%/75%) + 저장/닫기 중앙 배치 (운영판 스타일 1:1)
(4) DataGrid id 매핑 — 체크박스 ID 키 불일치 함정:
- DataGrid 는 row.id 로 체크박스 ID 관리, 백엔드 응답은 row.objid (postgres lowercase)
- 결과: checkedIds[0] 가 undefined → 상태변경/수정/삭제 다이얼로그가 objid=undefined 로 열려
detail 호출 안 됨 → 빈 폼 표시 (사용자 지적 "기본 정보 표시 안됨")
- 일괄 수정 (3 페이지) : ebom-regist / part-regist / part-search
gridRows = useMemo(() => rows.map(r => ({ ...r, id: r.objid })), [rows])
영업관리 페이지 동일 패턴 1:1
(5) STATUS_TITLE 매핑 운영판 1:1 — 운영 그리드는 'Y'/'N' 글자 그대로 표시:
CASE UPPER(T.STATUS)
WHEN 'CREATE' THEN '등록중'
WHEN 'CHANGEDESIGN' THEN '설계변경미배포'
WHEN 'DEPLOY' THEN '배포완료'
ELSE COALESCE(T.STATUS, '') END AS STATUS_TITLE
- 운영 매퍼는 ELSE '' 이지만 RPS 는 raw fallback (사용자 화면에서 식별 가능)
- 'Y'/'N' 매핑 라벨 추가 → 운영 스크린샷 확인 후 제거 (운영판은 raw)
미해결 (별 작업):
- 확정일 (DEPLOY_DATE) 표시 — 운영판은 별도 "배포" 액션 (deployBomReport 매퍼) 으로 채움.
RPS ebom-regist 에 배포 버튼 미구현 → 신규 BOM 확정일 빈값. 별 PR.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
운영판 wace 재확인 결과 BOM 등록은 XLSX가 아니라 CSV 가 진짜 입력 포맷이었음.
근거:
· openBomReportExcelImportPopUp.jsp : 제목 "PART 및 구조등록 CSV upload",
Drop Zone "Drag & Drop CSV 템플릿", fnc_setFileDropZone(..., "csv") 로 CSV 만 허용
· /partMng/parsingExcelFile.do 가 .csv 분기에서 별도 함수 parsingCsvFile() 호출
· CSV 11컬럼 : 수준 / 품번 / 품명 / 수량 / 항목수량 / 재료 / 열처리경도 / 열처리방법 /
표면처리 / 공급업체(MAKER) / 범주이름(PART_TYPE)
· CSV 는 PARENT_PART_NO 컬럼이 없고 "수준" 으로 부모-자식 자동 결정
· 숫자("1","2","3"): 깊이 D 의 부모 = D-1 의 최신 품번
· 점 표기법("1","1.1","1.4.1"): 마지막 점 이전 수준이 부모
backend (devBomExcelImportService.ts):
· XLSX(xlsx 라이브러리) 파싱 → CSV(iconv-lite) 파싱으로 완전 재작성
· 인코딩 자동 감지 1:1 — CP949 → UTF-8 → EUC-KR → MS949 순서, � 카운트로 베스트 선택,
UTF-8 BOM() 자동 제거
· CSV 영문 범주명 자동 변환 — Assy/ASSY→조립품, Buy/BUY→구매품, Make/MAKE→부품
· 범주별 ACCTFG/ODRFG 자동 설정 — 조립품(0001813)·부품(0001812) → ACCTFG=4·ODRFG=1,
구매품(0000063) → ACCTFG=7·ODRFG=0
· 기본값 일괄 — UNIT_DC=0001400(EA) · UNITMANG_DC=0001400 · UNITCHNG_NB=1 ·
LOT_FG=1 · USE_YN=1 · QC_FG=0 · SETITEM_FG=0 · REQ_FG=0
· 검증 1:1 — rowIndex > 2 에서만 모품번 자품번 목록 존재 검사, NOTE 누적
· 저장 로직(savePartBomMaster)은 동일 유지 — 자식 PART updatePartInfoFromCsv UPDATE /
insertpartInfo INSERT, 부모 PART 존재 시 lookup·없으면 "" (INSERT 안 함),
bom_part_qty INSERT 시 ACCTFG/ODRFG/UNIT_DC/UNITCHNG_NB 등 모든 컬럼 동기
frontend:
· BomExcelRow → BomCsvRow (LEVEL 컬럼 + ACCTFG/ODRFG/UNIT_DC/UNITCHNG_NB/LOT_FG/USE_YN/
QC_FG/SETITEM_FG/REQ_FG 자동 채움 필드 추가). BomExcelRow 는 호환 type alias 로 보존
· BomReportExcelImportDialog : 제목 "PART 및 구조등록 CSV upload", accept=".csv", Drop Zone
안내 텍스트 변경, 그리드 컬럼 — 결과/수준/모품번(자동)/품번/품명/수량/항목수량/재료/
열처리경도/열처리방법/표면처리/공급업체/범주/계정구분(자동)/조달구분(자동)
· 파싱 결과의 encoding 정보 표시 (CP949/UTF-8 등)
정적 자산:
· 운영 BOM_REPORT_EXCEL_IMPORT_TEMPLATE.xlsx 제거 (운영판도 실제 사용 안 함)
· 신규 BOM_REPORT_CSV_IMPORT_TEMPLATE.csv 추가 (11컬럼 헤더 + 4행 샘플)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 배치(REST API→DB) 저장 시 매핑 payload 에 from_connection_id 추가
— 등록된 연결 선택값이 DB 에 저장 안 돼 수정 화면 재진입 시 manual 로 표시되던 문제 해결
- 배치 실행 호출만 timeout 30s → 5분(300000ms) override
— 외부 API + 대량 INSERT 시 자주 끊기던 AxiosError 해결
- 권한관리 좌측 권한 카드에서 authCode 행 제거
— authName 만 노출(코드값은 hover tooltip 으로 유지). 검색은 authCode 도 매칭 유지
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
· wace fn_openSaleRegPopup(PROJECT_NO, "detail") 의도 재해석 — read-only 상세 조회 모드
· 행 전체 클릭(onRowClick) → PROJECT_NO 컬럼 셀 클릭(cellClick)으로 좁힘 (wace 1:1)
· 판매관리 페이지 라우팅 폐기 → ProjectInfoDialog 신설 (같은 탭, list row 직접 사용, 추가 API 호출 0)
· 표시 항목: 프로젝트번호/영업번호/주문유형/제품구분/국내해외/고객사/유무상/품번/품명/S/N/수주수량/접수일/요청납기/발주일/프로젝트명/작성자
· 영업관리 변경 롤백 (SaleListFilter.project_no, useSearchParams 자동 선택, 초기화 핸들러)
· 01-progress / 01-progress-verify 문서 갱신
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- getList SQL: 라인 집계에 product_summary(=PRODUCT_NAME, contract_item.product distinct join) / return_reason_summary 추가. wace는 헤더 product 폐지·라인으로 이동(운영 90건 contract_mgmt.product NULL) → 라인 집계로 그리드 표시
- GRID_COLUMNS 3개 추가: 제품구분 / 국내해외 / 반납사유
- searchForm.search_partName 필드 추가(초기화 포함). 검색 폼 UI는 PartSelect mode=partName 이미 존재
- docs/migration/sales/01-estimate-verify.md: wace ↔ RPS 항목 매핑 / 운영 데이터 코드 체계 / 갭 우선순위
- scripts/verify-estimate.sql: BEGIN/ROLLBACK 5개 시나리오 (등록·수정·G1·수주취소·그리드) 자동 검증
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
[ECR(Engineering Change Request) 관리]
- ecr_mng / product_mgmt / part_mng 테이블 + seq_ecr_no 시퀀스
- 설변요청 코드(0000090) 자식 코드 시드 (설계오류/품질개선/원가절감/고객요청/법규대응/부품단종)
- API: 목록/상세/등록·수정(merge)/조치완료/삭제 + 옵션(작성자/제품/부품/공통코드)
- 화면: 필터바, 그리드, 등록·수정 모달, 상세 모달, 조치완료 모달
[고객 CS 관리]
- customer_cs_mng 테이블 (기존 customer_mng 거래처 마스터와 충돌 회피)
- 공통코드 5종 카테고리(0000200~0000204) 자동 시드: 관리유형/제품구분/담당자/조치유형/CS상태
- API: 목록/상세/등록·수정/삭제/대시보드(요약·상태별·관리유형별·제품구분별)
- 화면: 요약 카드 4종, 10종 필터바, 14컬럼 그리드, 등록·수정·상세 모달
[결재(APPROVAL) 시스템 — wace_plm ApprovalService 포팅]
- approval / route / inboxtask / approval_target / approval_kind / amaranth_approval 6개 테이블
- 라이프사이클: 상신(startApproval) → 결재함(listInbox) → 승인/반려(approveTask/rejectTask)
→ 다음 결재자 ready 자동 전달, 마지막이면 route+approval+target 일괄 complete
- target_type 별 도메인 status 동기화 훅 (ECR_MNG/CUSTOMER_MNG)
- API: /api/wace-approval/{inbox,start,inbox/:id/approve|reject,by-target,:id,:id/amaranth-link}
[Amaranth(Wehago) 전자결재 RestAPI 연계]
- 외부 커넥션 'Amaranth - 결재' 자동 시드 (auth_config: callerName/accessToken/hashKey/groupSeq/aesKey)
- amaranthApprovalClient: 자바 AmaranthApprovalApiClient 1:1 포팅
HMAC-SHA256 wehago-sign / AES-128-CBC empSeq 암호화 / HTTPS / JSON 파싱
- 6개 endpoint: 인증토큰/결재함/문서목록/문서상세/SSO URL/문서상신
- 하드코딩 0건 — DB 외부 커넥션의 인증 정보를 매 호출 시 로드
- 통신 검증 완료 (dummy empSeq 로 응답 정상 수신)
- 프록시 라우트 /api/amaranth-approval/{box,docs,docs/:id,sso,submit,auth-token}
[wace_plm 데이터 import]
- WacePlmDataImportService: source PG 클라이언트 → 우리 DB ON CONFLICT DO NOTHING idempotent
- 환경변수 WACE_PLM_DB_* 만 읽음 (운영 비번 코드 0건, 미설정 시 명시적 에러)
- /api/wace-import/{all,ecr,cs,masters,approval} (SUPER_ADMIN 전용)
[Bugfix]
- 배치 편집 conditional 매핑 silent drop 방지 — 평가 필드/규칙 누락 시
어느 컬럼이 어떤 이유로 빠졌는지 toast 로 명시 + 저장 차단
- 시드 topup 강화 — extra_auth_config(aesKey 등) 누락된 기존 레코드 자동 보강
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- 검색 폼 정합성: wace JSP `<!-- 주석처리된 검색필터 -->` 블록까지 잘못 이식했던 부분 정정
- 견적: 11→7개 (제품구분/국내해외/유무상/요청납기 제거)
- 주문: 13→9개 (제품구분/국내해외/유무상/견적환종 제거)
- 매출: 10→11개 (출하지시상태 제거 + 제품구분·국내/해외 추가, JSP 순서로 재배치)
- 판매: 변경 없음 (원본 그대로 일치)
- 매출 백엔드: SaleListFilter에 productType/nation 추가, getRevenueList에 partObjId/serialNo/orderDate/productType/nation 5개 필터 처리
- 공통 UX
- 초기화 버튼을 4개 메뉴 동일하게 통일 (variant=ghost, 버튼 영역 끝)
- <Input type="date">는 빈 값 placeholder 숨김 + 캘린더 아이콘 숨김 + 영역 클릭으로 picker 자동(showPicker)
- 신규 공통 컴포넌트: CommCodeSelect/CustomerSelect/CustomerSearchDialog/PartSelect/ItemSearchDialog + backend salesCommonRoutes
- 문서: 01/02/04 검색 폼 표를 활성/비활성 분리 형식으로 정정, README에 8. 공통 UX 규칙 섹션 신설
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- RoleFormModal: 권한 코드 입력 필드 제거. 생성 시 ROLE_<base36 timestamp>
형태로 자동 부여 (시스템 내부 키, UI 비노출). 수정 모드에서도
authCode 는 기존 값 유지하고 입력 받지 않음.
- dashboard.ts getApiBaseUrl: NEXT_PUBLIC_API_URL 환경변수가 있으면 우선 사용.
fallback 포트를 8080 → 8090 (compose 외부 노출 포트)으로 정정해
'데이터를 불러올 수 없습니다 / Failed to fetch' 해결.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>