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:
parent
311811bc0a
commit
4637680de0
|
|
@ -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
|
||||
SET is_active = 'N'
|
||||
WHERE screen_id IN (
|
||||
SELECT screen_id
|
||||
FROM screen_definitions
|
||||
WHERE is_active = 'D'
|
||||
) AND is_active = 'Y'
|
||||
`;
|
||||
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'`,
|
||||
[]
|
||||
);
|
||||
|
||||
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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue