/* eslint-disable @typescript-eslint/no-explicit-any */ import { NextRequest } from "next/server"; import db from "@/db/db"; import { PROJECT_MASTER_CMCTB_PROJ_MAST } from "@/db/schema/MDG/mdg"; import { ToXMLFields, serveWsdl, createXMLParser, extractRequestData, convertXMLToDBData, createErrorResponse, createSuccessResponse, withSoapLogging } from "@/lib/soap/utils"; import { bulkUpsert } from "@/lib/soap/batch-utils"; // 서브테이블 없음 import { mapAndSaveMDGProjectData } from "@/lib/soap/mdg/mapper/project-mapper"; // 스키마에서 직접 타입 추론 type ProjectData = typeof PROJECT_MASTER_CMCTB_PROJ_MAST.$inferInsert; // XML에서 받는 데이터 구조 type ProjectXML = ToXMLFields>; // 처리된 데이터 구조 interface ProcessedProjectData { project: ProjectData; } export async function GET(request: NextRequest) { const url = new URL(request.url); if (url.searchParams.has('wsdl')) { return serveWsdl('IF_MDZ_EVCP_PROJECT_MASTER.wsdl'); } return new Response('Method Not Allowed', { status: 405 }); } export async function POST(request: NextRequest) { const url = new URL(request.url); if (url.searchParams.has('wsdl')) { return serveWsdl('IF_MDZ_EVCP_PROJECT_MASTER.wsdl'); } const body = await request.text(); return withSoapLogging( 'INBOUND', 'MDG', 'IF_MDZ_EVCP_PROJECT_MASTER', body, async () => { console.log('🚀 PROJECT_MASTER 수신 시작, 데이터 길이:', body.length); const parser = createXMLParser(['CMCTB_PROJ_MAST']); const parsedData = parser.parse(body); console.log('XML root keys:', Object.keys(parsedData)); const requestData = extractRequestData(parsedData, 'IF_MDZ_EVCP_PROJECT_MASTERReq'); if (!requestData) { console.error('Could not find valid request data in the received payload'); console.error('Received XML structure:', JSON.stringify(parsedData, null, 2)); throw new Error('Missing request data - could not find IF_MDZ_EVCP_PROJECT_MASTERReq or CMCTB_PROJ_MAST data'); } console.log('Validating request data structure:', `CMCTB_PROJ_MAST: ${requestData.CMCTB_PROJ_MAST ? 'found' : 'not found'}` ); if (requestData.CMCTB_PROJ_MAST && Array.isArray(requestData.CMCTB_PROJ_MAST) && requestData.CMCTB_PROJ_MAST.length > 0) { console.log('First CMCTB_PROJ_MAST sample:', JSON.stringify(requestData.CMCTB_PROJ_MAST[0], null, 2)); } // XML 데이터를 DB 삽입 가능한 형태로 변환 const processedProjects = transformProjectData(requestData.CMCTB_PROJ_MAST as ProjectXML[] || []); // 필수 필드 검증 for (const projectData of processedProjects) { if (!projectData.project.PROJ_NO) { throw new Error('Missing required field: PROJ_NO in project'); } } // 1) 원본 MDG 데이터 저장 (기존 로직 유지) await saveToDatabase(processedProjects); // 2) 비즈니스 테이블 projects에 매핑하여 저장 const projectMappingResult = await mapAndSaveMDGProjectData( processedProjects.map(p => p.project) ); if (!projectMappingResult.success) { throw new Error(`프로젝트 비즈니스 테이블 매핑 실패: ${projectMappingResult.message}`); } console.log(`🎉 처리 완료: ${processedProjects.length}개 프로젝트, ${projectMappingResult.processedCount}개 비즈니스 테이블 매핑`); return createSuccessResponse('http://60.101.108.100/api/IF_MDZ_EVCP_PROJECT_MASTER/'); } ).catch(error => { return createErrorResponse(error); }); } // XML 데이터를 DB 삽입 가능한 형태로 변환 function transformProjectData(projectData: ProjectXML[]): ProcessedProjectData[] { if (!projectData || !Array.isArray(projectData)) { return []; } return projectData.map(proj => { // Project 데이터 변환 const project = convertXMLToDBData( proj as Record ); // 필수 필드 보정 if (!project.PROJ_NO) { project.PROJ_NO = ''; } return { project }; }); } // 데이터베이스 저장 함수 async function saveToDatabase(processedProjects: ProcessedProjectData[]) { console.log(`데이터베이스(배치) 저장 시작: ${processedProjects.length}개 프로젝트`); try { await db.transaction(async (tx) => { const projectRows = processedProjects .map((p) => p.project) .filter((p): p is ProjectData => !!p.PROJ_NO); if (!projectRows.length) return; await bulkUpsert(tx, PROJECT_MASTER_CMCTB_PROJ_MAST, projectRows, 'PROJ_NO'); }); console.log(`데이터베이스(배치) 저장 완료: ${processedProjects.length}개 프로젝트`); return true; } catch (error) { console.error('데이터베이스 저장 중 오류 발생:', error); throw error; } }