Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into feat/dashboard

This commit is contained in:
dohyeons 2025-10-30 11:29:58 +09:00
commit 8c6aeb006b
1 changed files with 45 additions and 89 deletions

View File

@ -221,10 +221,8 @@ export default function CustomMetricTestWidget({ element }: CustomMetricTestWidg
const { sourceName, rows } = result.value;
// 집계된 데이터인지 확인 (행이 적고 숫자 컬럼이 있으면)
const hasAggregatedData = rows.length > 0 && rows.length <= 100;
if (hasAggregatedData && rows.length > 0) {
// 🎯 간단한 쿼리도 잘 작동하도록 개선된 로직
if (rows.length > 0) {
const firstRow = rows[0];
const columns = Object.keys(firstRow);
@ -235,28 +233,44 @@ export default function CustomMetricTestWidget({ element }: CustomMetricTestWidg
});
// 문자열 컬럼 찾기
const stringColumns = columns.filter((col) => {
const value = firstRow[col];
return typeof value === "string" || !numericColumns.includes(col);
});
const stringColumns = columns.filter((col) => !numericColumns.includes(col));
// console.log(`📊 [${sourceName}] 컬럼 분석:`, {
// 전체: columns,
// 숫자: numericColumns,
// 문자열: stringColumns,
// });
// 🆕 자동 집계 로직: 집계 컬럼 이름으로 판단 (count, 개수, sum, avg 등)
const isAggregated = numericColumns.some((col) =>
/count|개수|sum|합계|avg|평균|min|최소|max|최대|total|전체/i.test(col),
);
if (isAggregated && numericColumns.length > 0) {
// 집계 컬럼이 있으면 이미 집계된 데이터로 판단 (GROUP BY 결과)
// console.log(`✅ [${sourceName}] 집계된 데이터로 판단 (집계 컬럼 발견: ${numericColumns.join(", ")})`);
// 🎯 케이스 0: 1행인데 숫자 컬럼이 여러 개 → 각 컬럼을 별도 카드로
if (rows.length === 1 && numericColumns.length > 1) {
// 예: SELECT COUNT(*) AS 전체, SUM(...) AS 배송중, ...
numericColumns.forEach((col) => {
allMetrics.push({
label: col, // 컬럼명이 라벨
value: Number(firstRow[col]) || 0,
field: col,
aggregation: "custom",
color: colors[allMetrics.length % colors.length],
sourceName: sourceName,
rawData: [firstRow],
});
});
}
// 🎯 케이스 1: 컬럼이 2개 (라벨 + 값) → 가장 간단한 형태
else if (columns.length === 2) {
const labelCol = columns[0];
const valueCol = columns[1];
rows.forEach((row) => {
allMetrics.push({
label: String(row[labelCol] || ""),
value: Number(row[valueCol]) || 0,
field: valueCol,
aggregation: "custom",
color: colors[allMetrics.length % colors.length],
sourceName: sourceName,
rawData: [row],
});
});
}
// 🎯 케이스 2: 숫자 컬럼이 1개 이상 있음 → 집계된 데이터
else if (numericColumns.length > 0) {
rows.forEach((row, index) => {
// 라벨: 첫 번째 문자열 컬럼
// 라벨: 첫 번째 문자열 컬럼 (없으면 첫 번째 컬럼)
const labelField = stringColumns[0] || columns[0];
const label = String(row[labelField] || `항목 ${index + 1}`);
@ -264,8 +278,6 @@ export default function CustomMetricTestWidget({ element }: CustomMetricTestWidg
const valueField = numericColumns[0];
const value = Number(row[valueField]) || 0;
// console.log(` [${sourceName}] 메트릭: ${label} = ${value}`);
allMetrics.push({
label: label,
value: value,
@ -276,25 +288,18 @@ export default function CustomMetricTestWidget({ element }: CustomMetricTestWidg
rawData: [row],
});
});
} else {
// 숫자 컬럼이 없으면 자동 집계 (마지막 컬럼 기준)
// console.log(`✅ [${sourceName}] 자동 집계 모드 (숫자 컬럼 없음)`);
// 마지막 컬럼을 집계 기준으로 사용
}
// 🎯 케이스 3: 숫자 컬럼이 없음 → 마지막 컬럼 기준으로 카운트
else {
const aggregateField = columns[columns.length - 1];
// console.log(` [${sourceName}] 집계 기준 컬럼: ${aggregateField}`);
// 해당 컬럼의 값별로 카운트
const countMap = new Map<string, number>();
rows.forEach((row) => {
const value = String(row[aggregateField] || "기타");
countMap.set(value, (countMap.get(value) || 0) + 1);
});
// 카운트 결과를 메트릭으로 변환
countMap.forEach((count, label) => {
// console.log(` [${sourceName}] 자동 집계: ${label} = ${count}개`);
allMetrics.push({
label: label,
value: count,
@ -318,59 +323,10 @@ export default function CustomMetricTestWidget({ element }: CustomMetricTestWidg
});
}
// 🆕 숫자 컬럼이 없을 때의 기존 로직은 주석 처리
/* if (false && result.status === "fulfilled") {
// 숫자 컬럼이 없으면 각 컬럼별 고유값 개수 표시
// console.log(`📊 [${sourceName}] 문자열 데이터, 각 컬럼별 고유값 개수 표시`);
// 데이터 소스에서 선택된 컬럼 가져오기
const dataSourceConfig = (element?.dataSources || element?.chartConfig?.dataSources)?.find(
(ds) => ds.name === sourceName || ds.id === result.value?.sourceIndex.toString(),
);
const selectedColumns = dataSourceConfig?.selectedColumns || [];
// 선택된 컬럼이 있으면 해당 컬럼만, 없으면 전체 컬럼 표시
const columnsToShow = selectedColumns.length > 0 ? selectedColumns : columns;
// console.log(` [${sourceName}] 표시할 컬럼:`, columnsToShow);
columnsToShow.forEach((col) => {
// 해당 컬럼이 실제로 존재하는지 확인
if (!columns.includes(col)) {
console.warn(` [${sourceName}] 컬럼 "${col}"이 데이터에 없습니다.`);
return;
}
// 해당 컬럼의 고유값 개수 계산
const uniqueValues = new Set(rows.map((row) => row[col]));
const uniqueCount = uniqueValues.size;
// console.log(` [${sourceName}] ${col}: ${uniqueCount}개 고유값`);
allMetrics.push({
label: `${sourceName} - ${col} (고유값)`,
value: uniqueCount,
field: col,
aggregation: "distinct",
color: colors[allMetrics.length % colors.length],
sourceName: sourceName,
rawData: rows, // 원본 데이터 저장
});
});
// 총 행 개수도 추가
allMetrics.push({
label: `${sourceName} - 총 개수`,
value: rows.length,
field: "count",
aggregation: "count",
color: colors[allMetrics.length % colors.length],
sourceName: sourceName,
rawData: rows, // 원본 데이터 저장
});
} */
} else {
// 행이 많으면 각 컬럼별 고유값 개수 + 총 개수 표시
}
// 🎯 행이 많을 때도 간단하게 처리
else if (rows.length > 100) {
// 행이 많으면 총 개수만 표시
// console.log(`📊 [${sourceName}] 일반 데이터 (행 많음), 컬럼별 통계 표시`);
const firstRow = rows[0];