Remove outdated documents related to the approval system and WACE system analysis
- Deleted the following files as they are no longer relevant to the current project structure: - 결재 시스템 구현 현황 - 결재 시스템 v2 사용 가이드 - WACE 시스템 문제점 분석 및 개선 계획 - Agent Pipeline 한계점 분석 - AI 기반 화면 자동 생성 시스템 설계서 - WACE ERP Backend - 분석 문서 인덱스 These deletions help streamline the documentation and remove obsolete information, ensuring that only current and relevant resources are maintained.
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
# 다중 테이블 엑셀 업로드 범용 시스템
|
||||
|
||||
## 개요
|
||||
하나의 플랫 엑셀 파일로 계층적 다중 테이블(2~N개)에 데이터를 일괄 등록하는 범용 시스템.
|
||||
거래처 관리(customer_mng → customer_item_mapping → customer_item_prices)를 첫 번째 적용 대상으로 하되,
|
||||
공급업체, BOM 등 다른 화면에서도 재사용 가능하도록 설계한다.
|
||||
|
||||
## 핵심 기능
|
||||
1. 모드 선택: 어느 레벨까지 등록할지 사용자가 선택
|
||||
2. 템플릿 다운로드: 모드에 맞는 엑셀 양식 자동 생성
|
||||
3. 파일 업로드: 플랫 엑셀 → 계층 그룹핑 → 트랜잭션 UPSERT
|
||||
4. 컬럼 매핑: 엑셀 헤더 ↔ DB 컬럼 자동/수동 매핑
|
||||
|
||||
## DB 테이블 관계 (거래처 관리)
|
||||
|
||||
```
|
||||
customer_mng (Level 1 - 루트)
|
||||
PK: id (SERIAL)
|
||||
UNIQUE: customer_code
|
||||
└─ customer_item_mapping (Level 2)
|
||||
PK: id (UUID)
|
||||
FK: customer_id → customer_mng.id
|
||||
UPSERT키: customer_id + customer_item_code
|
||||
└─ customer_item_prices (Level 3)
|
||||
PK: id (UUID)
|
||||
FK: mapping_id → customer_item_mapping.id
|
||||
항상 INSERT (기간별 단가 이력)
|
||||
```
|
||||
|
||||
## 범용 설정 구조 (TableChainConfig)
|
||||
|
||||
```typescript
|
||||
interface TableLevel {
|
||||
tableName: string;
|
||||
label: string;
|
||||
// 부모와의 관계
|
||||
parentFkColumn?: string; // 이 테이블에서 부모를 참조하는 FK 컬럼
|
||||
parentRefColumn?: string; // 부모 테이블에서 참조되는 컬럼 (PK 또는 UNIQUE)
|
||||
// UPSERT 설정
|
||||
upsertMode: 'upsert' | 'insert'; // upsert: 기존 데이터 있으면 UPDATE, insert: 항상 신규
|
||||
upsertKeyColumns?: string[]; // UPSERT 매칭 키 (예: ['customer_code'])
|
||||
// 엑셀 매핑 컬럼
|
||||
columns: Array<{
|
||||
dbColumn: string;
|
||||
excelHeader: string;
|
||||
required: boolean;
|
||||
defaultValue?: any;
|
||||
}>;
|
||||
}
|
||||
|
||||
interface TableChainConfig {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
levels: TableLevel[]; // 0 = 루트, 1 = 자식, 2 = 손자...
|
||||
uploadModes: Array<{
|
||||
id: string;
|
||||
label: string;
|
||||
description: string;
|
||||
activeLevels: number[]; // 이 모드에서 활성화되는 레벨 인덱스
|
||||
}>;
|
||||
}
|
||||
```
|
||||
|
||||
## 거래처 관리 설정 예시
|
||||
|
||||
```typescript
|
||||
const customerChainConfig: TableChainConfig = {
|
||||
id: 'customer_management',
|
||||
name: '거래처 관리',
|
||||
description: '거래처, 품목매핑, 단가 일괄 등록',
|
||||
levels: [
|
||||
{
|
||||
tableName: 'customer_mng',
|
||||
label: '거래처',
|
||||
upsertMode: 'upsert',
|
||||
upsertKeyColumns: ['customer_code'],
|
||||
columns: [
|
||||
{ dbColumn: 'customer_code', excelHeader: '거래처코드', required: true },
|
||||
{ dbColumn: 'customer_name', excelHeader: '거래처명', required: true },
|
||||
{ dbColumn: 'division', excelHeader: '구분', required: false },
|
||||
{ dbColumn: 'contact_person', excelHeader: '담당자', required: false },
|
||||
{ dbColumn: 'contact_phone', excelHeader: '연락처', required: false },
|
||||
{ dbColumn: 'email', excelHeader: '이메일', required: false },
|
||||
{ dbColumn: 'business_number', excelHeader: '사업자번호', required: false },
|
||||
{ dbColumn: 'address', excelHeader: '주소', required: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: 'customer_item_mapping',
|
||||
label: '품목매핑',
|
||||
parentFkColumn: 'customer_id',
|
||||
parentRefColumn: 'id',
|
||||
upsertMode: 'upsert',
|
||||
upsertKeyColumns: ['customer_id', 'customer_item_code'],
|
||||
columns: [
|
||||
{ dbColumn: 'customer_item_code', excelHeader: '거래처품번', required: true },
|
||||
{ dbColumn: 'customer_item_name', excelHeader: '거래처품명', required: true },
|
||||
{ dbColumn: 'item_id', excelHeader: '품목ID', required: false },
|
||||
],
|
||||
},
|
||||
{
|
||||
tableName: 'customer_item_prices',
|
||||
label: '단가',
|
||||
parentFkColumn: 'mapping_id',
|
||||
parentRefColumn: 'id',
|
||||
upsertMode: 'insert',
|
||||
columns: [
|
||||
{ dbColumn: 'base_price', excelHeader: '기준단가', required: true },
|
||||
{ dbColumn: 'discount_type', excelHeader: '할인유형', required: false },
|
||||
{ dbColumn: 'discount_value', excelHeader: '할인값', required: false },
|
||||
{ dbColumn: 'start_date', excelHeader: '적용시작일', required: false },
|
||||
{ dbColumn: 'end_date', excelHeader: '적용종료일', required: false },
|
||||
{ dbColumn: 'currency_code', excelHeader: '통화', required: false },
|
||||
],
|
||||
},
|
||||
],
|
||||
uploadModes: [
|
||||
{ id: 'customer_only', label: '거래처만 등록', description: '거래처 기본정보만', activeLevels: [0] },
|
||||
{ id: 'customer_item', label: '거래처 + 품목정보', description: '거래처와 품목매핑', activeLevels: [0, 1] },
|
||||
{ id: 'customer_item_price', label: '거래처 + 품목 + 단가', description: '전체 등록', activeLevels: [0, 1, 2] },
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
## 처리 로직 (백엔드)
|
||||
|
||||
### 1단계: 그룹핑
|
||||
엑셀의 플랫 행을 계층별 그룹으로 변환:
|
||||
- Level 0 (거래처): customer_code 기준 그룹핑
|
||||
- Level 1 (품목매핑): customer_code + customer_item_code 기준 그룹핑
|
||||
- Level 2 (단가): 매 행마다 INSERT
|
||||
|
||||
### 2단계: 계단식 UPSERT (트랜잭션)
|
||||
```
|
||||
BEGIN TRANSACTION
|
||||
|
||||
FOR EACH unique customer_code:
|
||||
1. customer_mng UPSERT → 결과에서 id 획득 (returnedId)
|
||||
|
||||
FOR EACH unique customer_item_code (해당 거래처):
|
||||
2. customer_item_mapping의 customer_id = returnedId 주입
|
||||
UPSERT → 결과에서 id 획득 (mappingId)
|
||||
|
||||
FOR EACH price row (해당 품목매핑):
|
||||
3. customer_item_prices의 mapping_id = mappingId 주입
|
||||
INSERT
|
||||
|
||||
COMMIT (전체 성공) or ROLLBACK (하나라도 실패)
|
||||
```
|
||||
|
||||
### 3단계: 결과 반환
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"results": {
|
||||
"customer_mng": { "inserted": 2, "updated": 1 },
|
||||
"customer_item_mapping": { "inserted": 5, "updated": 2 },
|
||||
"customer_item_prices": { "inserted": 12 }
|
||||
},
|
||||
"errors": []
|
||||
}
|
||||
```
|
||||
|
||||
## 테스트 계획
|
||||
|
||||
### 1단계: 백엔드 서비스
|
||||
- [x] plan.md 작성
|
||||
- [ ] multiTableExcelService.ts 기본 구조 작성
|
||||
- [ ] 그룹핑 로직 구현
|
||||
- [ ] 계단식 UPSERT 로직 구현
|
||||
- [ ] 트랜잭션 처리
|
||||
- [ ] 에러 핸들링
|
||||
|
||||
### 2단계: API 엔드포인트
|
||||
- [ ] POST /api/data/multi-table/upload 추가
|
||||
- [ ] POST /api/data/multi-table/template 추가 (템플릿 다운로드)
|
||||
- [ ] 입력값 검증
|
||||
|
||||
### 3단계: 프론트엔드
|
||||
- [ ] MultiTableExcelUploadModal.tsx 컴포넌트 작성
|
||||
- [ ] 모드 선택 UI
|
||||
- [ ] 템플릿 다운로드 버튼
|
||||
- [ ] 파일 업로드 + 미리보기
|
||||
- [ ] 컬럼 매핑 UI
|
||||
- [ ] 업로드 결과 표시
|
||||
|
||||
### 4단계: 통합
|
||||
- [ ] 거래처 관리 화면에 연결
|
||||
- [ ] 실제 데이터로 테스트
|
||||
|
||||
## 진행 상태
|
||||
- 완료된 테스트는 [x]로 표시
|
||||
- 현재 진행 중인 테스트는 [진행중]으로 표시
|
||||
Reference in New Issue
Block a user