템플릿관리, 컴포넌트 관리
This commit is contained in:
302
backend-node/src/services/componentStandardService.ts
Normal file
302
backend-node/src/services/componentStandardService.ts
Normal file
@@ -0,0 +1,302 @@
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export interface ComponentStandardData {
|
||||
component_code: string;
|
||||
component_name: string;
|
||||
component_name_eng?: string;
|
||||
description?: string;
|
||||
category: string;
|
||||
icon_name?: string;
|
||||
default_size?: any;
|
||||
component_config: any;
|
||||
preview_image?: string;
|
||||
sort_order?: number;
|
||||
is_active?: string;
|
||||
is_public?: string;
|
||||
company_code: string;
|
||||
created_by?: string;
|
||||
updated_by?: string;
|
||||
}
|
||||
|
||||
export interface ComponentQueryParams {
|
||||
category?: string;
|
||||
active?: string;
|
||||
is_public?: string;
|
||||
company_code?: string;
|
||||
search?: string;
|
||||
sort?: string;
|
||||
order?: "asc" | "desc";
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
class ComponentStandardService {
|
||||
/**
|
||||
* 컴포넌트 목록 조회
|
||||
*/
|
||||
async getComponents(params: ComponentQueryParams = {}) {
|
||||
const {
|
||||
category,
|
||||
active = "Y",
|
||||
is_public,
|
||||
company_code,
|
||||
search,
|
||||
sort = "sort_order",
|
||||
order = "asc",
|
||||
limit,
|
||||
offset = 0,
|
||||
} = params;
|
||||
|
||||
const where: any = {};
|
||||
|
||||
// 활성화 상태 필터
|
||||
if (active) {
|
||||
where.is_active = active;
|
||||
}
|
||||
|
||||
// 카테고리 필터
|
||||
if (category && category !== "all") {
|
||||
where.category = category;
|
||||
}
|
||||
|
||||
// 공개 여부 필터
|
||||
if (is_public) {
|
||||
where.is_public = is_public;
|
||||
}
|
||||
|
||||
// 회사별 필터 (공개 컴포넌트 + 해당 회사 컴포넌트)
|
||||
if (company_code) {
|
||||
where.OR = [{ is_public: "Y" }, { company_code }];
|
||||
}
|
||||
|
||||
// 검색 조건
|
||||
if (search) {
|
||||
where.OR = [
|
||||
...(where.OR || []),
|
||||
{ component_name: { contains: search, mode: "insensitive" } },
|
||||
{ component_name_eng: { contains: search, mode: "insensitive" } },
|
||||
{ description: { contains: search, mode: "insensitive" } },
|
||||
];
|
||||
}
|
||||
|
||||
const orderBy: any = {};
|
||||
orderBy[sort] = order;
|
||||
|
||||
const components = await prisma.component_standards.findMany({
|
||||
where,
|
||||
orderBy,
|
||||
take: limit,
|
||||
skip: offset,
|
||||
});
|
||||
|
||||
const total = await prisma.component_standards.count({ where });
|
||||
|
||||
return {
|
||||
components,
|
||||
total,
|
||||
limit,
|
||||
offset,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 상세 조회
|
||||
*/
|
||||
async getComponent(component_code: string) {
|
||||
const component = await prisma.component_standards.findUnique({
|
||||
where: { component_code },
|
||||
});
|
||||
|
||||
if (!component) {
|
||||
throw new Error(`컴포넌트를 찾을 수 없습니다: ${component_code}`);
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 생성
|
||||
*/
|
||||
async createComponent(data: ComponentStandardData) {
|
||||
// 중복 코드 확인
|
||||
const existing = await prisma.component_standards.findUnique({
|
||||
where: { component_code: data.component_code },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
throw new Error(
|
||||
`이미 존재하는 컴포넌트 코드입니다: ${data.component_code}`
|
||||
);
|
||||
}
|
||||
|
||||
const component = await prisma.component_standards.create({
|
||||
data: {
|
||||
...data,
|
||||
created_date: new Date(),
|
||||
updated_date: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 수정
|
||||
*/
|
||||
async updateComponent(
|
||||
component_code: string,
|
||||
data: Partial<ComponentStandardData>
|
||||
) {
|
||||
const existing = await this.getComponent(component_code);
|
||||
|
||||
const component = await prisma.component_standards.update({
|
||||
where: { component_code },
|
||||
data: {
|
||||
...data,
|
||||
updated_date: new Date(),
|
||||
},
|
||||
});
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 삭제
|
||||
*/
|
||||
async deleteComponent(component_code: string) {
|
||||
const existing = await this.getComponent(component_code);
|
||||
|
||||
await prisma.component_standards.delete({
|
||||
where: { component_code },
|
||||
});
|
||||
|
||||
return { message: `컴포넌트가 삭제되었습니다: ${component_code}` };
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 정렬 순서 업데이트
|
||||
*/
|
||||
async updateSortOrder(
|
||||
updates: Array<{ component_code: string; sort_order: number }>
|
||||
) {
|
||||
const transactions = updates.map(({ component_code, sort_order }) =>
|
||||
prisma.component_standards.update({
|
||||
where: { component_code },
|
||||
data: { sort_order, updated_date: new Date() },
|
||||
})
|
||||
);
|
||||
|
||||
await prisma.$transaction(transactions);
|
||||
|
||||
return { message: "정렬 순서가 업데이트되었습니다." };
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 복제
|
||||
*/
|
||||
async duplicateComponent(
|
||||
source_code: string,
|
||||
new_code: string,
|
||||
new_name: string
|
||||
) {
|
||||
const source = await this.getComponent(source_code);
|
||||
|
||||
// 새 코드 중복 확인
|
||||
const existing = await prisma.component_standards.findUnique({
|
||||
where: { component_code: new_code },
|
||||
});
|
||||
|
||||
if (existing) {
|
||||
throw new Error(`이미 존재하는 컴포넌트 코드입니다: ${new_code}`);
|
||||
}
|
||||
|
||||
const component = await prisma.component_standards.create({
|
||||
data: {
|
||||
component_code: new_code,
|
||||
component_name: new_name,
|
||||
component_name_eng: source.component_name_eng,
|
||||
description: source.description,
|
||||
category: source.category,
|
||||
icon_name: source.icon_name,
|
||||
default_size: source.default_size as any,
|
||||
component_config: source.component_config as any,
|
||||
preview_image: source.preview_image,
|
||||
sort_order: source.sort_order,
|
||||
is_active: source.is_active,
|
||||
is_public: source.is_public,
|
||||
company_code: source.company_code,
|
||||
created_date: new Date(),
|
||||
created_by: source.created_by,
|
||||
updated_date: new Date(),
|
||||
updated_by: source.updated_by,
|
||||
},
|
||||
});
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* 카테고리 목록 조회
|
||||
*/
|
||||
async getCategories(company_code?: string) {
|
||||
const where: any = {
|
||||
is_active: "Y",
|
||||
};
|
||||
|
||||
if (company_code) {
|
||||
where.OR = [{ is_public: "Y" }, { company_code }];
|
||||
}
|
||||
|
||||
const categories = await prisma.component_standards.findMany({
|
||||
where,
|
||||
select: { category: true },
|
||||
distinct: ["category"],
|
||||
});
|
||||
|
||||
return categories
|
||||
.map((item) => item.category)
|
||||
.filter((category) => category !== null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 컴포넌트 통계
|
||||
*/
|
||||
async getStatistics(company_code?: string) {
|
||||
const where: any = {
|
||||
is_active: "Y",
|
||||
};
|
||||
|
||||
if (company_code) {
|
||||
where.OR = [{ is_public: "Y" }, { company_code }];
|
||||
}
|
||||
|
||||
const total = await prisma.component_standards.count({ where });
|
||||
|
||||
const byCategory = await prisma.component_standards.groupBy({
|
||||
by: ["category"],
|
||||
where,
|
||||
_count: { category: true },
|
||||
});
|
||||
|
||||
const byStatus = await prisma.component_standards.groupBy({
|
||||
by: ["is_active"],
|
||||
_count: { is_active: true },
|
||||
});
|
||||
|
||||
return {
|
||||
total,
|
||||
byCategory: byCategory.map((item) => ({
|
||||
category: item.category,
|
||||
count: item._count.category,
|
||||
})),
|
||||
byStatus: byStatus.map((item) => ({
|
||||
status: item.is_active,
|
||||
count: item._count.is_active,
|
||||
})),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default new ComponentStandardService();
|
||||
Reference in New Issue
Block a user