Files
wace_rps/docs/migration/development/03-eo-history.md
T
hjjeong c9adfd7327 개발관리>설계변경 리스트 메뉴 신설 (PR-C) — wace partMng 1:1 이식
backend (M5, read-only):
- devEoHistoryService: list + getByObjid
- partMngHistList SQL 1:1 (NVL→COALESCE, PART_MNG.OBJID bigint cast, CODE_NAME→LEFT JOIN comm_code)
- 동적 필터 10종 (Year/contract_objid/unit_code/part_no/part_name/change_option/eo_start~end/change_type/part_type/writer_id)
- 신규등록 제외 가드: NOT (HIS_STATUS='DEPLOY' AND CHANGE_TYPE IS NULL AND REVISION='RE') + BOM_STATUS='deploy'
- 품번변경(CHANGE_OPTION=0001790) 'A->B' 머지 CASE (part_no_disp/part_name_disp/revision_disp)

frontend (M5):
- change-list/page.tsx: 16셀 그리드 + 검색 8필드 + 페이징
- PartHisDetailDialog: 모든 필드 disabled, 4 섹션 (EO/프로젝트/PART/수량)
- AdminPageRenderer dynamic 임포트 + 기존 menu_info URL 그대로 사용

개발관리 5개 메뉴 (M1~M5) baseline 완료.

본 PR 제외 (별 PR): writer SmartSelect, change_type/change_option comm_code 그룹 SmartSelect (그룹 ID 확정 후)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 16:27:37 +09:00

7.0 KiB

PR-C : 설계변경 리스트 구현 명세 (M5)

작성: 2026-05-12 / 범위: 개발관리 M5 (설계변경 리스트) — read-only part_mng_history 조회.


1. 매퍼 쿼리 1:1 매핑

Query id Line 본 PR 매핑 용도
partMngHistList 7,787 GET /api/development/eo-history/list M5 그리드 (read-only)

추가 엔드포인트:

  • GET /api/development/eo-history/:objid — 행 클릭 상세 다이얼로그용 (raw row 반환).

2. API 명세

2.1 그리드 — GET /api/development/eo-history/list

Query (wace 10 필터 1:1):

Year?: string                    // TO_CHAR(project_mgmt.regdate, 'YYYY')
contract_objid?: string          // project_mgmt.objid
unit_code?: string               // part_bom_report.unit_code
part_no?: string                 // LIKE
part_name?: string               // LIKE
change_option?: string           // comm_code id (EO사유)
eo_start_date?: string
eo_end_date?: string
change_type?: string             // comm_code id (EO구분)
part_type?: string               // comm_code id
writer_id?: string
page?, page_size?

SQL (wace partMngHistList 1:1, vexplor 적응):

SELECT
   PM.OBJID,
   PM.EO_NO,
   TO_CHAR(CM.REGDATE, 'YYYY') AS YEAR,
   COALESCE(CM.CUSTOMER_PROJECT_NAME, CM2.CUSTOMER_PROJECT_NAME) AS PROJECT_NAME,
   COALESCE(CM2.PROJECT_NO, CM.PROJECT_NO) AS PROJECT_NO,
   /* 모품번: PART_MNG SP에서 PARENT_PART_NO로 조회. PART_MNG.OBJID는 bigint → varchar cast */
   (SELECT SP.PART_NO || ' ' || SP.PART_NAME
      FROM PART_MNG SP
     WHERE SP.OBJID::varchar = PM.PARENT_PART_NO) AS PARENT_PART_INFO,
   /* 품번변경(0001790) 시 'A->B' 머지 */
   CASE WHEN PM.CHANGE_OPTION = '0001790' THEN COALESCE(PM.PART_NO,'') || '->' || COALESCE(PM.CHG_PART_NO,'')
        ELSE PM.PART_NO END AS PART_NO_DISP,
   CASE WHEN PM.CHANGE_OPTION = '0001790'
        THEN COALESCE(PM.PART_NAME,'') || '->' ||
             COALESCE((SELECT P.PART_NAME FROM PART_MNG P WHERE P.OBJID::varchar = PM.CHG_PART_OBJID), '')
        ELSE PM.PART_NAME END AS PART_NAME_DISP,
   PM.PART_NO,            -- raw
   PM.PART_NAME,          -- raw
   PM.BOM_QTY_STATUS,
   CASE WHEN PM.BOM_QTY_STATUS = 'adding' THEN PM.QTY_TEMP ELSE PM.QTY END AS QTY,
   CASE WHEN PM.BOM_QTY_STATUS = 'adding' THEN ''
        WHEN PM.BOM_QTY_STATUS = 'beforeEdit' AND PM.QTY = PM.QTY_TEMP THEN ''
        ELSE PM.QTY_TEMP END AS QTY_TEMP,
   PM.CHANGE_TYPE,
   CC_CHGTYPE.code_name AS CHANGE_TYPE_NAME,
   PM.CHANGE_OPTION,
   CC_CHGOPT.code_name  AS CHANGE_OPTION_NAME,
   CASE WHEN PM.CHANGE_OPTION = '0001790'
        THEN COALESCE(PM.REVISION,'') || '->' || COALESCE(PM.CHG_PART_REV,'')
        ELSE PM.REVISION END AS REVISION_DISP,
   PM.REVISION,           -- raw
   PM.EO_DATE,
   PM.PART_TYPE,
   CC_PARTTYPE.code_name AS PART_TYPE_NAME,
   PM.WRITER,
   UI.user_name AS WRITER_NAME,
   COALESCE(WTS.UNIT_NO || '-' || WTS.TASK_NAME, '') AS UNIT_NAME,
   TO_CHAR(PM.HIS_REG_DATE, 'YYYY-MM-DD') AS HIS_REG_DATE_TITLE,
   PM.BOM_DEPLOY_DATE,
   TO_CHAR(PM.BOM_DEPLOY_DATE, 'YYYY-MM-DD') AS BOM_DEPLOY_DATE_TITLE
  FROM PART_MNG_HISTORY PM
  LEFT JOIN PROJECT_MGMT  CM   ON CM.OBJID  = PM.CONTRACT_OBJID
  LEFT JOIN PART_BOM_REPORT B  ON B.OBJID   = PM.BOM_REPORT_OBJID
  LEFT JOIN PROJECT_MGMT  CM2  ON CM2.OBJID = B.CONTRACT_OBJID
  LEFT JOIN PMS_WBS_TASK  WTS  ON WTS.OBJID = B.UNIT_CODE
  LEFT JOIN user_info     UI   ON UI.user_id = PM.WRITER
  LEFT JOIN COMM_CODE CC_CHGTYPE  ON CC_CHGTYPE.code_id  = PM.CHANGE_TYPE   AND CC_CHGTYPE.status='active'
  LEFT JOIN COMM_CODE CC_CHGOPT   ON CC_CHGOPT.code_id   = PM.CHANGE_OPTION AND CC_CHGOPT.status='active'
  LEFT JOIN COMM_CODE CC_PARTTYPE ON CC_PARTTYPE.code_id = PM.PART_TYPE     AND CC_PARTTYPE.status='active'
 WHERE 1=1
   /* 파트 신규등록건 조회 제외 — wace 1:1 */
   AND NOT (PM.HIS_STATUS = 'DEPLOY' AND PM.CHANGE_TYPE IS NULL AND PM.REVISION = 'RE')
   AND PM.REVISION IS NOT NULL
   AND COALESCE(PM.BOM_STATUS, '') = 'deploy'
   + 동적 ( 10 필터)
 ORDER BY COALESCE(PM.HIS_REG_DATE, PM.REG_DATE) DESC, PM.PART_NO

