Merge branch 'main' of http://39.117.244.52:3000/kjs/ERP-node into feature/screen-management
This commit is contained in:
@@ -30,6 +30,7 @@ export class EntityJoinController {
|
||||
autoFilter, // 🔒 멀티테넌시 자동 필터
|
||||
dataFilter, // 🆕 데이터 필터 (JSON 문자열)
|
||||
excludeFilter, // 🆕 제외 필터 (JSON 문자열) - 다른 테이블에 이미 존재하는 데이터 제외
|
||||
deduplication, // 🆕 중복 제거 설정 (JSON 문자열)
|
||||
userLang, // userLang은 별도로 분리하여 search에 포함되지 않도록 함
|
||||
...otherParams
|
||||
} = req.query;
|
||||
@@ -139,6 +140,24 @@ export class EntityJoinController {
|
||||
}
|
||||
}
|
||||
|
||||
// 🆕 중복 제거 설정 처리
|
||||
let parsedDeduplication: {
|
||||
enabled: boolean;
|
||||
groupByColumn: string;
|
||||
keepStrategy: "latest" | "earliest" | "base_price" | "current_date";
|
||||
sortColumn?: string;
|
||||
} | undefined = undefined;
|
||||
if (deduplication) {
|
||||
try {
|
||||
parsedDeduplication =
|
||||
typeof deduplication === "string" ? JSON.parse(deduplication) : deduplication;
|
||||
logger.info("중복 제거 설정 파싱 완료:", parsedDeduplication);
|
||||
} catch (error) {
|
||||
logger.warn("중복 제거 설정 파싱 오류:", error);
|
||||
parsedDeduplication = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const result = await tableManagementService.getTableDataWithEntityJoins(
|
||||
tableName,
|
||||
{
|
||||
@@ -156,13 +175,26 @@ export class EntityJoinController {
|
||||
screenEntityConfigs: parsedScreenEntityConfigs,
|
||||
dataFilter: parsedDataFilter, // 🆕 데이터 필터 전달
|
||||
excludeFilter: parsedExcludeFilter, // 🆕 제외 필터 전달
|
||||
deduplication: parsedDeduplication, // 🆕 중복 제거 설정 전달
|
||||
}
|
||||
);
|
||||
|
||||
// 🆕 중복 제거 처리 (결과 데이터에 적용)
|
||||
let finalData = result;
|
||||
if (parsedDeduplication?.enabled && parsedDeduplication.groupByColumn && Array.isArray(result.data)) {
|
||||
logger.info(`🔄 중복 제거 시작: 기준 컬럼 = ${parsedDeduplication.groupByColumn}, 전략 = ${parsedDeduplication.keepStrategy}`);
|
||||
const originalCount = result.data.length;
|
||||
finalData = {
|
||||
...result,
|
||||
data: this.deduplicateData(result.data, parsedDeduplication),
|
||||
};
|
||||
logger.info(`✅ 중복 제거 완료: ${originalCount}개 → ${finalData.data.length}개`);
|
||||
}
|
||||
|
||||
res.status(200).json({
|
||||
success: true,
|
||||
message: "Entity 조인 데이터 조회 성공",
|
||||
data: result,
|
||||
data: finalData,
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error("Entity 조인 데이터 조회 실패", error);
|
||||
@@ -537,6 +569,98 @@ export class EntityJoinController {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 중복 데이터 제거 (메모리 내 처리)
|
||||
*/
|
||||
private deduplicateData(
|
||||
data: any[],
|
||||
config: {
|
||||
groupByColumn: string;
|
||||
keepStrategy: "latest" | "earliest" | "base_price" | "current_date";
|
||||
sortColumn?: string;
|
||||
}
|
||||
): any[] {
|
||||
if (!data || data.length === 0) return data;
|
||||
|
||||
// 그룹별로 데이터 분류
|
||||
const groups: Record<string, any[]> = {};
|
||||
|
||||
for (const row of data) {
|
||||
const groupKey = row[config.groupByColumn];
|
||||
if (groupKey === undefined || groupKey === null) continue;
|
||||
|
||||
if (!groups[groupKey]) {
|
||||
groups[groupKey] = [];
|
||||
}
|
||||
groups[groupKey].push(row);
|
||||
}
|
||||
|
||||
// 각 그룹에서 하나의 행만 선택
|
||||
const result: any[] = [];
|
||||
|
||||
for (const [groupKey, rows] of Object.entries(groups)) {
|
||||
if (rows.length === 0) continue;
|
||||
|
||||
let selectedRow: any;
|
||||
|
||||
switch (config.keepStrategy) {
|
||||
case "latest":
|
||||
// 정렬 컬럼 기준 최신 (가장 큰 값)
|
||||
if (config.sortColumn) {
|
||||
rows.sort((a, b) => {
|
||||
const aVal = a[config.sortColumn!];
|
||||
const bVal = b[config.sortColumn!];
|
||||
if (aVal === bVal) return 0;
|
||||
if (aVal > bVal) return -1;
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
selectedRow = rows[0];
|
||||
break;
|
||||
|
||||
case "earliest":
|
||||
// 정렬 컬럼 기준 최초 (가장 작은 값)
|
||||
if (config.sortColumn) {
|
||||
rows.sort((a, b) => {
|
||||
const aVal = a[config.sortColumn!];
|
||||
const bVal = b[config.sortColumn!];
|
||||
if (aVal === bVal) return 0;
|
||||
if (aVal < bVal) return -1;
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
selectedRow = rows[0];
|
||||
break;
|
||||
|
||||
case "base_price":
|
||||
// base_price가 true인 행 선택
|
||||
selectedRow = rows.find((r) => r.base_price === true || r.base_price === "true") || rows[0];
|
||||
break;
|
||||
|
||||
case "current_date":
|
||||
// 오늘 날짜 기준 유효 기간 내 행 선택
|
||||
const today = new Date().toISOString().split("T")[0];
|
||||
selectedRow = rows.find((r) => {
|
||||
const startDate = r.start_date;
|
||||
const endDate = r.end_date;
|
||||
if (!startDate) return true;
|
||||
if (startDate <= today && (!endDate || endDate >= today)) return true;
|
||||
return false;
|
||||
}) || rows[0];
|
||||
break;
|
||||
|
||||
default:
|
||||
selectedRow = rows[0];
|
||||
}
|
||||
|
||||
if (selectedRow) {
|
||||
result.push(selectedRow);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
export const entityJoinController = new EntityJoinController();
|
||||
|
||||
Reference in New Issue
Block a user