213 lines
6.5 KiB
Markdown
213 lines
6.5 KiB
Markdown
# 집계 위젯 (Aggregation Widget) 개발 진행상황
|
|
|
|
## 개요
|
|
데이터의 합계, 평균, 개수, 최대값, 최소값 등을 집계하여 표시하는 위젯
|
|
|
|
## 파일 위치
|
|
- **V2 버전**: `frontend/lib/registry/components/v2-aggregation-widget/`
|
|
- `index.ts` - 컴포넌트 정의
|
|
- `types.ts` - 타입 정의
|
|
- `AggregationWidgetComponent.tsx` - 메인 컴포넌트
|
|
- `AggregationWidgetConfigPanel.tsx` - 설정 패널
|
|
- `AggregationWidgetRenderer.tsx` - 렌더러
|
|
|
|
- **기존 버전**: `frontend/lib/registry/components/aggregation-widget/`
|
|
|
|
---
|
|
|
|
## 완료된 기능
|
|
|
|
### 1. 기본 집계 기능
|
|
- [x] 테이블 데이터 조회 및 집계 (SUM, AVG, COUNT, MAX, MIN)
|
|
- [x] 숫자형 컬럼 자동 감지 (`inputType` / `webType` 기반)
|
|
- [x] 집계 결과 포맷팅 (숫자, 통화, 퍼센트)
|
|
- [x] 가로/세로 레이아웃 지원
|
|
|
|
### 2. 데이터 소스 타입
|
|
- [x] `table` - 테이블에서 직접 조회
|
|
- [x] `component` - 다른 컴포넌트(리피터 등)에서 데이터 수신
|
|
- [x] `selection` - 선택된 행 데이터로 집계
|
|
|
|
### 3. 필터 조건
|
|
- [x] 필터 추가/삭제/활성화 UI
|
|
- [x] 연산자: =, !=, >, >=, <, <=, LIKE, IN, IS NULL, IS NOT NULL
|
|
- [x] 필터 결합 방식: AND / OR
|
|
- [x] 값 소스 타입:
|
|
- [x] `static` - 고정값 입력
|
|
- [x] `formField` - 폼 필드에서 가져오기
|
|
- [x] `selection` - 선택된 행에서 가져오기 (부분 완료)
|
|
- [x] `urlParam` - URL 파라미터에서 가져오기
|
|
- [x] 카테고리 타입 컬럼 - 콤보박스로 값 선택
|
|
|
|
### 4. 자동 새로고침
|
|
- [x] `autoRefresh` - 주기적 새로고침
|
|
- [x] `refreshInterval` - 새로고침 간격 (초)
|
|
- [x] `refreshOnFormChange` - 폼 데이터 변경 시 새로고침
|
|
|
|
### 5. 스타일 설정
|
|
- [x] 배경색, 테두리, 패딩
|
|
- [x] 폰트 크기, 색상
|
|
- [x] 라벨/아이콘 표시 여부
|
|
|
|
---
|
|
|
|
## 미완료 기능
|
|
|
|
### 1. 선택 데이터 필터 - 소스 컴포넌트 연동 (진행중)
|
|
|
|
**현재 상태**:
|
|
- `FilterCondition`에 `sourceComponentId` 필드 추가됨
|
|
- 설정 패널 UI에 소스 컴포넌트 선택 드롭다운 추가됨
|
|
- 소스 컴포넌트 컬럼 로딩 함수 구현됨
|
|
|
|
**문제점**:
|
|
- `screenComponents`가 빈 배열로 전달되어 소스 컴포넌트 목록이 표시되지 않음
|
|
- `allComponents` → `screenComponents` 변환이 `getComponentConfigPanel.tsx`에서 수행되지만, 실제 컴포넌트 목록이 비어있음
|
|
|
|
**해결 필요 사항**:
|
|
1. `UnifiedPropertiesPanel`에서 `allComponents`가 제대로 전달되는지 확인
|
|
2. `getComponentConfigPanel.tsx`에서 `screenComponents` 변환 로직 디버깅
|
|
3. 필터링 조건 확인 (table-list, v2-table-list, unified-repeater 등)
|
|
|
|
**관련 코드**:
|
|
```typescript
|
|
// types.ts - FilterCondition
|
|
export interface FilterCondition {
|
|
// ...
|
|
sourceComponentId?: string; // 소스 컴포넌트 ID (NEW)
|
|
sourceColumnName?: string; // 소스 컬럼명
|
|
// ...
|
|
}
|
|
|
|
// AggregationWidgetConfigPanel.tsx
|
|
const selectableComponents = useMemo(() => {
|
|
return screenComponents.filter(comp =>
|
|
comp.componentType === "table-list" ||
|
|
comp.componentType === "v2-table-list" ||
|
|
// ...
|
|
);
|
|
}, [screenComponents]);
|
|
```
|
|
|
|
### 2. 런타임 선택 데이터 연동
|
|
|
|
**현재 상태**:
|
|
- `applyFilters` 함수에서 `selectedRows`를 사용하여 필터링
|
|
- 하지만 특정 컴포넌트(`sourceComponentId`)의 선택 데이터를 가져오는 로직 미구현
|
|
|
|
**해결 필요 사항**:
|
|
1. 각 컴포넌트별 선택 데이터를 관리하는 글로벌 상태 또는 이벤트 시스템 구현
|
|
2. `selectionChange` 이벤트에서 `componentId`별로 선택 데이터 저장
|
|
3. `applyFilters`에서 `sourceComponentId`에 해당하는 선택 데이터 사용
|
|
|
|
**예상 구현**:
|
|
```typescript
|
|
// 컴포넌트별 선택 데이터 저장 (전역 상태)
|
|
const componentSelections = useRef<Record<string, any[]>>({});
|
|
|
|
// 이벤트 리스너
|
|
window.addEventListener("selectionChange", (event) => {
|
|
const { componentId, selectedData } = event.detail;
|
|
componentSelections.current[componentId] = selectedData;
|
|
});
|
|
|
|
// 필터 적용 시
|
|
case "selection":
|
|
const sourceData = componentSelections.current[filter.sourceComponentId];
|
|
compareValue = sourceData?.[0]?.[filter.sourceColumnName];
|
|
break;
|
|
```
|
|
|
|
### 3. 리피터 컨테이너 내부 집계
|
|
|
|
**시나리오**:
|
|
- 리피터 컨테이너 내부에 집계 위젯 배치
|
|
- 각 반복 아이템별로 다른 집계 결과 표시
|
|
|
|
**현재 상태**:
|
|
- 리피터가 `formData`에 현재 아이템 데이터를 전달
|
|
- 필터에서 `valueSourceType: "formField"`를 사용하면 현재 아이템 기준 필터링 가능
|
|
- 테스트 미완료
|
|
|
|
**테스트 필요 케이스**:
|
|
1. 카테고리 리스트 리피터 + 집계 위젯 (해당 카테고리 상품 개수)
|
|
2. 주문 리스트 리피터 + 집계 위젯 (해당 주문의 상품 금액 합계)
|
|
|
|
---
|
|
|
|
## 사용 예시
|
|
|
|
### 기본 사용 (테이블 전체 집계)
|
|
```
|
|
데이터 소스: 테이블 → sales_order
|
|
집계 항목:
|
|
- 총 금액 (SUM of amount)
|
|
- 주문 건수 (COUNT)
|
|
- 평균 금액 (AVG of amount)
|
|
```
|
|
|
|
### 필터 사용 (조건부 집계)
|
|
```
|
|
데이터 소스: 테이블 → sales_order
|
|
필터 조건:
|
|
- status = '완료'
|
|
- order_date >= 2026-01-01
|
|
집계 항목:
|
|
- 완료 주문 금액 합계
|
|
```
|
|
|
|
### 선택 데이터 연동 (목표)
|
|
```
|
|
좌측: 품목 테이블 리스트 (item_mng)
|
|
우측: 집계 위젯
|
|
|
|
데이터 소스: 테이블 → sales_order
|
|
필터 조건:
|
|
- 컬럼: item_code
|
|
- 연산자: 같음 (=)
|
|
- 값 소스: 선택된 행
|
|
- 소스 컴포넌트: 품목 리스트
|
|
- 소스 컬럼: item_code
|
|
|
|
→ 품목 선택 시 해당 품목의 수주 금액 합계 표시
|
|
```
|
|
|
|
---
|
|
|
|
## 디버깅 로그
|
|
|
|
현재 설정 패널에 다음 로그가 추가되어 있음:
|
|
```typescript
|
|
console.log("[AggregationWidget] screenComponents:", screenComponents);
|
|
console.log("[AggregationWidget] selectableComponents:", filtered);
|
|
```
|
|
|
|
---
|
|
|
|
## 다음 단계
|
|
|
|
1. **소스 컴포넌트 목록 표시 문제 해결**
|
|
- `allComponents` 전달 경로 추적
|
|
- `screenComponents` 변환 로직 확인
|
|
|
|
2. **컴포넌트별 선택 데이터 관리 구현**
|
|
- 글로벌 상태 또는 Context 사용
|
|
- `selectionChange` 이벤트 표준화
|
|
|
|
3. **리피터 내부 집계 테스트**
|
|
- `formField` 필터로 현재 아이템 기준 집계 확인
|
|
|
|
4. **디버깅 로그 제거**
|
|
- 개발 완료 후 콘솔 로그 정리
|
|
|
|
---
|
|
|
|
## 관련 파일
|
|
|
|
- `frontend/lib/utils/getComponentConfigPanel.tsx` - `screenComponents` 변환
|
|
- `frontend/components/screen/panels/UnifiedPropertiesPanel.tsx` - `allComponents` 전달
|
|
- `frontend/components/screen/ScreenDesigner.tsx` - `layout.components` 전달
|
|
|
|
|
|
|