350 lines
10 KiB
TypeScript
350 lines
10 KiB
TypeScript
|
|
import { Request, Response } from "express";
|
||
|
|
import { PrismaClient } from "@prisma/client";
|
||
|
|
import { AuthenticatedRequest } from "../types/auth";
|
||
|
|
|
||
|
|
const prisma = new PrismaClient();
|
||
|
|
|
||
|
|
export class ButtonActionStandardController {
|
||
|
|
// 버튼 액션 목록 조회
|
||
|
|
static async getButtonActions(req: Request, res: Response) {
|
||
|
|
try {
|
||
|
|
const { active, category, search } = req.query;
|
||
|
|
|
||
|
|
const where: any = {};
|
||
|
|
|
||
|
|
if (active) {
|
||
|
|
where.is_active = active as string;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (category) {
|
||
|
|
where.category = category as string;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (search) {
|
||
|
|
where.OR = [
|
||
|
|
{ action_name: { contains: search as string, mode: "insensitive" } },
|
||
|
|
{
|
||
|
|
action_name_eng: {
|
||
|
|
contains: search as string,
|
||
|
|
mode: "insensitive",
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{ description: { contains: search as string, mode: "insensitive" } },
|
||
|
|
];
|
||
|
|
}
|
||
|
|
|
||
|
|
const buttonActions = await prisma.button_action_standards.findMany({
|
||
|
|
where,
|
||
|
|
orderBy: [{ sort_order: "asc" }, { action_type: "asc" }],
|
||
|
|
});
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: buttonActions,
|
||
|
|
message: "버튼 액션 목록을 성공적으로 조회했습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error("버튼 액션 목록 조회 오류:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "버튼 액션 목록 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "알 수 없는 오류",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 버튼 액션 상세 조회
|
||
|
|
static async getButtonAction(req: Request, res: Response) {
|
||
|
|
try {
|
||
|
|
const { actionType } = req.params;
|
||
|
|
|
||
|
|
const buttonAction = await prisma.button_action_standards.findUnique({
|
||
|
|
where: { action_type: actionType },
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!buttonAction) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "해당 버튼 액션을 찾을 수 없습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: buttonAction,
|
||
|
|
message: "버튼 액션 정보를 성공적으로 조회했습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error("버튼 액션 상세 조회 오류:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "버튼 액션 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "알 수 없는 오류",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 버튼 액션 생성
|
||
|
|
static async createButtonAction(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const {
|
||
|
|
action_type,
|
||
|
|
action_name,
|
||
|
|
action_name_eng,
|
||
|
|
description,
|
||
|
|
category = "general",
|
||
|
|
default_text,
|
||
|
|
default_text_eng,
|
||
|
|
default_icon,
|
||
|
|
default_color,
|
||
|
|
default_variant = "default",
|
||
|
|
confirmation_required = false,
|
||
|
|
confirmation_message,
|
||
|
|
validation_rules,
|
||
|
|
action_config,
|
||
|
|
sort_order = 0,
|
||
|
|
is_active = "Y",
|
||
|
|
} = req.body;
|
||
|
|
|
||
|
|
// 필수 필드 검증
|
||
|
|
if (!action_type || !action_name) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "액션 타입과 이름은 필수입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 중복 체크
|
||
|
|
const existingAction = await prisma.button_action_standards.findUnique({
|
||
|
|
where: { action_type },
|
||
|
|
});
|
||
|
|
|
||
|
|
if (existingAction) {
|
||
|
|
return res.status(409).json({
|
||
|
|
success: false,
|
||
|
|
message: "이미 존재하는 액션 타입입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const newButtonAction = await prisma.button_action_standards.create({
|
||
|
|
data: {
|
||
|
|
action_type,
|
||
|
|
action_name,
|
||
|
|
action_name_eng,
|
||
|
|
description,
|
||
|
|
category,
|
||
|
|
default_text,
|
||
|
|
default_text_eng,
|
||
|
|
default_icon,
|
||
|
|
default_color,
|
||
|
|
default_variant,
|
||
|
|
confirmation_required,
|
||
|
|
confirmation_message,
|
||
|
|
validation_rules,
|
||
|
|
action_config,
|
||
|
|
sort_order,
|
||
|
|
is_active,
|
||
|
|
created_by: req.user?.userId || "system",
|
||
|
|
updated_by: req.user?.userId || "system",
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
return res.status(201).json({
|
||
|
|
success: true,
|
||
|
|
data: newButtonAction,
|
||
|
|
message: "버튼 액션이 성공적으로 생성되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error("버튼 액션 생성 오류:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "버튼 액션 생성 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "알 수 없는 오류",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 버튼 액션 수정
|
||
|
|
static async updateButtonAction(req: AuthenticatedRequest, res: Response) {
|
||
|
|
try {
|
||
|
|
const { actionType } = req.params;
|
||
|
|
const {
|
||
|
|
action_name,
|
||
|
|
action_name_eng,
|
||
|
|
description,
|
||
|
|
category,
|
||
|
|
default_text,
|
||
|
|
default_text_eng,
|
||
|
|
default_icon,
|
||
|
|
default_color,
|
||
|
|
default_variant,
|
||
|
|
confirmation_required,
|
||
|
|
confirmation_message,
|
||
|
|
validation_rules,
|
||
|
|
action_config,
|
||
|
|
sort_order,
|
||
|
|
is_active,
|
||
|
|
} = req.body;
|
||
|
|
|
||
|
|
// 존재 여부 확인
|
||
|
|
const existingAction = await prisma.button_action_standards.findUnique({
|
||
|
|
where: { action_type: actionType },
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!existingAction) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "해당 버튼 액션을 찾을 수 없습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
const updatedButtonAction = await prisma.button_action_standards.update({
|
||
|
|
where: { action_type: actionType },
|
||
|
|
data: {
|
||
|
|
action_name,
|
||
|
|
action_name_eng,
|
||
|
|
description,
|
||
|
|
category,
|
||
|
|
default_text,
|
||
|
|
default_text_eng,
|
||
|
|
default_icon,
|
||
|
|
default_color,
|
||
|
|
default_variant,
|
||
|
|
confirmation_required,
|
||
|
|
confirmation_message,
|
||
|
|
validation_rules,
|
||
|
|
action_config,
|
||
|
|
sort_order,
|
||
|
|
is_active,
|
||
|
|
updated_by: req.user?.userId || "system",
|
||
|
|
updated_date: new Date(),
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: updatedButtonAction,
|
||
|
|
message: "버튼 액션이 성공적으로 수정되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error("버튼 액션 수정 오류:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "버튼 액션 수정 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "알 수 없는 오류",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 버튼 액션 삭제
|
||
|
|
static async deleteButtonAction(req: Request, res: Response) {
|
||
|
|
try {
|
||
|
|
const { actionType } = req.params;
|
||
|
|
|
||
|
|
// 존재 여부 확인
|
||
|
|
const existingAction = await prisma.button_action_standards.findUnique({
|
||
|
|
where: { action_type: actionType },
|
||
|
|
});
|
||
|
|
|
||
|
|
if (!existingAction) {
|
||
|
|
return res.status(404).json({
|
||
|
|
success: false,
|
||
|
|
message: "해당 버튼 액션을 찾을 수 없습니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
await prisma.button_action_standards.delete({
|
||
|
|
where: { action_type: actionType },
|
||
|
|
});
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
message: "버튼 액션이 성공적으로 삭제되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error("버튼 액션 삭제 오류:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "버튼 액션 삭제 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "알 수 없는 오류",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 버튼 액션 정렬 순서 업데이트
|
||
|
|
static async updateButtonActionSortOrder(
|
||
|
|
req: AuthenticatedRequest,
|
||
|
|
res: Response
|
||
|
|
) {
|
||
|
|
try {
|
||
|
|
const { buttonActions } = req.body; // [{ action_type: 'save', sort_order: 1 }, ...]
|
||
|
|
|
||
|
|
if (!Array.isArray(buttonActions)) {
|
||
|
|
return res.status(400).json({
|
||
|
|
success: false,
|
||
|
|
message: "유효하지 않은 데이터 형식입니다.",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
// 트랜잭션으로 일괄 업데이트
|
||
|
|
await prisma.$transaction(
|
||
|
|
buttonActions.map((item) =>
|
||
|
|
prisma.button_action_standards.update({
|
||
|
|
where: { action_type: item.action_type },
|
||
|
|
data: {
|
||
|
|
sort_order: item.sort_order,
|
||
|
|
updated_by: req.user?.userId || "system",
|
||
|
|
updated_date: new Date(),
|
||
|
|
},
|
||
|
|
})
|
||
|
|
)
|
||
|
|
);
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
message: "버튼 액션 정렬 순서가 성공적으로 업데이트되었습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error("버튼 액션 정렬 순서 업데이트 오류:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "정렬 순서 업데이트 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "알 수 없는 오류",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// 버튼 액션 카테고리 목록 조회
|
||
|
|
static async getButtonActionCategories(req: Request, res: Response) {
|
||
|
|
try {
|
||
|
|
const categories = await prisma.button_action_standards.groupBy({
|
||
|
|
by: ["category"],
|
||
|
|
where: {
|
||
|
|
is_active: "Y",
|
||
|
|
},
|
||
|
|
_count: {
|
||
|
|
category: true,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
|
||
|
|
const categoryList = categories.map((item) => ({
|
||
|
|
category: item.category,
|
||
|
|
count: item._count.category,
|
||
|
|
}));
|
||
|
|
|
||
|
|
return res.json({
|
||
|
|
success: true,
|
||
|
|
data: categoryList,
|
||
|
|
message: "버튼 액션 카테고리 목록을 성공적으로 조회했습니다.",
|
||
|
|
});
|
||
|
|
} catch (error) {
|
||
|
|
console.error("버튼 액션 카테고리 조회 오류:", error);
|
||
|
|
return res.status(500).json({
|
||
|
|
success: false,
|
||
|
|
message: "카테고리 조회 중 오류가 발생했습니다.",
|
||
|
|
error: error instanceof Error ? error.message : "알 수 없는 오류",
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|