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:
parent
67dced74bd
commit
74351e816b
|
|
@ -1346,54 +1346,67 @@ export class ScreenManagementService {
|
|||
// ========================================
|
||||
|
||||
/**
|
||||
* 템플릿 목록 조회 (회사별)
|
||||
* 템플릿 목록 조회 (회사별) (✅ Raw Query 전환 완료)
|
||||
*/
|
||||
async getTemplatesByCompany(
|
||||
companyCode: string,
|
||||
type?: string,
|
||||
isPublic?: boolean
|
||||
): Promise<ScreenTemplate[]> {
|
||||
const whereClause: any = {};
|
||||
const whereConditions: string[] = [];
|
||||
const params: any[] = [];
|
||||
|
||||
if (companyCode !== "*") {
|
||||
whereClause.company_code = companyCode;
|
||||
whereConditions.push(`company_code = $${params.length + 1}`);
|
||||
params.push(companyCode);
|
||||
}
|
||||
|
||||
if (type) {
|
||||
whereClause.template_type = type;
|
||||
whereConditions.push(`template_type = $${params.length + 1}`);
|
||||
params.push(type);
|
||||
}
|
||||
|
||||
if (isPublic !== undefined) {
|
||||
whereClause.is_public = isPublic;
|
||||
whereConditions.push(`is_public = $${params.length + 1}`);
|
||||
params.push(isPublic);
|
||||
}
|
||||
|
||||
const templates = await prisma.screen_templates.findMany({
|
||||
where: whereClause,
|
||||
orderBy: { created_date: "desc" },
|
||||
});
|
||||
const whereSQL = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" AND ")}` : "";
|
||||
|
||||
const templates = await query<any>(
|
||||
`SELECT * FROM screen_templates
|
||||
${whereSQL}
|
||||
ORDER BY created_date DESC`,
|
||||
params
|
||||
);
|
||||
|
||||
return templates.map(this.mapToScreenTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 템플릿 생성
|
||||
* 템플릿 생성 (✅ Raw Query 전환 완료)
|
||||
*/
|
||||
async createTemplate(
|
||||
templateData: Partial<ScreenTemplate>
|
||||
): Promise<ScreenTemplate> {
|
||||
const template = await prisma.screen_templates.create({
|
||||
data: {
|
||||
template_name: templateData.templateName!,
|
||||
template_type: templateData.templateType!,
|
||||
company_code: templateData.companyCode!,
|
||||
description: templateData.description,
|
||||
layout_data: templateData.layoutData
|
||||
? JSON.parse(JSON.stringify(templateData.layoutData))
|
||||
const [template] = await query<any>(
|
||||
`INSERT INTO screen_templates (
|
||||
template_name, template_type, company_code, description,
|
||||
layout_data, is_public, created_by
|
||||
) VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||
RETURNING *`,
|
||||
[
|
||||
templateData.templateName!,
|
||||
templateData.templateType!,
|
||||
templateData.companyCode!,
|
||||
templateData.description || null,
|
||||
templateData.layoutData
|
||||
? JSON.stringify(JSON.parse(JSON.stringify(templateData.layoutData)))
|
||||
: null,
|
||||
is_public: templateData.isPublic || false,
|
||||
created_by: templateData.createdBy,
|
||||
},
|
||||
});
|
||||
templateData.isPublic || false,
|
||||
templateData.createdBy || null,
|
||||
]
|
||||
);
|
||||
|
||||
return this.mapToScreenTemplate(template);
|
||||
}
|
||||
|
|
@ -1403,75 +1416,71 @@ export class ScreenManagementService {
|
|||
// ========================================
|
||||
|
||||
/**
|
||||
* 화면-메뉴 할당
|
||||
* 화면-메뉴 할당 (✅ Raw Query 전환 완료)
|
||||
*/
|
||||
async assignScreenToMenu(
|
||||
screenId: number,
|
||||
assignmentData: MenuAssignmentRequest
|
||||
): Promise<void> {
|
||||
// 중복 할당 방지
|
||||
const existingAssignment = await prisma.screen_menu_assignments.findFirst({
|
||||
where: {
|
||||
screen_id: screenId,
|
||||
menu_objid: assignmentData.menuObjid,
|
||||
company_code: assignmentData.companyCode,
|
||||
},
|
||||
});
|
||||
const existing = await query<{ assignment_id: number }>(
|
||||
`SELECT assignment_id FROM screen_menu_assignments
|
||||
WHERE screen_id = $1 AND menu_objid = $2 AND company_code = $3
|
||||
LIMIT 1`,
|
||||
[screenId, assignmentData.menuObjid, assignmentData.companyCode]
|
||||
);
|
||||
|
||||
if (existingAssignment) {
|
||||
if (existing.length > 0) {
|
||||
throw new Error("이미 할당된 화면입니다.");
|
||||
}
|
||||
|
||||
await prisma.screen_menu_assignments.create({
|
||||
data: {
|
||||
screen_id: screenId,
|
||||
menu_objid: assignmentData.menuObjid,
|
||||
company_code: assignmentData.companyCode,
|
||||
display_order: assignmentData.displayOrder || 0,
|
||||
created_by: assignmentData.createdBy,
|
||||
},
|
||||
});
|
||||
await query(
|
||||
`INSERT INTO screen_menu_assignments (
|
||||
screen_id, menu_objid, company_code, display_order, created_by
|
||||
) VALUES ($1, $2, $3, $4, $5)`,
|
||||
[
|
||||
screenId,
|
||||
assignmentData.menuObjid,
|
||||
assignmentData.companyCode,
|
||||
assignmentData.displayOrder || 0,
|
||||
assignmentData.createdBy || null,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 메뉴별 화면 목록 조회
|
||||
* 메뉴별 화면 목록 조회 (✅ Raw Query 전환 완료)
|
||||
*/
|
||||
async getScreensByMenu(
|
||||
menuObjid: number,
|
||||
companyCode: string
|
||||
): Promise<ScreenDefinition[]> {
|
||||
const assignments = await prisma.screen_menu_assignments.findMany({
|
||||
where: {
|
||||
menu_objid: menuObjid,
|
||||
company_code: companyCode,
|
||||
is_active: "Y",
|
||||
},
|
||||
include: {
|
||||
screen: true,
|
||||
},
|
||||
orderBy: { display_order: "asc" },
|
||||
});
|
||||
|
||||
return assignments.map((assignment) =>
|
||||
this.mapToScreenDefinition(assignment.screen)
|
||||
const screens = await query<any>(
|
||||
`SELECT sd.* FROM screen_menu_assignments sma
|
||||
INNER JOIN screen_definitions sd ON sma.screen_id = sd.screen_id
|
||||
WHERE sma.menu_objid = $1
|
||||
AND sma.company_code = $2
|
||||
AND sma.is_active = 'Y'
|
||||
ORDER BY sma.display_order ASC`,
|
||||
[menuObjid, companyCode]
|
||||
);
|
||||
|
||||
return screens.map((screen) => this.mapToScreenDefinition(screen));
|
||||
}
|
||||
|
||||
/**
|
||||
* 화면-메뉴 할당 해제
|
||||
* 화면-메뉴 할당 해제 (✅ Raw Query 전환 완료)
|
||||
*/
|
||||
async unassignScreenFromMenu(
|
||||
screenId: number,
|
||||
menuObjid: number,
|
||||
companyCode: string
|
||||
): Promise<void> {
|
||||
await prisma.screen_menu_assignments.deleteMany({
|
||||
where: {
|
||||
screen_id: screenId,
|
||||
menu_objid: menuObjid,
|
||||
company_code: companyCode,
|
||||
},
|
||||
});
|
||||
await query(
|
||||
`DELETE FROM screen_menu_assignments
|
||||
WHERE screen_id = $1 AND menu_objid = $2 AND company_code = $3`,
|
||||
[screenId, menuObjid, companyCode]
|
||||
);
|
||||
}
|
||||
|
||||
// ========================================
|
||||
|
|
|
|||
Loading…
Reference in New Issue