Implement Comma Value Resolution in Entity Join Service
- Added a new method `resolveCommaValues` in `EntityJoinService` to handle comma-separated values for entity joins, allowing for individual code resolution and label conversion. - Integrated the new method into `TableManagementService` to process data after executing join queries. - Enhanced the `DynamicComponentRenderer` to maintain entity label columns based on existing configurations. Made-with: Cursor
This commit is contained in:
parent
6395f4d032
commit
e305e78155
|
|
@ -823,6 +823,76 @@ export class EntityJoinService {
|
|||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 콤마 구분 다중값 해결 (겸직 부서 등)
|
||||
* entity join이 NULL인데 소스값에 콤마가 있으면 개별 코드를 각각 조회해서 라벨로 변환
|
||||
*/
|
||||
async resolveCommaValues(
|
||||
data: Record<string, any>[],
|
||||
joinConfigs: EntityJoinConfig[]
|
||||
): Promise<Record<string, any>[]> {
|
||||
if (!data.length || !joinConfigs.length) return data;
|
||||
|
||||
for (const config of joinConfigs) {
|
||||
const sourceCol = config.sourceColumn;
|
||||
const displayCol = config.displayColumns?.[0] || config.displayColumn;
|
||||
if (!displayCol || displayCol === "none") continue;
|
||||
|
||||
const aliasCol = config.aliasColumn || `${sourceCol}_${displayCol}`;
|
||||
const labelCol = `${sourceCol}_label`;
|
||||
|
||||
const codesSet = new Set<string>();
|
||||
const rowsToResolve: number[] = [];
|
||||
|
||||
data.forEach((row, idx) => {
|
||||
const srcVal = row[sourceCol];
|
||||
if (!srcVal || typeof srcVal !== "string" || !srcVal.includes(",")) return;
|
||||
|
||||
const joinedVal = row[aliasCol] || row[labelCol];
|
||||
if (joinedVal && joinedVal !== "") return;
|
||||
|
||||
rowsToResolve.push(idx);
|
||||
srcVal.split(",").map((v: string) => v.trim()).filter(Boolean).forEach((code: string) => codesSet.add(code));
|
||||
});
|
||||
|
||||
if (codesSet.size === 0) continue;
|
||||
|
||||
const codes = Array.from(codesSet);
|
||||
const refCol = config.referenceColumn || "id";
|
||||
const placeholders = codes.map((_, i) => `$${i + 1}`).join(",");
|
||||
try {
|
||||
const result = await query<Record<string, any>>(
|
||||
`SELECT "${refCol}"::TEXT as _key, "${displayCol}"::TEXT as _label
|
||||
FROM ${config.referenceTable}
|
||||
WHERE "${refCol}"::TEXT IN (${placeholders})`,
|
||||
codes
|
||||
);
|
||||
|
||||
const labelMap = new Map<string, string>();
|
||||
result.forEach((r) => labelMap.set(r._key, r._label));
|
||||
|
||||
for (const idx of rowsToResolve) {
|
||||
const srcVal = data[idx][sourceCol] as string;
|
||||
const resolvedLabels = srcVal
|
||||
.split(",")
|
||||
.map((v: string) => v.trim())
|
||||
.filter(Boolean)
|
||||
.map((code: string) => labelMap.get(code) || code)
|
||||
.join(", ");
|
||||
|
||||
data[idx][aliasCol] = resolvedLabels;
|
||||
data[idx][labelCol] = resolvedLabels;
|
||||
}
|
||||
|
||||
logger.info(`콤마 구분 entity 값 해결: ${sourceCol} → ${codesSet.size}개 코드, ${rowsToResolve.length}개 행`);
|
||||
} catch (err) {
|
||||
logger.warn(`콤마 구분 entity 값 해결 실패: ${sourceCol}`, err);
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
export const entityJoinService = new EntityJoinService();
|
||||
|
|
|
|||
|
|
@ -3588,12 +3588,15 @@ export class TableManagementService {
|
|||
`✅ [executeJoinQuery] 조회 완료: ${dataResult?.length}개 행`
|
||||
);
|
||||
|
||||
const data = Array.isArray(dataResult) ? dataResult : [];
|
||||
let data = Array.isArray(dataResult) ? dataResult : [];
|
||||
const total =
|
||||
Array.isArray(countResult) && countResult.length > 0
|
||||
? Number((countResult[0] as any).total)
|
||||
: 0;
|
||||
|
||||
// 콤마 구분 다중값 후처리 (겸직 부서 등)
|
||||
data = await entityJoinService.resolveCommaValues(data, joinConfigs);
|
||||
|
||||
const queryTime = Date.now() - startTime;
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1085,7 +1085,7 @@ export const V2Input = forwardRef<HTMLDivElement, V2InputProps>((props, ref) =>
|
|||
const hasCustomRadius = !!style?.borderRadius;
|
||||
|
||||
const customTextStyle: React.CSSProperties = {};
|
||||
if (style?.color) customTextStyle.color = style.color;
|
||||
if (style?.color) customTextStyle.color = getAdaptiveLabelColor(style.color);
|
||||
if (style?.fontSize) customTextStyle.fontSize = style.fontSize;
|
||||
if (style?.fontWeight) customTextStyle.fontWeight = style.fontWeight;
|
||||
if (style?.textAlign) customTextStyle.textAlign = style.textAlign as React.CSSProperties["textAlign"];
|
||||
|
|
|
|||
|
|
@ -102,12 +102,16 @@ function mergeColumnMeta(tableName: string | undefined, columnName: string | und
|
|||
if (dbInputType === "entity") {
|
||||
const refTable = meta.reference_table || meta.referenceTable;
|
||||
const refColumn = meta.reference_column || meta.referenceColumn;
|
||||
const displayCol = meta.display_column || meta.displayColumn;
|
||||
const rawDisplayCol = meta.display_column || meta.displayColumn;
|
||||
const displayCol = rawDisplayCol && rawDisplayCol !== "none" && rawDisplayCol !== "" ? rawDisplayCol : undefined;
|
||||
if (refTable) {
|
||||
merged.source = "entity";
|
||||
merged.entityTable = refTable;
|
||||
merged.entityValueColumn = refColumn || "id";
|
||||
merged.entityLabelColumn = displayCol || "name";
|
||||
// 화면 설정에 이미 entityLabelColumn이 있으면 유지, 없으면 DB 값 또는 기본값 사용
|
||||
if (!merged.entityLabelColumn) {
|
||||
merged.entityLabelColumn = displayCol || "name";
|
||||
}
|
||||
merged.fieldType = "entity";
|
||||
merged.inputType = "entity";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue