Files
wace_rps/docs/migration/sales/01-estimate.md
T
hjjeong 489fa50d11 영업관리 4개 메뉴 검색폼 wace 일치 + 공통 UX(초기화·date input) 정비
- 검색 폼 정합성: 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>
2026-05-08 10:42:16 +09:00

11 KiB

01. 견적관리 이식 상세

원본: /contractMgmt/estimateList_new.do (estimateList_new.jsp, 47KB) 대상: app/(main)/COMPANY_16/sales/estimate/page.tsx

1. 화면 구조 (wace_plm 원본)

1.1 검색 폼 (#plmSearchZon)

활성 7개 (estimateList_new.jsp line 1110~1170):

필드 name/id 타입 비고
주문유형 category_cd select2 (공통코드)
고객사 customer_objid select2 (SUPPLY_MNG+CLIENT_MNG) 'C_' 접두사로 두 테이블 구분
품번 search_partNo select2-part (검색어 → API) hidden search_partObjId 동행
품명 search_partName select2-part
시리얼 search_serialNo text
결재상태 appr_status select2 (대기/상신중/완료/반려/불필요)
접수일 from~to receipt_start_date / receipt_end_date date_icon

비활성 (JSP line 1174~1203 <!-- 주석처리된 검색필터 - 필요시 활성화 --> 블록 안) — 이식 대상 아님:

필드 name/id
제품 product
지역 area_cd
유/무상 paid_type
요청납기 from~to due_start_date / due_end_date

1.2 버튼 영역 (.plm_btn_wrap)

버튼 id 동작
조회 btnSearch fn_search()/contractMgmt/estimateGridList.do
삭제 btnDelete 선택행 → /contractMgmt/deleteEstimateMgmtInfo.do
견적요청등록 .btnRegist 팝업: /contractMgmt/estimateRegistFormPopup.do?actionType=regist
견적작성 btnEstimate 일반/장비 견적서 분기 → `fn_openEstimateTemplate(objId, "1"
결재상신 btnApproval 결재불필요 분기 → /contractMgmt/checkApprovalRequired.dofn_openAmaranthApproval
메일발송 btnMail 결재완료/불필요만 → /contractMgmt/estimateMailFormPopup.do

1.3 그리드 (_tabulGrid = Tabulator)

데이터 소스: POST /contractMgmt/estimateGridList.do (검색 폼 직렬화)

# 컬럼 field 정렬 비고
0 EST_OBJID (hidden) EST_OBJID
1 영업번호 CONTRACT_NO center 클릭 → fn_projectConceptDetail(OBJID)
2 주문유형 CATEGORY_NAME center
3 접수일 RECEIPT_DATE center
4 요청납기 EARLIEST_DUE_DATE center "{date} 외 {n}건" 포맷
5 고객사 CUSTOMER_NAME left
6 품명 ITEM_SUMMARY left "{itemName} 외 {n}건" 포맷
7 견적수량 ESTIMATE_QUANTITY right toLocaleString
8 유/무상 PAID_TYPE center
9 공급가액 EST_TOTAL_AMOUNT right 통화기호 변환 (CONTRACT_CURRENCY_NAME)
10 원화환산공급가액 EST_TOTAL_AMOUNT_KRW right
11 견적현황 EST_STATUS center 클릭 → fn_showEstimateList(OBJID)
11-1 추가견적(PDF 첨부수) ADD_EST_CNT center 📎 클릭 → fn_openAddEstimatePdf
12 AMARANTH_STATUS (hidden) AMARANTH_STATUS 아마란스 결재상태
13 결재상태 APPR_STATUS center 색상 표시

16개 더 있을 수 있음 — 559라인까지 컬럼 정의 이어짐. 구현 시 estimateList_new.jsp:342-559 직접 참고.

2. 백엔드 endpoint 매핑 (wace_plm → vexplor_rps)

wace_plm endpoint 메서드 용도 vexplor_rps 신규 endpoint (제안)
/contractMgmt/estimateList_new.do GET 페이지 진입 (JSP 렌더) (없음 — Next.js 페이지)
/contractMgmt/estimateGridList.do POST 그리드 데이터 조회 GET /api/sales/estimate/list?...
/contractMgmt/estimateRegistFormPopup.do GET 견적 등록/수정 팝업 (Next.js Dialog 컴포넌트)
/contractMgmt/saveEstimateMgmtInfo.do POST 견적 메타 저장 POST /api/sales/estimate / PUT /api/sales/estimate/:id
/contractMgmt/deleteEstimateMgmtInfo.do POST 견적 삭제 DELETE /api/sales/estimate/:id
/contractMgmt/createEstimateMgmtInfo.do POST 견적 신규 생성 POST /api/sales/estimate 와 통합
/contractMgmt/estimateTemplate1.do GET 일반 견적서 작성 화면 app/(pop)/sales/estimate/template1/page.tsx
/contractMgmt/estimateTemplate2.do GET 장비 견적서 작성 화면 app/(pop)/sales/estimate/template2/page.tsx
/contractMgmt/getEstimateTemplateList.do POST 템플릿 목록 GET /api/sales/estimate/:id/templates
/contractMgmt/getEstimateTemplateDataByObjId.do POST 템플릿 단건 GET /api/sales/estimate/templates/:templateId
/contractMgmt/saveEstimate.do POST 일반 견적서 저장 POST /api/sales/estimate/templates
/contractMgmt/saveEstimate2.do POST 장비 견적서 저장 위와 통합 (type 파라미터)
/contractMgmt/uploadPdfChunk.do POST PDF 청크 업로드 POST /api/sales/estimate/templates/:id/pdf-chunk
/contractMgmt/sendEstimateMail.do POST 견적 메일 발송 POST /api/sales/estimate/:id/mail
/contractMgmt/sendEstimateMailCustom.do POST 견적 메일 발송(커스텀) 위와 옵션 통합
/contractMgmt/estimateMailFormPopup.do GET 메일 발송 팝업 (Next.js Dialog)
/contractMgmt/getContractInfoForMail.do POST 메일 발송용 데이터 GET /api/sales/estimate/:id/mail-context
/contractMgmt/getCustomerContactInfo.do POST 고객사 연락처 GET /api/customers/:id/contacts (마스터 공용)
/contractMgmt/getEstimateDetail.do POST 견적 단건 상세 GET /api/sales/estimate/:id
/contractMgmt/checkApprovalRequired.do POST 결재 필요 여부 체크 GET /api/sales/estimate/:id/approval-check
/contractMgmt/setApprovalNotRequired.do POST 결재불필요 처리 POST /api/sales/estimate/:id/approval-skip
/contractMgmt/checkProjectExists.do POST 프로젝트 존재 체크 GET /api/sales/estimate/check-project?...
/contractMgmt/searchPartList.do POST 품목 검색 (select2) GET /api/items/search?q=... (마스터 공용)
/contractMgmt/itemPriceCompareList.do GET 가격비교 화면 app/(main)/COMPANY_16/sales/estimate/price-compare/page.tsx
/contractMgmt/getItemPriceCompareGridList.do GET 가격비교 그리드 GET /api/sales/item-price-compare?...
/contractMgmt/FileRegistPopup.do GET 첨부파일 등록 팝업 (Next.js Dialog + 파일 업로드 컴포넌트)
/contractMgmt/addEstimatePdfPopup.do GET 추가견적 PDF 첨부 팝업 (Next.js Dialog)

3. DB 테이블 (이식 대상)

3.1 핵심 테이블

테이블 역할 DDL 출처
estimate_mgmt 견적 헤더 (구버전) db/dbexport.pgsql:4340
estimate_template 견적 템플릿 / 신규 견적 헤더 dbexport에 없음 — 운영 DB에서 추출 필요
estimate_template_item 견적 라인 dbexport에 없음 — 운영 DB에서 추출 필요
contract_mgmt 영업번호(CONTRACT_NO)와 연결되는 영업/계약 헤더 db/dbexport.pgsql:2488
contract_item 견적/계약 품목 라인 database/contract_item_tables.sql
contract_item_serial 라인별 시리얼 위 SQL
contract_mgmt_option 옵션 db/dbexport.pgsql:2899
attach_file_info 첨부파일 (doc_type='contractMgmt01', addEstimatePdf 등) db/dbexport.pgsql:1387
approval / amaranth_approval 결재 (자체 + 아마란스) db/dbexport.pgsql:507
mail_log 견적 메일 이력 (필요 시 추출)

3.2 마스터 의존 (vexplor_rps에 매핑)

  • SUPPLY_MNG (objid) + CLIENT_MNG (objid, 'C_' prefix) → vexplor_rps customer_mng.id
    • 매핑 테이블: legacy_customer_map (legacy_objid VARCHAR PK, customer_mng_id INT)
  • PART_MGMT (objid) → vexplor_rps item_info.id
  • USER_INFO (user_id) → vexplor_rps user_info.user_id
  • DEPT_INFO (dept_code) → 확인 필요

3.3 estimate_mgmt 컬럼 (db/dbexport.pgsql:4340-4371)

CREATE TABLE public.estimate_mgmt (
    objid integer NOT NULL,
    customer_objid character varying,        -- → customer_mng.id (변환)
    category_cd character varying,           -- 공통코드
    product_group character varying,
    product character varying DEFAULT '0',
    product_std character varying,
    qty character varying,
    warranty character varying,
    product_price integer,
    other_price integer,
    total_price integer,
    contract_user_id character varying,      -- → user_info.user_id
    contract_date character varying,
    contract_phone character varying,
    contract_email character varying,
    contract_office_no character varying,
    contract_fax_no character varying,
    est_release_date character varying,
    regdate timestamp without time zone,
    writer character varying,
    estimate_no character varying,           -- 채번 (EST-YYYYMMDD-NNN)
    contract_product_price integer,
    sale character varying,
    final_total_price integer,
    contract_type character varying,
    note character varying,
    cus_request_date character varying,
    delivery_place character varying,
    product_code character varying,
    status character varying
);
-- 시퀀스: estimate_mgmt_seq

⚠️ 현재 신규 견적은 estimate_mgmt보다 estimate_template을 메인으로 쓰는 것으로 보임 (estimateList_new.jsp 분석 결과). 운영 DB DDL 확인이 우선.

4. 구현 순서

  1. 운영 DB에서 누락 DDL 추출
    pg_dump -h 211.115.91.141 -p 11133 -U postgres -d waceplm \
      --schema-only --table=estimate_template --table=estimate_template_item \
      --table=mail_log > /tmp/estimate_missing_ddl.sql
    
  2. 마이그레이션 파일 작성: db/migrations/100_create_estimate_tables.sql (estimate_mgmt + estimate_template + estimate_template_item + 매핑 테이블)
  3. 백엔드 작성:
    • backend-node/src/routes/estimateRoutes.ts
    • backend-node/src/controllers/estimateController.ts
    • backend-node/src/services/estimateService.ts
  4. 마스터 매핑 유틸: backend-node/src/utils/legacyIdMap.ts (customer/part objid 변환)
  5. 프론트엔드 작성:
    • frontend/app/(main)/COMPANY_16/sales/estimate/page.tsx (목록 + 검색 + 그리드)
    • 견적 등록/수정 Dialog 컴포넌트 (components/sales/EstimateRegistDialog.tsx)
    • 일반/장비 견적서 작성 페이지 (popup): frontend/app/(pop)/sales/estimate/template[1|2]/page.tsx
    • 메일 발송 Dialog
  6. 메뉴/권한: vexplor_rps 메뉴 관리에서 등록 + 권한 매핑
  7. 테스트: 견적 생성 → 일반/장비 견적서 작성 → 결재 → 메일 발송 → 추가견적 PDF 첨부

5. 주의사항 / 결정 보류 항목

  • 결재 시스템: wace_plm은 자체 approval + 외부 amaranth_approval 두 채널. RPS에서 둘 다 살릴지, 자체만 쓸지 결정 필요. (관리자 측에서 amaranth 연동 진행 중이라면 활용 가능)
  • PDF 생성/메일 발송: wace_plm은 SmartEditor 기반. Next.js에선 puppeteer 또는 react-pdf 등으로 대체 검토.
  • fn_projectConceptDetail (영업번호 클릭): 프로젝트 모듈 종속 → 프로젝트관리 이식 후 연결.
  • 품목 검색 select2: vexplor_rps의 item_info 마스터에 wace_plm PART_MGMT 데이터를 마이그레이션해 두어야 select2 동작.
  • 통화/환율: CONTRACT_CURRENCY_NAME, EST_TOTAL_AMOUNT_KRW 컬럼 — 환율 마스터 또는 환율 API 필요.