summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-08-27 08:51:15 +0000
committerjoonhoekim <26rote@gmail.com>2025-08-27 08:51:15 +0000
commitb203a0017f4b7150333024a1b1a5d1d9d21dea76 (patch)
tree4935c9d28ad6467903ab118a2dde4f3560c649ec /app
parentf3db693400328b2ddab70ddf6a811825b6a16489 (diff)
(김준회) ECC I/F 관련 작업
- ECC 인터페이스 수신테이블 notNull 조건 제거 (테스트 데이터 문제) - 수신 라우트의 구조 불일치 문제 처리
Diffstat (limited to 'app')
-rw-r--r--app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PO_INFORMATION/route.ts116
1 files changed, 67 insertions, 49 deletions
diff --git a/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PO_INFORMATION/route.ts b/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PO_INFORMATION/route.ts
index c2b9db46..6b882852 100644
--- a/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PO_INFORMATION/route.ts
+++ b/app/api/(S-ERP)/(ECC)/IF_ECC_EVCP_PO_INFORMATION/route.ts
@@ -88,14 +88,18 @@ export async function POST(request: NextRequest) {
async () => {
console.log('🚀 PO_INFORMATION 수신 시작, 데이터 길이:', body.length);
- // 1) XML 파싱
- const parser = createXMLParser(['T_HD', 'T_DT', 'T_PAY', 'T_KN', 'T_NOTE', 'T_NOTE2']);
+ // 1) XML 파싱 - 실제 XML 구조에 맞게 수정
+ const parser = createXMLParser(['ZMM_HD', 'ZMM_DT', 'ZMM_PAY', 'ZMM_KN', 'ZMM_NOTE', 'ZMM_NOTE2']);
const parsedData = parser.parse(body);
+ console.log('🔍 파싱된 XML 데이터 구조:', JSON.stringify(parsedData, null, 2));
// 2) SOAP Body 또는 루트에서 요청 데이터 추출
const requestData = extractRequestData(parsedData, 'IF_ECC_EVCP_PO_INFORMATIONReq');
+ console.log('🔍 추출된 요청 데이터:', JSON.stringify(requestData, null, 2));
+
if (!requestData) {
console.error('유효한 요청 데이터를 찾을 수 없습니다');
+ console.error('파싱된 데이터 키들:', Object.keys(parsedData));
throw new Error('Missing request data - IF_ECC_EVCP_PO_INFORMATIONReq not found');
}
@@ -149,55 +153,68 @@ export async function POST(request: NextRequest) {
// 데이터 변환 및 저장 관련 유틸리티
// -----------------------------------------------------------------------------
-// Root XML Request 타입
+// Root XML Request 타입 - 실제 XML 구조에 맞게 수정
type PORequestXML = {
CHG_GB?: string;
- T_HD?: HeaderXML[];
- T_DT?: DetailXML[];
- T_PAY?: PaymentXML[];
- T_KN?: AccountXML[];
- T_NOTE?: NoteXML[];
- T_NOTE2?: Note2XML[];
+ ZMM_HD?: HeaderXML[];
+ ZMM_DT?: DetailXML[];
+ ZMM_PAY?: PaymentXML[];
+ ZMM_KN?: AccountXML[];
+ ZMM_NOTE?: NoteXML[];
+ ZMM_NOTE2?: Note2XML[];
};
-// XML -> DB 데이터 변환 함수
+// XML -> DB 데이터 변환 함수 - 중첩 구조 처리
function transformPOData(requestData: PORequestXML): ProcessedPOData[] {
- const headers = requestData.T_HD || [];
- const details = requestData.T_DT || [];
- const payments = requestData.T_PAY || [];
- const accounts = requestData.T_KN || [];
- const notes = requestData.T_NOTE || [];
- const notes2 = requestData.T_NOTE2 || [];
+ console.log('🔍 변환할 요청 데이터:', JSON.stringify(requestData, null, 2));
+
+ const headers = requestData.ZMM_HD || [];
+ console.log(`📊 처리할 Header 수: ${headers.length}`);
return headers.map((header) => {
const headerKey = header.EBELN || '';
const fkData = { EBELN: headerKey };
-
- // Header 변환
+ console.log(`📦 처리 중인 Header: ${headerKey}`);
+
+ // Header 변환 (ZMM_DT, ZMM_NOTE, ZMM_NOTE2 필드 제외)
+ const headerFields = { ...header };
+ delete (headerFields as any).ZMM_DT;
+ delete (headerFields as any).ZMM_NOTE;
+ delete (headerFields as any).ZMM_NOTE2;
+
const headerConverted = convertXMLToDBData<HeaderData>(
- header as Record<string, string | undefined>,
- undefined // Header는 자체 필드만 사용
+ headerFields as Record<string, string | undefined>,
+ undefined
);
- // 해당 Header의 Detail들 필터 후 변환 (ZMM_KN도 함께 처리)
- const relatedDetails = details.filter((detail) => detail.EBELN === headerKey);
- const detailsWithAccounts: DetailWithAccounts[] = relatedDetails.map((detail) => {
+ // Header 내부의 중첩된 ZMM_DT 처리
+ const detailsFromHeader = (header as any).ZMM_DT || [];
+ console.log(`📋 ${headerKey}의 Detail 수: ${detailsFromHeader.length}`);
+
+ const detailsWithAccounts: DetailWithAccounts[] = detailsFromHeader.map((detail: any) => {
const detailKey = detail.EBELP || '';
const detailFkData = { EBELN: headerKey, EBELP: detailKey };
+ console.log(`📄 처리 중인 Detail: ${headerKey}-${detailKey}`);
- // Detail 변환
+ // Detail 변환 (ZMM_KN 필드 제외)
+ const detailFields = { ...detail };
+ delete detailFields.ZMM_KN;
+
const detailConverted = convertXMLToDBData<DetailData>(
- detail as Record<string, string | undefined>,
+ detailFields as Record<string, string | undefined>,
fkData
);
- // 해당 Detail의 Account들 필터 후 변환 (EBELN + EBELP로 매칭)
- const relatedAccounts = accounts.filter(
- (account) => account.EBELN === headerKey && account.EBELP === detailKey
- );
+ // Detail 내부의 중첩된 ZMM_KN 처리
+ const accountsFromDetail = detail.ZMM_KN || [];
+ console.log(`💳 ${headerKey}-${detailKey}의 Account 수: ${Array.isArray(accountsFromDetail) ? accountsFromDetail.length : (accountsFromDetail ? 1 : 0)}`);
+
+ // ZMM_KN이 배열이 아닌 경우 배열로 변환
+ const accountsArray = Array.isArray(accountsFromDetail) ? accountsFromDetail : (accountsFromDetail ? [accountsFromDetail] : []);
+
const accountsConverted = processNestedArray(
- relatedAccounts,
- (account) =>
+ accountsArray,
+ (account: any) =>
convertXMLToDBData<AccountData>(account as Record<string, string | undefined>, detailFkData),
detailFkData
);
@@ -212,40 +229,41 @@ function transformPOData(requestData: PORequestXML): ProcessedPOData[] {
const detailsConverted = detailsWithAccounts.map(d => d.detail);
const allAccountsConverted = detailsWithAccounts.flatMap(d => d.accounts);
- // 해당 Header의 Payment들 필터 후 변환
- const relatedPayments = payments.filter((payment) => payment.EBELN === headerKey);
- const paymentsConverted = processNestedArray(
- relatedPayments,
- (payment) =>
- convertXMLToDBData<PaymentData>(payment as Record<string, string | undefined>, fkData),
- fkData
- );
-
- // 해당 Header의 Note들 필터 후 변환
- const relatedNotes = notes.filter((note) => note.EBELN === headerKey);
+ // Header 내부의 중첩된 ZMM_NOTE 처리
+ const notesFromHeader = (header as any).ZMM_NOTE || [];
+ console.log(`📝 ${headerKey}의 Note 수: ${Array.isArray(notesFromHeader) ? notesFromHeader.length : (notesFromHeader ? 1 : 0)}`);
+
+ const notesArray = Array.isArray(notesFromHeader) ? notesFromHeader : (notesFromHeader ? [notesFromHeader] : []);
const notesConverted = processNestedArray(
- relatedNotes,
- (note) =>
+ notesArray,
+ (note: any) =>
convertXMLToDBData<NoteData>(note as Record<string, string | undefined>, fkData),
fkData
);
- // 해당 Header의 Note2들 필터 후 변환
- const relatedNotes2 = notes2.filter((note2) => note2.EBELN === headerKey);
+ // Header 내부의 중첩된 ZMM_NOTE2 처리
+ const notes2FromHeader = (header as any).ZMM_NOTE2 || [];
+ console.log(`📝 ${headerKey}의 Note2 수: ${Array.isArray(notes2FromHeader) ? notes2FromHeader.length : (notes2FromHeader ? 1 : 0)}`);
+
+ const notes2Array = Array.isArray(notes2FromHeader) ? notes2FromHeader : (notes2FromHeader ? [notes2FromHeader] : []);
const notes2Converted = processNestedArray(
- relatedNotes2,
- (note2) =>
+ notes2Array,
+ (note2: any) =>
convertXMLToDBData<Note2Data>(note2 as Record<string, string | undefined>, fkData),
fkData
);
+ // ZMM_PAY는 별도 처리 (현재 XML에는 없지만 구조상 유지)
+ const paymentsConverted: PaymentData[] = [];
+
+ console.log(`✅ ${headerKey} 변환 완료 - Details: ${detailsConverted.length}, Accounts: ${allAccountsConverted.length}, Notes: ${notesConverted.length}, Notes2: ${notes2Converted.length}`);
+
return {
header: headerConverted,
details: detailsConverted,
payments: paymentsConverted,
notes: notesConverted,
notes2: notes2Converted,
- // accounts는 이제 detail과 함께 처리되므로 별도로 저장하지 않음
accounts: allAccountsConverted,
};
});