import { Request, Response } from "express"; import { AuthenticatedRequest } from "../types/auth"; import { query, queryOne, transaction } from "../database/db"; export class ButtonActionStandardController { // 버튼 액션 목록 조회 static async getButtonActions(req: Request, res: Response) { try { const { active, category, search } = req.query; const whereConditions: string[] = []; const queryParams: any[] = []; let paramIndex = 1; if (active) { whereConditions.push(`is_active = $${paramIndex}`); queryParams.push(active as string); paramIndex++; } if (category) { whereConditions.push(`category = $${paramIndex}`); queryParams.push(category as string); paramIndex++; } if (search) { whereConditions.push(`(action_name ILIKE $${paramIndex} OR action_name_eng ILIKE $${paramIndex} OR description ILIKE $${paramIndex})`); queryParams.push(`%${search}%`); paramIndex++; } const whereClause = whereConditions.length > 0 ? `WHERE ${whereConditions.join(" AND ")}` : ""; const buttonActions = await query( `SELECT * FROM button_action_standards ${whereClause} ORDER BY sort_order ASC, action_type ASC`, queryParams ); 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 queryOne( "SELECT * FROM button_action_standards WHERE action_type = $1 LIMIT 1", [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 queryOne( "SELECT * FROM button_action_standards WHERE action_type = $1 LIMIT 1", [action_type] ); if (existingAction) { return res.status(409).json({ success: false, message: "이미 존재하는 액션 타입입니다.", }); } const [newButtonAction] = await query( `INSERT INTO button_action_standards ( 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, updated_by, created_date, updated_date ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, NOW(), NOW()) RETURNING *`, [ 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 ? JSON.stringify(validation_rules) : null, action_config ? JSON.stringify(action_config) : null, sort_order, is_active, req.user?.userId || "system", 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 queryOne( "SELECT * FROM button_action_standards WHERE action_type = $1 LIMIT 1", [actionType] ); if (!existingAction) { return res.status(404).json({ success: false, message: "해당 버튼 액션을 찾을 수 없습니다.", }); } const updateFields: string[] = []; const updateParams: any[] = []; let paramIndex = 1; if (action_name !== undefined) { updateFields.push(`action_name = $${paramIndex}`); updateParams.push(action_name); paramIndex++; } if (action_name_eng !== undefined) { updateFields.push(`action_name_eng = $${paramIndex}`); updateParams.push(action_name_eng); paramIndex++; } if (description !== undefined) { updateFields.push(`description = $${paramIndex}`); updateParams.push(description); paramIndex++; } if (category !== undefined) { updateFields.push(`category = $${paramIndex}`); updateParams.push(category); paramIndex++; } if (default_text !== undefined) { updateFields.push(`default_text = $${paramIndex}`); updateParams.push(default_text); paramIndex++; } if (default_text_eng !== undefined) { updateFields.push(`default_text_eng = $${paramIndex}`); updateParams.push(default_text_eng); paramIndex++; } if (default_icon !== undefined) { updateFields.push(`default_icon = $${paramIndex}`); updateParams.push(default_icon); paramIndex++; } if (default_color !== undefined) { updateFields.push(`default_color = $${paramIndex}`); updateParams.push(default_color); paramIndex++; } if (default_variant !== undefined) { updateFields.push(`default_variant = $${paramIndex}`); updateParams.push(default_variant); paramIndex++; } if (confirmation_required !== undefined) { updateFields.push(`confirmation_required = $${paramIndex}`); updateParams.push(confirmation_required); paramIndex++; } if (confirmation_message !== undefined) { updateFields.push(`confirmation_message = $${paramIndex}`); updateParams.push(confirmation_message); paramIndex++; } if (validation_rules !== undefined) { updateFields.push(`validation_rules = $${paramIndex}`); updateParams.push(validation_rules ? JSON.stringify(validation_rules) : null); paramIndex++; } if (action_config !== undefined) { updateFields.push(`action_config = $${paramIndex}`); updateParams.push(action_config ? JSON.stringify(action_config) : null); paramIndex++; } if (sort_order !== undefined) { updateFields.push(`sort_order = $${paramIndex}`); updateParams.push(sort_order); paramIndex++; } if (is_active !== undefined) { updateFields.push(`is_active = $${paramIndex}`); updateParams.push(is_active); paramIndex++; } updateFields.push(`updated_by = $${paramIndex}`); updateParams.push(req.user?.userId || "system"); paramIndex++; updateFields.push(`updated_date = $${paramIndex}`); updateParams.push(new Date()); paramIndex++; updateParams.push(actionType); const [updatedButtonAction] = await query( `UPDATE button_action_standards SET ${updateFields.join(", ")} WHERE action_type = $${paramIndex} RETURNING *`, updateParams ); 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 queryOne( "SELECT * FROM button_action_standards WHERE action_type = $1 LIMIT 1", [actionType] ); if (!existingAction) { return res.status(404).json({ success: false, message: "해당 버튼 액션을 찾을 수 없습니다.", }); } await query( "DELETE FROM button_action_standards WHERE action_type = $1", [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 transaction(async (client) => { for (const item of buttonActions) { await client.query( `UPDATE button_action_standards SET sort_order = $1, updated_by = $2, updated_date = NOW() WHERE action_type = $3`, [item.sort_order, req.user?.userId || "system", item.action_type] ); } }); 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 query<{ category: string; count: string }>( `SELECT category, COUNT(*) as count FROM button_action_standards WHERE is_active = $1 GROUP BY category`, ["Y"] ); const categoryList = categories.map((item) => ({ category: item.category, count: parseInt(item.count), })); 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 : "알 수 없는 오류", }); } } }