Files
wace_rps/docs/migration/sales/00-gap.md
T
hjjeong b7a6816ef2 영업관리 GAP 분석 문서 신설 + README 다음 작업 갱신
00-gap.md: wace_plm 원본 흐름 vs vexplor_rps 이식본 GAP 매트릭스. 다음 PR 우선순위(A: 수주확정→프로젝트 자동생성, B: 직접등록 통합폼, C: 결재·메일·PDF) 합의 문서.
README.md: §7 다음 작업 항목을 완료 처리하고 00-gap.md 우선 합의로 재정렬.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-08 14:48:24 +09:00

11 KiB
Raw Blame History

영업관리 이식 GAP 분석 (원본 wace_plm 대비)

작성: 2026-05-08 / 작성자: hjjeong 목적: vexplor_rps에 이식된 영업관리 4개 메뉴가 wace_plm 원본 흐름과 어디서 어긋나는지 정리하고, 다음 PR 우선순위를 합의하기 위한 단일 문서. 참고: 01-estimate.md, 02-order.md, feedback_wace_jsp_columns

0. 한 문장 요약

견적/주문 list와 SQL은 잘 이식됐지만 상태 전이 트리거(수주확정 → 프로젝트 자동생성)와 직접등록 통합폼, 결재 자동판정, PDF·SMTP 실작업이 통째로 빠져 있어, 사용자가 영업 흐름을 끝까지 돌릴 수 없는 상태.

0.1 이식 원칙 (모든 GAP 작업 공통)

