feat: Phase 2.1 추가 Prisma 호출 전환 (25+/46)

추가 전환 완료:

 조회 및 관리 함수들:
- checkScreenDependencies() - 화면 의존성 확인 (JOIN 쿼리)
- cleanupDeletedScreenMenuAssignments() - 메뉴 할당 정리
- permanentDeleteScreen() - 영구 삭제 (트랜잭션)
- getDeletedScreens() - 휴지통 목록 조회 (페이징 + 테이블 레이블)

📊 진행률: 25+/46 (54%+)
🎯 다음: $queryRaw 함수들 전환 (테이블/컬럼 정보 조회)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
kjs 2025-09-30 16:46:36 +09:00
parent 311811bc0a
commit 4637680de0
1 changed files with 92 additions and 56 deletions

View File

@ -315,14 +315,17 @@ export class ScreenManagementService {
}>;
}> {
// 권한 확인
const targetScreen = await prisma.screen_definitions.findUnique({
where: { screen_id: screenId },
});
const targetScreens = await query<{ company_code: string | null }>(
`SELECT company_code FROM screen_definitions WHERE screen_id = $1 LIMIT 1`,
[screenId]
);
if (!targetScreen) {
if (targetScreens.length === 0) {
throw new Error("화면을 찾을 수 없습니다.");
}
const targetScreen = targetScreens[0];
if (
userCompanyCode !== "*" &&
targetScreen.company_code !== "*" &&
@ -332,19 +335,27 @@ export class ScreenManagementService {
}
// 같은 회사의 모든 활성 화면에서 이 화면을 참조하는지 확인
const whereClause = {
is_active: { not: "D" },
...(userCompanyCode !== "*" && {
company_code: { in: [userCompanyCode, "*"] },
}),
};
const whereConditions: string[] = ["sd.is_active != 'D'"];
const params: any[] = [];
const allScreens = await prisma.screen_definitions.findMany({
where: whereClause,
include: {
layouts: true,
},
});
if (userCompanyCode !== "*") {
whereConditions.push(`sd.company_code IN ($${params.length + 1}, $${params.length + 2})`);
params.push(userCompanyCode, "*");
}
const whereSQL = whereConditions.join(" AND ");
// 화면과 레이아웃을 JOIN해서 조회
const allScreens = await query<any>(
`SELECT
sd.screen_id, sd.screen_name, sd.screen_code, sd.company_code,
sl.layout_id, sl.component_id, sl.component_type, sl.properties
FROM screen_definitions sd
LEFT JOIN screen_layouts sl ON sd.screen_id = sl.screen_id
WHERE ${whereSQL}
ORDER BY sd.screen_id, sl.layout_id`,
params
);
const dependencies: Array<{
screenId: number;
@ -660,44 +671,50 @@ export class ScreenManagementService {
}
/**
* ()
* () ( Raw Query )
*/
async cleanupDeletedScreenMenuAssignments(): Promise<{
updatedCount: number;
message: string;
}> {
const result = await prisma.$executeRaw`
UPDATE screen_menu_assignments
const result = await query(
`UPDATE screen_menu_assignments
SET is_active = 'N'
WHERE screen_id IN (
SELECT screen_id
FROM screen_definitions
WHERE is_active = 'D'
) AND is_active = 'Y'
`;
) AND is_active = 'Y'`,
[]
);
const updatedCount = result.length;
return {
updatedCount: Number(result),
message: `${result}개의 메뉴 할당이 정리되었습니다.`,
updatedCount,
message: `${updatedCount}개의 메뉴 할당이 정리되었습니다.`,
};
}
/**
* ( )
* ( ) ( Raw Query )
*/
async permanentDeleteScreen(
screenId: number,
userCompanyCode: string
): Promise<void> {
// 권한 확인
const existingScreen = await prisma.screen_definitions.findUnique({
where: { screen_id: screenId },
});
const screens = await query<{ company_code: string | null; is_active: string }>(
`SELECT company_code, is_active FROM screen_definitions WHERE screen_id = $1 LIMIT 1`,
[screenId]
);
if (!existingScreen) {
if (screens.length === 0) {
throw new Error("화면을 찾을 수 없습니다.");
}
const existingScreen = screens[0];
if (
userCompanyCode !== "*" &&
existingScreen.company_code !== userCompanyCode
@ -710,14 +727,16 @@ export class ScreenManagementService {
throw new Error("휴지통에 있는 화면만 영구 삭제할 수 있습니다.");
}
// 물리적 삭제 (CASCADE로 관련 레이아웃과 메뉴 할당도 함께 삭제됨)
await prisma.screen_definitions.delete({
where: { screen_id: screenId },
// 물리적 삭제 (수동으로 관련 데이터 삭제)
await transaction(async (client) => {
await client.query(`DELETE FROM screen_layouts WHERE screen_id = $1`, [screenId]);
await client.query(`DELETE FROM screen_menu_assignments WHERE screen_id = $1`, [screenId]);
await client.query(`DELETE FROM screen_definitions WHERE screen_id = $1`, [screenId]);
});
}
/**
*
* ( Raw Query )
*/
async getDeletedScreens(
companyCode: string,
@ -732,37 +751,54 @@ export class ScreenManagementService {
}
>
> {
const whereClause: any = { is_active: "D" };
const offset = (page - 1) * size;
const whereConditions: string[] = ["is_active = 'D'"];
const params: any[] = [];
if (companyCode !== "*") {
whereClause.company_code = companyCode;
whereConditions.push(`company_code = $${params.length + 1}`);
params.push(companyCode);
}
const [screens, total] = await Promise.all([
prisma.screen_definitions.findMany({
where: whereClause,
skip: (page - 1) * size,
take: size,
orderBy: { deleted_date: "desc" },
}),
prisma.screen_definitions.count({ where: whereClause }),
const whereSQL = whereConditions.join(" AND ");
const [screens, totalResult] = await Promise.all([
query<any>(
`SELECT * FROM screen_definitions
WHERE ${whereSQL}
ORDER BY deleted_date DESC NULLS LAST
LIMIT $${params.length + 1} OFFSET $${params.length + 2}`,
[...params, size, offset]
),
query<{ count: string }>(
`SELECT COUNT(*)::text as count FROM screen_definitions WHERE ${whereSQL}`,
params
),
]);
const total = parseInt(totalResult[0]?.count || "0", 10);
// 테이블 라벨 정보를 한 번에 조회
const tableNames = [
...new Set(screens.map((s) => s.table_name).filter(Boolean)),
...new Set(screens.map((s: any) => 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])
let tableLabelMap = new Map<string, string>();
if (tableNames.length > 0) {
const placeholders = tableNames.map((_, i) => `$${i + 1}`).join(", ");
const tableLabels = await query<{ table_name: string; table_label: string | null }>(
`SELECT table_name, table_label FROM table_labels WHERE table_name IN (${placeholders})`,
tableNames
);
tableLabelMap = new Map(
tableLabels.map((tl: any) => [tl.table_name, tl.table_label || tl.table_name])
);
}
return {
data: screens.map((screen) => ({
data: screens.map((screen: any) => ({
...this.mapToScreenDefinition(screen, tableLabelMap),
deletedDate: screen.deleted_date || undefined,
deletedBy: screen.deleted_by || undefined,