Response: { rows: EoHistoryRow[], total, page, pageSize }

2.2 단건 — GET /api/development/eo-history/:objid

SELECT PM.* FROM PART_MNG_HISTORY PM WHERE PM.OBJID = $1::numeric + comm_code JOIN (CHANGE_TYPE/OPTION/PART_TYPE 라벨).


3. Backend 파일 구조

backend-node/src/
  routes/devEoHistoryRoutes.ts        // 2 endpoint
  controllers/devEoHistoryController.ts
  services/devEoHistoryService.ts     // list + getByObjid

app.ts: app.use("/api/development", devEoHistoryRoutes).


4. Frontend 파일 구조

frontend/
  app/(main)/COMPANY_16/development/change-list/page.tsx
  components/development/PartHisDetailDialog.tsx
  lib/api/devEoHistory.ts

4.1 그리드 16셀 (wace partMngHisList.jsp:50~75 1:1)

key 라벨 정렬 너비
eo_no EO No left 100
project_no 프로젝트번호 left 120
project_name 프로젝트명 left 180
unit_name 유닛명 left 160
parent_part_info 모품번 left 160
part_no_disp 품번 left 160
part_name_disp 품명 left flex
qty 수량 right 70
qty_temp 변경수량 right 80
change_type_name EO구분 center 90
change_option_name EO사유 center 100
revision_disp Revision center 90
eo_date EO Date center 100
part_type_name PART구분 center 90
writer_name 담당자 center 90
his_reg_date_title 실행일 center 100

4.2 검색 폼 (wace 10 필드 1:1)

Year · contract_objid · unit_code · part_no · part_name · change_option · eo_start_date~end_date · change_type · part_type · writer_id

본 PR 1차: Year · 프로젝트 OBJID · part_no · part_name · eo_start_date~end_date · change_type · change_option · part_type (Smart 폼). writer_id 는 UserSelect 별 PR.

4.3 액션

  • 조회 (only) — read-only 메뉴
  • 행 클릭 → PartHisDetailDialog (모든 필드 disabled)

5. 검증 시나리오

  1. M5 페이지 진입 → part_mng_history 빈 그리드 (시드 후 표시 확인)
  2. PART 등록(M1) → 확정(deploy) 트랜잭션으로 part_mng_history INSERT (PR-A 의 deploy 경로)
    • 단, deploy 시 bom_status 가 NULL 이므로 본 SQL의 bom_status='deploy' 필터에서 제외됨
    • 본 메뉴는 BOM 변경 이력 표시 목적 — 실제 데이터는 M3 BOM 배포 시 INSERT됨 (PR-B 범위 밖)
  3. 검색 필터(year/part_no/change_type/eo_start_date) → 동적 WHERE 적용 확인
  4. 행 클릭 → 상세 다이얼로그에 모든 필드 표시 (raw + 라벨)

6. 적응 사항

# 항목 변경
1 NVL()COALESCE() wace는 Oracle 호환 NVL 사용, PG 표준은 COALESCE
2 PART_MNG.OBJID = PM.PARENT_PART_NO JOIN OBJID bigint vs PARENT_PART_NO varchar → cast ::varchar
3 CODE_NAME() 함수 LEFT JOIN comm_code 별칭으로 풀어 쓰기
4 wace STATUS_NQ/SEARCH_TYPE=CHANGE_LIST 필터 제거 본 PR 메뉴는 변경리스트 한 화면 — 필터 단순화