ERP-node/backend-node/src/services/componentStandardService.ts

303 lines
6.9 KiB
TypeScript
Raw Normal View History

2025-09-09 17:42:23 +09:00
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();