[RAPID] PCC: 수주복사 기능 (OCP)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 15:51:15 +09:00
parent 0772fb8642
commit fefba10438
3 changed files with 207 additions and 0 deletions

View File

@@ -0,0 +1,115 @@
---
title: 수주복사 기능 계획서
type: Plan (계획서)
feature: OCP (Order Copy)
date: 2026-03-26
---
# 수주복사 기능 계획서
## 개요
영업관리 > 주문서관리 페이지에 **수주복사** 버튼을 추가하여, 기존 수주 데이터를 복사하여 새로운 수주를 빠르게 등록할 수 있는 기능.
## 현재 동작
- 주문서관리 리스트 상단 버튼: 조회 → 수주입력 → 수주확정 → 수주취소 → 결재상신
- 수주 등록은 수주입력 버튼으로만 가능 (신규 입력 또는 선택 건 수정)
- 동일 수주건이 수량만 변경되어 반복 들어오는 경우, 매번 처음부터 입력해야 함
## 변경 후 동작
1. 조회 ↔ 수주입력 사이에 **수주복사** 버튼 추가
2. 리스트에서 1건 체크 → 수주복사 클릭
- 미선택: "복사할 행을 선택해주십시오" 경고
- 2건 이상: "한번에 한개의 수주만 복사 가능합니다" 경고
3. 복사 실행:
- 영업번호: 현재 연도 prefix 기준 MAX+1 (예: 26C-0712 → 26C-0713)
- 수주상태(CONTRACT_RESULT): 빈값으로 초기화
- 나머지 기본정보: 원본 그대로 복사
- 품목정보(CONTRACT_ITEM): 전체 복사 (수량, 단가, 금액 등)
- S/N 정보(CONTRACT_ITEM_SERIAL): 전체 복사
4. 복사 완료 후 리스트 자동 새로고침
5. 복사된 건은 신규이므로 수주입력 팝업에서 품목 삭제 아이콘 활성화
## 시각적 예시
```
버튼 영역 (변경 전):
[조회] [수주입력] [수주확정] [수주취소] [결재상신]
버튼 영역 (변경 후):
[조회] [수주복사] [수주입력] [수주확정] [수주취소] [결재상신]
```
## 아키텍처
```mermaid
sequenceDiagram
participant U as 사용자
participant JSP as orderMgmtList.jsp
participant C as ContractMgmtController
participant S as ContractMgmtService
participant DB as PostgreSQL
U->>JSP: 1건 선택 후 수주복사 클릭
JSP->>C: POST /contractMgmt/copyEstimateAndOrderInfo.do (sourceObjId)
C->>S: copyEstimateAndOrderInfo(request, paramMap)
S->>DB: SELECT MAX(CONTRACT_NO) → 새 영업번호 채번
S->>DB: INSERT CONTRACT_MGMT (복사, 수주상태 빈값)
S->>DB: INSERT CONTRACT_ITEM (품목 전체 복사)
S->>DB: INSERT CONTRACT_ITEM_SERIAL (S/N 전체 복사)
S-->>C: SUCCESS
C-->>JSP: "SUCCESS"
JSP->>U: 리스트 새로고침
```
## 변경 대상 파일
| 파일 | 변경 내용 |
|------|-----------|
| `WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp` | 수주복사 버튼 + fn_copy() JS 함수 |
| `src/com/pms/salesmgmt/controller/ContractMgmtController.java` | copyEstimateAndOrderInfo.do 엔드포인트 |
| `src/com/pms/salesmgmt/service/ContractMgmtService.java` | copyEstimateAndOrderInfo() 메서드 |
| `src/com/pms/salesmgmt/mapper/contractMgmt.xml` | 복사 관련 SQL 3종 |
## 코드 설계
### Mapper SQL
```sql
-- 1. 새 영업번호 채번
SELECT TO_CHAR(NOW(),'yy') || 'C-' || LPAD((
COALESCE(MAX(SUBSTRING(CONTRACT_NO FROM 5)::integer), 0) + 1
)::VARCHAR, 4, '0')
FROM CONTRACT_MGMT
WHERE CONTRACT_NO LIKE TO_CHAR(NOW(),'yy') || 'C-%'
-- 2. CONTRACT_MGMT 복사 (CONTRACT_RESULT 빈값)
INSERT INTO CONTRACT_MGMT (...) SELECT OBJID, CONTRACT_NO, '', ... FROM CONTRACT_MGMT WHERE OBJID =
-- 3. CONTRACT_ITEM 복사 (새 OBJID, SEQ 유지)
-- 4. CONTRACT_ITEM_SERIAL 복사 (새 ITEM_OBJID 매핑)
```
### Service 로직
1. 새 OBJID 생성 (CommonUtils.createObjId())
2. 영업번호 채번 쿼리 실행
3. CONTRACT_MGMT INSERT...SELECT
4. 원본 품목 목록 조회 → 각 품목마다 새 OBJID 생성하여 INSERT
5. 각 품목의 S/N 데이터 복사
6. sqlSession.commit()
## 예상 문제 및 대응
| 문제 | 원인 | 대응 방안 |
|------|------|-----------|
| 영업번호 중복 | 동시 복사 시 MAX+1 충돌 | CONTRACT_NO에 UNIQUE 제약이 없으므로 낮은 확률. 필요시 재시도 로직 |
| S/N 누락 | CONTRACT_ITEM_SERIAL 복사 누락 | 품목 단위 루프에서 S/N까지 함께 복사 |
## 설계 원칙
- 기존 saveEstimateAndOrderInfo 패턴 준수
- INSERT...SELECT로 DB 레벨 복사 (네트워크 왕복 최소화)
- 복사 건은 IS_DIRECT_ORDER = 'Y' 유지 (통합등록 팝업 사용)

