fix: 화면 복제 기능 개선 및 관련 버그 수정

- 화면 복제 기능을 개선하여 DB 구조 개편 후의 효율적인 화면 관리를 지원합니다.
- 그룹 복제 시 버튼의 `targetScreenId`가 새 화면으로 매핑되지 않는 버그를 수정하였습니다.
- 관련된 서비스 및 쿼리에서 `table_type_columns`를 사용하여 라벨 정보를 조회하도록 변경하였습니다.
- 여러 컨트롤러 및 서비스에서 `column_labels` 대신 `table_type_columns`를 참조하도록 업데이트하였습니다.
This commit is contained in:
DDD1542
2026-01-28 11:24:25 +09:00
parent 1753822211
commit 192b678bce
43 changed files with 7826 additions and 677 deletions

View File

@@ -1310,8 +1310,8 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
if (conditions.length > 0) {
const labelQuery = `
SELECT table_name, column_name, column_label
FROM column_labels
WHERE ${conditions.join(' OR ')}
FROM table_type_columns
WHERE (${conditions.join(' OR ')}) AND company_code = '*'
`;
const labelResult = await pool.query(labelQuery, params);
labelResult.rows.forEach((row: any) => {
@@ -1407,7 +1407,7 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
}
});
// 2. 추가 방식: 화면에서 사용하는 컬럼 중 column_labels.reference_table이 설정된 경우
// 2. 추가 방식: 화면에서 사용하는 컬럼 중 table_type_columns.reference_table이 설정된 경우
// 화면의 usedColumns/joinColumns에서 reference_table 조회
const referenceQuery = `
WITH screen_used_columns AS (
@@ -1513,8 +1513,8 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
cl.reference_column,
ref_cl.column_label as target_display_name
FROM screen_used_columns suc
JOIN column_labels cl ON cl.table_name = suc.main_table AND cl.column_name = suc.column_name
LEFT JOIN column_labels ref_cl ON ref_cl.table_name = cl.reference_table AND ref_cl.column_name = cl.reference_column
JOIN table_type_columns cl ON cl.table_name = suc.main_table AND cl.column_name = suc.column_name AND cl.company_code = '*'
LEFT JOIN table_type_columns ref_cl ON ref_cl.table_name = cl.reference_table AND ref_cl.column_name = cl.reference_column AND ref_cl.company_code = '*'
WHERE cl.reference_table IS NOT NULL
AND cl.reference_table != ''
AND cl.reference_table != suc.main_table
@@ -1524,7 +1524,7 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
const referenceResult = await pool.query(referenceQuery, [screenIds]);
logger.info("column_labels reference_table 조회 결과", {
logger.info("table_type_columns reference_table 조회 결과", {
screenIds,
referenceCount: referenceResult.rows.length,
references: referenceResult.rows.map((r: any) => ({
@@ -1804,7 +1804,7 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
rightPanelCount: rightPanelResult.rows.length
});
// 5. joinedTables에 대한 FK 컬럼을 column_labels에서 조회
// 5. joinedTables에 대한 FK 컬럼을 table_type_columns에서 조회
// rightPanelRelation에서 joinedTables가 있는 경우, 해당 테이블과 조인하는 FK 컬럼 찾기
const joinedTableFKLookups: Array<{ subTableName: string; refTable: string }> = [];
Object.values(screenSubTables).forEach((screenData: any) => {
@@ -1817,7 +1817,7 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
});
});
// column_labels에서 FK 컬럼 조회 (reference_table로 조인하는 컬럼 찾기)
// table_type_columns에서 FK 컬럼 조회 (reference_table로 조인하는 컬럼 찾기)
const joinColumnsByTable: { [key: string]: string[] } = {}; // tableName → [FK 컬럼들]
if (joinedTableFKLookups.length > 0) {
const uniqueLookups = joinedTableFKLookups.filter((item, index, self) =>
@@ -1836,10 +1836,11 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
cl.reference_table,
cl.reference_column,
tl.table_label as reference_table_label
FROM column_labels cl
FROM table_type_columns cl
LEFT JOIN table_labels tl ON cl.reference_table = tl.table_name
WHERE cl.table_name = ANY($1)
AND cl.reference_table = ANY($2)
AND cl.company_code = '*'
`;
const fkResult = await pool.query(fkQuery, [subTableNames, refTableNames]);
@@ -1884,7 +1885,7 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
});
}
// 5. 모든 fieldMappings의 한글명을 column_labels에서 가져와서 적용
// 5. 모든 fieldMappings의 한글명을 table_type_columns에서 가져와서 적용
// 모든 테이블/컬럼 조합을 수집
const columnLookups: Array<{ tableName: string; columnName: string }> = [];
Object.values(screenSubTables).forEach((screenData: any) => {
@@ -1909,7 +1910,7 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
index === self.findIndex((t) => t.tableName === item.tableName && t.columnName === item.columnName)
);
// column_labels에서 한글명 조회
// table_type_columns에서 한글명 조회
const columnLabelsMap: { [key: string]: string } = {};
if (uniqueColumnLookups.length > 0) {
const columnLabelsQuery = `
@@ -1917,10 +1918,11 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
table_name,
column_name,
column_label
FROM column_labels
FROM table_type_columns
WHERE (table_name, column_name) IN (
${uniqueColumnLookups.map((_, i) => `($${i * 2 + 1}, $${i * 2 + 2})`).join(', ')}
)
AND company_code = '*'
`;
const columnLabelsParams = uniqueColumnLookups.flatMap(item => [item.tableName, item.columnName]);
@@ -1930,9 +1932,9 @@ export const getScreenSubTables = async (req: AuthenticatedRequest, res: Respons
const key = `${row.table_name}.${row.column_name}`;
columnLabelsMap[key] = row.column_label;
});
logger.info("column_labels 한글명 조회 완료", { count: columnLabelsResult.rows.length });
logger.info("table_type_columns 한글명 조회 완료", { count: columnLabelsResult.rows.length });
} catch (error: any) {
logger.warn("column_labels 한글명 조회 실패 (무시하고 계속 진행):", error.message);
logger.warn("table_type_columns 한글명 조회 실패 (무시하고 계속 진행):", error.message);
}
}
@@ -2421,3 +2423,4 @@ export const getMenuTreeFromScreenGroups = async (req: AuthenticatedRequest, res
});
}
};