summaryrefslogtreecommitdiff
path: root/lib/soap/mdg
diff options
context:
space:
mode:
Diffstat (limited to 'lib/soap/mdg')
-rw-r--r--lib/soap/mdg/mapper/vendor-mapper.ts226
1 files changed, 182 insertions, 44 deletions
diff --git a/lib/soap/mdg/mapper/vendor-mapper.ts b/lib/soap/mdg/mapper/vendor-mapper.ts
index 8a560cc4..1bb542e0 100644
--- a/lib/soap/mdg/mapper/vendor-mapper.ts
+++ b/lib/soap/mdg/mapper/vendor-mapper.ts
@@ -1,4 +1,4 @@
-import { debugLog, debugSuccess, debugError } from '@/lib/debug-utils';
+import { debugLog, debugSuccess, debugError, debugWarn } from '@/lib/debug-utils';
import db from '@/db/db';
import { vendors } from '@/db/schema/vendors';
import {
@@ -96,12 +96,22 @@ export async function mapAndSaveMDGVendorData(
for (const mdgVendorData of mdgVendorDataList) {
try {
+ debugLog('벤더 매핑 시작', { vndrCode: mdgVendorData.VNDRCD });
+
// MDG 데이터를 vendors 테이블 구조에 매핑
const mappedVendor = mapMDGToVendor(mdgVendorData);
if (mappedVendor) {
mappedVendors.push(mappedVendor);
processedCount++;
+ debugSuccess('벤더 매핑 성공 및 저장 대기열 추가', {
+ vndrCode: mdgVendorData.VNDRCD,
+ vendorName: mappedVendor.vendorName
+ });
+ } else {
+ debugWarn('벤더 매핑 실패 - null 반환', {
+ vndrCode: mdgVendorData.VNDRCD
+ });
}
} catch (error) {
debugError('개별 벤더 매핑 중 오류', {
@@ -154,6 +164,8 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
for (const vndrCode of vndrCodes) {
try {
+ debugLog('MDG 테이블 조회 시작', { vndrCode });
+
// 1. BP_VENGEN 테이블에서 기본 벤더 정보 조회
const bpVengenData = await db
.select()
@@ -161,6 +173,12 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
.where(eq(VENDOR_MASTER_BP_HEADER_BP_VENGEN.VNDRCD, vndrCode))
.limit(1);
+ debugLog('BP_VENGEN 조회 완료', {
+ vndrCode,
+ found: bpVengenData.length > 0,
+ data: bpVengenData[0] || null
+ });
+
if (bpVengenData.length === 0) {
debugError('BP_VENGEN 데이터가 없음', { vndrCode });
continue;
@@ -175,6 +193,12 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
.where(eq(VENDOR_MASTER_BP_HEADER_BP_TAXNUM.VNDRCD, vndrCode))
.limit(1);
+ debugLog('BP_TAXNUM 조회 완료', {
+ vndrCode,
+ found: bpTaxnumData.length > 0,
+ taxId: bpTaxnumData[0]?.BIZ_PTNR_TX_NO || null
+ });
+
// 3. BP_POSTAL 테이블에서 주소 정보 조회
const bpPostalData = await db
.select()
@@ -182,6 +206,12 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
.where(eq(VENDOR_MASTER_BP_HEADER_ADDRESS_AD_POSTAL.VNDRCD, vndrCode))
.limit(1);
+ debugLog('BP_POSTAL 조회 완료', {
+ vndrCode,
+ found: bpPostalData.length > 0,
+ vendorName: bpPostalData[0]?.VNDRNM_1 || null
+ });
+
// 4. BP_ADDRESS_AD_TEL 테이블에서 전화번호 조회 (첫 번째만)
const bpTelData = await db
.select()
@@ -189,6 +219,12 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
.where(eq(VENDOR_MASTER_BP_HEADER_ADDRESS_AD_TEL.VNDRCD, vndrCode))
.limit(1);
+ debugLog('BP_TEL 조회 완료', {
+ vndrCode,
+ found: bpTelData.length > 0,
+ phone: bpTelData[0]?.TELNO || null
+ });
+
// 5. BP_ADDRESS_AD_EMAIL 테이블에서 이메일 조회 (첫 번째만)
const bpEmailData = await db
.select()
@@ -196,6 +232,12 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
.where(eq(VENDOR_MASTER_BP_HEADER_ADDRESS_AD_EMAIL.VNDRCD, vndrCode))
.limit(1);
+ debugLog('BP_EMAIL 조회 완료', {
+ vndrCode,
+ found: bpEmailData.length > 0,
+ email: bpEmailData[0]?.EMAIL_ADR || null
+ });
+
// 6. BP_ADDRESS_AD_URL 테이블에서 웹사이트 조회 (첫 번째만)
const bpUrlData = await db
.select()
@@ -203,6 +245,12 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
.where(eq(VENDOR_MASTER_BP_HEADER_ADDRESS_AD_URL.VNDRCD, vndrCode))
.limit(1);
+ debugLog('BP_URL 조회 완료', {
+ vndrCode,
+ found: bpUrlData.length > 0,
+ url: bpUrlData[0]?.URL || null
+ });
+
// 데이터 병합
const mdgVendorData: MDGVendorData = {
VNDRCD: vndrCode,
@@ -224,6 +272,13 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
CO_VLM: vengenData.CO_VLM || undefined,
};
+ debugSuccess('MDG 벤더 데이터 병합 완료', {
+ vndrCode,
+ hasVendorName: !!mdgVendorData.VNDRNM_1,
+ hasTaxId: !!mdgVendorData.BIZ_PTNR_TX_NO,
+ mergedData: mdgVendorData
+ });
+
vendorDataList.push(mdgVendorData);
} catch (error) {
@@ -274,6 +329,13 @@ async function fetchMDGVendorData(vndrCodes: string[]): Promise<MDGVendorData[]>
*/
function mapMDGToVendor(mdgVendorData: MDGVendorData): VendorData | null {
try {
+ debugLog('MDG 벤더 데이터 상세', {
+ vndrCode: mdgVendorData.VNDRCD,
+ vendorName: mdgVendorData.VNDRNM_1,
+ taxId: mdgVendorData.BIZ_PTNR_TX_NO,
+ fullData: mdgVendorData
+ });
+
// 필수 필드 검증
if (!mdgVendorData.VNDRCD) {
debugError('VNDRCD가 없는 벤더 데이터', { data: mdgVendorData });
@@ -282,16 +344,28 @@ function mapMDGToVendor(mdgVendorData: MDGVendorData): VendorData | null {
// taxId가 없으면 처리하지 않음 (vendors 테이블에서 필수)
if (!mdgVendorData.BIZ_PTNR_TX_NO) {
- debugError('BIZ_PTNR_TX_NO가 없는 벤더 데이터', { vndrCode: mdgVendorData.VNDRCD });
+ debugError('BIZ_PTNR_TX_NO가 없는 벤더 데이터', {
+ vndrCode: mdgVendorData.VNDRCD,
+ reason: '필수 필드 누락: taxId'
+ });
return null;
}
// vendorName이 없으면 처리하지 않음 (vendors 테이블에서 필수)
if (!mdgVendorData.VNDRNM_1) {
- debugError('VNDRNM_1이 없는 벤더 데이터', { vndrCode: mdgVendorData.VNDRCD });
+ debugError('VNDRNM_1이 없는 벤더 데이터', {
+ vndrCode: mdgVendorData.VNDRCD,
+ reason: '필수 필드 누락: vendorName'
+ });
return null;
}
+ debugSuccess('필수 필드 검증 통과', {
+ vndrCode: mdgVendorData.VNDRCD,
+ vendorName: mdgVendorData.VNDRNM_1,
+ taxId: mdgVendorData.BIZ_PTNR_TX_NO
+ });
+
// 주소 상세 정보 결합
const addressDetail = [mdgVendorData.ADR_1, mdgVendorData.ADR_2]
.filter(Boolean)
@@ -326,9 +400,9 @@ function mapMDGToVendor(mdgVendorData: MDGVendorData): VendorData | null {
// id, createdAt, updatedAt는 자동 생성
};
- debugLog('벤더 매핑 완료', {
- original: mdgVendorData.VNDRCD,
- mapped: mappedVendor.vendorCode
+ debugLog('벤더 매핑 완료 - 매핑된 데이터 상세', {
+ vndrCode: mdgVendorData.VNDRCD,
+ mappedVendor: mappedVendor
});
return mappedVendor;
@@ -349,56 +423,120 @@ async function saveVendorsToDatabase(mappedVendors: VendorData[]): Promise<void>
try {
debugLog('벤더 데이터베이스 저장 시작', { count: mappedVendors.length });
+ let insertCount = 0;
+ let updateCount = 0;
+ let errorCount = 0;
+
await db.transaction(async (tx) => {
// 기존 데이터와 중복 체크 및 UPSERT
for (const vendor of mappedVendors) {
- if (vendor.vendorCode) {
- // vendorCode가 있는 경우 기존 데이터 확인
- const existingVendor = await tx
- .select({ id: vendors.id })
- .from(vendors)
- .where(eq(vendors.vendorCode, vendor.vendorCode))
- .limit(1);
-
- if (existingVendor.length > 0) {
- // 기존 데이터 업데이트
- await tx
- .update(vendors)
- .set({
- vendorName: vendor.vendorName,
- taxId: vendor.taxId,
- address: vendor.address,
- addressDetail: vendor.addressDetail,
- postalCode: vendor.postalCode,
- country: vendor.country,
- phone: vendor.phone,
- email: vendor.email,
- website: vendor.website,
- status: vendor.status,
- representativeName: vendor.representativeName,
- representativeBirth: vendor.representativeBirth,
- representativeEmail: vendor.representativeEmail,
- representativePhone: vendor.representativePhone,
- corporateRegistrationNumber: vendor.corporateRegistrationNumber,
- businessSize: vendor.businessSize,
- updatedAt: new Date(),
- })
- .where(eq(vendors.vendorCode, vendor.vendorCode));
+ try {
+ debugLog('벤더 저장 시도', {
+ vendorCode: vendor.vendorCode,
+ vendorName: vendor.vendorName
+ });
+
+ if (vendor.vendorCode) {
+ // vendorCode가 있는 경우 기존 데이터 확인
+ const existingVendor = await tx
+ .select({ id: vendors.id })
+ .from(vendors)
+ .where(eq(vendors.vendorCode, vendor.vendorCode))
+ .limit(1);
+
+ debugLog('기존 벤더 조회 결과', {
+ vendorCode: vendor.vendorCode,
+ exists: existingVendor.length > 0,
+ existingId: existingVendor.length > 0 ? existingVendor[0].id : null
+ });
+
+ if (existingVendor.length > 0) {
+ // 기존 데이터 업데이트
+ debugLog('기존 벤더 업데이트 시작', {
+ vendorCode: vendor.vendorCode,
+ existingId: existingVendor[0].id
+ });
+
+ await tx
+ .update(vendors)
+ .set({
+ vendorName: vendor.vendorName,
+ taxId: vendor.taxId,
+ address: vendor.address,
+ addressDetail: vendor.addressDetail,
+ postalCode: vendor.postalCode,
+ country: vendor.country,
+ phone: vendor.phone,
+ email: vendor.email,
+ website: vendor.website,
+ status: vendor.status,
+ representativeName: vendor.representativeName,
+ representativeBirth: vendor.representativeBirth,
+ representativeEmail: vendor.representativeEmail,
+ representativePhone: vendor.representativePhone,
+ corporateRegistrationNumber: vendor.corporateRegistrationNumber,
+ businessSize: vendor.businessSize,
+ updatedAt: new Date(),
+ })
+ .where(eq(vendors.vendorCode, vendor.vendorCode));
+
+ updateCount++;
+ debugSuccess('벤더 업데이트 완료', {
+ vendorCode: vendor.vendorCode,
+ vendorName: vendor.vendorName
+ });
+ } else {
+ // 새 데이터 삽입
+ debugLog('신규 벤더 삽입 시작', {
+ vendorCode: vendor.vendorCode,
+ vendorData: vendor
+ });
+
+ await tx.insert(vendors).values(vendor);
+
+ insertCount++;
+ debugSuccess('벤더 삽입 완료', {
+ vendorCode: vendor.vendorCode,
+ vendorName: vendor.vendorName
+ });
+ }
} else {
- // 새 데이터 삽입
+ // vendorCode가 없는 경우 새 데이터 삽입
+ debugLog('vendorCode 없는 벤더 삽입 시작', { vendorData: vendor });
+
await tx.insert(vendors).values(vendor);
+
+ insertCount++;
+ debugSuccess('vendorCode 없는 벤더 삽입 완료', {
+ vendorName: vendor.vendorName
+ });
}
- } else {
- // vendorCode가 없는 경우 새 데이터 삽입
- await tx.insert(vendors).values(vendor);
+ } catch (vendorError) {
+ errorCount++;
+ debugError('개별 벤더 저장 중 오류', {
+ vendorCode: vendor.vendorCode,
+ vendorName: vendor.vendorName,
+ error: vendorError instanceof Error ? vendorError.message : 'Unknown error',
+ stack: vendorError instanceof Error ? vendorError.stack : undefined
+ });
+ // 개별 벤더 저장 실패 시 전체 트랜잭션을 롤백하도록 오류를 다시 던짐
+ throw vendorError;
}
}
});
- debugSuccess('벤더 데이터베이스 저장 완료', { count: mappedVendors.length });
+ debugSuccess('벤더 데이터베이스 저장 완료', {
+ total: mappedVendors.length,
+ inserted: insertCount,
+ updated: updateCount,
+ errors: errorCount
+ });
} catch (error) {
- debugError('벤더 데이터베이스 저장 중 오류', { error });
+ debugError('벤더 데이터베이스 저장 중 오류', {
+ error: error instanceof Error ? error.message : 'Unknown error',
+ stack: error instanceof Error ? error.stack : undefined
+ });
throw error;
}
} \ No newline at end of file