diff options
Diffstat (limited to 'lib/soap/mdg/send')
| -rw-r--r-- | lib/soap/mdg/send/vendor-master/action.ts | 13 | ||||
| -rw-r--r-- | lib/soap/mdg/send/vendor-master/send-single-vendor.ts | 238 |
2 files changed, 250 insertions, 1 deletions
diff --git a/lib/soap/mdg/send/vendor-master/action.ts b/lib/soap/mdg/send/vendor-master/action.ts index bdb2d579..c73d78c5 100644 --- a/lib/soap/mdg/send/vendor-master/action.ts +++ b/lib/soap/mdg/send/vendor-master/action.ts @@ -36,7 +36,7 @@ function createVendorMasterSoapBodyContent(supplierMaster: Record<string, string } // MDG로 VENDOR 마스터 SOAP XML 전송하는 함수 (sender.ts 사용) -async function sendVendorMasterToMDGInternal(supplierMaster: Record<string, string>): Promise<{ +export async function sendVendorMasterToMDGInternal(supplierMaster: Record<string, string>): Promise<{ success: boolean; message: string; responseText?: string; @@ -220,6 +220,17 @@ function buildSupplierMasterData(vendorData: NonNullable<Awaited<ReturnType<type // 메인 송신 함수들 // ======================================== +/** + * @deprecated 이 함수는 더 이상 사용되지 않습니다. + * 대신 sendSingleVendorToMDG()를 사용하세요. + * + * 이유: + * - 신규 벤더는 vendorCode가 없음 (MDG에서 생성) + * - 개별 벤더 데이터 전송이 필요 + * - vendors 테이블에서 직접 데이터 조회 필요 + * + * @see lib/soap/mdg/send/vendor-master/send-single-vendor.ts + */ // VENDOR 마스터 데이터를 MDG로 송신하는 액션 export async function sendVendorMasterToMDG(vendorCodes: string[]): Promise<{ success: boolean; diff --git a/lib/soap/mdg/send/vendor-master/send-single-vendor.ts b/lib/soap/mdg/send/vendor-master/send-single-vendor.ts new file mode 100644 index 00000000..d10792b7 --- /dev/null +++ b/lib/soap/mdg/send/vendor-master/send-single-vendor.ts @@ -0,0 +1,238 @@ +'use server' + +import db from "@/db/db" +import { vendors, vendorTypes } from "@/db/schema/vendors" +import { eq } from "drizzle-orm" +import { sendVendorMasterToMDGInternal } from "./action" +import { debugLog, debugError, debugSuccess } from '@/lib/debug-utils' +import { oracleKnex } from '@/lib/oracle-db/db' + +/** + * Oracle DB에서 ZZREQID 값 조회 + * + * @returns ZZREQID 값 (조회 실패 시 기본값 'HUIUN84.KIM') + */ +async function getZZREQID(): Promise<string> { + const DEFAULT_ZZREQID = 'HUIUN84.KIM' + + try { + debugLog(`🔍 [ZZREQID] Oracle DB에서 ZZREQID 조회 시작`) + + const query = ` + SELECT CDNM + FROM CMCTB_CDNM + WHERE CD_CLF = :cd_clf + AND CD = :cd + AND ROWNUM <= 1 + ` + + const results = await oracleKnex.raw(query, { + cd_clf: 'SRM0BN', + cd: '001' + }) + + debugLog(`🗄️ [ZZREQID] Oracle 쿼리 결과:`, { + resultType: typeof results, + isArray: Array.isArray(results), + }) + + // Oracle 결과 파싱 (여러 형태 처리) + let rows + if (Array.isArray(results)) { + // [rows, metaData] 형태 또는 바로 데이터 배열 + if (results.length > 0 && typeof results[0] === 'object' && !Array.isArray(results[0])) { + rows = results // 바로 데이터 배열 + } else { + rows = results[0] || [] // [rows, metaData] 형태 + } + } else if (results && typeof results === 'object' && results.rows) { + rows = results.rows || [] + } else { + rows = [] + } + + if (!Array.isArray(rows) || rows.length === 0) { + debugError(`⚠️ [ZZREQID] Oracle 조회 결과 없음, 기본값 사용: ${DEFAULT_ZZREQID}`) + return DEFAULT_ZZREQID + } + + const cdnm = rows[0]?.CDNM || rows[0]?.[0] + + if (!cdnm) { + debugError(`⚠️ [ZZREQID] CDNM 컬럼 값 없음, 기본값 사용: ${DEFAULT_ZZREQID}`) + return DEFAULT_ZZREQID + } + + debugSuccess(`✅ [ZZREQID] Oracle 조회 성공: ${cdnm}`) + return String(cdnm) + + } catch (error) { + debugError(`❌ [ZZREQID] Oracle 조회 실패, 기본값 사용:`, { + error: error instanceof Error ? error.message : '알 수 없는 오류', + defaultValue: DEFAULT_ZZREQID + }) + return DEFAULT_ZZREQID + } +} + +/** + * 개별 벤더 데이터를 MDG로 전송 + * + * @param input.vendorId - vendors 테이블의 ID + * @param input.mode - 'NEW_VENDOR' (신규) 또는 'REGULAR_VENDOR' (정규) + * @returns 전송 결과 + */ +export async function sendSingleVendorToMDG(input: { + vendorId: number + mode: 'NEW_VENDOR' | 'REGULAR_VENDOR' +}): Promise<{ + success: boolean + message: string + vendorId: number + responseText?: string + requestXml?: string +}> { + try { + debugLog(`📤 [MDG Single] 벤더 ID ${input.vendorId} 전송 시작 (모드: ${input.mode})`) + + // 1. 벤더 데이터 조회 (vendor_types 조인) + const [vendorData] = await db + .select({ + vendor: vendors, + vendorTypeName: vendorTypes.nameKo, + }) + .from(vendors) + .leftJoin(vendorTypes, eq(vendors.vendorTypeId, vendorTypes.id)) + .where(eq(vendors.id, input.vendorId)) + .limit(1) + + if (!vendorData) { + throw new Error(`벤더를 찾을 수 없습니다: ID ${input.vendorId}`) + } + + const vendor = vendorData.vendor + const vendorTypeName = vendorData.vendorTypeName + + debugLog(`📋 [MDG Single] 벤더 조회 완료: ${vendor.vendorName} (업체 유형: ${vendorTypeName || '없음'})`) + + // 2. Oracle DB에서 ZZREQID 조회 + const zzreqid = await getZZREQID() + debugLog(`🔑 [MDG Single] ZZREQID 값: ${zzreqid}`) + + // 3. MDG 포맷으로 데이터 매핑 + const supplierMaster = mapVendorToMDGFormat(vendor, vendorTypeName, zzreqid, input.mode) + + debugLog(`🔄 [MDG Single] 데이터 매핑 완료 (${Object.keys(supplierMaster).length}개 필드)`) + + // 3. MDG로 전송 + const result = await sendVendorMasterToMDGInternal(supplierMaster) + + if (!result.success) { + debugError(`❌ [MDG Single] 전송 실패: ${result.message}`) + throw new Error(`MDG 전송 실패: ${result.message}`) + } + + debugSuccess(`✅ [MDG Single] 전송 성공: ${vendor.vendorName}`) + + return { + success: true, + message: `벤더 '${vendor.vendorName}' MDG 전송 완료`, + vendorId: input.vendorId, + responseText: result.responseText, + requestXml: result.requestXml, + } + + } catch (error) { + debugError(`❌ [MDG Single] 전송 중 오류:`, error) + return { + success: false, + message: error instanceof Error ? error.message : 'Unknown error', + vendorId: input.vendorId, + } + } +} + +/** + * Vendor DB 데이터를 MDG SUPPLIER_MASTER 포맷으로 매핑 + */ +function mapVendorToMDGFormat( + vendor: typeof vendors.$inferSelect, + vendorTypeName: string | null, + zzreqid: string, + mode: 'NEW_VENDOR' | 'REGULAR_VENDOR' +): Record<string, string> { + debugLog(`🗺️ [MDG Mapper] 데이터 매핑 시작: ${vendor.vendorName}`) + + // 전화번호로 모바일 여부 판단 (+8210으로 시작하면 1, 아니면 0) + const phoneStr = vendor.phone?.trim() || '' + const isMobile = phoneStr.startsWith('+8210') ? '1' : '0' + + // 기본 매핑 (신규 벤더) + const mapping: Record<string, string> = { + // === 필수 필드 (고정값) === + BP_HEADER: `evcp${vendor.id}`, // 벤더 ID (evcp + ID) + ZZSRMCD: `evcp${vendor.id}`, // SRM 코드 (evcp + ID) + KTOKK: 'LIEF', // 고정값: Vendor account group + MASTERFLAG: 'V', // 고정값 + IBND_TYPE: 'I', // 고정값 + CONSNUMBER: '1', // 고정값: 단건 전송 + + // === 업체 기본 정보 === + SORT1: vendor.vendorName || '', // 검색어 (업체명과 동일) + NAME1: vendor.vendorName || '', // 업체명 + + // === 대표자 정보 === + J_1KFREPRE: vendor.representativeName || '', // 대표자명 + J_1KFTBUS: vendorTypeName || '', // 사업유형 (vendor_types의 name_ko) + J_1KFTIND: vendorTypeName || '', // 산업유형 (vendor_types의 name_ko) + + // === 요청자 정보 === + ZZREQID: zzreqid, // Oracle DB에서 동적 조회 (CMCTB_CDNM 테이블) + + // === 주소 정보 === + ADDRNO: '', // 빈 문자열 (보내면 안됨) + NATION: '', // 빈 문자열 (보내면 안됨) + COUNTRY: vendor.country || 'KR', // 국가코드 (기본값 KR) + POST_CODE1: vendor.postalCode || '00000', // 우편번호 (없으면 00000) + CITY1: vendor.addressDetail || '', // 상세주소 + STREET: vendor.address || '', // 기본주소 + + // === 연락처 정보 === + TEL_NUMBER: vendor.phone || '', // 전화번호 + R3_USER: isMobile, // 모바일 여부 (0: 일반전화, 1: +8210 시작) + URI_ADDR: vendor.website || '', // 홈페이지 주소 + SMTP_ADDR: vendor.representativeEmail || '', // 대표자 이메일 + + // === 세금 정보 === + TAXTYPE: 'KR2', // 고정값 (한국) + TAXNUM: vendor.taxId?.replace(/-/g, '') || '', // 사업자번호 (하이픈 제거) + BP_TX_TYP: 'KR2', // 고정값 (한국) + STCD3: vendor.corporateRegistrationNumber?.replace(/-/g, '') || '', // 법인등록번호 (하이픈 제거) + + // === 기업 정보 === + ZZIND03: vendor.businessSize || '', // 기업규모 (A=대기업, B=중견기업, C=중소기업, D=소기업) + + // === 무시할 필드들 (빈 문자열) === + LANGU: '', // 언어 키 (무시) + } + + // 정규 벤더의 경우 추가 필드 매핑 가능 + if (mode === 'REGULAR_VENDOR') { + // TODO: 정규 벤더 전송 시 추가 필드 매핑 + // 현재는 신규와 동일하게 처리 + debugLog(`ℹ️ [MDG Mapper] 정규 벤더 모드 (추가 필드 없음)`) + } + + // 빈 문자열인 필드만 포함 (null/undefined는 제외) + const result: Record<string, string> = {} + Object.entries(mapping).forEach(([key, value]) => { + if (value !== null && value !== undefined) { + result[key] = String(value) + } + }) + + debugLog(`✅ [MDG Mapper] 매핑 완료: ${Object.keys(result).length}개 필드`) + + return result +} + |
