라벨명 표시기능

This commit is contained in:
kjs
2025-09-08 14:20:01 +09:00
parent 1eeda775ef
commit 2d07041110
20 changed files with 1415 additions and 497 deletions

View File

@@ -105,8 +105,45 @@ export class ScreenManagementService {
prisma.screen_definitions.count({ where: whereClause }),
]);
// 테이블 라벨 정보를 한 번에 조회
const tableNames = [
...new Set(screens.map((s) => s.table_name).filter(Boolean)),
];
let tableLabelMap = new Map<string, string>();
if (tableNames.length > 0) {
try {
const tableLabels = await prisma.table_labels.findMany({
where: { table_name: { in: tableNames } },
select: { table_name: true, table_label: true },
});
tableLabelMap = new Map(
tableLabels.map((tl) => [
tl.table_name,
tl.table_label || tl.table_name,
])
);
// 테스트: company_mng 라벨 직접 확인
if (tableLabelMap.has("company_mng")) {
console.log(
"✅ company_mng 라벨 찾음:",
tableLabelMap.get("company_mng")
);
} else {
console.log("❌ company_mng 라벨 없음");
}
} catch (error) {
console.error("테이블 라벨 조회 오류:", error);
}
}
return {
data: screens.map((screen) => this.mapToScreenDefinition(screen)),
data: screens.map((screen) =>
this.mapToScreenDefinition(screen, tableLabelMap)
),
pagination: {
page,
size,
@@ -404,6 +441,8 @@ export class ScreenManagementService {
}
// 메뉴 할당 확인
// 메뉴에 할당된 화면인지 확인 (임시 주석 처리)
/*
const menuAssignments = await prisma.screen_menu_assignments.findMany({
where: {
screen_id: screenId,
@@ -425,6 +464,7 @@ export class ScreenManagementService {
referenceType: "menu_assignment",
});
}
*/
return {
hasDependencies: dependencies.length > 0,
@@ -666,9 +706,22 @@ export class ScreenManagementService {
prisma.screen_definitions.count({ where: whereClause }),
]);
// 테이블 라벨 정보를 한 번에 조회
const tableNames = [
...new Set(screens.map((s) => s.table_name).filter(Boolean)),
];
const tableLabels = await prisma.table_labels.findMany({
where: { table_name: { in: tableNames } },
select: { table_name: true, table_label: true },
});
const tableLabelMap = new Map(
tableLabels.map((tl) => [tl.table_name, tl.table_label || tl.table_name])
);
return {
data: screens.map((screen) => ({
...this.mapToScreenDefinition(screen),
...this.mapToScreenDefinition(screen, tableLabelMap),
deletedDate: screen.deleted_date || undefined,
deletedBy: screen.deleted_by || undefined,
deleteReason: screen.delete_reason || undefined,
@@ -1528,12 +1581,18 @@ export class ScreenManagementService {
// 유틸리티 메서드
// ========================================
private mapToScreenDefinition(data: any): ScreenDefinition {
private mapToScreenDefinition(
data: any,
tableLabelMap?: Map<string, string>
): ScreenDefinition {
const tableLabel = tableLabelMap?.get(data.table_name) || data.table_name;
return {
screenId: data.screen_id,
screenName: data.screen_name,
screenCode: data.screen_code,
tableName: data.table_name,
tableLabel: tableLabel, // 라벨이 있으면 라벨, 없으면 테이블명
companyCode: data.company_code,
description: data.description,
isActive: data.is_active,

View File

@@ -1,5 +1,6 @@
import { PrismaClient } from "@prisma/client";
import { logger } from "../utils/logger";
import { cache, CacheKeys } from "../utils/cache";
import {
TableInfo,
ColumnTypeInfo,
@@ -21,6 +22,13 @@ export class TableManagementService {
try {
logger.info("테이블 목록 조회 시작");
// 캐시에서 먼저 확인
const cachedTables = cache.get<TableInfo[]>(CacheKeys.TABLE_LIST);
if (cachedTables) {
logger.info(`테이블 목록 캐시에서 조회: ${cachedTables.length}`);
return cachedTables;
}
// information_schema는 여전히 $queryRaw 사용
const rawTables = await prisma.$queryRaw<any[]>`
SELECT
@@ -44,6 +52,9 @@ export class TableManagementService {
columnCount: Number(table.columnCount), // BigInt → Number 변환
}));
// 캐시에 저장 (10분 TTL)
cache.set(CacheKeys.TABLE_LIST, tables, 10 * 60 * 1000);
logger.info(`테이블 목록 조회 완료: ${tables.length}`);
return tables;
} catch (error) {
@@ -55,14 +66,59 @@ export class TableManagementService {
}
/**
* 테이블 컬럼 정보 조회
* 테이블 컬럼 정보 조회 (페이지네이션 지원)
* 메타데이터 조회는 Prisma로 변경 불가
*/
async getColumnList(tableName: string): Promise<ColumnTypeInfo[]> {
async getColumnList(
tableName: string,
page: number = 1,
size: number = 50
): Promise<{
columns: ColumnTypeInfo[];
total: number;
page: number;
size: number;
totalPages: number;
}> {
try {
logger.info(`컬럼 정보 조회 시작: ${tableName}`);
logger.info(
`컬럼 정보 조회 시작: ${tableName} (page: ${page}, size: ${size})`
);
// information_schema는 여전히 $queryRaw 사용
// 캐시 키 생성
const cacheKey = CacheKeys.TABLE_COLUMNS(tableName, page, size);
const countCacheKey = CacheKeys.TABLE_COLUMN_COUNT(tableName);
// 캐시에서 먼저 확인
const cachedResult = cache.get<{
columns: ColumnTypeInfo[];
total: number;
page: number;
size: number;
totalPages: number;
}>(cacheKey);
if (cachedResult) {
logger.info(
`컬럼 정보 캐시에서 조회: ${tableName}, ${cachedResult.columns.length}/${cachedResult.total}`
);
return cachedResult;
}
// 전체 컬럼 수 조회 (캐시 확인)
let total = cache.get<number>(countCacheKey);
if (!total) {
const totalResult = await prisma.$queryRaw<[{ count: bigint }]>`
SELECT COUNT(*) as count
FROM information_schema.columns c
WHERE c.table_name = ${tableName}
`;
total = Number(totalResult[0].count);
// 컬럼 수는 자주 변하지 않으므로 30분 캐시
cache.set(countCacheKey, total, 30 * 60 * 1000);
}
// 페이지네이션 적용한 컬럼 조회
const offset = (page - 1) * size;
const rawColumns = await prisma.$queryRaw<any[]>`
SELECT
c.column_name as "columnName",
@@ -87,6 +143,7 @@ export class TableManagementService {
LEFT JOIN column_labels cl ON c.table_name = cl.table_name AND c.column_name = cl.column_name
WHERE c.table_name = ${tableName}
ORDER BY c.ordinal_position
LIMIT ${size} OFFSET ${offset}
`;
// BigInt를 Number로 변환하여 JSON 직렬화 문제 해결
@@ -100,8 +157,23 @@ export class TableManagementService {
displayOrder: column.displayOrder ? Number(column.displayOrder) : null,
}));
logger.info(`컬럼 정보 조회 완료: ${tableName}, ${columns.length}`);
return columns;
const totalPages = Math.ceil(total / size);
const result = {
columns,
total,
page,
size,
totalPages,
};
// 캐시에 저장 (5분 TTL)
cache.set(cacheKey, result, 5 * 60 * 1000);
logger.info(
`컬럼 정보 조회 완료: ${tableName}, ${columns.length}/${total}개 (${page}/${totalPages} 페이지)`
);
return result;
} catch (error) {
logger.error(`컬럼 정보 조회 중 오류 발생: ${tableName}`, error);
throw new Error(
@@ -137,6 +209,40 @@ export class TableManagementService {
}
}
/**
* 테이블 라벨 업데이트
*/
async updateTableLabel(
tableName: string,
displayName: string,
description?: string
): Promise<void> {
try {
logger.info(`테이블 라벨 업데이트 시작: ${tableName}`);
// table_labels 테이블에 UPSERT
await prisma.$executeRaw`
INSERT INTO table_labels (table_name, table_label, description, created_date, updated_date)
VALUES (${tableName}, ${displayName}, ${description || ""}, NOW(), NOW())
ON CONFLICT (table_name)
DO UPDATE SET
table_label = EXCLUDED.table_label,
description = EXCLUDED.description,
updated_date = NOW()
`;
// 캐시 무효화
cache.delete(CacheKeys.TABLE_LIST);
logger.info(`테이블 라벨 업데이트 완료: ${tableName}`);
} catch (error) {
logger.error("테이블 라벨 업데이트 중 오류 발생:", error);
throw new Error(
`테이블 라벨 업데이트 실패: ${error instanceof Error ? error.message : "Unknown error"}`
);
}
}
/**
* 컬럼 설정 업데이트 (UPSERT 방식)
* Prisma ORM으로 변경