diff options
Diffstat (limited to 'app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PR_INFORMATION/route.ts')
| -rw-r--r-- | app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PR_INFORMATION/route.ts | 66 |
1 files changed, 29 insertions, 37 deletions
diff --git a/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PR_INFORMATION/route.ts b/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PR_INFORMATION/route.ts index 31b61ffc..fdf0c8d4 100644 --- a/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PR_INFORMATION/route.ts +++ b/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PR_INFORMATION/route.ts @@ -1,6 +1,9 @@ import { NextRequest } from 'next/server'; import db from '@/db/db'; - +import { + PR_INFORMATION_T_BID_HEADER, + PR_INFORMATION_T_BID_ITEM, +} from '@/db/schema/ECC/ecc'; import { ToXMLFields, serveWsdl, @@ -11,14 +14,13 @@ import { createErrorResponse, createSuccessResponse, createSoapResponse, - replaceSubTableData, withSoapLogging, } from '@/lib/soap/utils'; - import { - PR_INFORMATION_T_BID_HEADER, - PR_INFORMATION_T_BID_ITEM, -} from '@/db/schema/ECC/ecc'; + bulkUpsert, + bulkReplaceSubTableData +} from "@/lib/soap/batch-utils"; + // 스키마에서 타입 추론 type BidHeaderData = typeof PR_INFORMATION_T_BID_HEADER.$inferInsert; @@ -34,6 +36,7 @@ interface ProcessedPRData { bidItems: BidItemData[]; } +// GET 요청 처리는 ?wsdl 달고 있으면 WSDL 서비스 제공 export async function GET(request: NextRequest) { const url = new URL(request.url); if (url.searchParams.has('wsdl')) { @@ -43,6 +46,7 @@ export async function GET(request: NextRequest) { return new Response('Method Not Allowed', { status: 405 }); } +// POST 요청이 데이터 적재 요구 (SOAP) export async function POST(request: NextRequest) { const url = new URL(request.url); if (url.searchParams.has('wsdl')) { @@ -54,7 +58,7 @@ export async function POST(request: NextRequest) { // SOAP 로깅 래퍼 함수 사용 return withSoapLogging( 'INBOUND', - 'S-ERP', + 'ECC', 'IF_ECC_EVCP_PR_INFORMATION', body, async () => { @@ -155,45 +159,33 @@ function transformPRData(requestData: PRRequestXML): ProcessedPRData[] { // 데이터베이스 저장 함수 async function saveToDatabase(processedPRs: ProcessedPRData[]) { - console.log(`데이터베이스 저장 시작: ${processedPRs.length}개 PR 데이터`); + console.log(`데이터베이스(배치) 저장 시작: ${processedPRs.length}개 PR 데이터`); try { await db.transaction(async (tx) => { - for (const prData of processedPRs) { - const { bidHeader, bidItems } = prData; + // 1) 부모 테이블 데이터 준비 (키 없는 이상데이터 제거) + const bidHeaderRows = processedPRs + .map((c) => c.bidHeader) + .filter((h): h is BidHeaderData => !!h.ANFNR); - if (!bidHeader.ANFNR) { - console.warn('ANFNR가 없는 헤더 발견, 건너뜁니다.'); - continue; - } + const bidHeaderKeys = bidHeaderRows.map((h) => h.ANFNR as string); - // 1. 헤더 테이블 Upsert (ANFNR 기준) - await tx - .insert(PR_INFORMATION_T_BID_HEADER) - .values(bidHeader) - .onConflictDoUpdate({ - target: PR_INFORMATION_T_BID_HEADER.ANFNR, - set: { - ...bidHeader, - updatedAt: new Date(), - }, - }); - - // 2. 아이템 테이블 전체 교체 (ANFNR FK 기준) - await replaceSubTableData( - tx, - PR_INFORMATION_T_BID_ITEM, - bidItems, - 'ANFNR', - bidHeader.ANFNR - ); - } + // 2) 하위 테이블 데이터 평탄화 + const bidItems = processedPRs.flatMap((c) => c.bidItems); + + // 3) 부모 테이블 UPSERT (배치) + await bulkUpsert(tx, PR_INFORMATION_T_BID_HEADER, bidHeaderRows, 'ANFNR'); + + // 4) 하위 테이블 교체 (배치) + await Promise.all([ + bulkReplaceSubTableData(tx, PR_INFORMATION_T_BID_ITEM, bidItems, PR_INFORMATION_T_BID_ITEM.ANFNR, bidHeaderKeys), + ]); }); - console.log(`데이터베이스 저장 완료: ${processedPRs.length}개 PR`); + console.log(`데이터베이스(배치) 저장 완료: ${processedPRs.length}개 PR`); return true; } catch (error) { - console.error('데이터베이스 저장 중 오류 발생:', error); + console.error('데이터베이스(배치) 저장 중 오류 발생:', error); throw error; } }
\ No newline at end of file |
