489fa50d11
- 검색 폼 정합성: 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>
11 KiB
11 KiB
02. 주문서관리 이식 상세
원본:
/contractMgmt/orderMgmtList.do(orderMgmtList.jsp, 45KB) 대상:app/(main)/COMPANY_16/sales/order/page.tsx(기존 골격 대체 또는 신규 경로)
1. 화면 구조 (wace_plm 원본)
1.1 검색 폼 (#plmSearchZon)
활성 9개 (orderMgmtList.jsp line 1109~1182):
| 필드 | name | 타입 | 비고 |
|---|---|---|---|
| 주문유형 | category_cd |
select2 (공통코드) | |
| 발주번호 | search_poNo |
text | |
| 고객사 | customer_objid |
select2 (SUPPLY_MNG+CLIENT_MNG) |
'C_' 접두사 |
| 품번 | search_partNo |
select2-part | hidden search_partObjId 동행 |
| 품명 | search_partName |
select2-part | |
| 시리얼 | search_serialNo |
text | |
| 수주상태 | contract_result |
select2 (공통코드) | |
| 발주일 from~to | order_start_date / order_end_date |
date_icon | |
| 요청납기 from~to | due_start_date / due_end_date |
date_icon |
비활성 (JSP line 1184~ <!-- 주석처리된 검색필터 --> 블록 안) — 이식 대상 아님:
| 필드 | name |
|---|---|
| 제품 | product |
| 지역 | area_cd |
| 유/무상 | paid_type |
| 환종 | contract_currency |
1.2 버튼 영역
| 버튼 | id | 동작 |
|---|---|---|
| 조회 | btnSearch |
fn_search() → /contractMgmt/contractGridList.do |
| 수주복사 | btnCopy |
/contractMgmt/copyEstimateAndOrderInfo.do |
| 수주입력 | .btnRegist |
팝업: /contractMgmt/estimateAndOrderRegistFormPopup.do 또는 orderRegistFormPopup.do |
| 수주확정 | btnOrderConfirm |
(녹색) — 견적 → 수주 확정 처리 |
| 수주취소 | btnOrderCancel |
(빨강) — /contractMgmt/saveOrderCancelQty.do (수량별 취소) |
| 결재상신 | btnApproval |
결재 워크플로우 |
1.3 그리드 (_tabulGrid = Tabulator)
데이터 소스: POST /contractMgmt/contractGridList.do
| # | 컬럼 | field | 정렬 | 비고 |
|---|---|---|---|---|
| 1 | 영업번호 | CONTRACT_NO | center | frozen, anchor → fn_projectConceptDetail(OBJID) |
| 2 | 주문유형 | CATEGORY_NAME | center | |
| 3 | 발주일 | ORDER_DATE | center | |
| 4 | 발주번호 | PO_NO | center | |
| 5 | 요청납기 | EARLIEST_DUE_DATE | center | "{date} 외 {n}건" 포맷 |
| 6 | 고객사 | CUSTOMER_NAME | left | |
| 7 | 품명 | ITEM_SUMMARY | left | "{itemName} 외 {n}건" |
| 8 | 수주수량 | ORDER_QUANTITY | right | |
| 9 | 수주취소 | CANCEL_QTY_SUM | right | |
| 10 | 유/무상 | PAID_TYPE | center | |
| 11 | 수주상태 | CONTRACT_RESULT_NAME | left | |
| 12 | 공급가액 | ORDER_SUPPLY_PRICE_SUM | right | 통화기호 |
| 13 | 부가세 | ORDER_VAT_SUM | right | |
| 14 | 총액 | ORDER_TOTAL_AMOUNT_SUM | right | |
| 15 | 원화총액 | ORDER_TOTAL_AMOUNT_KRW | right | |
| 16 | 주문서첨부 | CU01_CNT | center | 📎 클릭 → /contractMgmt/FileRegistPopup.do |
| 17 | 주문서 | HAS_ORDER_DATA | center | 클릭 → /contractMgmt/orderFormView.do?objId=... |
| 18 | 고객사요청사항 | CUSTOMER_REQUEST | left | |
| 19 | 결재상태 | ORDER_APPR_STATUS | center | |
| 20 | 환종 | CONTRACT_CURRENCY_NAME | center | |
| 21 | 환율 | EXCHANGE_RATE | right | |
| 22 | S/N | SERIAL_NO | center | |
| 23 | 품번 | PART_NO | center | |
| 24 | 작성자 | WRITER_NAME | center | |
| 25 | 제품구분 | PRODUCT_NAME | center | |
| 26 | 국내/해외 | AREA_NAME | center | |
| 27 | 접수일 | RECEIPT_DATE | center |
일부 셀 클릭은
contractList.jsp로 form submit되어 다른 화면 이동 (line 194 참고).
2. 백엔드 endpoint 매핑
| wace_plm endpoint | 메서드 | 용도 | vexplor_rps 신규 endpoint |
|---|---|---|---|
/contractMgmt/orderMgmtList.do |
GET | 페이지 진입 | (Next.js page) |
/contractMgmt/contractGridList.do |
POST | 그리드 데이터 | GET /api/sales/order/list?... |
/contractMgmt/getPagingContractList.do |
POST | 페이징 조회 (legacy) | 위와 통합 |
/contractMgmt/orderRegistFormPopup.do |
GET | 수주 등록/수정 팝업 | (Next.js Dialog) |
/contractMgmt/estimateAndOrderRegistFormPopup.do |
GET | 견적+수주 통합 팝업 | (Next.js Dialog with mode) |
/contractMgmt/saveOrderInfo.do |
POST | 수주 저장 | POST /api/sales/order / PUT /api/sales/order/:id |
/contractMgmt/saveEstimateAndOrderInfo.do |
POST | 견적+수주 통합 저장 | 위와 통합 (mode 파라미터) |
/contractMgmt/copyEstimateAndOrderInfo.do |
POST | 수주 복사 | POST /api/sales/order/:id/copy |
/contractMgmt/updateOrderStatus.do |
POST | 수주 상태 변경(확정/취소 등) | PATCH /api/sales/order/:id/status |
/contractMgmt/saveOrderCancelQty.do |
POST | 라인별 취소 수량 저장 | POST /api/sales/order/:id/cancel-qty |
/contractMgmt/getContractItems.do |
POST | 수주 라인 조회 | GET /api/sales/order/:id/items |
/contractMgmt/getAllSerialNumbers.do |
POST | 라인 전체 시리얼 조회 | GET /api/sales/order/:id/serials |
/contractMgmt/orderFormView.do |
GET | 주문서 양식 화면 | app/(pop)/sales/order/[id]/form/page.tsx |
/contractMgmt/getOrderFormData.do |
POST | 주문서 양식 데이터 | GET /api/sales/order/:id/form-data |
/contractMgmt/getOrderTotalAmount.do |
POST | 합계 계산 | GET /api/sales/order/:id/totals |
/contractMgmt/orderMgmtGrodList.do (typo) |
POST | (구버전 그리드) | (사용 안함) |
/contractMgmt/getContractItemList.do |
POST | 계약 라인 조회 | 위 /items와 통합 |
/contractMgmt/contracMgmtReviewFormPopup.do (typo) |
GET | 계약 리뷰 팝업 | (Next.js Dialog) |
/contractMgmt/saveContractMgmtReviewInfo.do |
POST | 리뷰 정보 저장 | POST /api/sales/order/:id/review |
/contractMgmt/overlapOrder.do |
POST | 중복 수주 체크 | GET /api/sales/order/check-duplicate?... |
/contractMgmt/checkApprovalRequired.do |
POST | 결재 필요 여부 | (견적과 공유) |
/contractMgmt/deleteContractMngInfo.do |
POST | 계약(수주) 삭제 | DELETE /api/sales/order/:id |
/contractMgmt/FileRegistPopup.do |
GET | 첨부파일 팝업 | (공유 컴포넌트) |
/contractMgmt/getCustomerManagerList.do |
POST | 고객사 담당자 목록 | GET /api/customers/:id/contacts |
/contractMgmt/checkProjectExists.do |
POST | 프로젝트 존재 체크 | (견적과 공유) |
OrdersMgmtController(다른 컨트롤러,/ordersMgmt/*)는 별개 모듈로 보임 (입출고/미납 관리 위주). 본 메뉴와는 무관.
3. DB 테이블 (이식 대상)
| 테이블 | 역할 | DDL 출처 |
|---|---|---|
contract_mgmt |
수주(계약) 헤더 — 주문서의 메인 테이블 | db/dbexport.pgsql:2488 |
contract_item |
수주 라인 (품번/수량/단가/공급가/부가세/총액 + ORDER_* 컬럼들) | database/contract_item_tables.sql + database/add_order_columns_to_contract_item.sql |
contract_item_serial |
라인별 S/N | database/contract_item_tables.sql |
contract_mgmt_option |
수주 옵션 | db/dbexport.pgsql:2899 |
contract_base_data |
수주 기준 데이터 (공통 마스터) | (운영 DB 추출 필요) |
attach_file_info |
주문서 첨부 (doc_type='contractMgmt01') |
db/dbexport.pgsql:1387 |
approval |
결재 | db/dbexport.pgsql:507 |
3.1 contract_item 핵심 컬럼 (DDL 합본)
CREATE TABLE CONTRACT_ITEM (
OBJID VARCHAR(50) PRIMARY KEY,
CONTRACT_OBJID VARCHAR(50) NOT NULL REFERENCES CONTRACT_MGMT(OBJID) ON DELETE CASCADE,
SEQ INTEGER NOT NULL,
PART_NO VARCHAR(100) NOT NULL, -- → vexplor_rps item_info 매핑
PART_NAME VARCHAR(200) NOT NULL,
QUANTITY INTEGER NOT NULL DEFAULT 1, -- 견적 수량
DUE_DATE VARCHAR(10),
CUSTOMER_REQUEST TEXT,
-- 수주 컬럼 (add_order_columns 추가)
ORDER_QUANTITY VARCHAR(50),
ORDER_UNIT_PRICE VARCHAR(50),
ORDER_SUPPLY_PRICE VARCHAR(50),
ORDER_VAT VARCHAR(50),
ORDER_TOTAL_AMOUNT VARCHAR(50),
-- 공통
REGDATE TIMESTAMP NOT NULL DEFAULT NOW(),
WRITER VARCHAR(50),
CHGDATE TIMESTAMP,
CHG_USER_ID VARCHAR(50),
STATUS VARCHAR(20) DEFAULT 'ACTIVE'
);
CREATE TABLE CONTRACT_ITEM_SERIAL (
OBJID VARCHAR(50) PRIMARY KEY,
ITEM_OBJID VARCHAR(50) NOT NULL REFERENCES CONTRACT_ITEM(OBJID) ON DELETE CASCADE,
SEQ INTEGER NOT NULL,
SERIAL_NO VARCHAR(200) NOT NULL,
REGDATE TIMESTAMP NOT NULL DEFAULT NOW(),
WRITER VARCHAR(50),
STATUS VARCHAR(20) DEFAULT 'ACTIVE',
UNIQUE (ITEM_OBJID, SERIAL_NO)
);
3.2 contract_mgmt 주요 컬럼 (참고)
db/dbexport.pgsql:2488-2540 참조. 주문서에서 자주 쓰는 컬럼:
objid(PK),contract_no(영업번호 = CONTRACT_NO)customer_objid(고객사 —'C_'prefix로 client_mng 분기)category_cd,area_cd,product,paid_type(공통코드)po_no(발주번호),contract_date(발주일),req_del_date(요청납기)contract_currency,contract_currency_name,exchange_rate(?)result_cd→contract_result_name(수주상태)pm_user_id,salesman(담당자)regdate,writer,chg_user_id
4. 구현 순서
- 마이그레이션 SQL 작성:
db/migrations/101_create_order_tables.sql(contract_mgmt + contract_item + contract_item_serial + contract_mgmt_option + contract_base_data) - 백엔드:
backend-node/src/routes/orderRoutes.tsbackend-node/src/controllers/orderController.tsbackend-node/src/services/orderService.ts(트랜잭션 필수: 헤더 + 라인 + 시리얼 동시 저장)
- 프론트엔드:
frontend/app/(main)/COMPANY_16/sales/order/page.tsx(기존 파일 백업 후 신규 작성, 또는 새 라우트sales/contract-order)- 수주 등록/수정 Dialog (
components/sales/OrderRegistDialog.tsx) - 수주확정/취소 모달 (수량 입력)
- 라인별 시리얼 관리 모달
- 주문서 양식 출력 페이지 (PDF/인쇄)
5. 주의사항
- 견적 → 수주 전환:
estimateAndOrderRegistFormPopup은 견적 OBJID를 받아 수주 헤더를 생성하면서 라인을 복사. 트랜잭션 + 라인 컬럼 매핑(견적 QUANTITY → ORDER_QUANTITY) 필요. - 라인별 부분 취소:
saveOrderCancelQty는 라인의 ORDER_QUANTITY 일부만 취소하는 시나리오. UI에서 취소 수량 입력 → DB는 별도 취소이력 테이블 사용 가능성 (확인 필요). - 주문서 양식 (orderFormView): 인쇄용 별도 화면. PDF 다운로드 또는 인쇄 다이얼로그.
- 계약 리뷰 (Review): 사내 검토 단계 — 별도 결재 또는 메모/체크리스트.
contracMgmtReviewFormPopup(typo) 분석 필요. - vexplor_rps 기존
sales/order/page.tsx(order/page.tsx)는 이 도메인이 아닐 가능성. 백업 후 신규 작성 권장.