diff options
Diffstat (limited to 'app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_CUSTOMER_MASTER/route.ts')
| -rw-r--r-- | app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_CUSTOMER_MASTER/route.ts | 90 |
1 files changed, 46 insertions, 44 deletions
diff --git a/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_CUSTOMER_MASTER/route.ts b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_CUSTOMER_MASTER/route.ts index 9d08527b..0cedcade 100644 --- a/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_CUSTOMER_MASTER/route.ts +++ b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_CUSTOMER_MASTER/route.ts @@ -25,9 +25,12 @@ import { processNestedArray, createErrorResponse, createSuccessResponse, - replaceSubTableData, withSoapLogging -} from "@/lib/soap/mdg/utils"; +} from "@/lib/soap/utils"; +import { + bulkUpsert, + bulkReplaceSubTableData +} from "@/lib/soap/batch-utils"; // 스키마에서 직접 타입 추론 type BpHeaderData = typeof CUSTOMER_MASTER_BP_HEADER.$inferInsert; @@ -316,54 +319,53 @@ function transformCustomerData(bpHeaderData: BpHeaderXML[]): ProcessedCustomerDa * @param processedCustomers 변환된 CUSTOMER 데이터 배열 */ async function saveToDatabase(processedCustomers: ProcessedCustomerData[]) { - console.log(`데이터베이스 저장 시작: ${processedCustomers.length}개 고객 데이터`); - + console.log(`데이터베이스(배치) 저장 시작: ${processedCustomers.length}개 고객 데이터`); try { await db.transaction(async (tx) => { - for (const customerData of processedCustomers) { - const { bpHeader, addresses, adEmails, adFaxes, adPostals, adTels, adUrls, - bpCusgens, zvatregs, ztaxinds, zcompanies, zsales, zcpfns, bpTaxnums } = customerData; - - if (!bpHeader.BP_HEADER) { - console.warn('BP_HEADER가 없는 항목 발견, 건너뜁니다.'); - continue; - } + // 1) 부모 테이블 데이터 준비 + const bpHeaderRows = processedCustomers + .map((c) => c.bpHeader) + .filter((h): h is BpHeaderData => !!h.BP_HEADER); - // 1. BP_HEADER 테이블 Upsert (최상위 테이블 - unique 필드: BP_HEADER) - await tx.insert(CUSTOMER_MASTER_BP_HEADER) - .values(bpHeader) - .onConflictDoUpdate({ - target: CUSTOMER_MASTER_BP_HEADER.BP_HEADER, - set: { - ...bpHeader, - updatedAt: new Date(), - } - }); + const bpHeaderKeys = bpHeaderRows.map((h) => h.BP_HEADER as string); - // 2. 하위 테이블들 처리 - FK(BP_HEADER) 기준 전체 삭제 후 재삽입 - // 전체 데이터셋 기반 처리로 데이터 일관성 확보 - await Promise.all([ - // 2단계 테이블들 - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS, addresses, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN, bpCusgens, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_TAXNUM, bpTaxnums, 'BP_HEADER', bpHeader.BP_HEADER), - - // 3-4단계 테이블들 - 동일하게 FK(BP_HEADER) 기준 처리 - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_EMAIL, adEmails, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_FAX, adFaxes, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_POSTAL, adPostals, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_TEL, adTels, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_URL, adUrls, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZVATREG, zvatregs, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZTAXIND, ztaxinds, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZCOMPANY, zcompanies, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZSALES, zsales, 'BP_HEADER', bpHeader.BP_HEADER), - replaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZSALES_ZCPFN, zcpfns, 'BP_HEADER', bpHeader.BP_HEADER), - ]); - } + // 2) 하위 테이블 데이터 평탄화 + const addresses = processedCustomers.flatMap((c) => c.addresses); + const adEmails = processedCustomers.flatMap((c) => c.adEmails); + const adFaxes = processedCustomers.flatMap((c) => c.adFaxes); + const adPostals = processedCustomers.flatMap((c) => c.adPostals); + const adTels = processedCustomers.flatMap((c) => c.adTels); + const adUrls = processedCustomers.flatMap((c) => c.adUrls); + const bpCusgens = processedCustomers.flatMap((c) => c.bpCusgens); + const zvatregs = processedCustomers.flatMap((c) => c.zvatregs); + const ztaxinds = processedCustomers.flatMap((c) => c.ztaxinds); + const zcompanies = processedCustomers.flatMap((c) => c.zcompanies); + const zsales = processedCustomers.flatMap((c) => c.zsales); + const zcpfns = processedCustomers.flatMap((c) => c.zcpfns); + const bpTaxnums = processedCustomers.flatMap((c) => c.bpTaxnums); + + // 3) 부모 테이블 UPSERT (배치) + await bulkUpsert(tx, CUSTOMER_MASTER_BP_HEADER, bpHeaderRows, 'BP_HEADER'); + + // 4) 하위 테이블 교체 (배치) + await Promise.all([ + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS, addresses, CUSTOMER_MASTER_BP_HEADER_ADDRESS.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_EMAIL, adEmails, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_EMAIL.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_FAX, adFaxes, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_FAX.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_POSTAL, adPostals, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_POSTAL.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_TEL, adTels, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_TEL.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_URL, adUrls, CUSTOMER_MASTER_BP_HEADER_ADDRESS_AD_URL.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN, bpCusgens, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZVATREG, zvatregs, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZVATREG.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZTAXIND, ztaxinds, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZTAXIND.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZCOMPANY, zcompanies, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZCOMPANY.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZSALES, zsales, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZSALES.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZSALES_ZCPFN, zcpfns, CUSTOMER_MASTER_BP_HEADER_BP_CUSGEN_ZSALES_ZCPFN.BP_HEADER, bpHeaderKeys), + bulkReplaceSubTableData(tx, CUSTOMER_MASTER_BP_HEADER_BP_TAXNUM, bpTaxnums, CUSTOMER_MASTER_BP_HEADER_BP_TAXNUM.BP_HEADER, bpHeaderKeys), + ]); }); - console.log(`데이터베이스 저장 완료: ${processedCustomers.length}개 고객`); + console.log(`데이터베이스(배치) 저장 완료: ${processedCustomers.length}개 고객`); return true; } catch (error) { console.error('데이터베이스 저장 중 오류 발생:', error); |
