feat: 화면 서브 테이블 정보 조회 기능 추가
- 화면 그룹에 대한 서브 테이블 관계를 조회하는 API 및 라우트 구현 - 화면 그룹 목록에서 서브 테이블 정보를 포함하여 데이터 흐름을 시각화 - 프론트엔드에서 화면 선택 시 그룹 및 서브 테이블 정보 연동 기능 추가 - 화면 노드 및 관계 시각화 컴포넌트에 서브 테이블 정보 통합
This commit is contained in:
@@ -39,11 +39,25 @@ export const getScreenGroups = async (req: Request, res: Response) => {
|
||||
const countResult = await pool.query(countQuery, params);
|
||||
const total = parseInt(countResult.rows[0].total);
|
||||
|
||||
// 데이터 조회
|
||||
// 데이터 조회 (screens 배열 포함)
|
||||
const dataQuery = `
|
||||
SELECT
|
||||
sg.*,
|
||||
(SELECT COUNT(*) FROM screen_group_screens sgs WHERE sgs.group_id = sg.id) as screen_count
|
||||
(SELECT COUNT(*) FROM screen_group_screens sgs WHERE sgs.group_id = sg.id) as screen_count,
|
||||
(SELECT json_agg(
|
||||
json_build_object(
|
||||
'id', sgs.id,
|
||||
'screen_id', sgs.screen_id,
|
||||
'screen_name', sd.screen_name,
|
||||
'screen_role', sgs.screen_role,
|
||||
'display_order', sgs.display_order,
|
||||
'is_default', sgs.is_default,
|
||||
'table_name', sd.table_name
|
||||
) ORDER BY sgs.display_order
|
||||
) FROM screen_group_screens sgs
|
||||
LEFT JOIN screen_definitions sd ON sgs.screen_id = sd.screen_id
|
||||
WHERE sgs.group_id = sg.id
|
||||
) as screens
|
||||
FROM screen_groups sg
|
||||
${whereClause}
|
||||
ORDER BY sg.display_order ASC, sg.created_date DESC
|
||||
@@ -84,7 +98,8 @@ export const getScreenGroup = async (req: Request, res: Response) => {
|
||||
'screen_name', sd.screen_name,
|
||||
'screen_role', sgs.screen_role,
|
||||
'display_order', sgs.display_order,
|
||||
'is_default', sgs.is_default
|
||||
'is_default', sgs.is_default,
|
||||
'table_name', sd.table_name
|
||||
) ORDER BY sgs.display_order
|
||||
) FROM screen_group_screens sgs
|
||||
LEFT JOIN screen_definitions sd ON sgs.screen_id = sd.screen_id
|
||||
@@ -981,3 +996,109 @@ export const getMultipleScreenLayoutSummary = async (req: Request, res: Response
|
||||
}
|
||||
};
|
||||
|
||||
// ============================================================
|
||||
// 화면 서브 테이블 관계 조회 (조인/참조 테이블)
|
||||
// ============================================================
|
||||
|
||||
// 여러 화면의 서브 테이블 정보 조회 (메인 테이블 → 서브 테이블 관계)
|
||||
export const getScreenSubTables = async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { screenIds } = req.body;
|
||||
|
||||
if (!screenIds || !Array.isArray(screenIds) || screenIds.length === 0) {
|
||||
return res.status(400).json({ success: false, message: "screenIds 배열이 필요합니다." });
|
||||
}
|
||||
|
||||
// 화면별 메인 테이블과 서브 테이블 관계 조회
|
||||
// componentConfig에서 tableName, sourceTable 추출
|
||||
const query = `
|
||||
SELECT DISTINCT
|
||||
sd.screen_id,
|
||||
sd.screen_name,
|
||||
sd.table_name as main_table,
|
||||
COALESCE(
|
||||
sl.properties->'componentConfig'->>'tableName',
|
||||
sl.properties->'componentConfig'->>'sourceTable'
|
||||
) as sub_table,
|
||||
sl.properties->>'componentType' as component_type,
|
||||
sl.properties->'componentConfig'->>'targetTable' as target_table
|
||||
FROM screen_definitions sd
|
||||
JOIN screen_layouts sl ON sd.screen_id = sl.screen_id
|
||||
WHERE sd.screen_id = ANY($1)
|
||||
AND (
|
||||
sl.properties->'componentConfig'->>'tableName' IS NOT NULL
|
||||
OR sl.properties->'componentConfig'->>'sourceTable' IS NOT NULL
|
||||
)
|
||||
ORDER BY sd.screen_id
|
||||
`;
|
||||
|
||||
const result = await pool.query(query, [screenIds]);
|
||||
|
||||
// 화면별 서브 테이블 그룹화
|
||||
const screenSubTables: Record<number, {
|
||||
screenId: number;
|
||||
screenName: string;
|
||||
mainTable: string;
|
||||
subTables: Array<{
|
||||
tableName: string;
|
||||
componentType: string;
|
||||
relationType: string; // 'join' | 'lookup' | 'source'
|
||||
}>;
|
||||
}> = {};
|
||||
|
||||
result.rows.forEach((row: any) => {
|
||||
const screenId = row.screen_id;
|
||||
const mainTable = row.main_table;
|
||||
const subTable = row.sub_table;
|
||||
|
||||
// 메인 테이블과 동일한 경우 제외
|
||||
if (!subTable || subTable === mainTable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!screenSubTables[screenId]) {
|
||||
screenSubTables[screenId] = {
|
||||
screenId,
|
||||
screenName: row.screen_name,
|
||||
mainTable: mainTable || '',
|
||||
subTables: [],
|
||||
};
|
||||
}
|
||||
|
||||
// 중복 체크
|
||||
const exists = screenSubTables[screenId].subTables.some(
|
||||
(st) => st.tableName === subTable
|
||||
);
|
||||
|
||||
if (!exists) {
|
||||
// 관계 타입 추론
|
||||
let relationType = 'lookup';
|
||||
const componentType = row.component_type || '';
|
||||
if (componentType.includes('autocomplete') || componentType.includes('entity-search')) {
|
||||
relationType = 'lookup';
|
||||
} else if (componentType.includes('modal-repeater') || componentType.includes('selected-items')) {
|
||||
relationType = 'source';
|
||||
} else if (componentType.includes('table')) {
|
||||
relationType = 'join';
|
||||
}
|
||||
|
||||
screenSubTables[screenId].subTables.push({
|
||||
tableName: subTable,
|
||||
componentType: componentType,
|
||||
relationType: relationType,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
logger.info("화면 서브 테이블 정보 조회", { screenIds, resultCount: Object.keys(screenSubTables).length });
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
data: screenSubTables,
|
||||
});
|
||||
} catch (error: any) {
|
||||
logger.error("화면 서브 테이블 정보 조회 실패:", error);
|
||||
res.status(500).json({ success: false, message: "화면 서브 테이블 정보 조회에 실패했습니다.", error: error.message });
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user