/** * 리포트 셀 커스텀 입력값 컨트롤러 * * 리포트 디자이너에서 cellType="input"으로 지정한 셀에 대해 * 각 대상 레코드(quote 등)별로 사용자가 입력한 값을 관리 */ import type { Response } from "express"; import { getPool } from "../database/db"; import type { AuthenticatedRequest } from "../types/auth"; import { logger } from "../utils/logger"; // 목록 조회: 특정 리포트 + 타겟에 대한 모든 셀 값 export async function getList(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const { report_id, target_type, target_id } = req.query; if (!report_id || !target_type || !target_id) { return res.status(400).json({ success: false, message: "report_id, target_type, target_id는 필수입니다.", }); } const pool = getPool(); const result = await pool.query( `SELECT id, report_id, target_type, target_id, component_id, cell_id, value FROM report_cell_values WHERE company_code = $1 AND report_id = $2 AND target_type = $3 AND target_id = $4`, [companyCode, report_id, target_type, target_id], ); return res.json({ success: true, data: result.rows }); } catch (error: any) { logger.error("리포트 셀 값 조회 실패", { error: error.message }); return res.status(500).json({ success: false, message: error.message }); } } // UPSERT 단건: 같은 (report_id, target_type, target_id, component_id, cell_id)면 UPDATE, 아니면 INSERT export async function upsert(req: AuthenticatedRequest, res: Response) { try { const companyCode = req.user!.companyCode; const userId = req.user!.userId; const { report_id, target_type, target_id, component_id, cell_id, value } = req.body; if (!report_id || !target_type || !target_id || !component_id || !cell_id) { return res.status(400).json({ success: false, message: "필수 필드 누락", }); } const pool = getPool(); // value가 빈 문자열이면 DELETE (오버라이드 해제) if (value === "" || value === null || value === undefined) { await pool.query( `DELETE FROM report_cell_values WHERE company_code = $1 AND report_id = $2 AND target_type = $3 AND target_id = $4 AND component_id = $5 AND cell_id = $6`, [companyCode, report_id, target_type, target_id, component_id, cell_id], ); return res.json({ success: true, data: null }); } const result = await pool.query( `INSERT INTO report_cell_values (id, company_code, report_id, target_type, target_id, component_id, cell_id, value, created_by, updated_by) VALUES (gen_random_uuid()::text, $1, $2, $3, $4, $5, $6, $7, $8, $8) ON CONFLICT (company_code, report_id, target_type, target_id, component_id, cell_id) DO UPDATE SET value = EXCLUDED.value, updated_at = CURRENT_TIMESTAMP, updated_by = EXCLUDED.updated_by RETURNING *`, [ companyCode, report_id, target_type, target_id, component_id, cell_id, value, userId, ], ); return res.json({ success: true, data: result.rows[0] }); } catch (error: any) { logger.error("리포트 셀 값 저장 실패", { error: error.message }); return res.status(500).json({ success: false, message: error.message }); } }