import { Response } from "express"; import { query } from "../database/db"; import { logger } from "../utils/logger"; /** * 리포트 프리셋 컨트롤러 * - 회사별 + 리포트별로 사용자 조건 구성 저장/조회 * - 브라우저 localStorage가 아닌 서버 DB에 저장하여 기기/브라우저 간 공유 가능 */ /** * GET /report-presets?reportKey=xxx * 현재 회사 + report_key 에 해당하는 프리셋 목록 반환 */ export async function listPresets(req: any, res: Response): Promise { try { const companyCode = req.user?.companyCode; if (!companyCode) { res.status(401).json({ success: false, message: "인증 정보가 없습니다" }); return; } const reportKey = String(req.query.reportKey || ""); if (!reportKey) { res.status(400).json({ success: false, message: "reportKey가 필요합니다" }); return; } const rows = await query( `SELECT id, preset_name AS name, description, config_json AS config, created_by, created_at, updated_at FROM report_presets WHERE (company_code = $1 OR $1 = '*') AND report_key = $2 ORDER BY updated_at DESC NULLS LAST, id DESC`, [companyCode, reportKey] ); res.status(200).json({ success: true, data: rows }); } catch (error: any) { logger.error("리포트 프리셋 목록 조회 실패", { error: error.message }); res.status(500).json({ success: false, message: error.message }); } } /** * POST /report-presets * body: { reportKey, name, description, config } */ export async function createPreset(req: any, res: Response): Promise { try { const companyCode = req.user?.companyCode; const userId = req.user?.userId || null; if (!companyCode) { res.status(401).json({ success: false, message: "인증 정보가 없습니다" }); return; } const { reportKey, name, description, config } = req.body; if (!reportKey || !name || !config) { res.status(400).json({ success: false, message: "reportKey, name, config는 필수입니다" }); return; } const rows = await query( `INSERT INTO report_presets (company_code, report_key, preset_name, description, config_json, created_by, created_at, updated_at) VALUES ($1, $2, $3, $4, $5::jsonb, $6, NOW(), NOW()) RETURNING id, preset_name AS name, description, config_json AS config, created_by, created_at, updated_at`, [companyCode, reportKey, name, description || null, JSON.stringify(config), userId] ); res.status(200).json({ success: true, data: rows[0] }); } catch (error: any) { logger.error("리포트 프리셋 생성 실패", { error: error.message }); res.status(500).json({ success: false, message: error.message }); } } /** * PUT /report-presets/:id * body: { name?, description?, config? } */ export async function updatePreset(req: any, res: Response): Promise { try { const companyCode = req.user?.companyCode; if (!companyCode) { res.status(401).json({ success: false, message: "인증 정보가 없습니다" }); return; } const { id } = req.params; const { name, description, config } = req.body; const sets: string[] = []; const params: any[] = []; let idx = 1; if (name !== undefined) { sets.push(`preset_name = $${idx++}`); params.push(name); } if (description !== undefined) { sets.push(`description = $${idx++}`); params.push(description); } if (config !== undefined) { sets.push(`config_json = $${idx++}::jsonb`); params.push(JSON.stringify(config)); } sets.push("updated_at = NOW()"); params.push(id); const idParam = `$${idx++}`; params.push(companyCode); const companyParam = `$${idx++}`; const rows = await query( `UPDATE report_presets SET ${sets.join(", ")} WHERE id = ${idParam} AND (company_code = ${companyParam} OR ${companyParam} = '*') RETURNING id, preset_name AS name, description, config_json AS config, created_by, created_at, updated_at`, params ); if (rows.length === 0) { res.status(404).json({ success: false, message: "프리셋을 찾을 수 없거나 권한이 없습니다" }); return; } res.status(200).json({ success: true, data: rows[0] }); } catch (error: any) { logger.error("리포트 프리셋 수정 실패", { error: error.message }); res.status(500).json({ success: false, message: error.message }); } } /** * DELETE /report-presets/:id */ export async function deletePreset(req: any, res: Response): Promise { try { const companyCode = req.user?.companyCode; if (!companyCode) { res.status(401).json({ success: false, message: "인증 정보가 없습니다" }); return; } const { id } = req.params; const rows = await query( `DELETE FROM report_presets WHERE id = $1 AND (company_code = $2 OR $2 = '*') RETURNING id`, [id, companyCode] ); if (rows.length === 0) { res.status(404).json({ success: false, message: "프리셋을 찾을 수 없거나 권한이 없습니다" }); return; } res.status(200).json({ success: true }); } catch (error: any) { logger.error("리포트 프리셋 삭제 실패", { error: error.message }); res.status(500).json({ success: false, message: error.message }); } }