'use server' import { sendSoapXml, type SoapSendConfig, type SoapLogInfo, type SoapSendResult } from "@/lib/soap/sender"; // ECC PCR 확인 엔드포인트 (WSDL에 명시된 P2038_D 사용) const ECC_PCR_CONFIRM_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%5EP2MM3019_SO"; // PCR 확인 요청 데이터 타입 export interface PCRConfirmRequest { ZMM_PCR: Array<{ PCR_REQ: string; // PCR 요청번호 (M) PCR_REQ_SEQ: string; // PCR 요청순번 (M) PCR_DEC_DATE: string; // PCR 결정일 (M, YYYYMMDD) EBELN: string; // 구매오더 (M) EBELP: string; // 구매오더 품번 (M) WAERS?: string; // PCR 통화 PCR_NETPR?: string; // PCR 단가 PEINH?: string; // Price Unit, 수량에 대한 PER 당 단가 PCR_NETWR?: string; // PCR 금액 PCR_STATUS: string; // PCR 상태 (M) REJ_CD?: string; // Reject 코드 REJ_RSN?: string; // Reject 사유 CONFIRM_CD?: string; // Confirm 코드 CONFIRM_RSN?: string; // Confirm 사유 }>; } // PCR 확인 응답 데이터 타입 (참고용) export interface PCRConfirmResponse { ZMM_RT?: Array<{ PCR_REQ: string; // PCR 요청번호 PCR_REQ_SEQ: string; // PCR 요청순번 EBELN: string; // 구매오더 EBELP: string; // 구매오더 품번 MSGTY?: string; // Message Type MSGTXT?: string; // Message Text }>; } // 보낼 때 ZMM_PCR 객체 안에 담아보내야 함 // SEQ,Table,Field,M/O,Type,Size,Description // 1,ZMM_PCR,PCR_REQ,M,CHAR,10,PCR 요청번호 // 2,ZMM_PCR,PCR_REQ_SEQ,M,NUMC,5,PCR 요청순번 // 3,ZMM_PCR,PCR_DEC_DATE,M,DATS,8,PCR 결정일 // 4,ZMM_PCR,EBELN,M,CHAR,10,구매오더(PO번호) // 5,ZMM_PCR,EBELP,M,NUMC,5,구매오더 품번 // 6,ZMM_PCR,WAERS,,CUKY,5,PCR 통화 // 7,ZMM_PCR,PCR_NETPR,,CURR,"13,2",PCR 단가 // 8,ZMM_PCR,PEINH,,DEC,5,"Price Unit, 수량에 대한 PER 당 단가" // 9,ZMM_PCR,PCR_NETWR,,CURR,"13,2",PCR 금액 // 10,ZMM_PCR,PCR_STATUS,M,CHAR,1,PCR 상태 // 11,ZMM_PCR,REJ_CD,,CHAR,10,Reject 코드 // 12,ZMM_PCR,REJ_RSN,,CHAR,50,Reject 사유 // 13,ZMM_PCR,CONFIRM_CD,,CHAR,10,Confirm 코드 // 14,ZMM_PCR,CONFIRM_RSN,,CHAR,50,Confirm 사유 // 15,ZMM_RT,PCR_REQ,M,CHAR,10,PCR 요청번호 REPLY(NOT TO SEND) // 16,ZMM_RT,PCR_REQ_SEQ,M,NUMC,5,PCR 요청순번 REPLY(NOT TO SEND) // 17,ZMM_RT,EBELN,M,CHAR,10,구매오더 REPLY(NOT TO SEND) // 18,ZMM_RT,EBELP,M,NUMC,5,구매오더 품번 REPLY(NOT TO SEND) // 19,ZMM_RT,MSGTY,,CHAR,1,Message Type REPLY(NOT TO SEND) // 20,ZMM_RT,MSGTXT,,CHAR,100,Message Text REPLY(NOT TO SEND) // SOAP Body Content 생성 함수 function createPCRConfirmSoapBodyContent(pcrData: PCRConfirmRequest): Record { return { 'p1:MT_P2MM3019_S': { // WSDL에서 사용하는 p1 접두사 적용 'ZMM_PCR': pcrData.ZMM_PCR } }; } // PCR 데이터 검증 함수 function validatePCRConfirmData(pcrData: PCRConfirmRequest): { isValid: boolean; errors: string[] } { const errors: string[] = []; // ZMM_PCR 배열 검증 if (!pcrData.ZMM_PCR || !Array.isArray(pcrData.ZMM_PCR) || pcrData.ZMM_PCR.length === 0) { errors.push('ZMM_PCR은 필수이며 최소 1개 이상의 PCR 데이터가 있어야 합니다.'); } else { pcrData.ZMM_PCR.forEach((item, index) => { // 필수 필드 검증 if (!item.PCR_REQ || typeof item.PCR_REQ !== 'string' || item.PCR_REQ.trim() === '') { errors.push(`ZMM_PCR[${index}].PCR_REQ은 필수입니다.`); } else if (item.PCR_REQ.length > 10) { errors.push(`ZMM_PCR[${index}].PCR_REQ은 10자를 초과할 수 없습니다.`); } if (!item.PCR_REQ_SEQ || typeof item.PCR_REQ_SEQ !== 'string' || item.PCR_REQ_SEQ.trim() === '') { errors.push(`ZMM_PCR[${index}].PCR_REQ_SEQ는 필수입니다.`); } else if (item.PCR_REQ_SEQ.length > 5) { errors.push(`ZMM_PCR[${index}].PCR_REQ_SEQ는 5자를 초과할 수 없습니다.`); } if (!item.PCR_DEC_DATE || typeof item.PCR_DEC_DATE !== 'string' || item.PCR_DEC_DATE.trim() === '') { errors.push(`ZMM_PCR[${index}].PCR_DEC_DATE는 필수입니다.`); } else if (!/^\d{8}$/.test(item.PCR_DEC_DATE)) { errors.push(`ZMM_PCR[${index}].PCR_DEC_DATE는 YYYYMMDD 형식이어야 합니다.`); } if (!item.EBELN || typeof item.EBELN !== 'string' || item.EBELN.trim() === '') { errors.push(`ZMM_PCR[${index}].EBELN은 필수입니다.`); } else if (item.EBELN.length > 10) { errors.push(`ZMM_PCR[${index}].EBELN은 10자를 초과할 수 없습니다.`); } if (!item.EBELP || typeof item.EBELP !== 'string' || item.EBELP.trim() === '') { errors.push(`ZMM_PCR[${index}].EBELP는 필수입니다.`); } else if (item.EBELP.length > 5) { errors.push(`ZMM_PCR[${index}].EBELP는 5자를 초과할 수 없습니다.`); } if (!item.PCR_STATUS || typeof item.PCR_STATUS !== 'string' || item.PCR_STATUS.trim() === '') { errors.push(`ZMM_PCR[${index}].PCR_STATUS는 필수입니다.`); } else if (item.PCR_STATUS.length > 1) { errors.push(`ZMM_PCR[${index}].PCR_STATUS는 1자를 초과할 수 없습니다.`); } // 선택 필드 길이 검증 if (item.WAERS && item.WAERS.length > 5) { errors.push(`ZMM_PCR[${index}].WAERS는 5자를 초과할 수 없습니다.`); } if (item.REJ_CD && item.REJ_CD.length > 10) { errors.push(`ZMM_PCR[${index}].REJ_CD는 10자를 초과할 수 없습니다.`); } if (item.REJ_RSN && item.REJ_RSN.length > 50) { errors.push(`ZMM_PCR[${index}].REJ_RSN은 50자를 초과할 수 없습니다.`); } if (item.CONFIRM_CD && item.CONFIRM_CD.length > 10) { errors.push(`ZMM_PCR[${index}].CONFIRM_CD는 10자를 초과할 수 없습니다.`); } if (item.CONFIRM_RSN && item.CONFIRM_RSN.length > 50) { errors.push(`ZMM_PCR[${index}].CONFIRM_RSN은 50자를 초과할 수 없습니다.`); } }); } return { isValid: errors.length === 0, errors }; } // ECC로 PCR 확인 SOAP XML 전송하는 함수 async function sendPCRConfirmToECC(pcrData: PCRConfirmRequest): Promise { try { // 데이터 검증 const validation = validatePCRConfirmData(pcrData); if (!validation.isValid) { return { success: false, message: `데이터 검증 실패: ${validation.errors.join(', ')}` }; } // SOAP Body Content 생성 const soapBodyContent = createPCRConfirmSoapBodyContent(pcrData); // SOAP 전송 설정 const config: SoapSendConfig = { endpoint: ECC_PCR_CONFIRM_ENDPOINT, envelope: soapBodyContent, soapAction: 'http://sap.com/xi/WebService/soap1.1', timeout: 30000, // PCR 확인은 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_PCR_CONFIRM' }; const pcrReqs = pcrData.ZMM_PCR.map(item => `${item.PCR_REQ}-${item.PCR_REQ_SEQ}`).join(', '); console.log(`📤 PCR 확인 요청 전송 시작 - PCR Requests: ${pcrReqs}`); console.log(`🔍 확인 대상 PCR ${pcrData.ZMM_PCR.length}개`); // SOAP XML 전송 const result = await sendSoapXml(config, logInfo); if (result.success) { console.log(`✅ PCR 확인 요청 전송 성공 - PCR Requests: ${pcrReqs}`); } else { console.error(`❌ PCR 확인 요청 전송 실패 - PCR Requests: ${pcrReqs}, 오류: ${result.message}`); } return result; } catch (error) { console.error('❌ PCR 확인 전송 중 오류 발생:', error); return { success: false, message: error instanceof Error ? error.message : 'Unknown error' }; } } // ======================================== // 메인 PCR 확인 서버 액션 함수들 // ======================================== // 단일 PCR 확인 요청 처리 export async function confirmPCR(pcrItem: { PCR_REQ: string; PCR_REQ_SEQ: string; PCR_DEC_DATE: string; EBELN: string; EBELP: string; PCR_STATUS: string; WAERS?: string; PCR_NETPR?: string; PEINH?: string; PCR_NETWR?: string; REJ_CD?: string; REJ_RSN?: string; CONFIRM_CD?: string; CONFIRM_RSN?: string; }): Promise<{ success: boolean; message: string; responseData?: string; statusCode?: number; headers?: Record; endpoint?: string; requestXml?: string; pcrRequest?: string; }> { try { console.log(`🚀 PCR 확인 요청 시작 - PCR: ${pcrItem.PCR_REQ}-${pcrItem.PCR_REQ_SEQ}`); const pcrData: PCRConfirmRequest = { ZMM_PCR: [pcrItem] }; const result = await sendPCRConfirmToECC(pcrData); return { success: result.success, message: result.success ? 'PCR 확인 요청이 성공적으로 전송되었습니다.' : result.message, responseData: result.responseText, statusCode: result.statusCode, headers: result.headers, endpoint: result.endpoint, requestXml: result.requestXml, pcrRequest: `${pcrItem.PCR_REQ}-${pcrItem.PCR_REQ_SEQ}` }; } catch (error) { console.error('❌ PCR 확인 요청 처리 실패:', error); return { success: false, message: error instanceof Error ? error.message : 'Unknown error' }; } } // 여러 PCR 배치 확인 요청 처리 export async function confirmMultiplePCRs(pcrItems: Array<{ PCR_REQ: string; PCR_REQ_SEQ: string; PCR_DEC_DATE: string; EBELN: string; EBELP: string; PCR_STATUS: string; WAERS?: string; PCR_NETPR?: string; PEINH?: string; PCR_NETWR?: string; REJ_CD?: string; REJ_RSN?: string; CONFIRM_CD?: string; CONFIRM_RSN?: string; }>): Promise<{ success: boolean; message: string; results?: Array<{ pcrRequest: string; success: boolean; error?: string }>; }> { try { console.log(`🚀 배치 PCR 확인 요청 시작: ${pcrItems.length}개`); // 모든 PCR을 하나의 요청으로 처리 const pcrData: PCRConfirmRequest = { ZMM_PCR: pcrItems }; const result = await sendPCRConfirmToECC(pcrData); // 결과 정리 const results = pcrItems.map(item => ({ pcrRequest: `${item.PCR_REQ}-${item.PCR_REQ_SEQ}`, success: result.success, error: result.success ? undefined : result.message })); const successCount = result.success ? pcrItems.length : 0; const failCount = pcrItems.length - successCount; console.log(`🎉 배치 PCR 확인 완료: 성공 ${successCount}개, 실패 ${failCount}개`); return { success: result.success, message: result.success ? `배치 PCR 확인 성공: ${successCount}개` : `배치 PCR 확인 실패: ${result.message}`, results }; } catch (error) { console.error('❌ 배치 PCR 확인 중 전체 오류 발생:', error); return { success: false, message: error instanceof Error ? error.message : 'Unknown error' }; } } // 개별 처리 방식의 배치 PCR 확인 (각각 따로 전송) export async function confirmMultiplePCRsIndividually(pcrItems: Array<{ PCR_REQ: string; PCR_REQ_SEQ: string; PCR_DEC_DATE: string; EBELN: string; EBELP: string; PCR_STATUS: string; WAERS?: string; PCR_NETPR?: string; PEINH?: string; PCR_NETWR?: string; REJ_CD?: string; REJ_RSN?: string; CONFIRM_CD?: string; CONFIRM_RSN?: string; }>): Promise<{ success: boolean; message: string; results?: Array<{ pcrRequest: string; success: boolean; error?: string }>; }> { try { console.log(`🚀 개별 PCR 확인 요청 시작: ${pcrItems.length}개`); const results: Array<{ pcrRequest: string; success: boolean; error?: string }> = []; for (const pcrItem of pcrItems) { try { const pcrRequest = `${pcrItem.PCR_REQ}-${pcrItem.PCR_REQ_SEQ}`; console.log(`📤 PCR 확인 처리 중: ${pcrRequest}`); const pcrData: PCRConfirmRequest = { ZMM_PCR: [pcrItem] }; const result = await sendPCRConfirmToECC(pcrData); if (result.success) { console.log(`✅ PCR 확인 성공: ${pcrRequest}`); results.push({ pcrRequest, success: true }); } else { console.error(`❌ PCR 확인 실패: ${pcrRequest}, 오류: ${result.message}`); results.push({ pcrRequest, success: false, error: result.message }); } // 개별 처리간 지연 (시스템 부하 방지) if (pcrItems.length > 1) { await new Promise(resolve => setTimeout(resolve, 500)); } } catch (error) { const pcrRequest = `${pcrItem.PCR_REQ}-${pcrItem.PCR_REQ_SEQ}`; console.error(`❌ PCR 확인 처리 실패: ${pcrRequest}`, error); results.push({ pcrRequest, 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(`🎉 개별 PCR 확인 완료: 성공 ${successCount}개, 실패 ${failCount}개`); return { success: failCount === 0, message: `개별 PCR 확인 완료: 성공 ${successCount}개, 실패 ${failCount}개`, results }; } catch (error) { console.error('❌ 개별 PCR 확인 중 전체 오류 발생:', error); return { success: false, message: error instanceof Error ? error.message : 'Unknown error' }; } } // 테스트용 PCR 확인 함수 (샘플 데이터 포함) export async function confirmTestPCR(): Promise<{ success: boolean; message: string; responseData?: string; testData?: PCRConfirmRequest; }> { try { console.log('🧪 테스트용 PCR 확인 시작'); // 테스트용 샘플 데이터 생성 const testPCRData: PCRConfirmRequest = { ZMM_PCR: [{ PCR_REQ: 'TEST_PCR01', PCR_REQ_SEQ: '00001', PCR_DEC_DATE: '20241201', EBELN: 'TEST_PO01', EBELP: '00010', PCR_STATUS: 'A', WAERS: 'KRW', PCR_NETPR: '1000.00', PEINH: '1', PCR_NETWR: '1000.00', CONFIRM_CD: 'CONF', CONFIRM_RSN: '테스트 확인' }] }; const result = await sendPCRConfirmToECC(testPCRData); return { success: result.success, message: result.success ? '테스트 PCR 확인이 성공적으로 전송되었습니다.' : result.message, responseData: result.responseText, testData: testPCRData }; } catch (error) { console.error('❌ 테스트 PCR 확인 실패:', error); return { success: false, message: error instanceof Error ? error.message : 'Unknown error' }; } } // 사용하지 않는 유틸리티 함수들 삭제 (linter 오류 해결)