컴포넌트 화면편집기에 배치

This commit is contained in:
kjs
2025-09-10 14:09:32 +09:00
parent 3bf694ce24
commit 01860df8d7
56 changed files with 4572 additions and 778 deletions

View File

@@ -1,8 +1,14 @@
import { Response } from "express";
import { AuthenticatedRequest } from "../types/auth";
import { Request, Response } from "express";
import { templateStandardService } from "../services/templateStandardService";
import { handleError } from "../utils/errorHandler";
import { checkMissingFields } from "../utils/validation";
interface AuthenticatedRequest extends Request {
user?: {
userId: string;
companyCode: string;
company_code?: string;
[key: string]: any;
};
}
/**
* 템플릿 표준 관리 컨트롤러
@@ -11,26 +17,26 @@ export class TemplateStandardController {
/**
* 템플릿 목록 조회
*/
async getTemplates(req: AuthenticatedRequest, res: Response) {
async getTemplates(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
const {
active = "Y",
category,
search,
companyCode,
company_code,
is_public = "Y",
page = "1",
limit = "50",
} = req.query;
const user = req.user;
const userCompanyCode = user?.companyCode || "DEFAULT";
const userCompanyCode = user?.company_code || "DEFAULT";
const result = await templateStandardService.getTemplates({
active: active as string,
category: category as string,
search: search as string,
company_code: (companyCode as string) || userCompanyCode,
company_code: (company_code as string) || userCompanyCode,
is_public: is_public as string,
page: parseInt(page as string),
limit: parseInt(limit as string),
@@ -47,23 +53,24 @@ export class TemplateStandardController {
},
});
} catch (error) {
return handleError(
res,
error,
"템플릿 목록 조회 중 오류가 발생했습니다."
);
console.error("템플릿 목록 조회 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 목록 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 상세 조회
*/
async getTemplate(req: AuthenticatedRequest, res: Response) {
async getTemplate(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
const { templateCode } = req.params;
if (!templateCode) {
return res.status(400).json({
res.status(400).json({
success: false,
error: "템플릿 코드가 필요합니다.",
});
@@ -72,7 +79,7 @@ export class TemplateStandardController {
const template = await templateStandardService.getTemplate(templateCode);
if (!template) {
return res.status(404).json({
res.status(404).json({
success: false,
error: "템플릿을 찾을 수 없습니다.",
});
@@ -83,40 +90,46 @@ export class TemplateStandardController {
data: template,
});
} catch (error) {
return handleError(res, error, "템플릿 조회 중 오류가 발생했습니다.");
console.error("템플릿 조회 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 생성
*/
async createTemplate(req: AuthenticatedRequest, res: Response) {
async createTemplate(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const user = req.user;
const templateData = req.body;
// 필수 필드 검증
const requiredFields = [
"template_code",
"template_name",
"category",
"layout_config",
];
const missingFields = checkMissingFields(templateData, requiredFields);
if (missingFields.length > 0) {
return res.status(400).json({
if (
!templateData.template_code ||
!templateData.template_name ||
!templateData.category ||
!templateData.layout_config
) {
res.status(400).json({
success: false,
error: `필수 필드가 누락되었습니다: ${missingFields.join(", ")}`,
message:
"필수 필드가 누락되었습니다. (template_code, template_name, category, layout_config)",
});
}
// 회사 코드와 생성자 정보 추가
const templateWithMeta = {
...templateData,
company_code: user?.companyCode || "DEFAULT",
created_by: user?.userId || "system",
updated_by: user?.userId || "system",
company_code: user?.company_code || "DEFAULT",
created_by: user?.user_id || "system",
updated_by: user?.user_id || "system",
};
const newTemplate =
@@ -128,21 +141,29 @@ export class TemplateStandardController {
message: "템플릿이 성공적으로 생성되었습니다.",
});
} catch (error) {
return handleError(res, error, "템플릿 생성 중 오류가 발생했습니다.");
console.error("템플릿 생성 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 생성 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 수정
*/
async updateTemplate(req: AuthenticatedRequest, res: Response) {
async updateTemplate(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const { templateCode } = req.params;
const templateData = req.body;
const user = req.user;
if (!templateCode) {
return res.status(400).json({
res.status(400).json({
success: false,
error: "템플릿 코드가 필요합니다.",
});
@@ -151,7 +172,7 @@ export class TemplateStandardController {
// 수정자 정보 추가
const templateWithMeta = {
...templateData,
updated_by: user?.userId || "system",
updated_by: user?.user_id || "system",
};
const updatedTemplate = await templateStandardService.updateTemplate(
@@ -160,7 +181,7 @@ export class TemplateStandardController {
);
if (!updatedTemplate) {
return res.status(404).json({
res.status(404).json({
success: false,
error: "템플릿을 찾을 수 없습니다.",
});
@@ -172,19 +193,27 @@ export class TemplateStandardController {
message: "템플릿이 성공적으로 수정되었습니다.",
});
} catch (error) {
return handleError(res, error, "템플릿 수정 중 오류가 발생했습니다.");
console.error("템플릿 수정 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 수정 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 삭제
*/
async deleteTemplate(req: AuthenticatedRequest, res: Response) {
async deleteTemplate(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const { templateCode } = req.params;
if (!templateCode) {
return res.status(400).json({
res.status(400).json({
success: false,
error: "템플릿 코드가 필요합니다.",
});
@@ -194,7 +223,7 @@ export class TemplateStandardController {
await templateStandardService.deleteTemplate(templateCode);
if (!deleted) {
return res.status(404).json({
res.status(404).json({
success: false,
error: "템플릿을 찾을 수 없습니다.",
});
@@ -205,19 +234,27 @@ export class TemplateStandardController {
message: "템플릿이 성공적으로 삭제되었습니다.",
});
} catch (error) {
return handleError(res, error, "템플릿 삭제 중 오류가 발생했습니다.");
console.error("템플릿 삭제 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 삭제 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 정렬 순서 일괄 업데이트
*/
async updateSortOrder(req: AuthenticatedRequest, res: Response) {
async updateSortOrder(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const { templates } = req.body;
if (!Array.isArray(templates)) {
return res.status(400).json({
res.status(400).json({
success: false,
error: "templates는 배열이어야 합니다.",
});
@@ -230,25 +267,29 @@ export class TemplateStandardController {
message: "템플릿 정렬 순서가 성공적으로 업데이트되었습니다.",
});
} catch (error) {
return handleError(
res,
error,
"템플릿 정렬 순서 업데이트 중 오류가 발생했습니다."
);
console.error("템플릿 정렬 순서 업데이트 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 정렬 순서 업데이트 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 복제
*/
async duplicateTemplate(req: AuthenticatedRequest, res: Response) {
async duplicateTemplate(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const { templateCode } = req.params;
const { new_template_code, new_template_name } = req.body;
const user = req.user;
if (!templateCode || !new_template_code || !new_template_name) {
return res.status(400).json({
res.status(400).json({
success: false,
error: "필수 필드가 누락되었습니다.",
});
@@ -259,8 +300,8 @@ export class TemplateStandardController {
originalCode: templateCode,
newCode: new_template_code,
newName: new_template_name,
company_code: user?.companyCode || "DEFAULT",
created_by: user?.userId || "system",
company_code: user?.company_code || "DEFAULT",
created_by: user?.user_id || "system",
});
res.status(201).json({
@@ -269,17 +310,22 @@ export class TemplateStandardController {
message: "템플릿이 성공적으로 복제되었습니다.",
});
} catch (error) {
return handleError(res, error, "템플릿 복제 중 오류가 발생했습니다.");
console.error("템플릿 복제 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 복제 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 카테고리 목록 조회
*/
async getCategories(req: AuthenticatedRequest, res: Response) {
async getCategories(req: AuthenticatedRequest, res: Response): Promise<void> {
try {
const user = req.user;
const companyCode = user?.companyCode || "DEFAULT";
const companyCode = user?.company_code || "DEFAULT";
const categories =
await templateStandardService.getCategories(companyCode);
@@ -289,24 +335,28 @@ export class TemplateStandardController {
data: categories,
});
} catch (error) {
return handleError(
res,
error,
"템플릿 카테고리 조회 중 오류가 발생했습니다."
);
console.error("템플릿 카테고리 조회 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 카테고리 조회 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 가져오기 (JSON 파일에서)
*/
async importTemplate(req: AuthenticatedRequest, res: Response) {
async importTemplate(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const user = req.user;
const templateData = req.body;
if (!templateData.layout_config) {
return res.status(400).json({
res.status(400).json({
success: false,
error: "유효한 템플릿 데이터가 아닙니다.",
});
@@ -315,9 +365,9 @@ export class TemplateStandardController {
// 회사 코드와 생성자 정보 추가
const templateWithMeta = {
...templateData,
company_code: user?.companyCode || "DEFAULT",
created_by: user?.userId || "system",
updated_by: user?.userId || "system",
company_code: user?.company_code || "DEFAULT",
created_by: user?.user_id || "system",
updated_by: user?.user_id || "system",
};
const importedTemplate =
@@ -329,31 +379,41 @@ export class TemplateStandardController {
message: "템플릿이 성공적으로 가져왔습니다.",
});
} catch (error) {
return handleError(res, error, "템플릿 가져오기 중 오류가 발생했습니다.");
console.error("템플릿 가져오기 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 가져오기 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
/**
* 템플릿 내보내기 (JSON 형태로)
*/
async exportTemplate(req: AuthenticatedRequest, res: Response) {
async exportTemplate(
req: AuthenticatedRequest,
res: Response
): Promise<void> {
try {
const { templateCode } = req.params;
if (!templateCode) {
return res.status(400).json({
res.status(400).json({
success: false,
error: "템플릿 코드가 필요합니다.",
});
return;
}
const template = await templateStandardService.getTemplate(templateCode);
if (!template) {
return res.status(404).json({
res.status(404).json({
success: false,
error: "템플릿을 찾을 수 없습니다.",
});
return;
}
// 내보내기용 데이터 (메타데이터 제외)
@@ -373,7 +433,12 @@ export class TemplateStandardController {
data: exportData,
});
} catch (error) {
return handleError(res, error, "템플릿 내보내기 중 오류가 발생했습니다.");
console.error("템플릿 내보내기 중 오류:", error);
res.status(500).json({
success: false,
message: "템플릿 내보내기 중 오류가 발생했습니다.",
error: error instanceof Error ? error.message : "알 수 없는 오류",
});
}
}
}