summaryrefslogtreecommitdiff
path: root/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PCR
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-08-18 09:39:14 +0000
committerjoonhoekim <26rote@gmail.com>2025-08-18 09:39:14 +0000
commitaa71f75ace013b2fe982e5a104e61440458e0fd2 (patch)
tree5270f8f0d4cf8f411c6bc1a9f0e0ca21b3003c8f /app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PCR
parent13bc512bf26618d5c040fd9b19cc0afd7af7c55b (diff)
(김준회) PCR, PO, 변경PR 거절사유 수신 라우트 구현 (ECC 인터페이스), 세일즈포스 POC 테스트페이지 추가 (경로가 파트너 내부인 이유는 CORS 추가한 경로이기 때문이며, 수정될 수 있음), shi-api 유저 업데이트 로직 개선(분할정복패턴)
Diffstat (limited to 'app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PCR')
-rw-r--r--app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PCR/route.ts140
1 files changed, 140 insertions, 0 deletions
diff --git a/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PCR/route.ts b/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PCR/route.ts
new file mode 100644
index 00000000..97ebdb4b
--- /dev/null
+++ b/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PCR/route.ts
@@ -0,0 +1,140 @@
+import { NextRequest } from 'next/server';
+import db from '@/db/db';
+import { ZMM_PCR } from '@/db/schema/ECC/ecc';
+import {
+ ToXMLFields,
+ serveWsdl,
+ createXMLParser,
+ extractRequestData,
+ convertXMLToDBData,
+ createSoapResponse,
+ withSoapLogging,
+} from '@/lib/soap/utils';
+import {
+ bulkUpsert
+} from "@/lib/soap/batch-utils";
+
+type PCRData = typeof ZMM_PCR.$inferInsert;
+
+// GET 요청 처리는 ?wsdl 달고 있으면 WSDL 서비스 제공
+export async function GET(request: NextRequest) {
+ const url = new URL(request.url);
+ if (url.searchParams.has('wsdl')) {
+ return serveWsdl('IF_ECC_EVCP_PCR.wsdl');
+ }
+
+ 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')) {
+ return serveWsdl('IF_ECC_EVCP_PCR.wsdl');
+ }
+
+ const body = await request.text();
+
+ // SOAP 로깅 래퍼 함수 사용
+ return withSoapLogging(
+ 'INBOUND',
+ 'ECC',
+ 'IF_ECC_EVCP_PCR',
+ body,
+ async () => {
+ console.log('🚀 PCR 수신 시작, 데이터 길이:', body.length);
+
+ // 1) XML 파싱
+ const parser = createXMLParser(['T_PCR']);
+ const parsedData = parser.parse(body);
+
+ // 2) SOAP Body 또는 루트에서 요청 데이터 추출
+ const requestData = extractRequestData(parsedData, 'IF_ECC_EVCP_PCRReq');
+ if (!requestData) {
+ console.error('유효한 요청 데이터를 찾을 수 없습니다');
+ throw new Error('Missing request data - IF_ECC_EVCP_PCRReq not found');
+ }
+
+ // 3) XML 데이터를 DB 삽입 가능한 형태로 변환
+ const processedData = transformPCRData(requestData as PCRRequestXML);
+
+ // 4) 필수 필드 검증
+ for (const pcrData of processedData) {
+ if (!pcrData.PCR_REQ || !pcrData.PCR_REQ_SEQ || !pcrData.EBELN || !pcrData.EBELP) {
+ throw new Error('Missing required fields: PCR_REQ, PCR_REQ_SEQ, EBELN, EBELP');
+ }
+ }
+
+ // 5) 데이터베이스 저장
+ await saveToDatabase(processedData);
+
+ console.log(`🎉 처리 완료: ${processedData.length}개 PCR 데이터`);
+
+ // 6) 성공 응답 반환
+ return createSoapResponse('http://60.101.108.100/', {
+ 'tns:IF_ECC_EVCP_PCRRes': {
+ EV_TYPE: 'S',
+ },
+ });
+ }
+ ).catch((error) => {
+ // withSoapLogging에서 이미 에러 로그를 처리하므로, 여기서는 응답만 생성
+ return createSoapResponse('http://60.101.108.100/', {
+ 'tns:IF_ECC_EVCP_PCRRes': {
+ EV_TYPE: 'E',
+ EV_MESSAGE:
+ error instanceof Error ? error.message.slice(0, 100) : 'Unknown error',
+ },
+ });
+ });
+}
+
+// -----------------------------------------------------------------------------
+// 데이터 변환 및 저장 관련 유틸리티
+// -----------------------------------------------------------------------------
+
+// XML 구조 타입 정의
+type PCRDataXML = ToXMLFields<Omit<PCRData, 'id' | 'createdAt' | 'updatedAt'>>;
+
+// Root XML Request 타입
+type PCRRequestXML = {
+ CHG_GB?: string;
+ T_PCR?: PCRDataXML[];
+};
+
+// XML -> DB 데이터 변환 함수
+function transformPCRData(requestData: PCRRequestXML): PCRData[] {
+ const pcrItems = requestData.T_PCR || [];
+
+ return pcrItems.map((item) => {
+ // PCR 데이터 변환 (단일 테이블이므로 간단함)
+ const pcrDataConverted = convertXMLToDBData<PCRData>(
+ item as Record<string, string | undefined>,
+ undefined // PCR은 단일 테이블이므로 FK 데이터 불필요
+ );
+
+ return pcrDataConverted;
+ });
+}
+
+// 데이터베이스 저장 함수
+async function saveToDatabase(processedPCRs: PCRData[]) {
+ console.log(`데이터베이스(배치) 저장 시작: ${processedPCRs.length}개 PCR 데이터`);
+
+ try {
+ await db.transaction(async (tx) => {
+ // 필수 키 필드가 있는 데이터만 필터링 (PCR_REQ가 unique key)
+ const validPCRRows = processedPCRs.filter((pcr): pcr is PCRData => !!pcr.PCR_REQ);
+
+ // PCR 테이블에 UPSERT (배치)
+ // PCR_REQ가 unique 키이므로 이를 기준으로 upsert
+ await bulkUpsert(tx, ZMM_PCR, validPCRRows, 'PCR_REQ');
+ });
+
+ console.log(`데이터베이스(배치) 저장 완료: ${processedPCRs.length}개 PCR`);
+ return true;
+ } catch (error) {
+ console.error('데이터베이스(배치) 저장 중 오류 발생:', error);
+ throw error;
+ }
+} \ No newline at end of file