summaryrefslogtreecommitdiff
path: root/app/api/(S-ERP)
diff options
context:
space:
mode:
Diffstat (limited to 'app/api/(S-ERP)')
-rw-r--r--app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PR_INFORMATION/route.ts197
1 files changed, 161 insertions, 36 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 012f47fc..3cee4b42 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,9 +1,12 @@
import { NextRequest } from 'next/server';
import db from '@/db/db';
+import { eq } from 'drizzle-orm';
import {
PR_INFORMATION_T_BID_HEADER,
PR_INFORMATION_T_BID_ITEM,
} from '@/db/schema/ECC/ecc';
+import { rfqsLast, rfqPrItems } from '@/db/schema/rfqLast';
+import { biddings, prItemsForBidding, prDocuments } from '@/db/schema/bidding';
import {
ToXMLFields,
serveWsdl,
@@ -19,10 +22,12 @@ import {
bulkReplaceSubTableData
} from "@/lib/soap/batch-utils";
import {
- mapAndSaveECCRfqData
+ mapAndSaveECCRfqData,
+ deleteECCRfqData
} from "@/lib/soap/ecc/mapper/rfq-and-pr-mapper";
import {
- mapAndSaveECCBiddingData
+ mapAndSaveECCBiddingData,
+ deleteECCBiddingData
} from "@/lib/soap/ecc/mapper/bidding-and-pr-mapper";
@@ -94,45 +99,165 @@ export async function POST(request: NextRequest) {
}
}
- // 5) 원본 ECC 데이터 저장 (기존 로직 유지)
- await saveToDatabase(processedData);
+ // 5) CHG_GB에 따라 Create/Delete 분기 처리
+ // 전체 처리를 하나의 트랜잭션으로 묶어서 하나라도 실패하면 전부 롤백
+ const chgGb = requestData.CHG_GB || 'C'; // 기본값은 Create
+
+ await db.transaction(async (tx) => {
+ if (chgGb === 'D') {
+ // Delete 처리
+ console.log('삭제 모드로 데이터 처리 시작 (트랜잭션)');
+
+ // ZBSART에 따라 삭제할 데이터 분류
+ const anHeaders: BidHeaderData[] = [];
+ const abHeaders: BidHeaderData[] = [];
+
+ for (const prData of processedData) {
+ if (prData.bidHeader.ZBSART === 'AN') {
+ anHeaders.push(prData.bidHeader);
+ } else if (prData.bidHeader.ZBSART === 'AB') {
+ abHeaders.push(prData.bidHeader);
+ }
+ }
- // 6) ZBSART에 따라 비즈니스 테이블 분기 처리
- const anHeaders: BidHeaderData[] = [];
- const abHeaders: BidHeaderData[] = [];
- const anItems: BidItemData[] = [];
- const abItems: BidItemData[] = [];
+ let deletedRfqCount = 0;
+ let deletedBiddingCount = 0;
+
+ // AN (RFQ) 데이터 삭제 - 트랜잭션 내에서 직접 처리
+ if (anHeaders.length > 0) {
+ for (const eccHeader of anHeaders) {
+ const anfnr = eccHeader.ANFNR;
+ if (!anfnr) {
+ console.error('삭제할 ANFNR이 없음', { eccHeader });
+ continue;
+ }
+
+ // 해당 ANFNR의 RFQ 찾기
+ const existingRfq = await tx
+ .select({ id: rfqsLast.id, rfqCode: rfqsLast.rfqCode })
+ .from(rfqsLast)
+ .where(eq(rfqsLast.ANFNR, anfnr))
+ .limit(1);
+
+ if (existingRfq.length === 0) {
+ console.log(`ANFNR ${anfnr}에 해당하는 RFQ가 존재하지 않음`);
+ continue;
+ }
+
+ const rfqId = existingRfq[0].id;
+ const rfqCode = existingRfq[0].rfqCode;
+
+ if (!rfqCode) {
+ console.error('RFQ 코드가 없는 데이터는 건너뜀', { rfqId });
+ continue;
+ }
+
+ // rfqPrItems 삭제
+ await tx
+ .delete(rfqPrItems)
+ .where(eq(rfqPrItems.rfqsLastId, rfqId));
+
+ // rfqsLast 삭제
+ await tx
+ .delete(rfqsLast)
+ .where(eq(rfqsLast.id, rfqId));
+
+ deletedRfqCount++;
+ console.log(`RFQ ${rfqCode} 삭제 완료`);
+ }
+ }
- // ZBSART에 따라 데이터 분류
- for (const prData of processedData) {
- if (prData.bidHeader.ZBSART === 'AN') {
- anHeaders.push(prData.bidHeader);
- anItems.push(...prData.bidItems);
- } else if (prData.bidHeader.ZBSART === 'AB') {
- abHeaders.push(prData.bidHeader);
- abItems.push(...prData.bidItems);
- }
- }
+ // AB (Bidding) 데이터 삭제 - 트랜잭션 내에서 직접 처리
+ if (abHeaders.length > 0) {
+ for (const eccHeader of abHeaders) {
+ const anfnr = eccHeader.ANFNR;
+ if (!anfnr) {
+ console.error('삭제할 ANFNR이 없음', { eccHeader });
+ continue;
+ }
+
+ // 해당 ANFNR의 Bidding 찾기
+ const existingBidding = await tx
+ .select({ id: biddings.id, biddingNumber: biddings.biddingNumber })
+ .from(biddings)
+ .where(eq(biddings.ANFNR, anfnr))
+ .limit(1);
+
+ if (existingBidding.length === 0) {
+ console.log(`ANFNR ${anfnr}에 해당하는 Bidding이 존재하지 않음`);
+ continue;
+ }
+
+ const biddingId = existingBidding[0].id;
+ const biddingNumber = existingBidding[0].biddingNumber;
+
+ // prItemsForBidding 삭제
+ await tx
+ .delete(prItemsForBidding)
+ .where(eq(prItemsForBidding.biddingId, biddingId));
+
+ // prDocuments 삭제
+ await tx
+ .delete(prDocuments)
+ .where(eq(prDocuments.biddingId, biddingId));
+
+ // biddings 삭제
+ await tx
+ .delete(biddings)
+ .where(eq(biddings.id, biddingId));
+
+ deletedBiddingCount++;
+ console.log(`Bidding ${biddingNumber} 삭제 완료`);
+ }
+ }
- // AN (RFQ) 데이터 처리 - rfqsLast 테이블
- let rfqMappingResult: { success: boolean; message: string; processedCount: number } | null = null;
- if (anHeaders.length > 0) {
- rfqMappingResult = await mapAndSaveECCRfqData(anHeaders, anItems);
- if (!rfqMappingResult.success) {
- throw new Error(`RFQ 비즈니스 테이블 매핑 실패: ${rfqMappingResult.message}`);
- }
- }
+ console.log(`🗑️ 삭제 완료 (트랜잭션): ${processedData.length}개 PR 데이터, ${deletedRfqCount}개 RFQ 삭제, ${deletedBiddingCount}개 Bidding 삭제`);
+
+ } else {
+ // Create/Update 처리 (기존 로직)
+ console.log('생성/업데이트 모드로 데이터 처리 시작 (트랜잭션)');
+
+ // 5) 원본 ECC 데이터 저장 (기존 로직 유지)
+ await saveToDatabase(processedData);
+
+ // 6) ZBSART에 따라 비즈니스 테이블 분기 처리
+ const anHeaders: BidHeaderData[] = [];
+ const abHeaders: BidHeaderData[] = [];
+ const anItems: BidItemData[] = [];
+ const abItems: BidItemData[] = [];
+
+ // ZBSART에 따라 데이터 분류
+ for (const prData of processedData) {
+ if (prData.bidHeader.ZBSART === 'AN') {
+ anHeaders.push(prData.bidHeader);
+ anItems.push(...prData.bidItems);
+ } else if (prData.bidHeader.ZBSART === 'AB') {
+ abHeaders.push(prData.bidHeader);
+ abItems.push(...prData.bidItems);
+ }
+ }
- // AB (Bidding) 데이터 처리
- let biddingMappingResult: { success: boolean; message: string; processedCount: number } | null = null;
- if (abHeaders.length > 0) {
- biddingMappingResult = await mapAndSaveECCBiddingData(abHeaders, abItems);
- if (!biddingMappingResult.success) {
- throw new Error(`Bidding 비즈니스 테이블 매핑 실패: ${biddingMappingResult.message}`);
- }
- }
+ // AN (RFQ) 데이터 처리 - rfqsLast 테이블
+ let rfqMappingResult: { success: boolean; message: string; processedCount: number } | null = null;
+ if (anHeaders.length > 0) {
+ rfqMappingResult = await mapAndSaveECCRfqData(anHeaders, anItems);
+ if (!rfqMappingResult.success) {
+ throw new Error(`RFQ 비즈니스 테이블 매핑 실패: ${rfqMappingResult.message}`);
+ }
+ }
- console.log(`🎉 처리 완료: ${processedData.length}개 PR 데이터, ${rfqMappingResult?.processedCount || 0}개 RFQ 매핑, ${biddingMappingResult?.processedCount || 0}개 Bidding 매핑`);
+ // AB (Bidding) 데이터 처리
+ let biddingMappingResult: { success: boolean; message: string; processedCount: number } | null = null;
+ if (abHeaders.length > 0) {
+ biddingMappingResult = await mapAndSaveECCBiddingData(abHeaders, abItems);
+ if (!biddingMappingResult.success) {
+ throw new Error(`Bidding 비즈니스 테이블 매핑 실패: ${biddingMappingResult.message}`);
+ }
+ }
+
+ console.log(`🎉 처리 완료 (트랜잭션): ${processedData.length}개 PR 데이터, ${rfqMappingResult?.processedCount || 0}개 RFQ 매핑, ${biddingMappingResult?.processedCount || 0}개 Bidding 매핑`);
+ }
+ });
// 6) 성공 응답 반환
return createSoapResponse('http://60.101.108.100/', {