/** * 리포트 관리 컨트롤러 */ import { Request, Response, NextFunction } from "express"; import reportService from "../services/reportService"; import { CreateReportRequest, UpdateReportRequest, SaveLayoutRequest, CreateTemplateRequest, } from "../types/report"; export class ReportController { /** * 리포트 목록 조회 * GET /api/admin/reports */ async getReports(req: Request, res: Response, next: NextFunction) { try { const { page = "1", limit = "20", searchText = "", reportType = "", useYn = "Y", sortBy = "created_at", sortOrder = "DESC", } = req.query; const result = await reportService.getReports({ page: parseInt(page as string, 10), limit: parseInt(limit as string, 10), searchText: searchText as string, reportType: reportType as string, useYn: useYn as string, sortBy: sortBy as string, sortOrder: sortOrder as "ASC" | "DESC", }); return res.json({ success: true, data: result, }); } catch (error) { return next(error); } } /** * 리포트 상세 조회 * GET /api/admin/reports/:reportId */ async getReportById(req: Request, res: Response, next: NextFunction) { try { const { reportId } = req.params; const report = await reportService.getReportById(reportId); if (!report) { return res.status(404).json({ success: false, message: "리포트를 찾을 수 없습니다.", }); } return res.json({ success: true, data: report, }); } catch (error) { return next(error); } } /** * 리포트 생성 * POST /api/admin/reports */ async createReport(req: Request, res: Response, next: NextFunction) { try { const data: CreateReportRequest = req.body; const userId = (req as any).user?.userId || "SYSTEM"; // 필수 필드 검증 if (!data.reportNameKor || !data.reportType) { return res.status(400).json({ success: false, message: "리포트명과 리포트 타입은 필수입니다.", }); } const reportId = await reportService.createReport(data, userId); return res.status(201).json({ success: true, data: { reportId, }, message: "리포트가 생성되었습니다.", }); } catch (error) { return next(error); } } /** * 리포트 수정 * PUT /api/admin/reports/:reportId */ async updateReport(req: Request, res: Response, next: NextFunction) { try { const { reportId } = req.params; const data: UpdateReportRequest = req.body; const userId = (req as any).user?.userId || "SYSTEM"; const success = await reportService.updateReport(reportId, data, userId); if (!success) { return res.status(400).json({ success: false, message: "수정할 내용이 없습니다.", }); } return res.json({ success: true, message: "리포트가 수정되었습니다.", }); } catch (error) { return next(error); } } /** * 리포트 삭제 * DELETE /api/admin/reports/:reportId */ async deleteReport(req: Request, res: Response, next: NextFunction) { try { const { reportId } = req.params; const success = await reportService.deleteReport(reportId); if (!success) { return res.status(404).json({ success: false, message: "리포트를 찾을 수 없습니다.", }); } return res.json({ success: true, message: "리포트가 삭제되었습니다.", }); } catch (error) { return next(error); } } /** * 리포트 복사 * POST /api/admin/reports/:reportId/copy */ async copyReport(req: Request, res: Response, next: NextFunction) { try { const { reportId } = req.params; const userId = (req as any).user?.userId || "SYSTEM"; const newReportId = await reportService.copyReport(reportId, userId); if (!newReportId) { return res.status(404).json({ success: false, message: "리포트를 찾을 수 없습니다.", }); } return res.status(201).json({ success: true, data: { reportId: newReportId, }, message: "리포트가 복사되었습니다.", }); } catch (error) { return next(error); } } /** * 레이아웃 조회 * GET /api/admin/reports/:reportId/layout */ async getLayout(req: Request, res: Response, next: NextFunction) { try { const { reportId } = req.params; const layout = await reportService.getLayout(reportId); if (!layout) { return res.status(404).json({ success: false, message: "레이아웃을 찾을 수 없습니다.", }); } // components JSON 파싱 const layoutData = { ...layout, components: layout.components ? JSON.parse(layout.components) : [], }; return res.json({ success: true, data: layoutData, }); } catch (error) { return next(error); } } /** * 레이아웃 저장 * PUT /api/admin/reports/:reportId/layout */ async saveLayout(req: Request, res: Response, next: NextFunction) { try { const { reportId } = req.params; const data: SaveLayoutRequest = req.body; const userId = (req as any).user?.userId || "SYSTEM"; // 필수 필드 검증 if ( !data.canvasWidth || !data.canvasHeight || !data.pageOrientation || !data.components ) { return res.status(400).json({ success: false, message: "필수 레이아웃 정보가 누락되었습니다.", }); } await reportService.saveLayout(reportId, data, userId); return res.json({ success: true, message: "레이아웃이 저장되었습니다.", }); } catch (error) { return next(error); } } /** * 템플릿 목록 조회 * GET /api/admin/reports/templates */ async getTemplates(req: Request, res: Response, next: NextFunction) { try { const templates = await reportService.getTemplates(); return res.json({ success: true, data: templates, }); } catch (error) { return next(error); } } /** * 템플릿 생성 * POST /api/admin/reports/templates */ async createTemplate(req: Request, res: Response, next: NextFunction) { try { const data: CreateTemplateRequest = req.body; const userId = (req as any).user?.userId || "SYSTEM"; // 필수 필드 검증 if (!data.templateNameKor || !data.templateType) { return res.status(400).json({ success: false, message: "템플릿명과 템플릿 타입은 필수입니다.", }); } const templateId = await reportService.createTemplate(data, userId); return res.status(201).json({ success: true, data: { templateId, }, message: "템플릿이 생성되었습니다.", }); } catch (error) { return next(error); } } /** * 템플릿 삭제 * DELETE /api/admin/reports/templates/:templateId */ async deleteTemplate(req: Request, res: Response, next: NextFunction) { try { const { templateId } = req.params; const success = await reportService.deleteTemplate(templateId); if (!success) { return res.status(404).json({ success: false, message: "템플릿을 찾을 수 없거나 시스템 템플릿입니다.", }); } return res.json({ success: true, message: "템플릿이 삭제되었습니다.", }); } catch (error) { return next(error); } } /** * 쿼리 실행 * POST /api/admin/reports/:reportId/queries/:queryId/execute */ async executeQuery(req: Request, res: Response, next: NextFunction) { try { const { reportId, queryId } = req.params; const { parameters = {}, sqlQuery } = req.body; const result = await reportService.executeQuery( reportId, queryId, parameters, sqlQuery ); return res.json({ success: true, data: result, }); } catch (error: any) { return res.status(400).json({ success: false, message: error.message || "쿼리 실행에 실패했습니다.", }); } } } export default new ReportController();