JSP/Java/매퍼XML 안의 주석 블록(/* */, <!-- -->, //)은 비활성 옛 로직 보존 영역이다 — 절대 이식 대상이 아니다. 활성 코드만, 한 줄 한 줄 직접 따라가서 그대로 이식한다.

  • 운영 화면이 진실의 기준: waceplm.esgrin.com 운영 화면에 실제 보이는 항목/동작이 활성. 코드만 보면 활성/비활성 구분이 흐려짐.
  • 컬럼 정의(var columns = [...]): /* 주석처리된 컬럼 - 필요시 활성화 */ 블록 이하는 무시.
  • 검색 폼(#plmSearchZon): <!-- 주석처리된 검색필터 - 필요시 활성화 --> 블록 이하는 무시.
  • 서비스 메서드: 주석된 옛 SQL/분기 무시. 호출 그래프(controller → service → mapper)를 한 줄씩 따라가서 활성 경로만 추출.
  • 매퍼 XML: <!-- ... --> 블록 안의 SQL fragment는 무시. <select id="...">/<insert id="..."> 단위로 호출되는 것만 사용.
  • 자세한 함정 사례: 메모리 feedback_wace_jsp_columns (2026-05-08 영업관리 4개 메뉴 검색폼 사고 기록).

1. 원본 견적·주문 흐름 (10단계)

# 단계 wace_plm endpoint 핵심 테이블 변경
1 견적 list 조회 POST /contractMgmt/estimateGridList.do contract_mgmt(read, IS_DIRECT_ORDER!='Y' 필터)
2 견적요청 등록 POST /contractMgmt/saveContractMgmtInfo.do contract_mgmt + contract_item(N) + contract_item_serial(N) INSERT
3 직접등록 통합폼 (견적 없이 주문) POST /contractMgmt/saveEstimateAndOrderInfo.do 위와 동일 + IS_DIRECT_ORDER='Y' 강제 세팅
4 견적요청 → 견적작성 (식별자 contract_objid로 묶임. 명시적 컬럼 복사 없음) (없음)
5 견적 작성 (일반/장비) `POST /contractMgmt/saveEstimate.do saveEstimate2.do`
6 결재 사전판정 POST /contractMgmt/checkApprovalRequired.do (read only — 신규수주/가격인하 로직)
6a 결재불필요 자동처리 POST /contractMgmt/setApprovalNotRequired.do contract_mgmt.APPROVAL_REQUIRED='N' UPDATE
6b 아마란스 결재상신 POST /approval/getAmaranthSsoUrl.do amaranth_approval INSERT (외부 SSO)
7 메일 발송 POST /contractMgmt/sendEstimateMail.do mail_log INSERT + 실제 SMTP MailUtil.sendMailWithAttachFileUTF8
8 주문서 list 조회 POST /contractMgmt/contractGridList.do contract_mgmt(read, 모든 행) — 견적 list와 동일 테이블
9 수주확정 (전이) POST /contractMgmt/updateOrderStatus.do contract_mgmt.CONTRACT_RESULT UPDATE만 (새 INSERT 없음)
10 프로젝트 자동생성 (9의 부수효과) (9의 service 내부에서 호출) project_mgmt INSERT × N (라인별, Machine은 수량만큼) + project_no 채번

견적관리·주문서관리·판매관리·매출관리 4개 list는 모두 같은 contract_mgmt을 단계별 필터로 보여주는 구조. 단계 전이는 CONTRACT_RESULT 코드 변경으로 일어남.

2. GAP 매트릭스 (우선순위 순)

🔴 = 사용자 흐름 차단 / 🟠 = 핵심 기능 빠짐 / 🟡 = 보완 필요 / 🟢 = 백로그

# 우선 항목 원본 위치 이식본 현재 상태 권장 작업
G1 🔴 수주확정 시 프로젝트 자동생성 ContractMgmtService.updateOrderStatus (라인 29873113) + project.xml (75187581) salesOrderMgmtService.ts:521 updateStatusCONTRACT_RESULT UPDATE만 — 프로젝트 생성 호출 없음 updateStatus 트랜잭션 내에서: contract_item 루프 → PRODUCT='0000928'(Machine)이면 quantity만큼 N회, 아니면 1회 → project_no 채번 ({주문유형}-{제품구분}-{YYMMDD}-{순번3자리}) → project_mgmt INSERT
G2 🔴 직접등록 통합폼 (estimateAndOrderRegistFormPopup) ContractMgmtService.saveEstimateAndOrderInfo (라인 2664) endpoint 자체 부재. 주문관리 화면 "신규" 버튼이 견적 없이 주문 등록하는 흐름 미지원 POST /api/sales/order/direct 신설 — IS_DIRECT_ORDER='Y' 강제, contract_mgmt UPSERT + contract_item UPSERT + contract_item_serial 다중 INSERT
G3 🟠 견적요청등록 시 contract_item 다중 INSERT ContractMgmtService.saveContractMgmtInfo (라인 544) salesEstimateService.ts는 헤더만 INSERT, 라인 입력 누락 save 트랜잭션에 contract_item 다중 UPSERT + contract_item_serial 처리 추가
G4 🟠 결재 자동판정 (checkApprovalRequired) (별도 컨트롤러, 신규수주/가격인하 룰) 미구현. APPROVAL_REQUIRED='N' 라벨 표시만 룰 분석 후 endpoint 신설. 외부 amaranth SSO는 RPS 결재 모듈 결정 후
G5 🟠 견적템플릿 일반/장비 분기 + PDF ContractMgmtService.saveEstimateTemplate/2 (라인 1501/1591) + SmartEditor uploadPdfChunk 미이식. 추가견적 카운트(시연 시드)만 표시 template1/template2 popup 라우트 + puppeteer 또는 react-pdf PDF 생성 → attach_file_info doc_type='estimate02' INSERT
G6 🟠 SMTP 실제 발송 ContractMgmtService.sendEstimateMail (라인 1774-1968), MailUtil.sendMailWithAttachFileUTF8 (라인 1925) salesEstimateService.ts:618는 mail_log INSERT만 mailSendSimpleService(nodemailer) 통합 + HTML 본문 생성기(makeEstimateMailContents) 포팅 + 첨부 결합
G7 🟡 주문서 수정 시 contract_item UPSERT (OBJID 유지) mapper.upsertContractItemWithOrder (UPSERT 패턴) 이식본은 단순 UPDATE — 라인 변경 시 OBJID 유지 보장 안 됨 UPSERT(ON CONFLICT) 패턴 적용 + 삭제된 라인 처리 분기
G8 🟡 프로젝트 존재 시 견적·주문 삭제 방지 ContractMgmtService.deleteContractMngInfo (라인 794~808) salesOrderMgmtService.ts delete는 사전 체크 없음 delete 전에 project_mgmt WHERE contract_objid=$1 LIMIT 1 체크 → 있으면 거부
G9 🟡 견적요청 → 견적작성 라인 자동 복제 UI (원본은 사용자가 contract_item에서 수동 선택) 미구현 — 견적 작성 시 매번 라인 재입력 "이전 라인 복제" 버튼 + contract_item → estimate_template_item 일괄 복사
G10 🟢 환율 마스터 + EXCHANGE_RATE 자동 변환 contractBase SQL EST_TOTAL_AMOUNT_KRW 환산식 환산식만 있고 환율 마스터 미구축 환율 테이블 신설(또는 ECOS API 동기화)
G11 🟢 결재 모듈 (amaranth_approval / 자체) 외부 amaranth + APPR_STATUS 라벨 RPS 결재 정책 미정 vexplor approvalController 매핑 vs amaranth_approval 도입 결정

3. 코드/SQL 정합성 메모

3.1 견적·주문은 같은 contract_mgmt

원본은 상태 전이형 모델: 같은 contract_mgmt 행이 견적단계(IS_DIRECT_ORDER='N') → 수주(CONTRACT_RESULT='0000964') → FCST(CONTRACT_RESULT='0000968') 로 진행. 새 INSERT는 §3 통합폼과 §10 프로젝트 생성에서만 일어남. 우리 이식본은 이 단계 모델에 맞춰져 있어 list 단의 SQL은 정합성 OK.

3.2 project_no 채번 룰 (G1의 핵심)

형식: {주문유형}-{제품구분}-{YYMMDD}-{순번3자리}
예: R-CT-260507-001

주문유형 매핑 (CATEGORY_CD → 1글자):
  오버홀=O, 개조=M, 개발=D, 견적=Q, 수리=R, 판매=S, 기타=T

제품구분 매핑 (PRODUCT → 2글자):
  Machine=MC, A/S=AS, D/S=DS, B/S=BS, C/T=CT, A/C=AC, W/M=WM, 기타=원문

순번:
  같은 (주문유형 + 제품구분 + 날짜) 조합 내 MAX(순번)+1
  없으면 001부터

출처: wace_plm/src/com/pms/projectmgmt/mapper/project.xml:7518-7581. RPS의 project_mgmt 89건이 모두 이 룰로 채번되어 있으니, 이식 시 새 행도 같은 룰을 따라야 일관성 유지됨.

3.3 Machine 분기

contract_item 1라인의 PRODUCT가 0000928(Machine)이면 수량만큼 N회 project_mgmt INSERT (각 quantity=1). 그 외(A/S·D/S·C/T 등)는 1회 INSERT (수주수량 그대로). 이 분기 누락 시 시리얼 단위 추적이 깨짐.

3.4 첨부 파일 doc_type

단계 doc_type 그리드 컬럼
견적 PDF estimate01 (메인 견적서) (없음)
추가 견적 estimate02 "추가견적"
주문서 첨부 ORDER_DOC 또는 FTC_ORDER "주문서첨부" (CU01_CNT)

02-order.md에 주문서 첨부 컬럼이 미정의되어 있음 — 보완 필요.

4. 다음 PR 후보 (3개로 묶기)

PR-A: 수주확정 → 프로젝트 자동생성 (G1)

  • 단독 PR. SQL·트랜잭션 위주, UI 변경 거의 없음.
  • 작업: salesOrderMgmtService.updateStatus 안에 project 생성 로직 + project_no 채번 helper + Machine 분기.
  • 검증: 0000964/0000968 코드로 상태 변경 시 project_mgmt에 새 행 생기는지, project_no 형식 일치하는지.

PR-B: 직접등록 통합폼 (G2 + G3)

  • 주문관리 화면 "신규" 버튼이 통합 다이얼로그 띄움 → IS_DIRECT_ORDER='Y' + contract_item 다중 입력.
  • G3(견적요청등록 라인 입력)도 같은 라인 입력 컴포넌트 재사용 가능 → 묶어서.

PR-C: 결재·메일·PDF (G4 + G5 + G6)

  • 분량 큼. RPS 결재 정책 결정(G11) 선행 필요.
  • 단계: SMTP(G6) → PDF(G5) → 결재(G4) 순서로 사이즈 작은 것부터.

백로그

  • G7~G11은 위 3개 끝난 뒤 평가.

5. 검증 체크리스트 (PR마다)

  • 원본 endpoint와 이식 endpoint 매핑표 갱신 (이 문서 §1)
  • 영향 받는 테이블의 BEFORE/AFTER row count 기록
  • wace 운영 화면(waceplm.esgrin.com)과 동일 시나리오 비교 스크린샷
  • project_mgmt 새 행이 89건 + N 으로 늘어나는지 (G1)
  • IS_DIRECT_ORDER='Y' 행 신규 생성 확인 (G2)