diff options
Diffstat (limited to 'lib/soap/ecc/send/chemical-substance-check.ts')
| -rw-r--r-- | lib/soap/ecc/send/chemical-substance-check.ts | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/lib/soap/ecc/send/chemical-substance-check.ts b/lib/soap/ecc/send/chemical-substance-check.ts new file mode 100644 index 00000000..b5c4cc25 --- /dev/null +++ b/lib/soap/ecc/send/chemical-substance-check.ts @@ -0,0 +1,449 @@ +'use server' + +import { sendSoapXml } from "@/lib/soap/sender"; +import type { SoapSendConfig, SoapLogInfo, SoapSendResult } from "@/lib/soap/types"; + +// ECC 화학물질 조회 엔드포인트 (WSDL에 명시된 인터페이스 사용) +const ECC_CHEMICAL_SUBSTANCE_ENDPOINT = "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_MM%2FMMM%5E[P2MM_INTERFACE_NAME]"; + +// 화학물질 조회 요청 데이터 타입 +export interface ChemicalSubstanceCheckRequest { + T_LIST: Array<{ + BUKRS: string; // Company Code (M, CHAR 4) + WERKS: string; // Plant (M, CHAR 4) + LIFNR: string; // Vendor's account number (M, CHAR 10) + MATNR: string; // Material Number (M, CHAR 18) + }>; +} + +// 화학물질 조회 응답 데이터 타입 +export interface ChemicalSubstanceCheckResponse { + T_LIST: Array<{ + QINSPST: string; // Y/N (화학물질 여부) + SGTXT: string; // Text (상세 메시지) + }>; +} + +// 화학물질 조회 결과 타입 (DB 저장용) +export interface ChemicalSubstanceResult { + bukrs: string; + werks: string; + lifnr: string; + matnr: string; + hasChemicalSubstance: boolean; + message: string; + checkedAt: Date; +} + +// SOAP Body Content 생성 함수 +function createChemicalSubstanceCheckSoapBodyContent(data: ChemicalSubstanceCheckRequest): Record<string, unknown> { + return { + 'p1:MT_[INTERFACE_NAME]_S': { // 실제 인터페이스명으로 변경 필요 + 'T_LIST': data.T_LIST + } + }; +} + +// 화학물질 조회 데이터 검증 함수 +function validateChemicalSubstanceCheckData(data: ChemicalSubstanceCheckRequest): { isValid: boolean; errors: string[] } { + const errors: string[] = []; + + // T_LIST 배열 검증 + if (!data.T_LIST || !Array.isArray(data.T_LIST) || data.T_LIST.length === 0) { + errors.push('T_LIST는 필수이며 최소 1개 이상의 데이터가 있어야 합니다.'); + } else { + data.T_LIST.forEach((item, index) => { + // 필수 필드 검증 + if (!item.BUKRS || typeof item.BUKRS !== 'string' || item.BUKRS.trim() === '') { + errors.push(`T_LIST[${index}].BUKRS은 필수입니다.`); + } else if (item.BUKRS.length > 4) { + errors.push(`T_LIST[${index}].BUKRS은 4자를 초과할 수 없습니다.`); + } + + if (!item.WERKS || typeof item.WERKS !== 'string' || item.WERKS.trim() === '') { + errors.push(`T_LIST[${index}].WERKS는 필수입니다.`); + } else if (item.WERKS.length > 4) { + errors.push(`T_LIST[${index}].WERKS는 4자를 초과할 수 없습니다.`); + } + + if (!item.LIFNR || typeof item.LIFNR !== 'string' || item.LIFNR.trim() === '') { + errors.push(`T_LIST[${index}].LIFNR은 필수입니다.`); + } else if (item.LIFNR.length > 10) { + errors.push(`T_LIST[${index}].LIFNR은 10자를 초과할 수 없습니다.`); + } + + if (!item.MATNR || typeof item.MATNR !== 'string' || item.MATNR.trim() === '') { + errors.push(`T_LIST[${index}].MATNR은 필수입니다.`); + } else if (item.MATNR.length > 18) { + errors.push(`T_LIST[${index}].MATNR은 18자를 초과할 수 없습니다.`); + } + }); + } + + return { + isValid: errors.length === 0, + errors + }; +} + +// ECC로 화학물질 조회 SOAP XML 전송하는 함수 +async function sendChemicalSubstanceCheckToECC(data: ChemicalSubstanceCheckRequest): Promise<SoapSendResult> { + try { + // 데이터 검증 + const validation = validateChemicalSubstanceCheckData(data); + if (!validation.isValid) { + return { + success: false, + message: `데이터 검증 실패: ${validation.errors.join(', ')}` + }; + } + + // SOAP Body Content 생성 + const soapBodyContent = createChemicalSubstanceCheckSoapBodyContent(data); + + // SOAP 전송 설정 + const config: SoapSendConfig = { + endpoint: ECC_CHEMICAL_SUBSTANCE_ENDPOINT, + envelope: soapBodyContent, + soapAction: 'http://sap.com/xi/WebService/soap1.1', + timeout: 30000, // 화학물질 조회는 30초 타임아웃 + retryCount: 3, + retryDelay: 1000, + namespace: 'http://shi.samsung.co.kr/P2_MM/MMM', // ECC MM 모듈 네임스페이스 + prefix: 'p1' // WSDL에서 사용하는 p1 접두사 + }; + + // 로그 정보 + const logInfo: SoapLogInfo = { + direction: 'OUTBOUND', + system: 'S-ERP ECC', + interface: 'IF_ECC_EVCP_CHEMICAL_SUBSTANCE_CHECK' + }; + + const materials = data.T_LIST.map(item => `${item.BUKRS}/${item.WERKS}/${item.LIFNR}/${item.MATNR}`).join(', '); + console.log(`📤 화학물질 조회 요청 전송 시작 - Materials: ${materials}`); + console.log(`🔍 조회 대상 물질 ${data.T_LIST.length}개`); + + // SOAP XML 전송 + const result = await sendSoapXml(config, logInfo); + + if (result.success) { + console.log(`✅ 화학물질 조회 요청 전송 성공 - Materials: ${materials}`); + } else { + console.error(`❌ 화학물질 조회 요청 전송 실패 - Materials: ${materials}, 오류: ${result.message}`); + } + + return result; + + } catch (error) { + console.error('❌ 화학물질 조회 전송 중 오류 발생:', error); + return { + success: false, + message: error instanceof Error ? error.message : 'Unknown error' + }; + } +} + +// ======================================== +// 메인 화학물질 조회 서버 액션 함수들 +// ======================================== + +// 단일 화학물질 조회 요청 처리 +export async function checkChemicalSubstance(params: { + bukrs: string; + werks: string; + lifnr: string; + matnr: string; +}): Promise<{ + success: boolean; + message: string; + hasChemicalSubstance?: boolean; + responseData?: string; + statusCode?: number; + headers?: Record<string, string>; + endpoint?: string; + requestXml?: string; + material?: string; +}> { + try { + console.log(`🚀 화학물질 조회 요청 시작 - Material: ${params.bukrs}/${params.werks}/${params.lifnr}/${params.matnr}`); + + const requestData: ChemicalSubstanceCheckRequest = { + T_LIST: [{ + BUKRS: params.bukrs, + WERKS: params.werks, + LIFNR: params.lifnr, + MATNR: params.matnr + }] + }; + + const result = await sendChemicalSubstanceCheckToECC(requestData); + + let hasChemicalSubstance: boolean | undefined; + let message = result.message; + + if (result.success && result.responseText) { + try { + // 응답 파싱 로직 (실제 응답 구조에 따라 조정 필요) + // QINSPST = 'Y' 이면 화학물질 있음, 'N'이면 없음 + const responseData = JSON.parse(result.responseText); + if (responseData?.T_LIST?.[0]) { + const item = responseData.T_LIST[0]; + hasChemicalSubstance = item.QINSPST === 'Y'; + message = item.SGTXT || result.message; + } + } catch (parseError) { + console.warn('응답 데이터 파싱 실패:', parseError); + } + } + + return { + success: result.success, + message, + hasChemicalSubstance, + responseData: result.responseText, + statusCode: result.statusCode, + headers: result.headers, + endpoint: result.endpoint, + requestXml: result.requestXml, + material: `${params.bukrs}/${params.werks}/${params.lifnr}/${params.matnr}` + }; + + } catch (error) { + console.error('❌ 화학물질 조회 요청 처리 실패:', error); + return { + success: false, + message: error instanceof Error ? error.message : 'Unknown error' + }; + } +} + +// 여러 물질 배치 화학물질 조회 요청 처리 +export async function checkMultipleChemicalSubstances(items: Array<{ + bukrs: string; + werks: string; + lifnr: string; + matnr: string; +}>): Promise<{ + success: boolean; + message: string; + results?: Array<{ + material: string; + hasChemicalSubstance?: boolean; + success: boolean; + error?: string; + message?: string; + }>; +}> { + try { + console.log(`🚀 배치 화학물질 조회 요청 시작: ${items.length}개`); + + const requestData: ChemicalSubstanceCheckRequest = { + T_LIST: items.map(item => ({ + BUKRS: item.bukrs, + WERKS: item.werks, + LIFNR: item.lifnr, + MATNR: item.matnr + })) + }; + + const result = await sendChemicalSubstanceCheckToECC(requestData); + + let results: Array<{ + material: string; + hasChemicalSubstance?: boolean; + success: boolean; + error?: string; + message?: string; + }> | undefined; + + if (result.success && result.responseText) { + try { + const responseData = JSON.parse(result.responseText); + if (responseData?.T_LIST && Array.isArray(responseData.T_LIST)) { + results = responseData.T_LIST.map((item: any, index: number) => { + const originalItem = items[index]; + const material = `${originalItem.bukrs}/${originalItem.werks}/${originalItem.lifnr}/${originalItem.matnr}`; + + return { + material, + hasChemicalSubstance: item.QINSPST === 'Y', + success: true, + message: item.SGTXT + }; + }); + } + } catch (parseError) { + console.warn('배치 응답 데이터 파싱 실패:', parseError); + // 파싱 실패시 전체 실패로 처리 + results = items.map(item => ({ + material: `${item.bukrs}/${item.werks}/${item.lifnr}/${item.matnr}`, + success: false, + error: '응답 데이터 파싱 실패' + })); + } + } else { + // 전송 실패시 모든 항목 실패로 처리 + results = items.map(item => ({ + material: `${item.bukrs}/${item.werks}/${item.lifnr}/${item.matnr}`, + success: false, + error: result.message + })); + } + + const successCount = results?.filter(r => r.success).length || 0; + const failCount = (results?.length || 0) - successCount; + + console.log(`🎉 배치 화학물질 조회 완료: 성공 ${successCount}개, 실패 ${failCount}개`); + + return { + success: result.success, + message: result.success + ? `배치 화학물질 조회 성공: ${successCount}개` + : `배치 화학물질 조회 실패: ${result.message}`, + results + }; + + } catch (error) { + console.error('❌ 배치 화학물질 조회 중 전체 오류 발생:', error); + return { + success: false, + message: error instanceof Error ? error.message : 'Unknown error' + }; + } +} + +// 개별 처리 방식의 배치 화학물질 조회 (각각 따로 전송) +export async function checkMultipleChemicalSubstancesIndividually(items: Array<{ + bukrs: string; + werks: string; + lifnr: string; + matnr: string; +}>): Promise<{ + success: boolean; + message: string; + results?: Array<{ + material: string; + hasChemicalSubstance?: boolean; + success: boolean; + error?: string; + message?: string; + }>; +}> { + try { + console.log(`🚀 개별 화학물질 조회 요청 시작: ${items.length}개`); + + const results: Array<{ + material: string; + hasChemicalSubstance?: boolean; + success: boolean; + error?: string; + message?: string; + }> = []; + + for (const item of items) { + try { + const material = `${item.bukrs}/${item.werks}/${item.lifnr}/${item.matnr}`; + console.log(`📤 화학물질 조회 처리 중: ${material}`); + + const checkResult = await checkChemicalSubstance(item); + + results.push({ + material, + hasChemicalSubstance: checkResult.hasChemicalSubstance, + success: checkResult.success, + error: checkResult.success ? undefined : checkResult.message, + message: checkResult.message + }); + + // 개별 처리간 지연 (시스템 부하 방지) + if (items.length > 1) { + await new Promise(resolve => setTimeout(resolve, 500)); + } + + } catch (error) { + const material = `${item.bukrs}/${item.werks}/${item.lifnr}/${item.matnr}`; + console.error(`❌ 화학물질 조회 처리 실패: ${material}`, error); + results.push({ + material, + success: false, + error: error instanceof Error ? error.message : 'Unknown error' + }); + } + } + + const successCount = results.filter(r => r.success).length; + const failCount = results.length - successCount; + + console.log(`🎉 개별 화학물질 조회 완료: 성공 ${successCount}개, 실패 ${failCount}개`); + + return { + success: failCount === 0, + message: `개별 화학물질 조회 완료: 성공 ${successCount}개, 실패 ${failCount}개`, + results + }; + + } catch (error) { + console.error('❌ 개별 화학물질 조회 중 전체 오류 발생:', error); + return { + success: false, + message: error instanceof Error ? error.message : 'Unknown error' + }; + } +} + +// 테스트용 화학물질 조회 함수 (샘플 데이터 포함) +export async function checkTestChemicalSubstance(): Promise<{ + success: boolean; + message: string; + hasChemicalSubstance?: boolean; + responseData?: string; + testData?: ChemicalSubstanceCheckRequest; +}> { + try { + console.log('🧪 테스트용 화학물질 조회 시작'); + + // 테스트용 샘플 데이터 생성 + const testData: ChemicalSubstanceCheckRequest = { + T_LIST: [{ + BUKRS: '1000', + WERKS: '1000', + LIFNR: 'TEST_VENDOR', + MATNR: 'TEST_MATERIAL' + }] + }; + + const result = await sendChemicalSubstanceCheckToECC(testData); + + let hasChemicalSubstance: boolean | undefined; + let message = result.message; + + if (result.success && result.responseText) { + try { + const responseData = JSON.parse(result.responseText); + if (responseData?.T_LIST?.[0]) { + const item = responseData.T_LIST[0]; + hasChemicalSubstance = item.QINSPST === 'Y'; + message = item.SGTXT || result.message; + } + } catch (parseError) { + console.warn('테스트 응답 데이터 파싱 실패:', parseError); + } + } + + return { + success: result.success, + message, + hasChemicalSubstance, + responseData: result.responseText, + testData + }; + + } catch (error) { + console.error('❌ 테스트 화학물질 조회 실패:', error); + return { + success: false, + message: error instanceof Error ? error.message : 'Unknown error' + }; + } +} |
