개발관리>PART 등록·조회 메뉴 신설 (PR-A) — wace partMng 1:1 이식
backend (M1+M2):
- devPartService: listTemp/listRelease/getByObjid/create/update/deploy/removeMany
- partMngBaseSimple SELECT + 추가 15컬럼(acctfg/odrfg/unit_dc/unitmang_dc/lot_fg 등) 라벨/CASE
- deploy 트랜잭션 3단계 (isLastInit → part_mng_history INSERT → partMngDeploy + EO_NO 채번)
- EO_NO 분기: is_longd='1'→EOB{yy}-{seq} / else EO{yy}-{seq}
- objidUtil: wace CommonUtils.createObjId() 1:1 (bigint objid 채번)
- DDL: 9 신규 테이블 + part_mng 15컬럼 ALTER (운영판 1:1 추출)
frontend (M1+M2):
- part-regist (M1) / part-search (M2): 23셀 그리드 + 검색폼 + 액션
- PartFormDialog: 등록/수정 통합 (mode prop, 4 섹션)
- PartDetailDialog: 읽기 전용 + "수정" dispatch
- AdminPageRenderer dynamic 임포트 2건 + menu_info URL spec 정렬
본 PR 제외 (별 PR): 도면 다중 업로드, ERP 업로드, Excel Import, BOM_PART_QTY R/W
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
# 개발관리 이식 GAP 분석 (원본 wace_plm 대비)
|
||||
|
||||
> 작성: 2026-05-12 / 작성자: hjjeong
|
||||
> 대상 메뉴 5종 (1 도메인 `development/`):
|
||||
> - PART 등록 / PART 조회 / E-BOM 등록 / E-BOM 조회 / 설계변경 리스트
|
||||
> 원본 위치: `wace_plm/WebContent/WEB-INF/view/partMng/` (단일 디렉토리) + `mapper/partMng.xml` 단일 매퍼.
|
||||
|
||||
---
|
||||
|
||||
## 0. 한 문장 요약
|
||||
|
||||
5개 메뉴 모두 wace `partMng/` 단일 디렉토리 + `partMng.xml` 매퍼에 1:1 매핑됨. 의존 테이블 15개 중 **6개 보유(`part_mng`/`comm_code`/`pms_wbs_task`/`project_mgmt`/`user_info`/`product_mgmt`)** · **9개 신규 추가 완료(`300_part_bom.sql`)** · **`part_mng`에 누락 15컬럼 ALTER 완료(`301_alter_part_mng.sql`)**. 5개 메뉴 모두 P1에서 실데이터 표시 가능.
|
||||
|
||||
## 0.1 이식 원칙
|
||||
|
||||
- JSP/매퍼XML 안의 `/* */`, `<!-- -->`, `//` 주석 블록은 비활성. 활성 코드만 이식.
|
||||
- `company_code` 멀티테넌시 분기는 vexplor_rps 측에 만들지 않음 (COMPANY_16 단독).
|
||||
- `CODE_NAME()`은 영업/프로젝트와 동일하게 `LEFT JOIN comm_code CC_X ON CC_X.code_id=...` 패턴 통일.
|
||||
- `client_mng`/`supply_mng` → vexplor는 `customer_mng`로 통합되어 있으나, 개발관리 5개 메뉴는 `customer_mng`를 직접 참조하지 않음(`project_mgmt.customer_objid` 경유). 분기 변환 불필요.
|
||||
- 금액 1,234.00 / 수량 1,234 / 모든 숫자 right-align (memory `feedback_number_format.md`).
|
||||
- wace JSP 컬럼 정의 끝의 주석 블록은 비활성 항목 — grep만으로 카운트하지 말 것 (memory `feedback_wace_jsp_columns.md`).
|
||||
|
||||
---
|
||||
|
||||
## 1. 메뉴 ↔ JSP ↔ 매퍼 1:1 매핑
|
||||
|
||||
| # | 메뉴 | wace JSP | 매퍼 쿼리 (partMng.xml) | LOC |
|
||||
|---|---|---|---|---:|
|
||||
| M1 | **PART 등록** | `partMngTempList.jsp` | `partMngTempGridList` (S), `partMngDeploy` (U), `partMngDelete` (D) | 649 |
|
||||
| M2 | **PART 조회** | `partMngList.jsp` | `partMngGridList` (S), `partMngDelete` (D), `partMngFormPopUp` (S) | 834 |
|
||||
| M3 | **E-BOM 등록** | `structureList.jsp` | `getBOMStandardStructureGridList` (S), `deleteStructure` (D), `structureStatusChange` (U) | 782 |
|
||||
| M4 | **E-BOM 조회** | `structureAscendingList.jsp` | `structureAscendingList`/`structureAscendingListExcel`/`structureDescendingExcelList` (S) | 1,064 |
|
||||
| M5 | **설계변경 리스트** | `partMngHisList.jsp` | `partMngHistList` (S, read-only) | 198 |
|
||||
|
||||
vexplor_rps 측 라우트(예정):
|
||||
|
||||
```
|
||||
GET /api/development/part-temp/list (M1 그리드)
|
||||
POST /api/development/part-temp/deploy (M1 확정)
|
||||
DEL /api/development/part-temp (M1·M2 삭제 공용)
|
||||
GET /api/development/part/list (M2 그리드)
|
||||
GET /api/development/part/:objid (M2 상세 팝업)
|
||||
GET /api/development/ebom/list (M3 그리드)
|
||||
PUT /api/development/ebom/status (M3 상태변경)
|
||||
DEL /api/development/ebom/:objid (M3 삭제)
|
||||
GET /api/development/ebom/ascending (M4 정전개)
|
||||
GET /api/development/ebom/descending (M4 역전개)
|
||||
GET /api/development/eo/history/list (M5 그리드)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 메뉴별 검색 필드 & 그리드 컬럼 (활성만)
|
||||
|
||||
### M1 PART 등록 (`partMngTempList.jsp`)
|
||||
|
||||
**검색**: SEARCH_PART_NO, SEARCH_PART_NAME (둘 다 autocomplete)
|
||||
**그리드 23셀**: PART_NO · PART_NAME · CU01_CNT(3D) · CU02_CNT(2D) · CU03_CNT(PDF) · MATERIAL · HEAT_TREATMENT_HARDNESS · HEAT_TREATMENT_METHOD · SURFACE_TREATMENT · MAKER · PART_TYPE_TITLE · SPEC · ACCTFG_NM · ODRFG_NM · UNIT_DC_NM · UNITMANG_DC_NM · UNITCHNG_NB · LOT_FG_NM · USE_YN_NM · QC_FG_NM · SETITEM_FG_NM · REQ_FG_NM · UNIT_LENGTH/QTY
|
||||
**액션**: 확정(Deploy) · 삭제 · 등록 · Excel Upload · 도면다중업로드 · 조회
|
||||
**팝업**: partMngFormPopUp(신규) · partMngDetailPopUp(편집) · openPartExcelImportPopUp
|
||||
**핵심 의존 테이블**: `part_mng` (메인) · `order_spec_mng` · `admin_supply_mng` · `bom_part_qty`
|
||||
|
||||
### M2 PART 조회 (`partMngList.jsp`)
|
||||
|
||||
**검색**: 없음(메인 조회 화면). 그리드 컬럼 동일하게 23셀(M1과 동일).
|
||||
**액션**: 등록 · 삭제 · 도면연동 · ERP업로드(전체/단일/모두) · Excel Upload · 조회
|
||||
**팝업**: partMngFormPopUp · partMngDetailPopUp · FileRegistPopup · openPartExcelImportPopUp
|
||||
**핵심 의존 테이블**: `part_mng` · `bom_part_qty`
|
||||
|
||||
### M3 E-BOM 등록 (`structureList.jsp`)
|
||||
|
||||
**검색 9 필드**: customer_cd · project_name · unit_code · SEARCH_UNIT_NAME · SEARCH_WRITER · product_cd · SEARCH_PART_NO · SEARCH_PART_NAME · search_fromDate~toDate · status
|
||||
**그리드 9셀**: PRODUCT_NAME · PART_NO · PART_NAME · BOM_CNT · DEPT_USER_NAME · REG_DATE · DEPLOY_DATE · REVISION · STATUS
|
||||
**액션**: 조회 · 삭제 · E-BOM등록 · 상태변경
|
||||
**팝업**: setStructureStandardFormPopup · setBomCopyFormPopup · setStructurePopupMainFS · changeDesignNotePopUp · structureStatusChangePopup · openBomReportExcelImportPopUp
|
||||
**핵심 의존 테이블**: `part_bom_report` · `supply_mng` · `project_mgmt` · `pms_wbs_task` · `user_info` · `bom_part_qty` · `part_mng` · `comm_code`
|
||||
|
||||
### M4 E-BOM 조회 (`structureAscendingList.jsp`)
|
||||
|
||||
**검색 4 필드**: project_name · unit_code · search_partNo · search_partName
|
||||
**그리드**: 동적 — MAX_LEVEL 레벨 컬럼 + 품번 · 품명 · 3D/2D/PDF · 수량 · 변경일 · 변경항목 · 규격 · 재질 · 중량 · 비고
|
||||
**액션**: 정전개조회 · 역전개조회 · 엑셀다운로드(정/역전개)
|
||||
**팝업**: partMngDetailPopUp(클릭) · FileRegistPopup(도면)
|
||||
**핵심 의존 테이블**: `bom_part_qty` · `sales_bom_report` · `part_bom_report` · `product_mgmt_upg_detail`/`_master` · `part_mng` · `project_mgmt` · `pms_wbs_task` · `user_info` · `product_mgmt`
|
||||
|
||||
### M5 설계변경 리스트 (`partMngHisList.jsp`)
|
||||
|
||||
**검색 10 필드**: Year · contract_objid · unit_code · part_no · part_name · change_option · eo_start_date~end_date · change_type · part_type · writer_id
|
||||
**그리드 16셀**: EO_NO · PROJECT_NO · PROJECT_NAME · UNIT_NAME · PARENT_PART_INFO · PART_NO · PART_NAME · QTY · QTY_TEMP · CHANGE_TYPE_NAME · CHANGE_OPTION_NAME · REVISION · EO_DATE · PART_TYPE_NAME · WRITER_NAME · HIS_REG_DATE_TITLE
|
||||
**액션**: 조회만(Read-Only)
|
||||
**팝업**: partMngHisDetailPopUp(행 클릭)
|
||||
**핵심 의존 테이블**: `part_mng_history` · `project_mgmt` · `part_bom_report` · `pms_wbs_task` · `user_info` · `comm_code`
|
||||
|
||||
---
|
||||
|
||||
## 3. RPS DB 보유 매트릭스 (적용 완료)
|
||||
|
||||
| 테이블 | M1 | M2 | M3 | M4 | M5 | 종류 | RPS 상태 |
|
||||
|---|:-:|:-:|:-:|:-:|:-:|---|---|
|
||||
| `part_mng` | R/W | R/W | R | R | R | 메인 | ✅ +15컬럼 ALTER(`301_alter_part_mng.sql`) |
|
||||
| `bom_part_qty` | R | R | R/W | R | R | BOM 수량 | ✅ 신규(`300`) |
|
||||
| `part_bom_report` | R | R | R/W | R | R | BOM 리포트 헤더 | ✅ 신규(`300`) |
|
||||
| `part_mng_history` | – | – | – | – | R | 변경이력 | ✅ 신규(`300`) |
|
||||
| `order_spec_mng` | R | – | – | – | – | 발주 스펙 | ✅ 신규(`300`) |
|
||||
| `admin_supply_mng` | R | – | – | – | – | 공급사(관리자) | ✅ 신규(`300`) |
|
||||
| `supply_mng` | – | – | R | – | – | 공급사 | ✅ 신규(`300`) |
|
||||
| `sales_bom_report` | – | – | – | R | – | 영업 BOM 단가 | ✅ 신규(`300`) |
|
||||
| `product_mgmt_upg_master` | – | – | – | R | – | 제품 업그레이드 마스터 | ✅ 신규(`300`) |
|
||||
| `product_mgmt_upg_detail` | – | – | – | R | – | 제품 업그레이드 디테일 | ✅ 신규(`300`) |
|
||||
| `project_mgmt` | – | – | R | R | R | 프로젝트 | ✅ 기존 |
|
||||
| `pms_wbs_task` | – | – | R | R | R | 작업/유닛 | ✅ 기존 |
|
||||
| `user_info` | – | – | R | R | R | 사용자 | ✅ 기존(컬럼명 매핑 필요) |
|
||||
| `comm_code` | – | – | R | R | R | 공통코드 | ✅ 기존 |
|
||||
| `product_mgmt` | – | – | R | R | – | 제품 | ✅ 기존 |
|
||||
|
||||
**→ 5개 메뉴 모두 P1에서 실데이터 표시 가능.**
|
||||
|
||||
---
|
||||
|
||||
## 4. GAP 매트릭스
|
||||
|
||||
| # | 우선 | 항목 | 권장 작업 |
|
||||
|---|---|---|---|
|
||||
| **DEV-1** | 🔴 | 개발관리 메뉴 자체 부재 → 5개 메뉴 운영판 1:1 이식 | **본 PR 시리즈 (3 묶음)** |
|
||||
| **DEV-2** | 🔴 | `part_mng` 15컬럼 누락 (열처리/표면처리/단위/Y-N flag) | ✅ **완료** — `301_alter_part_mng.sql` |
|
||||
| **DEV-3** | 🔴 | 9개 테이블 부재 | ✅ **완료** — `300_part_bom.sql` (BEGIN/COMMIT 트랜잭션, IDEMPOTENT) |
|
||||
| **DEV-4** | 🟠 | `user_info` 컬럼명 매핑 (wace `empseq`/`rank` ↔ vexplor `emp_seq`/`rank_code`+`rank_name`) | 코드 측 alias로 처리 |
|
||||
| **DEV-5** | 🟠 | M3 상태값(작성중/적용완료 등) — wace는 `comm_code` 0000099 자식 사용 | comm_code 그대로 사용. RPS DB에 이미 존재 여부 확인 후 부재 시 INSERT |
|
||||
| **DEV-6** | 🟠 | M1·M2 팝업(등록/상세) 다이얼로그 — wace `partMngFormPopUp.jsp` 별도 LOC 큼 | M1·M2 묶음 PR에 포함 (한 번에 가는 게 효율) |
|
||||
| **DEV-7** | 🟡 | M1 도면 다중 업로드 / M2 ERP 업로드 | 본 PR 시리즈 제외 (별 PR) |
|
||||
| **DEV-8** | 🟡 | M3 BOM Excel Import / M4 엑셀 다운로드 | 본 PR 시리즈 제외 (별 PR) |
|
||||
| **DEV-9** | 🟢 | M4 동적 MAX_LEVEL 컬럼 — BOM 트리 깊이에 따라 컬럼 추가 | DataGrid 동적 컬럼 모드. 본 PR(E-BOM 묶음)에 포함 |
|
||||
| **DEV-10** | 🟢 | `admin_supply_mng.employee_email` 운영 타입 버그(`xid`) | ✅ **완료** — `300` 추출 시 `character varying`으로 정정 |
|
||||
|
||||
---
|
||||
|
||||
## 5. PR 묶음 스코프 (3 PR 시리즈)
|
||||
|
||||
### 5.1 PR-A : PART 등록·조회 묶음 (M1+M2)
|
||||
|
||||
**범위**:
|
||||
- backend: `routes/devPartRoutes.ts` + `services/devPartService.ts` + `controllers/devPartController.ts`
|
||||
- 엔드포인트: `/api/development/part-temp/list`·`/deploy`, `/api/development/part/list`·`/:objid`, `/api/development/part` (DELETE)
|
||||
- frontend:
|
||||
- `app/(main)/COMPANY_16/development/part-regist/page.tsx` (M1)
|
||||
- `app/(main)/COMPANY_16/development/part-search/page.tsx` (M2)
|
||||
- `components/development/PartFormDialog.tsx` (등록/수정 공용)
|
||||
- `components/development/PartDetailDialog.tsx` (상세)
|
||||
- `lib/api/devPart.ts`
|
||||
- 매퍼 1:1: `partMngTempGridList` · `partMngGridList` · `partMngFormPopUp` · `partMngDeploy` · `partMngDelete`
|
||||
|
||||
**제외**: 도면 다중 업로드 · ERP 업로드 · Excel Import → 별 PR
|
||||
|
||||
### 5.2 PR-B : E-BOM 등록·조회 묶음 (M3+M4)
|
||||
|
||||
**범위**:
|
||||
- backend: `routes/devBomRoutes.ts` + `services/devBomService.ts` + `controllers/devBomController.ts`
|
||||
- 엔드포인트: `/api/development/ebom/list`·`/status`·`/:objid` (DELETE), `/api/development/ebom/ascending`·`/descending`
|
||||
- frontend:
|
||||
- `app/(main)/COMPANY_16/development/ebom-regist/page.tsx` (M3)
|
||||
- `app/(main)/COMPANY_16/development/ebom-search/page.tsx` (M4)
|
||||
- `components/development/BomStandardFormDialog.tsx` (M3 등록)
|
||||
- `components/development/BomStatusChangeDialog.tsx` (M3 상태변경)
|
||||
- `lib/api/devBom.ts`
|
||||
- M4 동적 MAX_LEVEL 컬럼 처리 (DataGrid 동적 컬럼)
|
||||
|
||||
**제외**: BOM Excel Import · 정/역전개 엑셀 다운로드 → 별 PR
|
||||
|
||||
### 5.3 PR-C : 설계변경 리스트 (M5)
|
||||
|
||||
**범위**:
|
||||
- backend: `routes/devEoHistoryRoutes.ts` + `services/devEoHistoryService.ts` + `controllers/devEoHistoryController.ts`
|
||||
- 엔드포인트: `/api/development/eo/history/list` (read-only)
|
||||
- frontend:
|
||||
- `app/(main)/COMPANY_16/development/change-list/page.tsx`
|
||||
- `components/development/PartHisDetailDialog.tsx` (행 클릭 상세)
|
||||
- `lib/api/devEoHistory.ts`
|
||||
- read-only — INSERT/UPDATE/DELETE 없음
|
||||
|
||||
---
|
||||
|
||||
## 6. 사용자 결정 사항 (2026-05-12)
|
||||
|
||||
| # | 항목 | 결정 |
|
||||
|---|---|---|
|
||||
| 1 | 도메인 폴더 | 단일 `development/` |
|
||||
| 2 | 메뉴 진행 순서 | PART 묶음(M1+M2) → E-BOM 묶음(M3+M4) → 설계변경(M5) |
|
||||
| 3 | 문서 구조 | 단일 00-gap.md (본 문서) + 묶음별 *.md (총 3개) |
|
||||
| 4 | DDL 적용 | 운영DB → vexplor_rps 직접 적용 완료 (9 신규 + 1 ALTER) |
|
||||
|
||||
---
|
||||
|
||||
## 7. 다음 단계
|
||||
|
||||
1. **PR-A** : `01-part.md` 작성 → backend route → frontend page 2개 → verify
|
||||
2. **PR-B** : `02-ebom.md` 작성 → backend route → frontend page 2개 → verify
|
||||
3. **PR-C** : `03-eo-history.md` 작성 → backend route → frontend page → verify
|
||||
@@ -0,0 +1,313 @@
|
||||
# PR-A : PART 등록·조회 묶음 구현 명세
|
||||
|
||||
> 작성: 2026-05-12 / 범위: 개발관리 M1(PART 등록) + M2(PART 조회) — 같은 `part_mng` 테이블 R/W, 매퍼 공유.
|
||||
|
||||
---
|
||||
|
||||
## 1. 매퍼 쿼리 1:1 매핑
|
||||
|
||||
원본 `wace_plm/src/com/pms/mapper/partMng.xml`:
|
||||
|
||||
| Query id | Line | 본 PR 매핑 | 용도 |
|
||||
|---|---:|---|---|
|
||||
| `partMngBaseSimple` (sql) | 78 | (서비스 측 공통 SELECT fragment) | PART_MNG 메인 88+ 컬럼 SELECT |
|
||||
| `partMngTempGridList` | 2,354 | `GET /api/development/part-temp/list` | M1 그리드 (status != 'release') + ORDER_SPEC_MNG·ADMIN_SUPPLY_MNG JOIN |
|
||||
| `partMngGridList` | 1,903 | `GET /api/development/part/list` | M2 그리드 (status = 'release' 고정) |
|
||||
| `partMngInfo` | 2,699 | `GET /api/development/part/:objid` | 상세 단건 (편집 팝업 진입) |
|
||||
| `insertpartInfo` | 7,625 | `POST /api/development/part` | 신규 등록 (38 컬럼 INSERT) |
|
||||
| `updatePartDetail` | 2,711 | `PUT /api/development/part/:objid` | 상세 수정 (21 컬럼 UPDATE) |
|
||||
| `partMngDeploy` | 4,190 | `POST /api/development/part-temp/deploy` | 확정 (M1→M2) STATUS='release', EO_NO 채번 |
|
||||
| `partMngIsLastInit` | 4,230 | (deploy 트랜잭션 내부) | 동일 PART_NO 이전 IS_LAST='0' |
|
||||
| `insertPartMngHistory` | 4,244 | (deploy 트랜잭션 내부) | PART_MNG_HISTORY 이력 INSERT |
|
||||
| `partMngDelete` | 4,486 | `DELETE /api/development/part` (body: `objids: string[]`) | 다중 삭제 |
|
||||
|
||||
`partMngBaseSimple` SELECT 핵심: `PART_MNG P` + `COMM_CODE CC_UNIT`(UNIT) + `COMM_CODE CC_PART`(PART_TYPE) + `admin_supply_mng SUP`(SUPPLY_CODE) + LATERAL `BOM_PART_QTY`(LAST_PART_OBJID·status='deploy'·최신 1행) + LATERAL `COMM_CODE`(CHANGE_OPTION 다중 라벨) + `ATTACH_FILE_INFO`(3D/2D/PDF 파일 카운트). 23개 그리드 컬럼 + CODE_NAME 라벨 + Y/N flag CASE 변환 자체 처리.
|
||||
|
||||
---
|
||||
|
||||
## 2. API 엔드포인트 명세
|
||||
|
||||
### 2.1 M1 그리드 — `GET /api/development/part-temp/list`
|
||||
|
||||
**Query**:
|
||||
```
|
||||
search_part_no?: string
|
||||
search_part_name?: string
|
||||
search_material?: string
|
||||
search_spec?: string
|
||||
search_part_type?: string (PART_TYPE_CODE comm_code id)
|
||||
writer?: string
|
||||
status?: string // 단일: 'create'/'changing'/'editing'
|
||||
status_arr?: string[] // 다중 (둘 중 하나만 사용)
|
||||
product_code?: string
|
||||
upg_no?: string
|
||||
page?: number // 기본 1
|
||||
page_size?: number // 기본 20
|
||||
```
|
||||
|
||||
**SQL** (요약):
|
||||
```sql
|
||||
SELECT T.*, SORT (REVISION), O.PARTNER_TITLE, Q.OBJID/CHILD_OBJID/QTY/QTY_TEMP, Q_QTY (CASE),
|
||||
(SELECT PART_NO FROM PART_MNG SP WHERE SP.OBJID = Q.PARENT_PART_NO) PARENT_PART_INFO
|
||||
FROM <partMngBaseSimple> T
|
||||
LEFT JOIN (ORDER_SPEC_MNG OSM JOIN ADMIN_SUPPLY_MNG SUP) O ON T.OBJID::VARCHAR = O.PART_OBJID::VARCHAR
|
||||
LEFT JOIN BOM_PART_QTY Q ON (
|
||||
T.OBJID IN (SELECT DISTINCT PM1.OBJID FROM PART_MNG PM1, PART_MNG PM2
|
||||
WHERE PM1.STATUS='changing' AND PM2.STATUS!='changing'
|
||||
AND PM2.OBJID = Q.PART_NO AND PM1.PART_NO = PM2.PART_NO)
|
||||
AND Q.STATUS = 'beforeEdit'
|
||||
)
|
||||
WHERE 1=1 + 동적 (SEARCH_PART_NO/NAME/MATERIAL/SPEC/PART_TYPE, WRITER, STATUS, STATUS_ARR)
|
||||
ORDER BY PARENT_PART_INFO, T.PART_NO
|
||||
```
|
||||
|
||||
**Response**:
|
||||
```ts
|
||||
{
|
||||
rows: PartTempRow[]; // 그리드 23셀 + 추가 필드
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
}
|
||||
```
|
||||
|
||||
### 2.2 M2 그리드 — `GET /api/development/part/list`
|
||||
|
||||
**Query**: 위 + `search_year?` `search_hardness?` `search_method?` `search_surface?` `customer_objid?` `customer_cd?` `project_name?` `unit_code?` `search_design_date_from?` `search_design_date_to?` `is_last?` `eo?`
|
||||
|
||||
**SQL** (요약):
|
||||
```sql
|
||||
SELECT NUM (ROW_NUMBER), T.*,
|
||||
DECODE(PART_TYPE, '0000063', '1',
|
||||
(SELECT SUM(...) FROM BOM_PART_QTY Q WHERE Q.LAST_PART_OBJID=T.OBJID)::CHARACTER) BOM_QTY
|
||||
FROM <partMngBaseSimple> T
|
||||
WHERE 1=1 AND T.status='release' -- M1 vs M2 핵심 차이
|
||||
+ 동적 (M1 검색 필드 + 추가 5종)
|
||||
```
|
||||
|
||||
**Response**: `{ rows: PartRow[]; total, page, pageSize }`
|
||||
|
||||
### 2.3 단건 상세 — `GET /api/development/part/:objid`
|
||||
|
||||
```sql
|
||||
SELECT T.* FROM <partMngBaseSimple> T WHERE T.OBJID = #{OBJID}
|
||||
```
|
||||
|
||||
→ `PartRow` 단일 반환. 404 시 `{ error: 'not_found' }`.
|
||||
|
||||
### 2.4 신규 등록 — `POST /api/development/part`
|
||||
|
||||
**Body** (38 컬럼, 핵심):
|
||||
```ts
|
||||
{
|
||||
part_objid: string; // numeric, 클라이언트 채번 (nanoid-based) 또는 서버 채번
|
||||
part_no: string;
|
||||
part_name: string;
|
||||
unit?: string; // comm_code
|
||||
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; // comm_code (PART_TYPE_CODE)
|
||||
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; // comm_code 계정구분
|
||||
odrfg?: string; // 0=구매/1=생산/8=Phantom
|
||||
unit_dc?: string; unitmang_dc?: string;
|
||||
unitchng_nb?: string;
|
||||
lot_fg?: '0'|'1';
|
||||
use_yn?: '0'|'1';
|
||||
qc_fg?: '0'|'1';
|
||||
setitem_fg?: '0'|'1';
|
||||
req_fg?: '0'|'1';
|
||||
unit_length?: string;
|
||||
unit_qty?: string;
|
||||
}
|
||||
```
|
||||
|
||||
**SQL**: `insertpartInfo` (7,625) 그대로. `STATUS='create'`, `REG_DATE=now()`, `IS_LAST='1'`, `WRITER=#{CONNECTUSERID}` (서버에서 `req.user.user_id` 주입).
|
||||
|
||||
**채번 정책**: `part_mng.objid` 는 **`bigint`** 타입(다른 영업관리 테이블 `contract_mgmt.objid` 등은 varchar — `genObjid("CM")` 패턴 사용). bigint 컬럼은 prefix-string 못 쓰므로 **wace `CommonUtils.createObjId()` 1:1 구현** 사용:
|
||||
|
||||
```typescript
|
||||
// backend-node/src/utils/objidUtil.ts (신규)
|
||||
import { randomUUID } from 'crypto';
|
||||
|
||||
function javaStringHashCode(s: string): number {
|
||||
let h = 0;
|
||||
for (let i = 0; i < s.length; i++) h = (Math.imul(31, h) + s.charCodeAt(i)) | 0;
|
||||
return h;
|
||||
}
|
||||
|
||||
/** wace CommonUtils.createObjId() 1:1 — UUID v4 → 하이픈 제거(32 hex) → Java String.hashCode (int32) → String. 결과: -2,147,483,648 ~ 2,147,483,647. */
|
||||
export function createObjId(): string {
|
||||
return String(javaStringHashCode(randomUUID().replaceAll('-', '')));
|
||||
}
|
||||
```
|
||||
|
||||
INSERT 시 `body.part_objid` 가 비어 있으면 서버에서 `createObjId()` 호출(클라이언트 채번도 허용하되 권장 X).
|
||||
|
||||
### 2.5 상세 수정 — `PUT /api/development/part/:objid`
|
||||
|
||||
**Body** (21 컬럼, `updatePartDetail` 1:1):
|
||||
`part_name, material, heat_treatment_hardness, heat_treatment_method, surface_treatment, maker, part_type, acctfg, odrfg, spec, unit_dc, unitmang_dc, unitchng_nb, lot_fg, use_yn, qc_fg, setitem_fg, req_fg, unit_length, unit_qty, remark`
|
||||
|
||||
→ `EDIT_DATE = NOW()` 자동.
|
||||
|
||||
### 2.6 확정 — `POST /api/development/part-temp/deploy`
|
||||
|
||||
**Body**: `{ objids: string[] }` — 다중 선택 확정.
|
||||
|
||||
**트랜잭션 (각 objid에 대해 순차 처리)**:
|
||||
1. `partMngIsLastInit`: 같은 PART_NO 모든 행 `IS_LAST='0'`
|
||||
2. `insertPartMngHistory`: 현재 행을 `PART_MNG_HISTORY`로 복사 (이력 보존)
|
||||
3. `partMngDeploy`: 본 행 `IS_LAST='1'`, `STATUS='release'`, `DEPLOY_DATE=NOW()`, `REVISION=COALESCE(REVISION,'RE')`, `EO_DATE=...`, `EO_NO=` 채번 (IS_LONGD에 따라 `EOB{yy}-{seq}` or `EO{yy}-{seq}`)
|
||||
|
||||
**EO_NO 채번 SQL** (wace 운영판 그대로):
|
||||
```sql
|
||||
CASE WHEN P.IS_LONGD = '1' THEN
|
||||
'EOB' || TO_CHAR(NOW(),'yy') || '-' || LPAD(
|
||||
(SELECT COALESCE(SUBSTR(MAX(EO_NO),7,8)::INTEGER+1, 1)
|
||||
FROM PART_MNG SP
|
||||
WHERE SP.EO_NO LIKE 'EOB' || TO_CHAR(NOW(),'yy') || '-%'
|
||||
AND SP.PART_NO != P.PART_NO
|
||||
AND SP.REVISION != P.REVISION
|
||||
)||'', 4, '0')
|
||||
ELSE
|
||||
'EO' || TO_CHAR(NOW(),'yy') || '-' || LPAD(... 'EO{yy}-{seq}' ...)
|
||||
END
|
||||
```
|
||||
|
||||
**Response**: `{ deployed: number, eo_nos: Record<objid, eo_no> }`
|
||||
|
||||
### 2.7 다중 삭제 — `DELETE /api/development/part`
|
||||
|
||||
**Body**: `{ objids: string[] }`
|
||||
|
||||
**SQL** (wace 그대로 POSITION 트릭):
|
||||
```sql
|
||||
DELETE FROM PART_MNG WHERE POSITION(OBJID||',' IN #{checkArr}||',') > 0
|
||||
```
|
||||
|
||||
→ backend-node에서는 PostgreSQL 표준인 `WHERE OBJID = ANY($1::numeric[])` 로 정리(동일 효과 + 인덱스 활용 가능).
|
||||
|
||||
---
|
||||
|
||||
## 3. Backend 파일 구조
|
||||
|
||||
```
|
||||
backend-node/src/
|
||||
routes/
|
||||
devPartRoutes.ts // Express Router — 7 endpoint
|
||||
controllers/
|
||||
devPartController.ts // req/res 처리, validation
|
||||
services/
|
||||
devPartService.ts // SQL 실행 (pg 트랜잭션 처리 포함)
|
||||
devPartSqlFragments.ts // partMngBaseSimple SELECT fragment 재사용
|
||||
```
|
||||
|
||||
`app.ts`에 `app.use('/api/development', devPartRoutes)` 추가 (또는 메뉴 묶음 라우터 도입 시 그쪽).
|
||||
|
||||
---
|
||||
|
||||
## 4. Frontend 파일 구조
|
||||
|
||||
```
|
||||
frontend/
|
||||
app/(main)/COMPANY_16/development/
|
||||
part-regist/
|
||||
page.tsx // M1 그리드 + 상단 액션 + 페이징
|
||||
part-search/
|
||||
page.tsx // M2 그리드 + 상단 액션 + 페이징
|
||||
components/development/
|
||||
PartFormDialog.tsx // 신규/수정 통합 (mode prop)
|
||||
PartDetailDialog.tsx // 읽기 전용 상세
|
||||
lib/api/
|
||||
devPart.ts // 7 endpoint 호출 함수 + 타입
|
||||
```
|
||||
|
||||
### 4.1 그리드 23셀 (M1·M2 공통)
|
||||
|
||||
| key | 라벨 | 정렬 | 너비 |
|
||||
|---|---|---|---:|
|
||||
| part_no | 품번 | left | 140 |
|
||||
| part_name | 품명 | left | 220 |
|
||||
| cu01_cnt | 3D | right | 60 |
|
||||
| cu02_cnt | 2D | right | 60 |
|
||||
| cu03_cnt | PDF | right | 60 |
|
||||
| material | 재료 | left | 100 |
|
||||
| heat_treatment_hardness | 열처리경도 | left | 110 |
|
||||
| heat_treatment_method | 열처리방법 | left | 110 |
|
||||
| surface_treatment | 표면처리 | left | 100 |
|
||||
| maker | 메이커 | left | 100 |
|
||||
| part_type_title | 범주이름 | left | 100 |
|
||||
| spec | 규격 | left | 140 |
|
||||
| acctfg_nm | 계정구분 | center | 80 |
|
||||
| odrfg_nm | 조달구분 | center | 80 |
|
||||
| unit_dc_nm | 재고단위 | center | 80 |
|
||||
| unitmang_dc_nm | 관리단위 | center | 80 |
|
||||
| unitchng_nb | 환산수량 | right | 90 |
|
||||
| lot_fg_nm | LOT구분 | center | 80 |
|
||||
| use_yn_nm | 사용여부 | center | 80 |
|
||||
| qc_fg_nm | 검사여부 | center | 80 |
|
||||
| setitem_fg_nm | SET품여부 | center | 90 |
|
||||
| req_fg_nm | 의뢰여부 | center | 80 |
|
||||
| unit_length / unit_qty | 개당길이/수량 | right | 100 |
|
||||
|
||||
추가 (M1만): `partner_title`, `q_qty`, `parent_part_info`
|
||||
추가 (M2만): `bom_qty`
|
||||
|
||||
### 4.2 검색 폼
|
||||
|
||||
**M1 (PART 등록)** — 2 필드: SEARCH_PART_NO · SEARCH_PART_NAME (둘 다 PartSelect autocomplete)
|
||||
**M2 (PART 조회)** — 메인 조회 화면 (별도 검색 폼 없음, 그리드 헤더 inline 필터로 처리하거나 상단 간소화 검색바 1줄로 통합 — 본 PR 우선 `<Input>` 2개로 시작, 추후 보강)
|
||||
|
||||
### 4.3 액션 버튼 (각 page 상단)
|
||||
|
||||
**M1**: 등록 · 수정 · 삭제 · 확정 · 조회
|
||||
**M2**: 등록 · 수정 · 삭제 · 조회 (도면연동/ERP업로드/Excel은 본 PR 제외)
|
||||
|
||||
### 4.4 PartFormDialog (신규/수정 통합)
|
||||
|
||||
- mode: `'create' | 'edit'`
|
||||
- 38 필드 — `<Input>` + `<CommCodeSelect>` 조합
|
||||
- 검증: part_no/part_name 필수, comm_code 필드는 SmartSelect
|
||||
- 신규: POST → 신규 행 추가
|
||||
- 수정: PUT → 21 필드만 전송 (insertpartInfo는 38, updatePartDetail는 21 — wace 그대로)
|
||||
|
||||
### 4.5 PartDetailDialog (읽기 전용)
|
||||
|
||||
행 더블클릭 시 진입. 모든 필드 disabled. "수정" 버튼 → PartFormDialog(mode='edit') 전환.
|
||||
|
||||
---
|
||||
|
||||
## 5. 본 PR 제외 항목
|
||||
|
||||
| 항목 | 사유 / 후속 |
|
||||
|---|---|
|
||||
| 도면 다중 업로드 (M1) | `ATTACH_FILE_INFO` 다파일 업로드 — 별 PR |
|
||||
| ERP 업로드 (M2) | wace 외부 시스템 연동 — 별 PR |
|
||||
| Excel Upload (M1·M2) | `openPartExcelImportPopUp.jsp` 별도 — 별 PR |
|
||||
| BOM_PART_QTY R/W (M3 영역) | PR-B 에서 다룸 |
|
||||
| EO_NO 채번 분기 일부 (`IS_LONGD` flag) | 본 PR 포함 — 운영판 그대로 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 검증 시나리오 (verify.md 기준)
|
||||
|
||||
1. M1 페이지 진입 → 그리드 표시(status != 'release') 확인
|
||||
2. "등록" → PartFormDialog 신규 → POST → M1 그리드에 새 행
|
||||
3. M1 행 선택 → "확정" → POST deploy → STATUS='release', EO_NO 채번 확인
|
||||
4. M2 페이지 진입 → deploy된 행이 M2 그리드에 표시
|
||||
5. M2 행 선택 → "수정" → PartFormDialog 수정 → PUT
|
||||
6. M2 행 다중 선택 → "삭제" → DELETE → 그리드에서 제거
|
||||
7. 검색 (SEARCH_PART_NO/NAME) → 필터 적용 확인
|
||||
8. 운영DB 11133/waceplm 의 동일 SQL 결과와 vexplor_rps 결과 행 수 비교 (sanity)
|
||||
@@ -0,0 +1,428 @@
|
||||
-- ============================================================
|
||||
-- 개발관리(PART/E-BOM/설계변경) 운영 DDL — wace_plm 운영DB(211.115.91.141:11133/waceplm) 추출
|
||||
-- 추출일: 2026-05-12
|
||||
-- 추출 방법: information_schema + pg_indexes + pg_description 쿼리
|
||||
-- (pg_dump 14.19 ↔ PG 16.8 mismatch로 pg_dump 사용 불가)
|
||||
--
|
||||
-- 대상 테이블 9개 (운영 카운트):
|
||||
-- admin_supply_mng 28 cols / 7건 ← 공급업체 마스터(관리자)
|
||||
-- bom_part_qty 19 cols / 835건 ← BOM 수량 트리
|
||||
-- order_spec_mng 12 cols / 12,522건 ← 발주 스펙 이력
|
||||
-- part_bom_report 23 cols / 40건 ← BOM 리포트 헤더
|
||||
-- part_mng_history 59 cols / 263건 ← 파트 이력(설계변경)
|
||||
-- product_mgmt_upg_detail 7 cols / 87건 ← 제품 업그레이드 디테일
|
||||
-- product_mgmt_upg_master 5 cols / 6건 ← 제품 업그레이드 마스터
|
||||
-- sales_bom_report 16 cols / 1,529건 ← 영업 BOM 단가
|
||||
-- supply_mng 29 cols / 1건 ← 공급업체(고객)
|
||||
--
|
||||
-- 비고:
|
||||
-- · 운영 스키마 1:1 보존 — 컬럼 순서/타입/길이/default 모두 운영과 동일.
|
||||
-- · objid 컬럼은 wace Java 측에서 UUID/임의 채번(연관 시퀀스 없음 — 확인 완료).
|
||||
-- · admin_supply_mng.objid·supply_mng.objid는 numeric, default 0(운영 그대로).
|
||||
-- · admin_supply_mng.employee_email 운영 타입이 'xid'(PostgreSQL 시스템 타입, transaction id)
|
||||
-- → 데이터 의미(이메일)와 무관한 운영 측 추정 실수. character varying 으로 정정 적용.
|
||||
-- · part_mng_history.objid는 numeric NOT NULL (PK)이지만 default 미지정.
|
||||
-- · product_mgmt_upg_master PK는 (objid, target_objid) 복합키.
|
||||
-- · sales_bom_report 의 supply_objid*/price* 컬럼 length 가 들쭉날쭉한 부분은 운영 그대로.
|
||||
-- · sales_bom_report_parent_objid_idx 는 UNIQUE 인덱스(운영 정의 그대로 — 1 BOM당 1 단가).
|
||||
-- · company_code 분기 없음(vexplor_rps는 COMPANY_16 단독).
|
||||
-- ============================================================
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 1) admin_supply_mng (공급업체 마스터 — 관리자 측 입력)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS admin_supply_mng CASCADE;
|
||||
CREATE TABLE admin_supply_mng (
|
||||
objid numeric NOT NULL DEFAULT '0'::numeric,
|
||||
supply_code character varying(100) DEFAULT 'NULL::character varying'::character varying,
|
||||
supply_name character varying(100) DEFAULT 'NULL::character varying'::character varying,
|
||||
reg_no character varying(100) DEFAULT 'NULL::character varying'::character varying,
|
||||
supply_address character varying(500) DEFAULT 'NULL::character varying'::character varying,
|
||||
supply_busname character varying(100) DEFAULT 'NULL::character varying'::character varying,
|
||||
supply_stockname character varying(100) DEFAULT 'NULL::character varying'::character varying,
|
||||
supply_tel_no character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
supply_fax_no character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
charge_user_name character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
payment_method character varying,
|
||||
reg_id character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
reg_date timestamp,
|
||||
status character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
area_cd character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
bus_reg_no character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
office_no character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
email character varying DEFAULT 'NULL::character varying'::character varying,
|
||||
account_code character varying,
|
||||
remark character varying,
|
||||
account_bank character varying,
|
||||
account_number character varying,
|
||||
account_user_name character varying,
|
||||
employee_name character varying,
|
||||
employee_position character varying,
|
||||
employee_number character varying,
|
||||
-- 운영은 'xid' 시스템 타입으로 잘못 정의됨. 의미상 이메일 → character varying 으로 정정.
|
||||
employee_email character varying,
|
||||
david character varying(50),
|
||||
CONSTRAINT admin_supply_mng_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 2) bom_part_qty (BOM 수량 트리 — 835건)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS bom_part_qty CASCADE;
|
||||
CREATE TABLE bom_part_qty (
|
||||
bom_report_objid character varying(64) NOT NULL,
|
||||
objid character varying(64) NOT NULL,
|
||||
parent_objid character varying(64) DEFAULT 'NULL::character varying'::character varying,
|
||||
child_objid character varying(64) DEFAULT 'NULL::character varying'::character varying,
|
||||
parent_part_no character varying(64) DEFAULT 'NULL::character varying'::character varying,
|
||||
part_no character varying(64) DEFAULT 'NULL::character varying'::character varying,
|
||||
qty character varying,
|
||||
regdate timestamp,
|
||||
seq integer,
|
||||
status character varying,
|
||||
deploy_date character varying,
|
||||
deploy_user_id character varying,
|
||||
edit_date character varying,
|
||||
writer character varying,
|
||||
qty_temp character varying,
|
||||
last_part_objid character varying,
|
||||
editer character varying,
|
||||
item_qty character varying,
|
||||
supplier character varying,
|
||||
CONSTRAINT bom_part_qty_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
CREATE INDEX bom_part_qty_bom_report_objid2_idx ON bom_part_qty USING btree (bom_report_objid, last_part_objid, part_no);
|
||||
CREATE INDEX bom_part_qty_bom_report_objid_idx ON bom_part_qty USING btree (bom_report_objid);
|
||||
CREATE INDEX bom_part_qty_last_part_objid_idx ON bom_part_qty USING btree (last_part_objid);
|
||||
CREATE INDEX bom_part_qty_parent_objid_idx ON bom_part_qty USING btree (parent_objid);
|
||||
CREATE INDEX idx_bom_part_qty_part_no ON bom_part_qty USING btree (part_no) WHERE ((part_no IS NOT NULL) AND ((part_no)::text <> ''::text));
|
||||
|
||||
COMMENT ON COLUMN bom_part_qty.status IS '상태';
|
||||
COMMENT ON COLUMN bom_part_qty.deploy_date IS '배포일';
|
||||
COMMENT ON COLUMN bom_part_qty.deploy_user_id IS '배포자';
|
||||
COMMENT ON COLUMN bom_part_qty.edit_date IS '수정일';
|
||||
COMMENT ON COLUMN bom_part_qty.writer IS '등록자';
|
||||
COMMENT ON COLUMN bom_part_qty.qty_temp IS '수량(설변중)';
|
||||
COMMENT ON COLUMN bom_part_qty.last_part_objid IS '마지막 품번키';
|
||||
COMMENT ON COLUMN bom_part_qty.editer IS '수정자';
|
||||
COMMENT ON COLUMN bom_part_qty.item_qty IS '항목수량';
|
||||
COMMENT ON COLUMN bom_part_qty.supplier IS '공급업체';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 3) order_spec_mng (발주 스펙 이력 — 12,522건, 운영 최다)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS order_spec_mng CASCADE;
|
||||
CREATE TABLE order_spec_mng (
|
||||
objid character varying NOT NULL,
|
||||
seq character varying NOT NULL,
|
||||
part_objid character varying NOT NULL,
|
||||
partner_rank character varying,
|
||||
partner_objid character varying,
|
||||
partner_price character varying,
|
||||
partner_qty character varying,
|
||||
apply_date character varying,
|
||||
remark character varying,
|
||||
regdate timestamp,
|
||||
is_last character varying,
|
||||
writer character varying,
|
||||
CONSTRAINT order_spec_mng_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 4) part_bom_report (BOM 리포트 헤더 — 40건)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS part_bom_report CASCADE;
|
||||
CREATE TABLE part_bom_report (
|
||||
objid character varying NOT NULL DEFAULT ''::character varying,
|
||||
customer_objid character varying,
|
||||
contract_objid character varying,
|
||||
unit_code character varying,
|
||||
revision character varying,
|
||||
writer character varying(64),
|
||||
regdate timestamp,
|
||||
status character varying(64),
|
||||
deploy_date character varying(64),
|
||||
eo_no character varying(100),
|
||||
eo_date character varying(100),
|
||||
note character varying(2000),
|
||||
edit_date timestamp,
|
||||
editer character varying,
|
||||
unit_code_old character varying,
|
||||
multi_break_yn character varying,
|
||||
multi_yn character varying,
|
||||
multi_master_yn character varying,
|
||||
multi_master_objid character varying,
|
||||
product_cd character varying,
|
||||
part_no character varying,
|
||||
part_name character varying,
|
||||
version character varying,
|
||||
CONSTRAINT part_bom_report_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
CREATE INDEX idx_part_bom_report_customer ON part_bom_report USING btree (customer_objid) WHERE ((customer_objid IS NOT NULL) AND ((customer_objid)::text <> ''::text));
|
||||
CREATE INDEX idx_part_bom_report_regdate ON part_bom_report USING btree (regdate DESC);
|
||||
CREATE INDEX idx_part_bom_report_writer ON part_bom_report USING btree (writer);
|
||||
CREATE INDEX part_bom_report_contract_objid_idx ON part_bom_report USING btree (contract_objid);
|
||||
CREATE INDEX part_bom_report_unit_code_idx ON part_bom_report USING btree (unit_code, contract_objid);
|
||||
|
||||
COMMENT ON COLUMN part_bom_report.objid IS 'OBJECT ID';
|
||||
COMMENT ON COLUMN part_bom_report.customer_objid IS '고객사 OBJID';
|
||||
COMMENT ON COLUMN part_bom_report.contract_objid IS '계약objid';
|
||||
COMMENT ON COLUMN part_bom_report.unit_code IS 'unit';
|
||||
COMMENT ON COLUMN part_bom_report.revision IS 'rev';
|
||||
COMMENT ON COLUMN part_bom_report.writer IS '작성자';
|
||||
COMMENT ON COLUMN part_bom_report.regdate IS '등록일';
|
||||
COMMENT ON COLUMN part_bom_report.status IS '상태';
|
||||
COMMENT ON COLUMN part_bom_report.deploy_date IS '배포일';
|
||||
COMMENT ON COLUMN part_bom_report.edit_date IS '수정일';
|
||||
COMMENT ON COLUMN part_bom_report.editer IS '수정자';
|
||||
COMMENT ON COLUMN part_bom_report.unit_code_old IS 'UNIT_CODE';
|
||||
COMMENT ON COLUMN part_bom_report.multi_break_yn IS '동시적용프로젝트 깨짐 여부';
|
||||
COMMENT ON COLUMN part_bom_report.multi_yn IS '동시적용프로젝트 여부';
|
||||
COMMENT ON COLUMN part_bom_report.multi_master_yn IS '동시적용프로젝트 마스터 여부';
|
||||
COMMENT ON COLUMN part_bom_report.multi_master_objid IS '동시적용프로젝트 마스터 키';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 5) part_mng_history (파트 이력 — 설계변경 핵심, 59 cols / 263건)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS part_mng_history CASCADE;
|
||||
CREATE TABLE part_mng_history (
|
||||
objid numeric NOT NULL,
|
||||
product_mgmt_objid character varying(100) DEFAULT NULL::character varying,
|
||||
upg_no character varying(100) DEFAULT NULL::character varying,
|
||||
part_no character varying(100) DEFAULT NULL::character varying,
|
||||
part_name character varying(100) DEFAULT NULL::character varying,
|
||||
unit character varying(50) DEFAULT NULL::character varying,
|
||||
qty character varying(50) DEFAULT NULL::character varying,
|
||||
spec character varying(100) DEFAULT 'NULL::character varying'::character varying,
|
||||
material character varying(100) DEFAULT NULL::character varying,
|
||||
weight character varying(50) DEFAULT NULL::character varying,
|
||||
part_type character varying(100) DEFAULT NULL::character varying,
|
||||
remark character varying(1000) DEFAULT NULL::character varying,
|
||||
es_spec character varying(100) DEFAULT NULL::character varying,
|
||||
ms_spec character varying(100) DEFAULT NULL::character varying,
|
||||
change_option character varying(50) DEFAULT NULL::character varying,
|
||||
design_apply_point character varying(50) DEFAULT NULL::character varying,
|
||||
management_flag character varying(50) DEFAULT NULL::character varying,
|
||||
revision character varying(50) DEFAULT NULL::character varying,
|
||||
status character varying(30) DEFAULT NULL::character varying,
|
||||
reg_date timestamp,
|
||||
edit_date timestamp,
|
||||
writer character varying(30) DEFAULT NULL::character varying,
|
||||
is_last character varying(5) DEFAULT NULL::character varying,
|
||||
eo_no character varying,
|
||||
eo_temp character varying,
|
||||
excel_upload_seq character varying,
|
||||
sourcing_code character varying,
|
||||
sub_material character varying(100) DEFAULT 'NULL::character varying'::character varying,
|
||||
parent_part_no character varying,
|
||||
design_date character varying,
|
||||
eo_date character varying,
|
||||
deploy_date timestamp,
|
||||
thickness character varying,
|
||||
width character varying,
|
||||
height character varying,
|
||||
out_diameter character varying,
|
||||
in_diameter character varying,
|
||||
length character varying,
|
||||
supply_code character varying,
|
||||
change_type character varying,
|
||||
contract_objid character varying,
|
||||
maker character varying,
|
||||
qty_temp character varying,
|
||||
bom_report_objid character varying,
|
||||
parent_part_objid character varying,
|
||||
parent_qty_child_objid character varying,
|
||||
bom_qty_status character varying,
|
||||
his_reg_date timestamp,
|
||||
his_writer character varying,
|
||||
his_status character varying,
|
||||
qty_child_objid character varying,
|
||||
bom_status character varying,
|
||||
bom_deploy_date timestamp,
|
||||
chg_part_objid character varying,
|
||||
chg_part_no character varying,
|
||||
chg_part_rev character varying,
|
||||
heat_treatment_hardness character varying,
|
||||
heat_treatment_method character varying,
|
||||
surface_treatment character varying,
|
||||
CONSTRAINT part_mng_history_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN part_mng_history.qty_temp IS '수량(설변중)';
|
||||
COMMENT ON COLUMN part_mng_history.bom_report_objid IS 'BOM 키';
|
||||
COMMENT ON COLUMN part_mng_history.parent_part_objid IS '부모 파트 키';
|
||||
COMMENT ON COLUMN part_mng_history.parent_qty_child_objid IS '부모 구조 키';
|
||||
COMMENT ON COLUMN part_mng_history.bom_qty_status IS 'BOM 상태';
|
||||
COMMENT ON COLUMN part_mng_history.his_reg_date IS '등록일';
|
||||
COMMENT ON COLUMN part_mng_history.his_writer IS '등록자';
|
||||
COMMENT ON COLUMN part_mng_history.his_status IS '상태';
|
||||
COMMENT ON COLUMN part_mng_history.qty_child_objid IS '구조 키';
|
||||
COMMENT ON COLUMN part_mng_history.bom_status IS 'BOM 상태';
|
||||
COMMENT ON COLUMN part_mng_history.bom_deploy_date IS '배포일';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 6) product_mgmt_upg_detail (제품 업그레이드 디테일 — 87건)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS product_mgmt_upg_detail CASCADE;
|
||||
CREATE TABLE product_mgmt_upg_detail (
|
||||
objid integer NOT NULL,
|
||||
target_objid integer,
|
||||
upg_name character varying(100),
|
||||
upg_code character varying(100),
|
||||
vc character varying(100),
|
||||
note character varying(1000),
|
||||
product_objid integer,
|
||||
CONSTRAINT product_mgmt_upg_detail_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN product_mgmt_upg_detail.objid IS 'objid';
|
||||
COMMENT ON COLUMN product_mgmt_upg_detail.target_objid IS 'upg_masterobjid';
|
||||
COMMENT ON COLUMN product_mgmt_upg_detail.upg_name IS 'upg명';
|
||||
COMMENT ON COLUMN product_mgmt_upg_detail.upg_code IS 'upg코드';
|
||||
COMMENT ON COLUMN product_mgmt_upg_detail.vc IS 'vc';
|
||||
COMMENT ON COLUMN product_mgmt_upg_detail.note IS '비고';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 7) product_mgmt_upg_master (제품 업그레이드 마스터 — 6건, 복합 PK)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS product_mgmt_upg_master CASCADE;
|
||||
CREATE TABLE product_mgmt_upg_master (
|
||||
objid integer NOT NULL,
|
||||
target_objid integer NOT NULL,
|
||||
spec_name character varying NOT NULL,
|
||||
writer character varying,
|
||||
regdate timestamp,
|
||||
CONSTRAINT product_mgmt_upg_master_pkey PRIMARY KEY (objid, target_objid)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN product_mgmt_upg_master.objid IS '제품사양마스터코드';
|
||||
COMMENT ON COLUMN product_mgmt_upg_master.target_objid IS '양산마스터코드';
|
||||
COMMENT ON COLUMN product_mgmt_upg_master.spec_name IS '사양명';
|
||||
COMMENT ON COLUMN product_mgmt_upg_master.writer IS '작성자';
|
||||
COMMENT ON COLUMN product_mgmt_upg_master.regdate IS '동록일';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 8) sales_bom_report (영업 BOM 단가 — 1,529건)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS sales_bom_report CASCADE;
|
||||
CREATE TABLE sales_bom_report (
|
||||
objid character varying NOT NULL DEFAULT ''::character varying,
|
||||
parent_objid character varying,
|
||||
supply_objid character varying,
|
||||
price character varying,
|
||||
supply_objid1 character varying,
|
||||
price1 character varying(64),
|
||||
supply_objid2 character varying(100),
|
||||
price2 character varying(64),
|
||||
supply_objid3 character varying(64),
|
||||
price3 character varying(100),
|
||||
supply_objid4 character varying(100),
|
||||
price4 character varying(2000),
|
||||
writer character varying,
|
||||
regdate timestamp,
|
||||
update_date timestamp,
|
||||
modifier character varying,
|
||||
CONSTRAINT sales_bom_report_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
-- 운영 인덱스는 UNIQUE — 1 BOM(parent_objid) 당 1 단가행
|
||||
CREATE UNIQUE INDEX sales_bom_report_parent_objid_idx ON sales_bom_report USING btree (parent_objid);
|
||||
|
||||
COMMENT ON COLUMN sales_bom_report.objid IS '키';
|
||||
COMMENT ON COLUMN sales_bom_report.parent_objid IS 'bom_report_objid';
|
||||
COMMENT ON COLUMN sales_bom_report.supply_objid IS '공급업체key';
|
||||
COMMENT ON COLUMN sales_bom_report.price IS '단가';
|
||||
COMMENT ON COLUMN sales_bom_report.supply_objid1 IS '레이져업체명';
|
||||
COMMENT ON COLUMN sales_bom_report.price1 IS '단가';
|
||||
COMMENT ON COLUMN sales_bom_report.supply_objid2 IS '용접업체명';
|
||||
COMMENT ON COLUMN sales_bom_report.price2 IS '단가';
|
||||
COMMENT ON COLUMN sales_bom_report.supply_objid3 IS '가공업체명';
|
||||
COMMENT ON COLUMN sales_bom_report.price3 IS '단가';
|
||||
COMMENT ON COLUMN sales_bom_report.supply_objid4 IS '후처리';
|
||||
COMMENT ON COLUMN sales_bom_report.price4 IS '단가';
|
||||
COMMENT ON COLUMN sales_bom_report.writer IS '담당자';
|
||||
COMMENT ON COLUMN sales_bom_report.regdate IS '작성일';
|
||||
COMMENT ON COLUMN sales_bom_report.update_date IS '수정일';
|
||||
COMMENT ON COLUMN sales_bom_report.modifier IS '수정자';
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- 9) supply_mng (공급업체/고객 — 1건)
|
||||
-- ------------------------------------------------------------
|
||||
DROP TABLE IF EXISTS supply_mng CASCADE;
|
||||
CREATE TABLE supply_mng (
|
||||
objid numeric NOT NULL DEFAULT 0,
|
||||
supply_code character varying(100) DEFAULT NULL::character varying,
|
||||
supply_name character varying(100) DEFAULT NULL::character varying,
|
||||
reg_no character varying(100) DEFAULT NULL::character varying,
|
||||
supply_address character varying(500) DEFAULT NULL::character varying,
|
||||
supply_busname character varying(100) DEFAULT NULL::character varying,
|
||||
supply_stockname character varying(100) DEFAULT NULL::character varying,
|
||||
supply_tel_no character varying(30) DEFAULT NULL::character varying,
|
||||
supply_fax_no character varying(30) DEFAULT NULL::character varying,
|
||||
charge_user_name character varying(100) DEFAULT NULL::character varying,
|
||||
payment_method character varying(100),
|
||||
reg_id character varying(100) DEFAULT NULL::character varying,
|
||||
reg_date timestamp,
|
||||
status character varying(32) DEFAULT NULL::character varying,
|
||||
area_cd character varying(32) DEFAULT NULL::character varying,
|
||||
bus_reg_no character varying(100) DEFAULT NULL::character varying,
|
||||
office_no character varying(32) DEFAULT 'NULL::character varying'::character varying,
|
||||
email character varying(32) DEFAULT 'NULL::character varying'::character varying,
|
||||
cus_no character varying,
|
||||
manager1_name character varying(100),
|
||||
manager1_email character varying(100),
|
||||
manager2_name character varying(100),
|
||||
manager2_email character varying(100),
|
||||
manager3_name character varying(100),
|
||||
manager3_email character varying(100),
|
||||
manager4_name character varying(100),
|
||||
manager4_email character varying(100),
|
||||
manager5_name character varying(100),
|
||||
manager5_email character varying(100),
|
||||
CONSTRAINT supply_mng_pkey PRIMARY KEY (objid)
|
||||
);
|
||||
|
||||
COMMENT ON COLUMN supply_mng.supply_code IS '구분';
|
||||
COMMENT ON COLUMN supply_mng.supply_name IS '고객명';
|
||||
COMMENT ON COLUMN supply_mng.reg_no IS '법인/주민번호';
|
||||
COMMENT ON COLUMN supply_mng.supply_address IS '주소';
|
||||
COMMENT ON COLUMN supply_mng.supply_busname IS '업태';
|
||||
COMMENT ON COLUMN supply_mng.supply_stockname IS '업종';
|
||||
COMMENT ON COLUMN supply_mng.supply_tel_no IS '핸드폰';
|
||||
COMMENT ON COLUMN supply_mng.supply_fax_no IS '팩스번호';
|
||||
COMMENT ON COLUMN supply_mng.charge_user_name IS '대표자명';
|
||||
COMMENT ON COLUMN supply_mng.reg_id IS '실사용자명';
|
||||
COMMENT ON COLUMN supply_mng.reg_date IS '등록일';
|
||||
COMMENT ON COLUMN supply_mng.status IS '상태';
|
||||
COMMENT ON COLUMN supply_mng.area_cd IS '지역';
|
||||
COMMENT ON COLUMN supply_mng.bus_reg_no IS '사업자등록번호';
|
||||
COMMENT ON COLUMN supply_mng.office_no IS '오피스no';
|
||||
COMMENT ON COLUMN supply_mng.email IS '이메일';
|
||||
COMMENT ON COLUMN supply_mng.cus_no IS '고객번호';
|
||||
COMMENT ON COLUMN supply_mng.manager1_name IS '담당자1 이름';
|
||||
COMMENT ON COLUMN supply_mng.manager1_email IS '담당자1 이메일';
|
||||
COMMENT ON COLUMN supply_mng.manager2_name IS '담당자2 이름';
|
||||
COMMENT ON COLUMN supply_mng.manager2_email IS '담당자2 이메일';
|
||||
COMMENT ON COLUMN supply_mng.manager3_name IS '담당자3 이름';
|
||||
COMMENT ON COLUMN supply_mng.manager3_email IS '담당자3 이메일';
|
||||
COMMENT ON COLUMN supply_mng.manager4_name IS '담당자4 이름';
|
||||
COMMENT ON COLUMN supply_mng.manager4_email IS '담당자4 이메일';
|
||||
COMMENT ON COLUMN supply_mng.manager5_name IS '담당자5 이름';
|
||||
COMMENT ON COLUMN supply_mng.manager5_email IS '담당자5 이메일';
|
||||
|
||||
COMMIT;
|
||||
|
||||
-- ============================================================
|
||||
-- vexplor_rps 적용 방법 (메인 agent 검토 후 직접 실행):
|
||||
-- PGPASSWORD='vexplor0909!!' psql -h 211.115.91.141 -p 11134 -U postgres -d vexplor_rps \
|
||||
-- -f /Users/jhj/vexplor_rps/docs/migration/development/ddl-extracted/300_part_bom.sql
|
||||
--
|
||||
-- 적용 후 검증:
|
||||
-- PGPASSWORD='vexplor0909!!' psql -h 211.115.91.141 -p 11134 -U postgres -d vexplor_rps -c "
|
||||
-- SELECT relname, (SELECT count(*) FROM pg_attribute WHERE attrelid = c.oid AND attnum > 0 AND NOT attisdropped) AS cols
|
||||
-- FROM pg_class c WHERE relkind='r' AND relnamespace=(SELECT oid FROM pg_namespace WHERE nspname='public')
|
||||
-- AND relname IN ('admin_supply_mng','bom_part_qty','order_spec_mng','part_bom_report','part_mng_history','product_mgmt_upg_detail','product_mgmt_upg_master','sales_bom_report','supply_mng')
|
||||
-- ORDER BY relname;"
|
||||
-- 기대값: 28 / 19 / 12 / 23 / 59 / 7 / 5 / 16 / 29
|
||||
-- ============================================================
|
||||
@@ -0,0 +1,45 @@
|
||||
-- ============================================================
|
||||
-- part_mng ALTER — 개발관리 메뉴(PART 등록/조회) 누락 컬럼 추가
|
||||
-- 추출일: 2026-05-12
|
||||
-- 출처: 211.115.91.141:11133/waceplm (PG 16.8)
|
||||
-- 대상: 211.115.91.141:11134/vexplor_rps
|
||||
--
|
||||
-- 사유: wace PART 등록/조회 그리드 23개 컬럼 중 15개가 vexplor part_mng 에 부재.
|
||||
-- 전부 ADD COLUMN IF NOT EXISTS 로 안전하게 추가 (IDEMPOTENT).
|
||||
-- ============================================================
|
||||
|
||||
BEGIN;
|
||||
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS heat_treatment_hardness character varying;
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS heat_treatment_method character varying;
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS surface_treatment character varying;
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS acctfg character varying;
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS odrfg character varying;
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS unit_dc character varying(20);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS unitmang_dc character varying(20);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS unitchng_nb numeric(11,6);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS lot_fg character(1);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS use_yn character(1);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS qc_fg character(1);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS setitem_fg character(1);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS req_fg character(1);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS unit_length character varying(20);
|
||||
ALTER TABLE part_mng ADD COLUMN IF NOT EXISTS unit_qty character varying(20);
|
||||
|
||||
COMMENT ON COLUMN part_mng.heat_treatment_hardness IS '열처리경도';
|
||||
COMMENT ON COLUMN part_mng.heat_treatment_method IS '열처리방법';
|
||||
COMMENT ON COLUMN part_mng.surface_treatment IS '표면처리';
|
||||
COMMENT ON COLUMN part_mng.acctfg IS '계정구분 (comm_code)';
|
||||
COMMENT ON COLUMN part_mng.odrfg IS '조달구분 (comm_code)';
|
||||
COMMENT ON COLUMN part_mng.unit_dc IS '재고단위 (comm_code)';
|
||||
COMMENT ON COLUMN part_mng.unitmang_dc IS '관리단위 (comm_code)';
|
||||
COMMENT ON COLUMN part_mng.unitchng_nb IS '환산수량';
|
||||
COMMENT ON COLUMN part_mng.lot_fg IS 'LOT구분 (Y/N)';
|
||||
COMMENT ON COLUMN part_mng.use_yn IS '사용여부 (Y/N)';
|
||||
COMMENT ON COLUMN part_mng.qc_fg IS '검사여부 (Y/N)';
|
||||
COMMENT ON COLUMN part_mng.setitem_fg IS 'SET품여부 (Y/N)';
|
||||
COMMENT ON COLUMN part_mng.req_fg IS '의뢰여부 (Y/N)';
|
||||
COMMENT ON COLUMN part_mng.unit_length IS '개당길이';
|
||||
COMMENT ON COLUMN part_mng.unit_qty IS '개당수량';
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user