feat: Phase 2.1 Stage 3 complete - 템플릿 & 메뉴 관리 전환 (17/46)
Stage 3 완료: 템플릿 & 메뉴 관리 Raw Query 전환 ✅ 전환 완료 (5개 Prisma 호출): **템플릿 관리 (2개):** 11. getTemplatesByCompany() - 템플릿 목록 조회 (동적 WHERE) 12. createTemplate() - 템플릿 생성 (JSON layout_data) **메뉴 할당 관리 (3개):** 13. assignScreenToMenu() - 메뉴 할당 (중복 확인 + INSERT) 14. getScreensByMenu() - 메뉴별 화면 조회 (JOIN screen_definitions) 15. unassignScreenFromMenu() - 메뉴 할당 해제 (DELETE) 📊 진행률: 17/46 (37.0%) 🎯 다음: Stage 4 복잡한 기능 (트랜잭션, Raw Query 개선) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1346,54 +1346,67 @@ export class ScreenManagementService {
|
|||||||
// ========================================
|
// ========================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 템플릿 목록 조회 (회사별)
|
* 템플릿 목록 조회 (회사별) (✅ Raw Query 전환 완료)
|
||||||
*/
|
*/
|
||||||
async getTemplatesByCompany(
|
async getTemplatesByCompany(
|
||||||
companyCode: string,
|
companyCode: string,
|
||||||
type?: string,
|
type?: string,
|
||||||
isPublic?: boolean
|
isPublic?: boolean
|
||||||
): Promise<ScreenTemplate[]> {
|
): Promise<ScreenTemplate[]> {
|
||||||
const whereClause: any = {};
|
const whereConditions: string[] = [];
|
||||||
|
const params: any[] = [];
|
||||||
|
|
||||||
if (companyCode !== "*") {
|
if (companyCode !== "*") {
|
||||||
whereClause.company_code = companyCode;
|
whereConditions.push(`company_code = $${params.length + 1}`);
|
||||||
|
params.push(companyCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type) {
|
if (type) {
|
||||||
whereClause.template_type = type;
|
whereConditions.push(`template_type = $${params.length + 1}`);
|
||||||
|
params.push(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPublic !== undefined) {
|
if (isPublic !== undefined) {
|
||||||
whereClause.is_public = isPublic;
|
whereConditions.push(`is_public = $${params.length + 1}`);
|
||||||
|
params.push(isPublic);
|
||||||
}
|
}
|
||||||
|
|
||||||
const templates = await prisma.screen_templates.findMany({
|
const whereSQL = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" AND ")}` : "";
|
||||||
where: whereClause,
|
|
||||||
orderBy: { created_date: "desc" },
|
const templates = await query<any>(
|
||||||
});
|
`SELECT * FROM screen_templates
|
||||||
|
${whereSQL}
|
||||||
|
ORDER BY created_date DESC`,
|
||||||
|
params
|
||||||
|
);
|
||||||
|
|
||||||
return templates.map(this.mapToScreenTemplate);
|
return templates.map(this.mapToScreenTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 템플릿 생성
|
* 템플릿 생성 (✅ Raw Query 전환 완료)
|
||||||
*/
|
*/
|
||||||
async createTemplate(
|
async createTemplate(
|
||||||
templateData: Partial<ScreenTemplate>
|
templateData: Partial<ScreenTemplate>
|
||||||
): Promise<ScreenTemplate> {
|
): Promise<ScreenTemplate> {
|
||||||
const template = await prisma.screen_templates.create({
|
const [template] = await query<any>(
|
||||||
data: {
|
`INSERT INTO screen_templates (
|
||||||
template_name: templateData.templateName!,
|
template_name, template_type, company_code, description,
|
||||||
template_type: templateData.templateType!,
|
layout_data, is_public, created_by
|
||||||
company_code: templateData.companyCode!,
|
) VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||||
description: templateData.description,
|
RETURNING *`,
|
||||||
layout_data: templateData.layoutData
|
[
|
||||||
? JSON.parse(JSON.stringify(templateData.layoutData))
|
templateData.templateName!,
|
||||||
|
templateData.templateType!,
|
||||||
|
templateData.companyCode!,
|
||||||
|
templateData.description || null,
|
||||||
|
templateData.layoutData
|
||||||
|
? JSON.stringify(JSON.parse(JSON.stringify(templateData.layoutData)))
|
||||||
: null,
|
: null,
|
||||||
is_public: templateData.isPublic || false,
|
templateData.isPublic || false,
|
||||||
created_by: templateData.createdBy,
|
templateData.createdBy || null,
|
||||||
},
|
]
|
||||||
});
|
);
|
||||||
|
|
||||||
return this.mapToScreenTemplate(template);
|
return this.mapToScreenTemplate(template);
|
||||||
}
|
}
|
||||||
@@ -1403,75 +1416,71 @@ export class ScreenManagementService {
|
|||||||
// ========================================
|
// ========================================
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 화면-메뉴 할당
|
* 화면-메뉴 할당 (✅ Raw Query 전환 완료)
|
||||||
*/
|
*/
|
||||||
async assignScreenToMenu(
|
async assignScreenToMenu(
|
||||||
screenId: number,
|
screenId: number,
|
||||||
assignmentData: MenuAssignmentRequest
|
assignmentData: MenuAssignmentRequest
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
// 중복 할당 방지
|
// 중복 할당 방지
|
||||||
const existingAssignment = await prisma.screen_menu_assignments.findFirst({
|
const existing = await query<{ assignment_id: number }>(
|
||||||
where: {
|
`SELECT assignment_id FROM screen_menu_assignments
|
||||||
screen_id: screenId,
|
WHERE screen_id = $1 AND menu_objid = $2 AND company_code = $3
|
||||||
menu_objid: assignmentData.menuObjid,
|
LIMIT 1`,
|
||||||
company_code: assignmentData.companyCode,
|
[screenId, assignmentData.menuObjid, assignmentData.companyCode]
|
||||||
},
|
);
|
||||||
});
|
|
||||||
|
|
||||||
if (existingAssignment) {
|
if (existing.length > 0) {
|
||||||
throw new Error("이미 할당된 화면입니다.");
|
throw new Error("이미 할당된 화면입니다.");
|
||||||
}
|
}
|
||||||
|
|
||||||
await prisma.screen_menu_assignments.create({
|
await query(
|
||||||
data: {
|
`INSERT INTO screen_menu_assignments (
|
||||||
screen_id: screenId,
|
screen_id, menu_objid, company_code, display_order, created_by
|
||||||
menu_objid: assignmentData.menuObjid,
|
) VALUES ($1, $2, $3, $4, $5)`,
|
||||||
company_code: assignmentData.companyCode,
|
[
|
||||||
display_order: assignmentData.displayOrder || 0,
|
screenId,
|
||||||
created_by: assignmentData.createdBy,
|
assignmentData.menuObjid,
|
||||||
},
|
assignmentData.companyCode,
|
||||||
});
|
assignmentData.displayOrder || 0,
|
||||||
|
assignmentData.createdBy || null,
|
||||||
|
]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 메뉴별 화면 목록 조회
|
* 메뉴별 화면 목록 조회 (✅ Raw Query 전환 완료)
|
||||||
*/
|
*/
|
||||||
async getScreensByMenu(
|
async getScreensByMenu(
|
||||||
menuObjid: number,
|
menuObjid: number,
|
||||||
companyCode: string
|
companyCode: string
|
||||||
): Promise<ScreenDefinition[]> {
|
): Promise<ScreenDefinition[]> {
|
||||||
const assignments = await prisma.screen_menu_assignments.findMany({
|
const screens = await query<any>(
|
||||||
where: {
|
`SELECT sd.* FROM screen_menu_assignments sma
|
||||||
menu_objid: menuObjid,
|
INNER JOIN screen_definitions sd ON sma.screen_id = sd.screen_id
|
||||||
company_code: companyCode,
|
WHERE sma.menu_objid = $1
|
||||||
is_active: "Y",
|
AND sma.company_code = $2
|
||||||
},
|
AND sma.is_active = 'Y'
|
||||||
include: {
|
ORDER BY sma.display_order ASC`,
|
||||||
screen: true,
|
[menuObjid, companyCode]
|
||||||
},
|
|
||||||
orderBy: { display_order: "asc" },
|
|
||||||
});
|
|
||||||
|
|
||||||
return assignments.map((assignment) =>
|
|
||||||
this.mapToScreenDefinition(assignment.screen)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return screens.map((screen) => this.mapToScreenDefinition(screen));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 화면-메뉴 할당 해제
|
* 화면-메뉴 할당 해제 (✅ Raw Query 전환 완료)
|
||||||
*/
|
*/
|
||||||
async unassignScreenFromMenu(
|
async unassignScreenFromMenu(
|
||||||
screenId: number,
|
screenId: number,
|
||||||
menuObjid: number,
|
menuObjid: number,
|
||||||
companyCode: string
|
companyCode: string
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
await prisma.screen_menu_assignments.deleteMany({
|
await query(
|
||||||
where: {
|
`DELETE FROM screen_menu_assignments
|
||||||
screen_id: screenId,
|
WHERE screen_id = $1 AND menu_objid = $2 AND company_code = $3`,
|
||||||
menu_objid: menuObjid,
|
[screenId, menuObjid, companyCode]
|
||||||
company_code: companyCode,
|
);
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
|
|||||||
Reference in New Issue
Block a user