summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-10-17 18:46:22 +0900
committerjoonhoekim <26rote@gmail.com>2025-10-17 18:46:22 +0900
commit7349504c6a92fdc115cf59d9deef76880a8287c0 (patch)
treeb6a2e4fb8936aaf1a9e917c31556723378816367 /lib
parentab8b726fee9a82ba98c550a151988c86dc096efd (diff)
(김준회) MDG 벤더 송신 테스트페이지 개선, SWP 페이지 텍스트 수정
Diffstat (limited to 'lib')
-rw-r--r--lib/soap/mdg/send/vendor-master/action.ts119
-rw-r--r--lib/soap/sender.ts58
2 files changed, 118 insertions, 59 deletions
diff --git a/lib/soap/mdg/send/vendor-master/action.ts b/lib/soap/mdg/send/vendor-master/action.ts
index d95f630c..bdb2d579 100644
--- a/lib/soap/mdg/send/vendor-master/action.ts
+++ b/lib/soap/mdg/send/vendor-master/action.ts
@@ -19,6 +19,7 @@ import {
import { eq, sql, desc } from "drizzle-orm";
import { CSV_FIELDS } from './csv-fields';
import { sendSoapXml, type SoapSendConfig, type SoapLogInfo } from "@/lib/soap/sender";
+import { debugLog, debugError, debugSuccess } from '@/lib/debug-utils';
// SAP XI 엔드포인트 URL
const MDG_ENDPOINT_URL = "http://shii8dvddb01.hec.serp.shi.samsung.net:50000/sap/xi/engine?type=entry&version=3.0&Sender.Service=P2038_Q&Interface=http%3A%2F%2Fshi.samsung.co.kr%2FP2_MD%2FMDZ%5EP2MD3007_AO&QualityOfService=ExactlyOnce";
@@ -39,6 +40,10 @@ async function sendVendorMasterToMDGInternal(supplierMaster: Record<string, stri
success: boolean;
message: string;
responseText?: string;
+ requestXml?: string;
+ responseHeaders?: Record<string, string>;
+ statusCode?: number;
+ requestHeaders?: Record<string, string>;
}> {
try {
// SOAP Body Content 생성
@@ -63,26 +68,42 @@ async function sendVendorMasterToMDGInternal(supplierMaster: Record<string, stri
interface: 'IF_MDZ_EVCP_VENDOR_MASTER'
};
- console.log(`📤 VENDOR 마스터 전송 시작`);
- console.log(`🔍 SUPPLIER_MASTER 데이터: ${Object.keys(supplierMaster).length}개 필드`);
+ debugLog(`📤 VENDOR 마스터 전송 시작`);
+ debugLog(`🔍 SUPPLIER_MASTER 데이터: ${Object.keys(supplierMaster).length}개 필드`);
// SOAP XML 전송
const result = await sendSoapXml(config, logInfo);
+ // 응답 상세 정보 로깅
+ debugLog('📊 SOAP 전송 결과 상세:', {
+ success: result.success,
+ message: result.message,
+ statusCode: result.statusCode,
+ hasResponseText: !!result.responseText,
+ responseTextLength: result.responseText?.length,
+ hasRequestXml: !!result.requestXml,
+ requestXmlLength: result.requestXml?.length,
+ headers: result.headers
+ });
+
if (result.success) {
- console.log(`✅ VENDOR 마스터 전송 성공`);
+ debugSuccess(`✅ VENDOR 마스터 전송 성공`);
} else {
- console.error(`❌ VENDOR 마스터 전송 실패, 오류: ${result.message}`);
+ debugError(`❌ VENDOR 마스터 전송 실패, 오류: ${result.message}`);
}
return {
success: result.success,
message: result.success ? '전송 성공' : result.message,
- responseText: result.responseText
+ responseText: result.responseText,
+ requestXml: result.requestXml,
+ responseHeaders: result.headers,
+ statusCode: result.statusCode,
+ requestHeaders: result.requestHeaders
};
} catch (error) {
- console.error('❌ VENDOR 마스터 전송 중 오류 발생:', error);
+ debugError('❌ VENDOR 마스터 전송 중 오류 발생:', error);
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error'
@@ -148,7 +169,7 @@ async function fetchVendorData(vendorCode: string) {
};
} catch (error) {
- console.error(`VENDOR ${vendorCode} 데이터 조회 실패:`, error);
+ debugError(`VENDOR ${vendorCode} 데이터 조회 실패:`, error);
throw error;
}
}
@@ -206,13 +227,13 @@ export async function sendVendorMasterToMDG(vendorCodes: string[]): Promise<{
results?: Array<{ vendorCode: string; success: boolean; error?: string }>;
}> {
try {
- console.log(`🚀 VENDOR_MASTER 송신 시작: ${vendorCodes.length}개 벤더`);
+ debugLog(`🚀 VENDOR_MASTER 송신 시작: ${vendorCodes.length}개 벤더`);
const results: Array<{ vendorCode: string; success: boolean; error?: string }> = [];
for (const vendorCode of vendorCodes) {
try {
- console.log(`📤 VENDOR ${vendorCode} 데이터 조회 중...`);
+ debugLog(`📤 VENDOR ${vendorCode} 데이터 조회 중...`);
const vendorData = await fetchVendorData(vendorCode);
@@ -226,18 +247,18 @@ export async function sendVendorMasterToMDG(vendorCodes: string[]): Promise<{
}
const supplierMaster = buildSupplierMasterData(vendorData);
- console.log(`📄 VENDOR ${vendorCode} 데이터 생성 완료`);
+ debugLog(`📄 VENDOR ${vendorCode} 데이터 생성 완료`);
const result = await sendVendorMasterToMDGInternal(supplierMaster);
if (result.success) {
- console.log(`✅ VENDOR ${vendorCode} MDG 전송 성공`);
+ debugSuccess(`✅ VENDOR ${vendorCode} MDG 전송 성공`);
results.push({
vendorCode,
success: true
});
} else {
- console.error(`❌ VENDOR ${vendorCode} 전송 실패: ${result.message}`);
+ debugError(`❌ VENDOR ${vendorCode} 전송 실패: ${result.message}`);
results.push({
vendorCode,
success: false,
@@ -246,7 +267,7 @@ export async function sendVendorMasterToMDG(vendorCodes: string[]): Promise<{
}
} catch (error) {
- console.error(`❌ VENDOR ${vendorCode} 전송 실패:`, error);
+ debugError(`❌ VENDOR ${vendorCode} 전송 실패:`, error);
results.push({
vendorCode,
success: false,
@@ -258,7 +279,7 @@ export async function sendVendorMasterToMDG(vendorCodes: string[]): Promise<{
const successCount = results.filter(r => r.success).length;
const failCount = results.length - successCount;
- console.log(`🎉 VENDOR_MASTER 송신 완료: 성공 ${successCount}개, 실패 ${failCount}개`);
+ debugSuccess(`🎉 VENDOR_MASTER 송신 완료: 성공 ${successCount}개, 실패 ${failCount}개`);
return {
success: failCount === 0,
@@ -267,7 +288,7 @@ export async function sendVendorMasterToMDG(vendorCodes: string[]): Promise<{
};
} catch (error) {
- console.error('❌ VENDOR_MASTER 송신 중 전체 오류 발생:', error);
+ debugError('❌ VENDOR_MASTER 송신 중 전체 오류 발생:', error);
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error'
@@ -314,14 +335,17 @@ export async function sendTestVendorDataToMDG(formData: Record<string, string>):
message: string;
responseData?: unknown;
generatedXML?: string;
+ responseHeaders?: Record<string, string>;
+ statusCode?: number;
+ requestHeaders?: Record<string, string>;
}> {
try {
- console.log('🚀 테스트용 VENDOR 데이터 송신 시작');
+ debugLog('🚀 테스트용 VENDOR 데이터 송신 시작');
// 필수 필드 검증
const validation = validateMandatoryFields(formData);
if (!validation.isValid) {
- console.error('❌ 필수 필드 누락:', validation.missingFields);
+ debugError('❌ 필수 필드 누락:', validation.missingFields);
return {
success: false,
message: validation.errorMessage,
@@ -342,21 +366,38 @@ export async function sendTestVendorDataToMDG(formData: Record<string, string>):
supplierMaster[f.field] = formData[f.field] ?? '';
});
- console.log('📄 SUPPLIER_MASTER 데이터 생성 완료');
+ debugLog('📄 SUPPLIER_MASTER 데이터 생성 완료');
const result = await sendVendorMasterToMDGInternal(supplierMaster);
+ // 응답 정보 상세 로깅
+ debugLog('📊 테스트 송신 결과:', {
+ success: result.success,
+ statusCode: result.statusCode,
+ responseHeaders: result.responseHeaders,
+ hasResponseText: !!result.responseText,
+ responseTextLength: result.responseText?.length,
+ hasRequestXml: !!result.requestXml,
+ requestXmlLength: result.requestXml?.length
+ });
+
return {
success: result.success,
message: result.success ? '테스트 송신이 완료되었습니다.' : result.message,
- responseData: result.responseText
+ responseData: result.responseText,
+ generatedXML: result.requestXml,
+ responseHeaders: result.responseHeaders,
+ statusCode: result.statusCode,
+ requestHeaders: result.requestHeaders
};
} catch (error) {
- console.error('❌ 테스트 송신 실패:', error);
+ debugError('❌ 테스트 송신 실패:', error);
return {
success: false,
- message: error instanceof Error ? error.message : 'Unknown error'
+ message: error instanceof Error ? error.message : 'Unknown error',
+ responseData: undefined,
+ generatedXML: undefined
};
}
}
@@ -386,14 +427,14 @@ export async function sendAllVendorsToMDG() {
};
}
- console.log(`⚠️ 전체 VENDOR 송신 요청: ${vendorCodes.length}개`);
+ debugLog(`⚠️ 전체 VENDOR 송신 요청: ${vendorCodes.length}개`);
const batchSize = 10;
const results: Array<{ vendorCode: string; success: boolean; error?: string }> = [];
for (let i = 0; i < vendorCodes.length; i += batchSize) {
const batch = vendorCodes.slice(i, i + batchSize);
- console.log(`📦 배치 ${Math.floor(i / batchSize) + 1} 처리 중... (${batch.length}개)`);
+ debugLog(`📦 배치 ${Math.floor(i / batchSize) + 1} 처리 중... (${batch.length}개)`);
const batchResult = await sendVendorMasterToMDG(batch);
if (batchResult.results) {
@@ -415,7 +456,7 @@ export async function sendAllVendorsToMDG() {
};
} catch (error) {
- console.error('전체 VENDOR 송신 중 오류:', error);
+ debugError('전체 VENDOR 송신 중 오류:', error);
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error'
@@ -430,7 +471,7 @@ export async function sendModifiedVendorsToMDG(): Promise<{
results?: Array<{ vendorCode: string; success: boolean; error?: string }>;
}> {
try {
- console.log('🔍 수정된 VENDOR 데이터 조회 중...');
+ debugLog('🔍 수정된 VENDOR 데이터 조회 중...');
const modifiedVendors = await db
.select({
@@ -446,21 +487,21 @@ export async function sendModifiedVendorsToMDG(): Promise<{
const vendorCodes = modifiedVendors.map(v => v.VNDRCD);
if (vendorCodes.length === 0) {
- console.log('📝 수정된 VENDOR 데이터가 없습니다.');
+ debugLog('📝 수정된 VENDOR 데이터가 없습니다.');
return {
success: true,
message: '수정된 VENDOR 데이터가 없습니다.'
};
}
- console.log(`📋 수정된 VENDOR ${vendorCodes.length}개 발견:`, vendorCodes);
+ debugLog(`📋 수정된 VENDOR ${vendorCodes.length}개 발견:`, vendorCodes);
const batchSize = 10;
const results: Array<{ vendorCode: string; success: boolean; error?: string }> = [];
for (let i = 0; i < vendorCodes.length; i += batchSize) {
const batch = vendorCodes.slice(i, i + batchSize);
- console.log(`📦 수정 데이터 배치 ${Math.floor(i / batchSize) + 1} 처리 중... (${batch.length}개)`);
+ debugLog(`📦 수정 데이터 배치 ${Math.floor(i / batchSize) + 1} 처리 중... (${batch.length}개)`);
const batchResult = await sendVendorMasterToMDG(batch);
if (batchResult.results) {
@@ -475,7 +516,7 @@ export async function sendModifiedVendorsToMDG(): Promise<{
const successCount = results.filter(r => r.success).length;
const failCount = results.length - successCount;
- console.log(`🎯 수정된 VENDOR 송신 완료: 성공 ${successCount}개, 실패 ${failCount}개`);
+ debugSuccess(`🎯 수정된 VENDOR 송신 완료: 성공 ${successCount}개, 실패 ${failCount}개`);
return {
success: failCount === 0,
@@ -484,7 +525,7 @@ export async function sendModifiedVendorsToMDG(): Promise<{
};
} catch (error) {
- console.error('❌ 수정된 VENDOR 송신 중 오류:', error);
+ debugError('❌ 수정된 VENDOR 송신 중 오류:', error);
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error'
@@ -509,7 +550,7 @@ export async function sendNVendorsToMDG(
};
}
- console.log(`🧪 테스트용 VENDOR 송신: ${count}건 (${startFrom}번째부터)`);
+ debugLog(`🧪 테스트용 VENDOR 송신: ${count}건 (${startFrom}번째부터)`);
const vendors = await db
.select({ VNDRCD: VENDOR_MASTER_BP_HEADER.VNDRCD })
@@ -526,11 +567,11 @@ export async function sendNVendorsToMDG(
};
}
- console.log(`📋 테스트 대상 VENDOR ${vendorCodes.length}개:`, vendorCodes);
+ debugLog(`📋 테스트 대상 VENDOR ${vendorCodes.length}개:`, vendorCodes);
const result = await sendVendorMasterToMDG(vendorCodes);
- console.log(`🧪 테스트 송신 완료: ${vendorCodes.length}개 처리`);
+ debugSuccess(`🧪 테스트 송신 완료: ${vendorCodes.length}개 처리`);
return {
...result,
@@ -538,7 +579,7 @@ export async function sendNVendorsToMDG(
};
} catch (error) {
- console.error('❌ 테스트 송신 중 오류:', error);
+ debugError('❌ 테스트 송신 중 오류:', error);
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error'
@@ -555,7 +596,7 @@ export async function sendRecentModifiedVendorsToMDG(
results?: Array<{ vendorCode: string; success: boolean; error?: string }>;
}> {
try {
- console.log(`🕒 최근 수정된 VENDOR ${count}건 조회 중...`);
+ debugLog(`🕒 최근 수정된 VENDOR ${count}건 조회 중...`);
const recentVendors = await db
.select({
@@ -578,12 +619,12 @@ export async function sendRecentModifiedVendorsToMDG(
};
}
- console.log(`📋 최근 수정된 VENDOR ${vendorCodes.length}개:`,
+ debugLog(`📋 최근 수정된 VENDOR ${vendorCodes.length}개:`,
recentVendors.map(v => `${v.VNDRCD}(${v.updatedAt?.toISOString()})`));
const result = await sendVendorMasterToMDG(vendorCodes);
- console.log(`🕒 최근 수정 데이터 송신 완료`);
+ debugSuccess(`🕒 최근 수정 데이터 송신 완료`);
return {
...result,
@@ -591,7 +632,7 @@ export async function sendRecentModifiedVendorsToMDG(
};
} catch (error) {
- console.error('❌ 최근 수정 데이터 송신 중 오류:', error);
+ debugError('❌ 최근 수정 데이터 송신 중 오류:', error);
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error'
@@ -644,7 +685,7 @@ export async function getVendorSendStatistics(): Promise<{
};
} catch (error) {
- console.error('통계 조회 실패:', error);
+ debugError('통계 조회 실패:', error);
throw error;
}
}
diff --git a/lib/soap/sender.ts b/lib/soap/sender.ts
index 1dfc8730..d12665cb 100644
--- a/lib/soap/sender.ts
+++ b/lib/soap/sender.ts
@@ -2,6 +2,7 @@
import { withSoapLogging } from "@/lib/soap/utils";
import { XMLBuilder } from 'fast-xml-parser';
+import { debugLog, debugError, debugWarn, debugSuccess } from '@/lib/debug-utils';
// 기본 인증 정보 타입
export interface SoapAuthConfig {
@@ -97,6 +98,7 @@ export async function sendSoapXml(
logInfo: SoapLogInfo,
auth?: SoapAuthConfig
): Promise<SoapSendResult> {
+ let xmlData: string | undefined;
try {
// 인증 정보 설정 (기본값 사용)
const authConfig = auth || getDefaultAuth();
@@ -109,10 +111,10 @@ export async function sendSoapXml(
config.prefix
);
- const xmlData = await generateSoapXml(soapEnvelope);
+ xmlData = await generateSoapXml(soapEnvelope);
- console.log('📤 SOAP XML 전송 시작');
- console.log('🔍 전송 XML (첫 500자):', xmlData.substring(0, 500));
+ debugLog('📤 SOAP XML 전송 시작');
+ debugLog('🔍 전송 XML (첫 500자):', xmlData.substring(0, 500));
// 요청 헤더 및 fetch 옵션을 사전에 구성
const requestHeaders: Record<string, string> = {
@@ -124,9 +126,9 @@ export async function sendSoapXml(
if (authConfig.username && authConfig.password) {
const credentials = Buffer.from(`${authConfig.username}:${authConfig.password}`).toString('base64');
requestHeaders['Authorization'] = `Basic ${credentials}`;
- console.log('🔐 Basic Authentication 헤더 추가 완료');
+ debugSuccess('🔐 Basic Authentication 헤더 추가 완료');
} else {
- console.warn('⚠️ SOAP 인증 정보가 설정되지 않았습니다.');
+ debugWarn('⚠️ SOAP 인증 정보가 설정되지 않았습니다.');
}
const fetchOptions: RequestInit = {
@@ -136,14 +138,18 @@ export async function sendSoapXml(
};
// Body 루트 요소(p1:MT_...)에 기본 네임스페이스를 부여하여 하위 무접두사 요소들도 동일 네임스페이스로 인식되도록 처리
- const envelopeObj = soapEnvelope as Record<string, any>;
- const bodyObj = envelopeObj['soap:Envelope']?.['soap:Body'] as Record<string, any> | undefined;
+ const envelopeObj = soapEnvelope as Record<string, unknown>;
+ const bodyObj = envelopeObj['soap:Envelope'] as Record<string, unknown> | undefined;
if (bodyObj && typeof bodyObj === 'object') {
- const rootKeys = Object.keys(bodyObj);
- if (rootKeys.length > 0) {
- const rootKey = rootKeys[0];
- if (bodyObj[rootKey] && typeof bodyObj[rootKey] === 'object') {
- bodyObj[rootKey]['@_xmlns'] = namespace;
+ const soapBody = bodyObj['soap:Body'] as Record<string, unknown> | undefined;
+ if (soapBody && typeof soapBody === 'object') {
+ const rootKeys = Object.keys(soapBody);
+ if (rootKeys.length > 0) {
+ const rootKey = rootKeys[0];
+ const rootValue = soapBody[rootKey];
+ if (rootValue && typeof rootValue === 'object') {
+ (rootValue as Record<string, unknown>)['@_xmlns'] = namespace;
+ }
}
}
}
@@ -183,8 +189,19 @@ export async function sendSoapXml(
const response = result as Response;
const responseText = await response.text();
- console.log('📥 SOAP 응답 수신:', response.status, response.statusText);
- console.log('🔍 응답 XML (첫 500자):', responseText.substring(0, 500));
+ // 응답 헤더 수집 (디버깅용)
+ const responseHeadersDebug: Record<string, string> = {};
+ response.headers.forEach((value, key) => {
+ responseHeadersDebug[key] = value;
+ });
+
+ debugLog('📥 SOAP 응답 수신:', {
+ status: response.status,
+ statusText: response.statusText,
+ headers: responseHeadersDebug,
+ bodyLength: responseText.length
+ });
+ debugLog('🔍 응답 바디 (전체):', responseText);
// HTTP 상태 코드가 비정상이거나 SOAP Fault 포함 시 실패로 처리하되 본문을 그대로 반환
if (!response.ok || responseText.includes('soap:Fault') || responseText.includes('SOAP:Fault')) {
@@ -222,10 +239,11 @@ export async function sendSoapXml(
};
} catch (error) {
- console.error('❌ SOAP XML 전송 실패:', error);
+ debugError('❌ SOAP XML 전송 실패:', error);
return {
success: false,
- message: error instanceof Error ? error.message : 'Unknown error'
+ message: error instanceof Error ? error.message : 'Unknown error',
+ requestXml: xmlData // 에러가 발생해도 생성된 XML이 있다면 반환
};
}
}
@@ -241,7 +259,7 @@ export async function sendSoapXmlWithRetry(
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
- console.log(`🔄 SOAP 전송 시도 ${attempt}/${maxRetries}`);
+ debugLog(`🔄 SOAP 전송 시도 ${attempt}/${maxRetries}`);
const result = await sendSoapXml(config, logInfo, auth);
@@ -251,12 +269,12 @@ export async function sendSoapXmlWithRetry(
// 마지막 시도가 아니면 재시도
if (attempt < maxRetries) {
- console.log(`⏳ ${retryDelay}ms 후 재시도...`);
+ debugLog(`⏳ ${retryDelay}ms 후 재시도...`);
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
} catch (error) {
- console.error(`❌ SOAP 전송 시도 ${attempt} 실패:`, error);
+ debugError(`❌ SOAP 전송 시도 ${attempt} 실패:`, error);
if (attempt === maxRetries) {
return {
@@ -266,7 +284,7 @@ export async function sendSoapXmlWithRetry(
}
// 마지막 시도가 아니면 재시도
- console.log(`⏳ ${retryDelay}ms 후 재시도...`);
+ debugLog(`⏳ ${retryDelay}ms 후 재시도...`);
await new Promise(resolve => setTimeout(resolve, retryDelay));
}
}