import { query, queryOne } from "../database/db"; export interface DataflowDiagram { diagram_id: number; diagram_name: string; relationships: any; // JSON 타입 company_code: string; created_at?: Date; updated_at?: Date; created_by?: string; updated_by?: string; } export interface CreateDataflowDiagramData { diagram_name: string; relationships: any; company_code: string; created_by?: string; } export interface UpdateDataflowDiagramData { diagram_name?: string; relationships?: any; updated_by?: string; } export class DataflowDiagramService { /** * 관계도 목록 조회 (페이지네이션) */ async getDataflowDiagrams( companyCode: string, page: number = 1, size: number = 20, searchTerm: string = "" ) { const skip = (page - 1) * size; const whereClause: any = { company_code: companyCode, }; if (searchTerm) { whereClause.diagram_name = { contains: searchTerm, mode: "insensitive", }; } // WHERE 절 구성 const whereParts: string[] = ["company_code = $1"]; const params: any[] = [companyCode]; if (searchTerm) { whereParts.push("diagram_name ILIKE $2"); params.push(`%${searchTerm}%`); } const whereSQL = whereParts.join(" AND "); const [diagrams, totalResult] = await Promise.all([ query( `SELECT * FROM dataflow_diagrams WHERE ${whereSQL} ORDER BY created_at DESC LIMIT $${params.length + 1} OFFSET $${params.length + 2}`, [...params, size, skip] ), queryOne<{ count: string }>( `SELECT COUNT(*) as count FROM dataflow_diagrams WHERE ${whereSQL}`, params ), ]); const total = parseInt(totalResult?.count || "0", 10); return { diagrams, pagination: { page, size, total, totalPages: Math.ceil(total / size), }, }; } /** * 특정 관계도 조회 */ async getDataflowDiagramById( diagramId: number, companyCode: string ): Promise { return await queryOne( `SELECT * FROM dataflow_diagrams WHERE diagram_id = $1 AND company_code = $2`, [diagramId, companyCode] ); } /** * 관계도 생성 */ async createDataflowDiagram( data: CreateDataflowDiagramData ): Promise { const result = await queryOne( `INSERT INTO dataflow_diagrams (diagram_name, relationships, company_code, created_by, created_at, updated_at) VALUES ($1, $2, $3, $4, NOW(), NOW()) RETURNING *`, [ data.diagram_name, JSON.stringify(data.relationships), data.company_code, data.created_by || null, ] ); return result!; } /** * 관계도 수정 */ async updateDataflowDiagram( diagramId: number, companyCode: string, data: UpdateDataflowDiagramData ): Promise { // 먼저 해당 관계도가 존재하는지 확인 const existingDiagram = await this.getDataflowDiagramById( diagramId, companyCode ); if (!existingDiagram) { return null; } // 동적 UPDATE 쿼리 생성 const updateFields: string[] = ["updated_at = NOW()"]; const params: any[] = []; let paramIndex = 1; if (data.diagram_name !== undefined) { updateFields.push(`diagram_name = $${paramIndex++}`); params.push(data.diagram_name); } if (data.relationships !== undefined) { updateFields.push(`relationships = $${paramIndex++}`); params.push(JSON.stringify(data.relationships)); } if (data.updated_by !== undefined) { updateFields.push(`updated_by = $${paramIndex++}`); params.push(data.updated_by); } params.push(diagramId); return await queryOne( `UPDATE dataflow_diagrams SET ${updateFields.join(", ")} WHERE diagram_id = $${paramIndex} RETURNING *`, params ); } /** * 관계도 삭제 */ async deleteDataflowDiagram( diagramId: number, companyCode: string ): Promise { // 먼저 해당 관계도가 존재하는지 확인 const existingDiagram = await this.getDataflowDiagramById( diagramId, companyCode ); if (!existingDiagram) { return false; } await query( `DELETE FROM dataflow_diagrams WHERE diagram_id = $1`, [diagramId] ); return true; } /** * 관계도 복제 */ async copyDataflowDiagram( diagramId: number, companyCode: string, newName?: string, createdBy?: string ): Promise { const originalDiagram = await this.getDataflowDiagramById( diagramId, companyCode ); if (!originalDiagram) { return null; } // 복제본 이름 생성 let copyName = newName; if (!copyName) { // "(1)", "(2)" 형식으로 이름 생성 const baseName = originalDiagram.diagram_name; let counter = 1; while (true) { copyName = `${baseName} (${counter})`; const existing = await queryOne( `SELECT * FROM dataflow_diagrams WHERE company_code = $1 AND diagram_name = $2`, [companyCode, copyName] ); if (!existing) break; counter++; } } return await this.createDataflowDiagram({ diagram_name: copyName, relationships: originalDiagram.relationships, company_code: companyCode, created_by: createdBy, }); } }