3db55d9fd9
페이지 경로 이동 (menu_info 등록 경로와 일치)
- sales/purchase-request → purchase-request/request (구매요청서관리)
- sales/purchase-proposal → purchase-request/proposal (품의서관리)
- 사이드바 '구매요청' top-level 그룹(objid=100025) 하위 2개 메뉴와 1:1 매칭
UI 문자열 정리
- PageHeader description 2곳에서 wace 매퍼명 노출 제거
- 미구현 액션 toast 3개를 일반 안내문으로 교체 ("XXX 기능은 준비 중입니다.")
문서
- docs/migration/sales/09-purchase-request.md 신규 — 두 메뉴 매핑/컬럼/SQL 정합성/구매관리>품의서관리와의 차이/백로그
- docs/migration/sales/README.md — 이식 대상 4개 → 6개, 매핑표/다음작업 갱신
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
12 KiB
영업관리 이식 (wace_plm → vexplor_rps)
작성: 2026-05-07 / 작성자: hjjeong 대상: vexplor_rps (RPS 전용 분기, COMPANY_16 단독 운영) 원본: wace_plm (Java 7 / Spring 3.2.4 / JSP / MyBatis)
0. 정책 (사용자 확정 사항)
- 이식 방식: JSP → Next.js 리라이트 (백엔드도 Java→Node 재작성, vexplor_rps
backend-node패턴 채택) - 스키마 정책: 하이브리드 — 도메인 테이블(
contract_mgmt,estimate_mgmt,sales_registration등)은 wace_plm 원본 스키마를 그대로 가져오고, 거래처/품목 등 마스터는 vexplor_rps 기존 테이블(customer_mng,item_info)에 매핑 - 관리자 메뉴: 이식 대상 아님 (vexplor 그대로 사용)
- 이식 대상 메뉴 6개 (초기 4개 + 2026-05-15 확장 2개):
- 견적관리 (
/contractMgmt/estimateList_new.do) - 주문서관리 (
/contractMgmt/orderMgmtList.do) - 판매관리 (
/contractMgmt/salesMgmtList.do→ SalesNcollect로 위임) - 매출관리 (
/revenueMgmt/revenueList.do) - 구매요청서관리 (
/salesMng/purchaseRequestRegList.do) — 2026-05-15 추가 - 품의서관리(영업) (
/salesMng/purchaseRegProposalMngList.do) — 2026-05-15 추가
- 견적관리 (
1. 메뉴 매핑표
| # | 메뉴명 | wace_plm URL | wace_plm JSP | wace_plm Controller / Service | vexplor_rps 신규 위치 (제안) | 상세 문서 |
|---|---|---|---|---|---|---|
| 1 | 견적관리 | /contractMgmt/estimateList_new.do |
contractMgmt/estimateList_new.jsp (47KB) |
ContractMgmtController (1629–2510 line) / ContractMgmtService |
app/(main)/COMPANY_16/sales/estimate/page.tsx + backend-node/src/{routes,services}/estimateRoutes.ts |
01-estimate.md |
| 2 | 주문서관리 | /contractMgmt/orderMgmtList.do |
contractMgmt/orderMgmtList.jsp (45KB) |
ContractMgmtController (2504–3169 line) / ContractMgmtService |
app/(main)/COMPANY_16/sales/order/page.tsx (재작성) + backend-node/src/{routes,services}/orderMgmtRoutes.ts |
02-order.md |
| 3 | 판매관리 | /contractMgmt/salesMgmtList.do (위임) → /salesNcollectMgmt/sales.do |
salesmgmt/salesMgmt/*.jsp |
SalesNcollectMgmtController (line 763~) / SalesNcollectMgmtService |
app/(main)/COMPANY_16/sales/sale/page.tsx + backend-node/src/{routes,services}/saleRoutes.ts |
03-sale.md |
| 4 | 매출관리 | /revenueMgmt/revenueList.do |
salesmgmt/salesMgmt/revenueMgmtList.jsp |
SalesNcollectMgmtController (line 103, 214) / SalesNcollectMgmtService |
app/(main)/COMPANY_16/sales/revenue/page.tsx + backend-node/src/{routes,services}/revenueRoutes.ts |
04-revenue.md |
| 5 | 구매요청서관리 | /salesMng/purchaseRequestRegList.do |
salesMng/purchaseRequestRegList.jsp (728줄) |
SalesMngController (210~258) / salesMng.getSalesRequestMasterGridList (DOC_TYPE_FILTER='PURCHASE_REG') |
app/(main)/COMPANY_16/purchase-request/request/page.tsx + backend-node/src/{routes,services}/salesPurchaseRequestRoutes.ts |
09-purchase-request.md |
| 6 | 품의서관리 (영업) | /salesMng/purchaseRegProposalMngList.do |
salesMng/purchaseRegProposalMngList.jsp (313줄) |
SalesMngController (1363~1389) / salesMng.getPurchaseRegProposalMngGridList |
app/(main)/COMPANY_16/purchase-request/proposal/page.tsx + backend-node/src/{routes,services}/salesPurchaseRequestRoutes.ts |
09-purchase-request.md |
| ─ | 마스터 매핑 | (전 메뉴 공통) | — | — | — | 05-master-mapping.md |
⚠️ vexplor_rps의 기존 sales/quote/sales/order 페이지는 별도 도메인(
quote_mng/quote_detail)으로 만들어져 있음. 이식 후 사용 중지 또는 별도 모듈로 이름 변경 검토 필요. 신규 페이지는estimate/,order/신규 경로로 작성하는 것을 권장.
2. 도메인 테이블 (wace_plm → vexplor_rps 그대로 이식)
이식 대상 테이블. 새 vexplor_rps DB에 CREATE TABLE 그대로 적용 (컬럼명/타입 유지).
| 우선순위 | 테이블 | 용도 | dbexport.pgsql line |
|---|---|---|---|
| ★★★ | contract_mgmt |
계약/주문서 헤더 | 2488 |
| ★★★ | contract_item |
계약/주문서 상세 라인 | (DDL: database/contract_item_tables.sql) |
| ★★★ | estimate_mgmt |
견적 헤더 (구버전) | 4340 |
| ★★★ | estimate_template |
견적 템플릿 = 새 견적의 헤더(estimateList_new가 사용) | (CREATE 미발견, 운영 DB 추출 필요) |
| ★★★ | estimate_template_item |
견적 템플릿 라인 = 새 견적의 상세 | (CREATE 미발견, 운영 DB 추출 필요) |
| ★★ | counselingmgmt |
상담관리 — 이식 대상 아님 (사용자 확정) | 2989 |
| ★★ | contract_mgmt_option |
주문 옵션 | 2899 |
| ★★ | contract_item_serial |
주문 라인 시리얼 | (DDL: database/contract_item_tables.sql) |
| ★★ | sales_registration |
판매 등록 (= 판매·매출 집계 원장) | (dbexport에서 위치 확인 필요) |
| ★ | attach_file_info |
첨부파일 (PDF/이미지) | 1387 |
| ★ | approval |
결재 | 507 |
| ★ | mail_log |
메일 발송 로그 (견적 메일링) | (필요 시) |
| ★ | pms_pjt_year_goal |
연도 목표 (대시보드용) | (필요 시) |
✅ 운영 DB DDL 추출 완료 (2026-05-07)
운영 DB(211.115.91.141:11133/waceplm PG 16.8)에서 누락된 5개 테이블을 추출하여 ddl-extracted/에 정리. 주요 발견:
estimate_template/estimate_template_item발견 → 100_create_estimate_template.sqlsales_registration/shipment_log발견 → 101_create_sales_registration.sqlmail_log발견 → 102_create_mail_log.sqlfinal_data,end_count,transaction_statement_*,tax_invoice_*— 존재하지 않음- 매출관리의 마감/세금계산서/수출신고 컬럼은 모두
shipment_log에 통합되어 있음 - 운영 데이터 카운트: 견적 5건, 견적라인 7건, 판매 10건, 분할출하 0건, 메일로그 7,805건 → 도메인은 사실상 신규 시스템, 데이터 이주 부담 거의 없음
자세한 내용은 ddl-extracted/README.md.
3. 마스터 매핑 (wace_plm 마스터 → vexplor_rps 마스터로 변환)
| wace_plm 테이블 | wace_plm 키 컬럼 | vexplor_rps 테이블 | vexplor_rps 키 | 변환 규칙 |
|---|---|---|---|---|
SUPPLY_MNG (공급/고객사 통합) |
objid (numeric) |
customer_mng |
id (integer) |
양방향 매핑 테이블 필요 (legacy_supply_objid → customer_mng.id) |
CLIENT_MNG (일반 거래처) |
objid (numeric) |
customer_mng |
id |
위와 동일 (wace_plm은 customer_objid가 'C_' 접두사로 두 테이블 구분) |
USER_INFO |
user_id |
user_info |
user_id |
동일 키 사용 가능 (있다면 그대로) |
DEPT_INFO |
dept_code |
(vexplor_rps department) |
(확인 필요) | TBD |
PART_MGMT / PRODUCT_MGMT |
objid |
item_info |
id |
매핑 테이블 필요 |
ATTACH_FILE_INFO |
target_objid + doc_type |
(vexplor_rps 파일 시스템) | (확인 필요) | TBD |
마스터 마이그레이션 절차 (제안)
- wace_plm
SUPPLY_MNG+CLIENT_MNG→customer_mng로 INSERT (legacy_objid 컬럼 추가) - wace_plm
PART_MGMT(+PRODUCT_MGMT?) →item_info로 INSERT (legacy_part_objid 컬럼 추가) - 도메인 테이블(
contract_mgmt,estimate_mgmt등) 이식 시 외래 컬럼은 wace_plm objid를 그대로 가져오고, 별도 매핑 테이블(legacy_id_map)을 통해 vexplor_rps 마스터 id로 변환
4. 백엔드 패턴 (vexplor_rps backend-node)
라우트 (예: quoteRoutes.ts 패턴)
import { Router } from "express";
import { authenticateToken } from "../middleware/authMiddleware";
import * as ctrl from "../controllers/<feature>Controller";
const router = Router();
router.use(authenticateToken);
router.get("/list", ctrl.getList);
router.get("/generate-number", ctrl.generateNumber);
router.get("/:id", ctrl.getById);
router.post("/", ctrl.create);
router.put("/:id", ctrl.update);
router.delete("/:id", ctrl.remove);
export default router;
서비스 (예: quoteService.ts 패턴)
getPool()(PG raw)- companyCode 멀티테넌시:
WHERE company_code = $1(RPS는COMPANY_16고정) - 소프트삭제:
use_yn = 'Y' - 트랜잭션:
pool.connect()→BEGIN/COMMIT/ROLLBACK - 자동 채번:
generateNumber()(예:EST-YYYYMMDD-001)
컨트롤러
- 인증:
req.user.companyCode,req.user.userId사용 - 응답:
res.json({ data, totalCount })또는res.json({ success, message })
5. 프론트엔드 패턴 (vexplor_rps Next.js)
"use client";
import { DataGrid, DataGridColumn } from "@/components/common/DataGrid";
import { DynamicSearchFilter, FilterValue } from "@/components/common/DynamicSearchFilter";
import { apiClient } from "@/lib/api/client";
import { useAuth } from "@/hooks/useAuth";
// ... shadcn/ui Button, Dialog, Select, Input, Label ...
- 검색 필터:
DynamicSearchFilter(테이블 카테고리/공통코드 자동 바인딩) - 그리드:
DataGrid(선택, 정렬, 포맷팅) - 채번 / 단일 조회 / 저장 / 삭제:
apiClient.get/post/put/delete - 권한:
useCurrent2ndLevelMenuObjid+ 관리자에서 권한 매핑
6. 진행 체크리스트 (메뉴별)
각 메뉴 1개 이식 = 다음 9단계.
- (a) 운영 DB에서 해당 테이블 schema-only dump 추출
- (b)
db/migrations/에NNN_create_<feature>_tables.sql작성 - (c) wace_plm Controller endpoint 목록 추출 →
backend-node/src/routes/<feature>Routes.ts매핑표 작성 - (d)
backend-node/src/services/<feature>Service.ts작성 (raw SQL) - (e)
backend-node/src/controllers/<feature>Controller.ts작성 - (f)
backend-node/src/server.ts또는 라우트 등록 위치에 마운트 - (g)
frontend/app/(main)/COMPANY_16/sales/<feature>/page.tsx작성 (DataGrid + Filter + Modal) - (h) 메뉴 트리에 등록 (vexplor_rps 메뉴 관리 화면 또는 메뉴 시드)
- (i) 권한 매핑 + 수동 테스트
7. 다음 작업
운영 DB DDL 추출완료 (2026-05-07)01~04 상세 매핑 + 1차 이식완료 (2026-05-08)00-gap.md PR-A/B/C 흐름 + G7~G11 결재상신완료 (2026-05-11)구매요청서관리·품의서관리(영업) 1차 스캐폴드완료 (2026-05-15, 커밋7e7c6a0a, 09-purchase-request.md)- 다음: 구매요청서작성 다이얼로그 + 품의서생성 액션 + 영업>품의서 Amaranth 결재상신(target_type='PROPOSAL', formId='1163'). sales_request_part 운영DB DDL 추출 선행.
8. 공통 UX 규칙 (검색 폼 / 영업관리 4개 메뉴 동일 적용)
8.1 버튼 영역
상단 우측 버튼 영역에 다음 순서로 배치 — 모든 메뉴 공통:
조회(variant="outline"+<Search>아이콘)- 메뉴 고유 액션 버튼들 (등록/수정/삭제/확정 등)
초기화(variant="ghost") —searchFormstate를 모든 키 빈 값으로 reset
<Button size="sm" variant="ghost"
onClick={() => setSearchForm({ /* 모든 키 "" */ })}>
초기화
</Button>
8.2 date input
<Input type="date">사용 시 별도 처리 불필요. 다음은Input컴포넌트 +globals.css에 자동 반영:- 빈 값일 때
'YYYY/MM/DD'자리표시 텍스트 숨김 (data-empty="true" 자동) - 캘린더 아이콘 숨김 (
::-webkit-calendar-picker-indicator { display: none }) - input 영역 어디 클릭해도 picker 자동 표시 (
showPicker())
- 빈 값일 때
- 위 동작은
frontend/components/ui/input.tsx+frontend/app/globals.css에서 일괄 처리.
8.3 검색 폼 그리드
grid grid-cols-2 md:grid-cols-4 lg:grid-cols-7 gap-x-2 gap-y-1.5 p-2 border rounded-md bg-muted/30- 라벨:
text-[11px] mb-0.5 block text-muted-foreground - 입력:
h-8 text-xs(date는px-1 flex-1 min-w-0추가)
8.4 wace JSP 주석 함정
검색 폼 추출 시 JSP 끝부분 <!-- 주석처리된 검색필터 - 필요시 활성화 --> 블록은 이식 대상 아님. 활성/비활성 분리 표로 문서화. 자세한 내용은 메모리 feedback_wace_jsp_columns.