View File

@@ -0,0 +1,51 @@
---
title: 수주복사 기능 맥락노트
type: Context Note (맥락노트)
feature: OCP (Order Copy)
date: 2026-03-26
---
# 수주복사 기능 맥락노트
## 왜 이 작업을 하는가
동일 수주건이 수량만 변경되어 반복 들어오는 경우가 많아, 기존 수주 데이터를 복사하여 수량만 수정 후 등록할 수 있는 기능이 필요. 매번 처음부터 입력하는 비효율을 제거.
## 핵심 결정 사항과 근거
### 결정 1: 영업번호 채번 방식 — MAX+1
- **결정:** 시퀀스(contract_mgmt_seq) 대신 현재 MAX CONTRACT_NO에서 +1
- **근거:** 사용자 요청. 시퀀스는 gap이 발생할 수 있으나 MAX+1은 연속 번호 보장
- **대안 (미채택):** contract_mgmt_seq 시퀀스 사용 — 기존 saveEstimateAndOrderInfo에서 사용하는 방식이나, 사용자가 MAX+1 명시
### 결정 2: 수주상태만 빈값, 나머지 전체 복사
- **결정:** CONTRACT_RESULT만 빈값으로 초기화, 나머지 모든 컬럼(기본정보+품목+S/N) 그대로 복사
- **근거:** 사용자 요구사항 — "수주상태만 빈값으로 나머지 데이터는 똑같이 복사"
### 결정 3: 서버 사이드 복사 (INSERT...SELECT)
- **결정:** JS에서 데이터를 읽어서 재전송하는 대신, 서버에서 DB 레벨 복사
- **근거:** 네트워크 왕복 최소화, 데이터 정합성 보장, 품목+S/N 데이터량이 많을 수 있음
### 결정 4: 삭제 아이콘 별도 처리 불필요
- **결정:** estimateAndOrderRegistFormPopup.jsp 수정 안함
- **근거:** 삭제 아이콘은 기본 활성화 상태이고, hasProject=true일 때만 비활성화됨. 복사된 건은 신규(프로젝트 없음)이므로 자동으로 활성화
## 관련 파일 위치
- 리스트 JSP: `WebContent/WEB-INF/view/contractMgmt/orderMgmtList.jsp`
- 팝업 JSP: `WebContent/WEB-INF/view/contractMgmt/estimateAndOrderRegistFormPopup.jsp`
- Controller: `src/com/pms/salesmgmt/controller/ContractMgmtController.java`
- Service: `src/com/pms/salesmgmt/service/ContractMgmtService.java`
- Mapper: `src/com/pms/salesmgmt/mapper/contractMgmt.xml`
## 기술 참고
- 영업번호 형식: `{YY}C-{NNNN}` (예: 26C-0713)
- 기존 채번: `contract_mgmt_seq` 시퀀스 (saveEstimateAndOrderInfo 쿼리 line 5075)
- 품목 테이블: CONTRACT_ITEM (STATUS='ACTIVE'인 것만 복사)
- S/N 테이블: CONTRACT_ITEM_SERIAL (STATUS='ACTIVE'인 것만 복사)
- 품목 삭제 아이콘: `fn_deleteItemRow()` — hasProject 체크 후 활성/비활성 (line 1194-1205)

View File

@@ -0,0 +1,41 @@
---
title: 수주복사 기능 체크리스트
type: Checklist (체크리스트)
feature: OCP (Order Copy)
date: 2026-03-26
---
# 수주복사 기능 체크리스트
## 공정 상태: 0%
## 구현 체크리스트
- [ ] Mapper XML: copyContractMgmt 쿼리 (MAX+1 채번 + INSERT...SELECT)
- [ ] Mapper XML: copyContractItems 쿼리 (품목 복사)
- [ ] Mapper XML: copyContractItemSerials 쿼리 (S/N 복사)
- [ ] Service: copyEstimateAndOrderInfo() 메서드
- [ ] Controller: copyEstimateAndOrderInfo.do 엔드포인트
- [ ] JSP: 수주복사 버튼 추가 (조회 ↔ 수주입력 사이)
- [ ] JSP: fn_copy() 함수 (단일선택 검증 + AJAX 호출)
## 검증 체크리스트
- [ ] 미선택 시 경고 메시지 표시
- [ ] 2건 이상 선택 시 경고 메시지 표시
- [ ] 1건 선택 후 복사 → 새 영업번호(MAX+1)로 리스트에 등록
- [ ] 복사된 건의 수주상태가 빈값인지 확인
- [ ] 복사된 건의 품목정보가 원본과 동일한지 확인
- [ ] 복사된 건의 S/N 정보가 원본과 동일한지 확인
- [ ] 복사된 건 선택 → 수주입력 팝업에서 삭제 아이콘 활성화 확인
## 정리
- [ ] 코드 컴파일 확인
- [ ] 불필요한 디버그 로그 제거
## 변경 이력
| 날짜 | 내용 |
|------|------|
| 2026-03-26 | 최초 작성 |