'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 { 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 { 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; 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' }; } }