diff options
Diffstat (limited to 'app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts')
| -rw-r--r-- | app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts | 117 |
1 files changed, 48 insertions, 69 deletions
diff --git a/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts index 987d4002..3051fd8f 100644 --- a/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts +++ b/app/api/(S-ERP)/(MDG)/IF_MDZ_EVCP_ORGANIZATION_MASTER/route.ts @@ -30,7 +30,12 @@ import { createSuccessResponse, replaceSubTableData, withSoapLogging -} from "@/lib/soap/mdg/utils"; +} from "@/lib/soap/utils"; +import { + bulkUpsert, + bulkReplaceSubTableData +} from "@/lib/soap/batch-utils"; +import { coerce } from "zod/v4"; // 스키마에서 직접 타입 추론 type CctrData = typeof ORGANIZATION_MASTER_HRHMTB_CCTR.$inferInsert; @@ -376,75 +381,49 @@ async function saveToDatabase(processedOrganizations: ProcessedOrganizationData) try { await db.transaction(async (tx) => { - // CCTR 테이블 처리 (unique 필드: CCTR) - for (const { cctr, texts } of processedOrganizations.cctrItems) { - if (!cctr.CCTR) continue; - - await tx.insert(ORGANIZATION_MASTER_HRHMTB_CCTR) - .values(cctr) - .onConflictDoUpdate({ - target: ORGANIZATION_MASTER_HRHMTB_CCTR.CCTR, - set: { ...cctr, updatedAt: new Date() } - }); - - await replaceSubTableData(tx, ORGANIZATION_MASTER_HRHMTB_CCTR_TEXT, texts, 'CCTR', cctr.CCTR); - } - - // PCTR 테이블 처리 (unique 필드: PCTR) - for (const { pctr, texts } of processedOrganizations.pctrItems) { - if (!pctr.PCTR) continue; - - await tx.insert(ORGANIZATION_MASTER_HRHMTB_PCTR) - .values(pctr) - .onConflictDoUpdate({ - target: ORGANIZATION_MASTER_HRHMTB_PCTR.PCTR, - set: { ...pctr, updatedAt: new Date() } - }); - - // PCTR의 TEXT는 CCTR_TEXT 테이블을 사용하므로 처리하지 않음 - } - // 나머지 단일 테이블들 처리 - const tableProcessors = [ - { items: processedOrganizations.zbukrsItems, table: ORGANIZATION_MASTER_HRHMTB_ZBUKRS, key: 'ZBUKRS' }, - { items: processedOrganizations.zekgrpItems, table: ORGANIZATION_MASTER_HRHMTB_ZEKGRP, key: 'ZEKGRP' }, - { items: processedOrganizations.zekorgItems, table: ORGANIZATION_MASTER_HRHMTB_ZEKORG, key: 'ZEKORG' }, - { items: processedOrganizations.zlgortItems, table: ORGANIZATION_MASTER_HRHMTB_ZLGORT, key: 'ZLGORT' }, - { items: processedOrganizations.zspartItems, table: ORGANIZATION_MASTER_HRHMTB_ZSPART, key: 'ZSPART' }, - { items: processedOrganizations.zvkburItems, table: ORGANIZATION_MASTER_HRHMTB_ZVKBUR, key: 'ZVKBUR' }, - { items: processedOrganizations.zvkgrpItems, table: ORGANIZATION_MASTER_HRHMTB_ZVKGRP, key: 'ZVKGRP' }, - { items: processedOrganizations.zvkorgItems, table: ORGANIZATION_MASTER_HRHMTB_ZVKORG, key: 'ZVKORG' }, - { items: processedOrganizations.zvstelItems, table: ORGANIZATION_MASTER_HRHMTB_ZVSTEL, key: 'ZVSTEL' }, - { items: processedOrganizations.zvtwegItems, table: ORGANIZATION_MASTER_HRHMTB_ZVTWEG, key: 'ZVTWEG' }, - { items: processedOrganizations.zwerksItems, table: ORGANIZATION_MASTER_HRHMTB_ZWERKS, key: 'ZWERKS' } - ]; - - for (const { items, table, key } of tableProcessors) { - for (const item of items) { - if (!(item as any)[key]) continue; - - await tx.insert(table) - .values(item) - .onConflictDoUpdate({ - target: (table as any)[key], - set: { ...item, updatedAt: new Date() } - }); - } - } - - // ZGSBER 테이블 처리 (TEXT 포함) - for (const { zgsber, texts } of processedOrganizations.zgsberItems) { - if (!zgsber.ZGSBER) continue; - - await tx.insert(ORGANIZATION_MASTER_HRHMTB_ZGSBER) - .values(zgsber) - .onConflictDoUpdate({ - target: ORGANIZATION_MASTER_HRHMTB_ZGSBER.ZGSBER, - set: { ...zgsber, updatedAt: new Date() } - }); - - await replaceSubTableData(tx, ORGANIZATION_MASTER_HRHMTB_ZGSBER_TEXT, texts, 'ZGSBER', zgsber.ZGSBER); - } + // 1) 부모 테이블 데이터 준비 (root) + const cctrRows = processedOrganizations.cctrItems.map((c) => c.cctr).filter((c): c is CctrData => !!c.CCTR); + const pctrRows = processedOrganizations.pctrItems; + const zbukrsRows = processedOrganizations.zbukrsItems; + const zekgrpRows = processedOrganizations.zekgrpItems; + const zekorgRows = processedOrganizations.zekorgItems; + const zgsberRows = processedOrganizations.zgsberItems.map((zgsber) => zgsber.zgsber).filter((zgsber): zgsber is ZgsberData => !!zgsber.ZGSBER); + const zlgortRows = processedOrganizations.zlgortItems; + const zspartRows = processedOrganizations.zspartItems; + const zvkburRows = processedOrganizations.zvkburItems; + const zvkgrpRows = processedOrganizations.zvkgrpItems; + const zvkorgRows = processedOrganizations.zvkorgItems; + const zvstelRows = processedOrganizations.zvstelItems; + const zvtwegRows = processedOrganizations.zvtwegItems; + const zwerksRows = processedOrganizations.zwerksItems; + + const cctrIds = cctrRows.map((cctr) => cctr.CCTR as string); + const zgsberIds = zgsberRows.map((zgsber) => zgsber.ZGSBER as string); + + // 2) 하위 테이블 데이터 평탄화 (2건) + const cctrTexts = processedOrganizations.cctrItems.flatMap((cctr) => cctr.texts); + const zgsberTexts = processedOrganizations.zgsberItems.flatMap((zgsber) => zgsber.texts); + + // 3) 부모 테이블 UPSERT (배치) + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_CCTR, cctrRows, 'CCTR'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_PCTR, pctrRows, 'PCTR'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZBUKRS, zbukrsRows, 'ZBUKRS'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZEKGRP, zekgrpRows, 'ZEKGRP'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZEKORG, zekorgRows, 'ZEKORG'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZGSBER, zgsberRows, 'ZGSBER'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZLGORT, zlgortRows, 'ZLGORT'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZSPART, zspartRows, 'ZSPART'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZVKBUR, zvkburRows, 'ZVKBUR'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZVKGRP, zvkgrpRows, 'ZVKGRP'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZVKORG, zvkorgRows, 'ZVKORG'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZVSTEL, zvstelRows, 'ZVSTEL'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZVTWEG, zvtwegRows, 'ZVTWEG'); + await bulkUpsert(tx, ORGANIZATION_MASTER_HRHMTB_ZWERKS, zwerksRows, 'ZWERKS'); + + // 4) 하위 테이블 교체 (배치) (2건) + await bulkReplaceSubTableData(tx, ORGANIZATION_MASTER_HRHMTB_CCTR_TEXT, cctrTexts, ORGANIZATION_MASTER_HRHMTB_CCTR_TEXT.CCTR, cctrIds); + await bulkReplaceSubTableData(tx, ORGANIZATION_MASTER_HRHMTB_ZGSBER_TEXT, zgsberTexts, ORGANIZATION_MASTER_HRHMTB_ZGSBER_TEXT.ZGSBER, zgsberIds); }); console.log('조직 마스터 데이터 처리 완료.'); |
