From 8c08e7f8e98394f1a28351b65134becaccebd4d2 Mon Sep 17 00:00:00 2001 From: SeongHyun Kim Date: Thu, 12 Feb 2026 09:19:17 +0900 Subject: [PATCH] =?UTF-8?q?fix(pop-dashboard):=20=EC=A7=91=EA=B3=84=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=84=A4=EC=A0=95=20=EC=9C=A0=ED=9A=A8?= =?UTF-8?q?=EC=84=B1=20=EA=B2=80=EC=A6=9D=20=EA=B0=95=ED=99=94=20-=20?= =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=20=EC=BB=AC=EB=9F=BC=EC=97=90=20SUM?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9=20=EB=B0=A9=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 팀원 pull 후 대시보드 500 에러 발생 원인 해결: - subType별 허용 집계 함수 제한 (stat-card는 COUNT만) - SUM/AVG 선택 시 숫자 타입 컬럼만 표시 - 비호환 집계 함수 선택 시 컬럼 자동 초기화 - subType 변경 시 비호환 aggregation 자동 전환 (STEP 7.5) - chart 모드 groupBy 미설정 경고 추가 Co-authored-by: Cursor --- .../pop-dashboard/PopDashboardConfig.tsx | 119 +++- popdocs/PLAN.md | 630 ++++++++++-------- popdocs/STATUS.md | 27 +- 3 files changed, 474 insertions(+), 302 deletions(-) diff --git a/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx b/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx index 52f18d27..f64e09ae 100644 --- a/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx +++ b/frontend/lib/registry/pop-components/pop-dashboard/PopDashboardConfig.tsx @@ -60,6 +60,7 @@ import type { JoinConfig, JoinType, ItemStyleConfig, + AggregationType, } from "../types"; import { TEXT_ALIGN_LABELS, @@ -132,6 +133,50 @@ const JOIN_TYPE_LABELS: Record = { right: "RIGHT JOIN", }; +// ===== 집계 함수 유효성 검증 유틸 ===== + +// 아이템 타입별 사용 가능한 집계 함수 +const SUBTYPE_AGGREGATION_MAP: Record = { + "kpi-card": ["count", "sum", "avg", "min", "max"], + chart: ["count", "sum", "avg", "min", "max"], + gauge: ["count", "sum", "avg", "min", "max"], + "stat-card": ["count"], +}; + +// 집계 함수 라벨 +const AGGREGATION_LABELS: Record = { + count: "건수 (COUNT)", + sum: "합계 (SUM)", + avg: "평균 (AVG)", + min: "최소 (MIN)", + max: "최대 (MAX)", +}; + +// 숫자 전용 집계 함수 (숫자 컬럼에만 사용 가능) +const NUMERIC_ONLY_AGGREGATIONS: AggregationType[] = ["sum", "avg"]; + +// PostgreSQL 숫자 타입 판별용 패턴 +const NUMERIC_TYPE_PATTERNS = [ + "int", "integer", "bigint", "smallint", + "numeric", "decimal", "real", "double", + "float", "serial", "bigserial", "smallserial", + "money", "number", +]; + +/** 컬럼이 숫자 타입인지 판별 */ +function isNumericColumn(col: ColumnInfo): boolean { + const t = (col.type || "").toLowerCase(); + const u = (col.udtName || "").toLowerCase(); + return NUMERIC_TYPE_PATTERNS.some( + (pattern) => t.includes(pattern) || u.includes(pattern) + ); +} + +/** 현재 집계 함수가 숫자 전용(sum/avg)인지 판별 */ +function isNumericOnlyAggregation(aggType: string | undefined): boolean { + return !!aggType && NUMERIC_ONLY_AGGREGATIONS.includes(aggType as AggregationType); +} + const FILTER_OPERATOR_LABELS: Record = { "=": "같음 (=)", "!=": "다름 (!=)", @@ -149,9 +194,11 @@ const FILTER_OPERATOR_LABELS: Record = { function DataSourceEditor({ dataSource, onChange, + subType, }: { dataSource: DataSourceConfig; onChange: (ds: DataSourceConfig) => void; + subType?: DashboardSubType; }) { // 테이블 목록 (Combobox용) const [tables, setTables] = useState([]); @@ -268,7 +315,15 @@ function DataSourceEditor({ @@ -331,10 +390,15 @@ function DataSourceEditor({ /> - 컬럼을 찾을 수 없습니다. + {isNumericOnlyAggregation(dataSource.aggregation?.type) + ? "숫자 타입 컬럼이 없습니다." + : "컬럼을 찾을 수 없습니다."} - {columns.map((col) => ( + {(isNumericOnlyAggregation(dataSource.aggregation?.type) + ? columns.filter(isNumericColumn) + : columns + ).map((col) => ( 차트에서 X축 카테고리로 사용됩니다

+ {subType === "chart" && !dataSource.aggregation?.groupBy?.length && ( +

+ 차트 모드에서는 그룹핑(X축)을 설정해야 의미 있는 차트가 표시됩니다 +

+ )} )} @@ -1144,9 +1213,30 @@ function ItemEditor({