ERP-node/frontend/lib/registry/components/repeat-screen-modal/README.md

410 lines
15 KiB
Markdown

# RepeatScreenModal 컴포넌트 v3.1
## 개요
`RepeatScreenModal`은 선택한 데이터를 기반으로 여러 개의 카드를 생성하고, 각 카드의 내부 레이아웃을 자유롭게 구성할 수 있는 컴포넌트입니다.
## v3.1 주요 변경사항 (2025-11-28)
### 1. 외부 테이블 데이터 소스
테이블 행에서 **외부 테이블의 데이터를 조회**하여 표시할 수 있습니다.
```
예시: 수주 관리에서 출하 계획 이력 조회
┌─────────────────────────────────────────────────────────────────┐
│ 카드: 품목 A │
├─────────────────────────────────────────────────────────────────┤
│ [행 1] 헤더: 품목코드, 품목명 │
├─────────────────────────────────────────────────────────────────┤
│ [행 2] 테이블: shipment_plan 테이블에서 조회 │
│ → sales_order_id로 조인하여 출하 계획 이력 표시 │
└─────────────────────────────────────────────────────────────────┘
```
### 2. 테이블 행 CRUD
테이블 행에서 **행 추가/수정/삭제** 기능을 지원합니다.
- **추가**: 새 행 추가 버튼으로 빈 행 생성
- **수정**: 편집 가능한 컬럼 직접 수정
- **삭제**: 행 삭제 (확인 팝업 옵션)
### 3. Footer 버튼 영역
모달 하단에 **커스터마이징 가능한 버튼 영역**을 제공합니다.
```
┌─────────────────────────────────────────────────────────────────┐
│ 카드 내용... │
├─────────────────────────────────────────────────────────────────┤
│ [초기화] [취소] [저장] │
└─────────────────────────────────────────────────────────────────┘
```
### 4. 집계 연산식 지원
집계 행에서 **컬럼 간 사칙연산**을 지원합니다.
```typescript
// 예: 미출하 수량 = 수주수량 - 출하수량
{
sourceType: "formula",
formula: "{order_qty} - {ship_qty}",
label: "미출하 수량"
}
```
---
## v3 주요 변경사항 (기존)
### 자유 레이아웃 시스템
기존의 "simple 모드 / withTable 모드" 구분을 없애고, **행(Row)을 추가하고 각 행마다 타입을 선택**하는 방식으로 변경되었습니다.
```
┌─────────────────────────────────────────────────────────────────┐
│ 카드 │
├─────────────────────────────────────────────────────────────────┤
│ [행 1] 타입: 헤더 → 품목코드, 품목명, 규격 │
├─────────────────────────────────────────────────────────────────┤
│ [행 2] 타입: 집계 → 총수주잔량, 현재고, 가용재고 │
├─────────────────────────────────────────────────────────────────┤
│ [행 3] 타입: 테이블 → 수주번호, 거래처, 납기일, 출하계획 │
├─────────────────────────────────────────────────────────────────┤
│ [행 4] 타입: 테이블 → 또 다른 테이블도 가능! │
└─────────────────────────────────────────────────────────────────┘
```
### 행 타입
| 타입 | 설명 | 사용 시나리오 |
|------|------|---------------|
| **헤더 (header)** | 필드들을 가로/세로로 나열 | 품목정보, 거래처정보 표시 |
| **필드 (fields)** | 헤더와 동일, 편집 가능 | 폼 입력 영역 |
| **집계 (aggregation)** | 그룹 내 데이터 집계값 표시 | 총수량, 합계금액 등 |
| **테이블 (table)** | 그룹 내 각 행을 테이블로 표시 | 수주목록, 품목목록 등 |
---
## 설정 방법
### 1. 기본 설정 탭
- **카드 제목 표시**: 카드 상단에 제목을 표시할지 여부
- **카드 제목 템플릿**: `{field_name}` 형식으로 동적 제목 생성
- **카드 간격**: 카드 사이의 간격 (8px ~ 32px)
- **테두리**: 카드 테두리 표시 여부
- **저장 모드**: 전체 저장 / 개별 저장
### 2. 데이터 소스 탭
- **소스 테이블**: 데이터를 조회할 테이블
- **필터 필드**: formData에서 필터링할 필드 (예: selectedIds)
### 3. 그룹 탭
- **그룹핑 활성화**: 여러 행을 하나의 카드로 묶을지 여부
- **그룹 기준 필드**: 그룹핑할 필드 (예: part_code)
- **집계 설정**:
- 원본 필드: 합계할 필드 (예: balance_qty)
- 집계 타입: sum, count, avg, min, max
- 결과 필드명: 집계 결과를 저장할 필드명
- 라벨: 표시될 라벨
### 4. 레이아웃 탭
#### 행 추가
4가지 타입의 행을 추가할 수 있습니다:
- **헤더**: 필드 정보 표시 (읽기전용)
- **집계**: 그룹 집계값 표시
- **테이블**: 그룹 내 행들을 테이블로 표시
- **필드**: 입력 필드 (편집가능)
#### 헤더/필드 행 설정
- **방향**: 가로 / 세로
- **배경색**: 없음, 파랑, 초록, 보라, 주황
- **컬럼**: 필드명, 라벨, 타입, 너비, 편집 가능, 필수
- **소스 설정**: 직접 / 조인 / 수동
- **저장 설정**: 저장할 테이블과 컬럼
#### 집계 행 설정
- **레이아웃**: 가로 나열 / 그리드
- **그리드 컬럼 수**: 2, 3, 4개
- **집계 필드**: 그룹 탭에서 정의한 집계 결과 선택
- **스타일**: 배경색, 폰트 크기
#### 테이블 행 설정 (v3.1 확장)
- **테이블 제목**: 선택사항
- **헤더 표시**: 테이블 헤더 표시 여부
- **외부 테이블 데이터 소스**: (v3.1 신규)
- 소스 테이블: 조회할 외부 테이블
- 조인 조건: 외부 테이블 키 ↔ 카드 데이터 키
- 정렬: 정렬 컬럼 및 방향
- **CRUD 설정**: (v3.1 신규)
- 추가: 새 행 추가 허용
- 수정: 행 수정 허용
- 삭제: 행 삭제 허용 (확인 팝업 옵션)
- **테이블 컬럼**: 필드명, 라벨, 타입, 너비, 편집 가능
- **저장 설정**: 편집 가능한 컬럼의 저장 위치
### 5. Footer 탭 (v3.1 신규)
- **Footer 사용**: Footer 영역 활성화
- **위치**: 컨텐츠 아래 / 하단 고정 (sticky)
- **정렬**: 왼쪽 / 가운데 / 오른쪽
- **버튼 설정**:
- 라벨: 버튼 텍스트
- 액션: 저장 / 취소 / 닫기 / 초기화 / 커스텀
- 스타일: 기본 / 보조 / 외곽선 / 삭제 / 고스트
- 아이콘: 저장 / X / 초기화 / 없음
---
## 데이터 흐름
```
1. formData에서 selectedIds 가져오기
2. 소스 테이블에서 해당 ID들의 데이터 조회
3. 그룹핑 활성화 시 groupByField 기준으로 그룹화
4. 각 그룹에 대해 집계값 계산
5. 외부 테이블 데이터 소스가 설정된 테이블 행의 데이터 로드 (v3.1)
6. 카드 렌더링 (contentRows 기반)
7. 사용자 편집 (CRUD 포함)
8. Footer 버튼 또는 기본 저장 버튼으로 저장
9. 기본 데이터 + 외부 테이블 데이터 일괄 저장
```
---
## 사용 예시
### 출하계획 등록 (v3.1 - 외부 테이블 + CRUD)
```typescript
{
showCardTitle: true,
cardTitle: "{part_code} - {part_name}",
dataSource: {
sourceTable: "sales_order_mng",
filterField: "selectedIds"
},
grouping: {
enabled: true,
groupByField: "part_code",
aggregations: [
{ sourceField: "balance_qty", type: "sum", resultField: "total_balance", label: "총수주잔량" },
{ sourceField: "id", type: "count", resultField: "order_count", label: "수주건수" }
]
},
contentRows: [
{
id: "row-1",
type: "header",
columns: [
{ id: "c1", field: "part_code", label: "품목코드", type: "text", editable: false },
{ id: "c2", field: "part_name", label: "품목명", type: "text", editable: false }
],
layout: "horizontal"
},
{
id: "row-2",
type: "aggregation",
aggregationLayout: "horizontal",
aggregationFields: [
{ sourceType: "aggregation", aggregationResultField: "total_balance", label: "총수주잔량", backgroundColor: "blue" },
{ sourceType: "formula", formula: "{order_qty} - {ship_qty}", label: "미출하 수량", backgroundColor: "orange" }
]
},
{
id: "row-3",
type: "table",
tableTitle: "출하 계획 이력",
showTableHeader: true,
// 외부 테이블에서 데이터 조회
tableDataSource: {
enabled: true,
sourceTable: "shipment_plan",
joinConditions: [
{ sourceKey: "sales_order_id", referenceKey: "id" }
],
orderBy: { column: "created_date", direction: "desc" }
},
// CRUD 설정
tableCrud: {
allowCreate: true,
allowUpdate: true,
allowDelete: true,
newRowDefaults: {
sales_order_id: "{id}",
status: "READY"
},
deleteConfirm: { enabled: true }
},
tableColumns: [
{ id: "tc1", field: "plan_date", label: "계획일", type: "date", editable: true },
{ id: "tc2", field: "plan_qty", label: "계획수량", type: "number", editable: true },
{ id: "tc3", field: "status", label: "상태", type: "text", editable: false },
{ id: "tc4", field: "memo", label: "비고", type: "text", editable: true }
]
}
],
// Footer 설정
footerConfig: {
enabled: true,
position: "sticky",
alignment: "right",
buttons: [
{ id: "btn-cancel", label: "취소", action: "cancel", variant: "outline" },
{ id: "btn-save", label: "저장", action: "save", variant: "default", icon: "save" }
]
}
}
```
---
## 타입 정의 (v3.1)
### TableDataSourceConfig
```typescript
interface TableDataSourceConfig {
enabled: boolean; // 외부 데이터 소스 사용 여부
sourceTable: string; // 조회할 테이블
joinConditions: JoinCondition[]; // 조인 조건
orderBy?: {
column: string; // 정렬 컬럼
direction: "asc" | "desc"; // 정렬 방향
};
limit?: number; // 최대 행 수
}
interface JoinCondition {
sourceKey: string; // 외부 테이블의 조인 키
referenceKey: string; // 카드 데이터의 참조 키
referenceType?: "card" | "row"; // 참조 소스
}
```
### TableCrudConfig
```typescript
interface TableCrudConfig {
allowCreate: boolean; // 행 추가 허용
allowUpdate: boolean; // 행 수정 허용
allowDelete: boolean; // 행 삭제 허용
newRowDefaults?: Record<string, string>; // 신규 행 기본값 ({field} 형식 지원)
deleteConfirm?: {
enabled: boolean; // 삭제 확인 팝업
message?: string; // 확인 메시지
};
targetTable?: string; // 저장 대상 테이블
}
```
### FooterConfig
```typescript
interface FooterConfig {
enabled: boolean; // Footer 사용 여부
buttons?: FooterButtonConfig[];
position?: "sticky" | "static";
alignment?: "left" | "center" | "right";
}
interface FooterButtonConfig {
id: string;
label: string;
action: "save" | "cancel" | "close" | "reset" | "custom";
variant?: "default" | "secondary" | "outline" | "destructive" | "ghost";
icon?: string;
disabled?: boolean;
customAction?: {
type: string;
config?: Record<string, any>;
};
}
```
### AggregationDisplayConfig (v3.1 확장)
```typescript
interface AggregationDisplayConfig {
// 값 소스 타입
sourceType: "aggregation" | "formula" | "external" | "externalFormula";
// aggregation: 기존 집계 결과 참조
aggregationResultField?: string;
// formula: 컬럼 간 연산
formula?: string; // 예: "{order_qty} - {ship_qty}"
// external: 외부 테이블 조회 (향후 구현)
externalSource?: ExternalValueSource;
// externalFormula: 외부 테이블 + 연산 (향후 구현)
externalSources?: ExternalValueSource[];
externalFormula?: string;
// 표시 설정
label: string;
icon?: string;
backgroundColor?: string;
textColor?: string;
fontSize?: "xs" | "sm" | "base" | "lg" | "xl" | "2xl";
format?: "number" | "currency" | "percent";
decimalPlaces?: number;
}
```
---
## 레거시 호환
v2에서 사용하던 `cardMode`, `cardLayout`, `tableLayout` 설정도 계속 지원됩니다.
새로운 프로젝트에서는 `contentRows`를 사용하는 것을 권장합니다.
---
## 주의사항
1. **집계는 그룹핑 필수**: 집계 행은 그룹핑이 활성화되어 있어야 의미가 있습니다.
2. **테이블은 그룹핑 필수**: 테이블 행도 그룹핑이 활성화되어 있어야 그룹 내 행들을 표시할 수 있습니다.
3. **단순 모드**: 그룹핑 없이 사용하면 1행 = 1카드로 동작합니다. 이 경우 헤더/필드 타입만 사용 가능합니다.
4. **외부 테이블 CRUD**: 외부 테이블 데이터 소스가 설정된 테이블에서만 CRUD가 동작합니다.
5. **연산식**: 사칙연산(+, -, *, /)과 괄호만 지원됩니다. 복잡한 함수는 지원하지 않습니다.
---
## 변경 이력
### v3.1 (2025-11-28)
- 외부 테이블 데이터 소스 기능 추가
- 테이블 행 CRUD (추가/수정/삭제) 기능 추가
- Footer 버튼 영역 기능 추가
- 집계 연산식 (formula) 지원 추가
- 다단계 조인 타입 정의 추가 (향후 구현 예정)
### v3.0
- 자유 레이아웃 시스템 도입
- contentRows 기반 행 타입 선택 방식
- 헤더/필드/집계/테이블 4가지 행 타입 지원
### v2.0
- simple 모드 / withTable 모드 구분
- cardLayout / tableLayout 분리