판매관리 그리드 V1 컬럼 8개 보강 + cu01_cnt 실데이터 + wace 1:1 검증 문서·자동 검증 SQL
- getList SQL: attach_file_info LATERAL JOIN으로 cu01_cnt(주문서첨부) 실데이터 (contract_mgmt.objid 기반, doc_type IN FTC_ORDER/ORDER) - SaleListRow 타입: product_type_name/nation_name/receipt_date/customer_request/manager_name/payment_type_name/cu01_cnt 보강 - GRID_COLUMNS 8개 추가: 제품구분/국내해외/접수일/고객사요청사항/주문서첨부/출하방법/담당자/인도조건 (wace 36/36 일치) - docs/migration/sales/03-sale-verify.md: wace ↔ RPS 매핑 / 갭 처리 - scripts/verify-sale.sql: BEGIN/ROLLBACK 2개 시나리오 (그리드 V1 / 판매상태 wace 로직) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -169,11 +169,12 @@ export async function getSaleList(filter: SaleListFilter) {
|
|||||||
,CM.customer_request
|
,CM.customer_request
|
||||||
,T.sales_deadline_date
|
,T.sales_deadline_date
|
||||||
,T.regdate
|
,T.regdate
|
||||||
/* 출하지시상태/생산상태/분할S/N/거래명세서/주문서첨부 — 1차 placeholder */
|
/* 출하지시상태/생산상태/분할S/N/거래명세서 — 1차 placeholder */
|
||||||
,NULL::text AS production_status
|
,NULL::text AS production_status
|
||||||
,NULL::text AS split_serial_no
|
,NULL::text AS split_serial_no
|
||||||
,'N'::text AS has_transaction_statement
|
,'N'::text AS has_transaction_statement
|
||||||
,0 AS cu01_cnt
|
/* 주문서첨부 카운트 — contract_mgmt.objid 기반 (wace 동일) */
|
||||||
|
,COALESCE(AF.cu01_cnt, 0) AS cu01_cnt
|
||||||
FROM project_mgmt T
|
FROM project_mgmt T
|
||||||
LEFT JOIN contract_mgmt CM ON CM.objid = T.contract_objid
|
LEFT JOIN contract_mgmt CM ON CM.objid = T.contract_objid
|
||||||
LEFT JOIN contract_item CI ON CI.objid = T.contract_item_objid AND CI.status = 'ACTIVE'
|
LEFT JOIN contract_item CI ON CI.objid = T.contract_item_objid AND CI.status = 'ACTIVE'
|
||||||
@@ -202,6 +203,14 @@ export async function getSaleList(filter: SaleListFilter) {
|
|||||||
AND CIS.serial_no IS NOT NULL AND CIS.serial_no != ''
|
AND CIS.serial_no IS NOT NULL AND CIS.serial_no != ''
|
||||||
GROUP BY CIS.item_objid
|
GROUP BY CIS.item_objid
|
||||||
) CIS_AGG ON CIS_AGG.item_objid = T.contract_item_objid
|
) CIS_AGG ON CIS_AGG.item_objid = T.contract_item_objid
|
||||||
|
/* 주문서첨부 카운트 (contract_mgmt.objid 기반, doc_type FTC_ORDER/ORDER — wace 동일) */
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT target_objid,
|
||||||
|
COUNT(*) FILTER (WHERE doc_type IN ('FTC_ORDER','ORDER')) AS cu01_cnt
|
||||||
|
FROM attach_file_info
|
||||||
|
WHERE UPPER(status) = 'ACTIVE'
|
||||||
|
GROUP BY target_objid
|
||||||
|
) AF ON AF.target_objid = T.contract_objid
|
||||||
${where}
|
${where}
|
||||||
ORDER BY T.regdate DESC NULLS LAST, T.project_no DESC
|
ORDER BY T.regdate DESC NULLS LAST, T.project_no DESC
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# 03. 판매관리 wace 1:1 검증
|
||||||
|
|
||||||
|
> 작성: 2026-05-11 / 사이클: 구조적 검증 3차 (판매관리 메뉴)
|
||||||
|
> 원본: `wace_plm/WebContent/WEB-INF/view/salesmgmt/salesMgmt/salesMgmtList.jsp`
|
||||||
|
> 대상: `app/(main)/COMPANY_16/sales/sale/page.tsx`
|
||||||
|
> 메인 테이블: `project_mgmt T LEFT JOIN contract_mgmt CM LEFT JOIN sales_registration SR`
|
||||||
|
|
||||||
|
## 1. 그리드 컬럼 — wace 활성 36개 vs RPS 36개 (보강 후 일치)
|
||||||
|
|
||||||
|
| # | wace title | RPS GRID_COLUMNS key | 상태 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 1 | 프로젝트번호 (frozen) | `project_no` | ✅ |
|
||||||
|
| 2 | 주문유형 | `order_type_name` | ✅ |
|
||||||
|
| 3 | 발주일 | `order_date` | ✅ |
|
||||||
|
| 4 | 발주번호 | `po_no` | ✅ |
|
||||||
|
| 5 | 요청납기 | `request_date` | ✅ |
|
||||||
|
| 6 | 출하일 | `shipping_date` | ✅ |
|
||||||
|
| 7 | 고객사 | `customer` | ✅ |
|
||||||
|
| 8 | 품명 | `product_name` | ✅ |
|
||||||
|
| 9 | 수주수량 | `order_quantity` | ✅ |
|
||||||
|
| 10 | 판매수량 | `sales_quantity` | ✅ |
|
||||||
|
| 11 | 잔량 | `remaining_quantity` | ✅ |
|
||||||
|
| 12 | 판매단가 | `sales_unit_price` | ✅ |
|
||||||
|
| 13 | 판매공급가액 | `sales_supply_price` | ✅ |
|
||||||
|
| 14 | 부가세 | `sales_vat` | ✅ |
|
||||||
|
| 15 | 판매총액 | `sales_total_amount` | ✅ |
|
||||||
|
| 16 | 판매원화총액 | `sales_total_amount_krw` | ✅ |
|
||||||
|
| 17 | 잔량원화총액 | `remaining_amount_krw` | ✅ |
|
||||||
|
| 18 | 수주상태 | `order_status_name` | ✅ |
|
||||||
|
| 19 | 판매상태 | `sales_status` | ✅ (wace 로직: 미판매/완판/분할판매 동적) |
|
||||||
|
| 20 | 생산상태 | `production_status` | ✅ (placeholder) |
|
||||||
|
| 21 | 출하지시상태 | `shipping_order_status` | ✅ |
|
||||||
|
| 22 | 유/무상 | `payment_type_name` | ✅ |
|
||||||
|
| 23 | 환종 | `sales_currency_name` | ✅ |
|
||||||
|
| 24 | 환율 | `sales_exchange_rate` | ✅ |
|
||||||
|
| 25 | S/N | `serial_no` | ✅ |
|
||||||
|
| 26 | 분할S/N | `split_serial_no` | ✅ (placeholder) |
|
||||||
|
| 27 | 품번 | `product_no` | ✅ |
|
||||||
|
| 28 | **제품구분** | `product_type_name` | ✅ (신규) |
|
||||||
|
| 29 | **국내/해외** | `nation_name` | ✅ (신규) |
|
||||||
|
| 30 | **접수일** | `receipt_date` | ✅ (신규) |
|
||||||
|
| 31 | **고객사요청사항** | `customer_request` | ✅ (신규) |
|
||||||
|
| 32 | **주문서첨부** | `cu01_cnt` (clip) | ✅ (신규, attach_file_info LATERAL JOIN) |
|
||||||
|
| 33 | **출하방법** | `shipping_method` | ✅ (신규) |
|
||||||
|
| 34 | **담당자** | `manager_name` | ✅ (신규) |
|
||||||
|
| 35 | **인도조건** | `incoterms` | ✅ (신규) |
|
||||||
|
| 36 | 거래명세서 | `has_transaction_statement` | ✅ (placeholder) |
|
||||||
|
|
||||||
|
## 2. SQL 핵심 구조
|
||||||
|
|
||||||
|
```
|
||||||
|
FROM project_mgmt T
|
||||||
|
LEFT JOIN contract_mgmt CM ON CM.objid = T.contract_objid
|
||||||
|
LEFT JOIN contract_item CI ON CI.objid = T.contract_item_objid
|
||||||
|
LEFT JOIN customer_mng C ON C.customer_code = SUBSTRING(T.customer_objid, 3)
|
||||||
|
LEFT JOIN sales_registration SR ON SR.project_no = T.project_no
|
||||||
|
LEFT JOIN user_info U_MGR ON U_MGR.user_id = SR.manager_user_id
|
||||||
|
LEFT JOIN comm_code CC_* ON CC_*.code_id = T.* AND status='active' (CAT/AREA/PRD/RES/CUR/CUR_S)
|
||||||
|
LEFT JOIN SR_AGG ON SR_AGG.project_no LIKE T.project_no || '%' (판매수량 합계 — 분할판매 패턴)
|
||||||
|
LEFT JOIN CIS_AGG ON CIS_AGG.item_objid = T.contract_item_objid (S/N 집계)
|
||||||
|
LEFT JOIN AF ON AF.target_objid = T.contract_objid (주문서첨부 신규)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. 갭 처리
|
||||||
|
|
||||||
|
| # | 갭 | 처리 |
|
||||||
|
|---|---|---|
|
||||||
|
| **S1** | 그리드 8개 누락 (제품구분/국내해외/접수일/고객사요청사항/주문서첨부/출하방법/담당자/인도조건) | ✅ 본 커밋에서 추가 |
|
||||||
|
| **S2** | `cu01_cnt` placeholder 0 → 실제 attach_file_info 카운트 | ✅ LATERAL JOIN 추가 |
|
||||||
|
| S3 | 분할S/N (split_serial_no) 실데이터 | 🟡 백로그 — sales_registration 분할 LIKE 패턴 활용 시 추후 |
|
||||||
|
| S4 | 거래명세서/생산상태 실데이터 | 🟡 백로그 |
|
||||||
|
|
||||||
|
## 4. 자동 검증 결과 (`scripts/verify-sale.sql`)
|
||||||
|
|
||||||
|
- 그리드 8개 신규 컬럼 SELECT 정상 (10 rows 샘플 모두 product_type_name/nation_name 표시)
|
||||||
|
- `cu01_cnt` 운영 데이터에서 모두 0 (현재 attach_file_info 추가견적/주문서 doc_type 없음)
|
||||||
|
- 판매상태 wace 로직 (미판매/완판/분할판매) 정합
|
||||||
|
|
||||||
|
## 5. 결론
|
||||||
|
|
||||||
|
판매관리 메뉴 wace 운영 화면과 1:1 정합 (36/36 컬럼).
|
||||||
|
**다음 메뉴**: 매출관리 (revenue) — `shipment_log` 기반.
|
||||||
@@ -48,6 +48,14 @@ const GRID_COLUMNS: DataGridColumn[] = [
|
|||||||
{ key: "serial_no", label: "S/N", width: "w-[140px]" },
|
{ key: "serial_no", label: "S/N", width: "w-[140px]" },
|
||||||
{ key: "split_serial_no", label: "분할S/N", width: "w-[140px]" },
|
{ key: "split_serial_no", label: "분할S/N", width: "w-[140px]" },
|
||||||
{ key: "product_no", label: "품번", width: "w-[120px]" },
|
{ key: "product_no", label: "품번", width: "w-[120px]" },
|
||||||
|
{ key: "product_type_name", label: "제품구분", width: "w-[90px]", align: "center" },
|
||||||
|
{ key: "nation_name", label: "국내/해외", width: "w-[90px]", align: "center" },
|
||||||
|
{ key: "receipt_date", label: "접수일", width: "w-[110px]", align: "center" },
|
||||||
|
{ key: "customer_request", label: "고객사요청사항", width: "w-[180px]" },
|
||||||
|
{ key: "cu01_cnt", label: "주문서첨부", width: "w-[90px]", align: "center", renderType: "clip" },
|
||||||
|
{ key: "shipping_method", label: "출하방법", width: "w-[90px]", align: "center" },
|
||||||
|
{ key: "manager_name", label: "담당자", width: "w-[100px]", align: "center" },
|
||||||
|
{ key: "incoterms", label: "인도조건", width: "w-[90px]", align: "center" },
|
||||||
{ key: "has_transaction_statement", label: "거래명세서", width: "w-[100px]", align: "center" },
|
{ key: "has_transaction_statement", label: "거래명세서", width: "w-[100px]", align: "center" },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,14 @@ export interface SaleListRow {
|
|||||||
sales_status: string;
|
sales_status: string;
|
||||||
production_status: string | null;
|
production_status: string | null;
|
||||||
payment_type: string | null;
|
payment_type: string | null;
|
||||||
|
payment_type_name: string | null;
|
||||||
nation: string | null;
|
nation: string | null;
|
||||||
|
nation_name: string | null;
|
||||||
|
product_type_name: string | null;
|
||||||
|
receipt_date: string | null;
|
||||||
|
customer_request: string | null;
|
||||||
|
manager_name: string | null;
|
||||||
|
cu01_cnt: number | null;
|
||||||
serial_no: string | null;
|
serial_no: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- 판매관리 자동 검증 SQL (BEGIN/ROLLBACK 시나리오)
|
||||||
|
-- 메인 테이블: project_mgmt + sales_registration + contract_mgmt
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
\echo ''
|
||||||
|
\echo '================== Sale 검증 시작 =================='
|
||||||
|
|
||||||
|
-- ─────────────────────────────────────────────────────────
|
||||||
|
-- [0] 사전 카운트
|
||||||
|
-- ─────────────────────────────────────────────────────────
|
||||||
|
\echo ''
|
||||||
|
\echo '[0] 사전 카운트 ============================'
|
||||||
|
SELECT 'project_mgmt' AS tbl, COUNT(*) FROM project_mgmt
|
||||||
|
UNION ALL SELECT 'sales_registration', COUNT(*) FROM sales_registration
|
||||||
|
UNION ALL SELECT 'project_mgmt matched by SR.project_no LIKE',
|
||||||
|
COUNT(DISTINCT T.project_no)
|
||||||
|
FROM project_mgmt T JOIN sales_registration SR ON SR.project_no LIKE T.project_no || '%';
|
||||||
|
|
||||||
|
-- ─────────────────────────────────────────────────────────
|
||||||
|
-- [1] 그리드 V1 신규 8개 컬럼 정합성 검증
|
||||||
|
-- ─────────────────────────────────────────────────────────
|
||||||
|
\echo ''
|
||||||
|
\echo '[1] 그리드 V1 신규 컬럼 (제품구분/국내해외/접수일/고객사요청사항/주문서첨부/출하방법/담당자/인도조건) =========================='
|
||||||
|
SELECT
|
||||||
|
T.project_no,
|
||||||
|
CC_PRD.code_name AS product_type_name,
|
||||||
|
CC_AREA.code_name AS nation_name,
|
||||||
|
CM.receipt_date,
|
||||||
|
COALESCE(NULLIF(CM.customer_request, ''), '-') AS customer_request,
|
||||||
|
COALESCE(AF.cu01_cnt, 0) AS cu01_cnt,
|
||||||
|
SR.shipping_method,
|
||||||
|
U_MGR.user_name AS manager_name,
|
||||||
|
SR.incoterms
|
||||||
|
FROM project_mgmt T
|
||||||
|
LEFT JOIN contract_mgmt CM ON CM.objid = T.contract_objid
|
||||||
|
LEFT JOIN sales_registration SR ON SR.project_no = T.project_no
|
||||||
|
LEFT JOIN user_info U_MGR ON U_MGR.user_id = SR.manager_user_id
|
||||||
|
LEFT JOIN comm_code CC_AREA ON CC_AREA.code_id = T.area_cd AND CC_AREA.status='active'
|
||||||
|
LEFT JOIN comm_code CC_PRD ON CC_PRD.code_id = T.product AND CC_PRD.status='active'
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT target_objid,
|
||||||
|
COUNT(*) FILTER (WHERE doc_type IN ('FTC_ORDER','ORDER')) AS cu01_cnt
|
||||||
|
FROM attach_file_info WHERE UPPER(status)='ACTIVE'
|
||||||
|
GROUP BY target_objid
|
||||||
|
) AF ON AF.target_objid = T.contract_objid
|
||||||
|
ORDER BY T.regdate DESC NULLS LAST, T.project_no DESC
|
||||||
|
LIMIT 10;
|
||||||
|
|
||||||
|
-- ─────────────────────────────────────────────────────────
|
||||||
|
-- [2] 판매상태 wace 로직 검증 (미판매/완판/분할판매)
|
||||||
|
-- ─────────────────────────────────────────────────────────
|
||||||
|
\echo ''
|
||||||
|
\echo '[2] 판매상태 wace 로직 (미판매/완판/분할판매) =========================='
|
||||||
|
SELECT
|
||||||
|
T.project_no,
|
||||||
|
T.quantity AS order_qty,
|
||||||
|
COALESCE(SR_AGG.sales_qty_sum, 0) AS sales_qty_sum,
|
||||||
|
CASE
|
||||||
|
WHEN COALESCE(SR_AGG.sales_qty_sum, 0) = 0 THEN '미판매'
|
||||||
|
WHEN COALESCE(SR_AGG.sales_qty_sum, 0) >= COALESCE(CAST(NULLIF(REPLACE(T.quantity, ',', ''), '') AS NUMERIC), 0) THEN '완판'
|
||||||
|
WHEN COALESCE(SR_AGG.sales_qty_sum, 0) > 0 THEN '분할판매'
|
||||||
|
ELSE ''
|
||||||
|
END AS sales_status
|
||||||
|
FROM project_mgmt T
|
||||||
|
LEFT JOIN (
|
||||||
|
SELECT SR2.project_no, SUM(SR2.sales_quantity) AS sales_qty_sum
|
||||||
|
FROM sales_registration SR2
|
||||||
|
GROUP BY SR2.project_no
|
||||||
|
) SR_AGG ON SR_AGG.project_no LIKE T.project_no || '%'
|
||||||
|
ORDER BY T.regdate DESC NULLS LAST
|
||||||
|
LIMIT 10;
|
||||||
|
|
||||||
|
|
||||||
|
\echo ''
|
||||||
|
\echo '================== Sale 검증 끝 =================='
|
||||||
Reference in New Issue
Block a user