'use server'; import { oracleKnex } from '@/lib/oracle-db/db'; import type { PosFileInfo, GetDcmtmIdParams, GetDcmtmIdResult } from './types'; import { debugLog, debugError, debugSuccess, debugProcess } from '@/lib/debug-utils'; /** * 자재코드로 POS 파일의 DCMTM_ID를 조회하는 서버 액션 * * @param params - 자재코드를 포함한 조회 파라미터 * @returns POS 파일 정보 목록 (여러 파일이 있을 수 있음) */ export async function getDcmtmIdByMaterialCode( params: GetDcmtmIdParams ): Promise { try { const { materialCode } = params; debugLog(`🔍 DCMTM_ID 조회 시작`, { materialCode }); if (!materialCode) { debugError(`❌ 자재코드가 제공되지 않음`); return { success: false, error: '자재코드가 제공되지 않았습니다.', }; } // Oracle 쿼리 실행 const query = ` SELECT Y.PROJ_NO, Y.POS_NO, Y.POS_REV_NO, Y.FILE_SER, Y.FILE_NM, Y.DCMTM_ID FROM PLDTB_POS_ITEM X, PLDTB_POS_ITEM_FILE Y, PLMTB_EMLS Z WHERE X.PROJ_NO = Y.PROJ_NO AND X.POS_NO = Y.POS_NO AND X.POS_REV_NO = Y.POS_REV_NO AND X.POS_NO = Z.DOC_NO AND NVL(X.APP_ID, ' ') <> ' ' AND NVL(Z.PUR_REQ_NO, ' ') <> ' ' AND Z.MAT_NO = ? `; debugProcess(`🗄️ Oracle 쿼리 실행`, { materialCode, query: query.trim() }); const results = await oracleKnex.raw(query, [materialCode]); debugLog(`🗄️ Oracle 쿼리 결과`, { materialCode, resultType: typeof results, hasRows: results && results[0] ? results[0].length : 0 }); // Oracle 결과 처리 (oracledb 드라이버의 결과 구조에 따라) const rows = results[0] || results.rows || results; debugLog(`📊 Oracle 결과 구조 분석`, { materialCode, resultStructure: { hasZeroIndex: !!results[0], hasRowsProperty: !!results.rows, rowsType: typeof rows, isArray: Array.isArray(rows), rowCount: Array.isArray(rows) ? rows.length : 0 }, firstRow: Array.isArray(rows) && rows.length > 0 ? rows[0] : null }); if (!Array.isArray(rows) || rows.length === 0) { debugLog(`⚠️ POS 파일을 찾을 수 없음 (자재코드: ${materialCode})`); return { success: false, error: '해당 자재코드에 대한 POS 파일을 찾을 수 없습니다.', }; } // 결과를 PosFileInfo 형태로 변환 debugProcess(`🔄 Oracle 결과를 PosFileInfo로 변환 중...`); const files: PosFileInfo[] = rows.map((row: Record, index: number) => { const fileInfo = { projNo: (row.PROJ_NO || row[0]) as string, posNo: (row.POS_NO || row[1]) as string, posRevNo: (row.POS_REV_NO || row[2]) as string, fileSer: (row.FILE_SER || row[3]) as string, fileName: (row.FILE_NM || row[4]) as string, dcmtmId: (row.DCMTM_ID || row[5]) as string, }; debugLog(`📄 파일 ${index + 1} 변환 결과`, { materialCode, index, original: row, converted: fileInfo }); return fileInfo; }); debugSuccess(`✅ DCMTM_ID 조회 성공 (자재코드: ${materialCode}, 파일 수: ${files.length})`); return { success: true, files, }; } catch (error) { debugError('❌ DCMTM_ID 조회 실패', { materialCode: params.materialCode, error: error instanceof Error ? error.message : '알 수 없는 오류', stack: error instanceof Error ? error.stack : undefined }); return { success: false, error: error instanceof Error ? error.message : '데이터베이스 조회 중 오류가 발생했습니다.', }; } } /** * 단일 DCMTM_ID만 필요한 경우를 위한 헬퍼 함수 * 여러 파일이 있을 경우 첫 번째 파일의 DCMTM_ID를 반환 */ export async function getFirstDcmtmId( params: GetDcmtmIdParams ): Promise<{ success: boolean; dcmtmId?: string; fileName?: string; error?: string; }> { const result = await getDcmtmIdByMaterialCode(params); if (!result.success || !result.files || result.files.length === 0) { return { success: false, error: result.error, }; } const firstFile = result.files[0]; return { success: true, dcmtmId: firstFile.dcmtmId, fileName: firstFile.fileName, }; }