'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, isArray: Array.isArray(results), resultKeys: results && typeof results === 'object' ? Object.keys(results) : null, resultLength: Array.isArray(results) ? results.length : null, resultValue: results }); // Oracle 결과 처리 (oracledb 드라이버의 결과 구조에 따라) // Knex.js oracledb 클라이언트의 실제 결과 구조: // - 데이터 행들의 배열: [{PROJ_NO: '...', ...}, {PROJ_NO: '...', ...}] // - 또는 [rows, metaData] 형태 // - 또는 { rows: [...], metaData: [...] } 형태 let rows; if (Array.isArray(results)) { debugLog(`🔍 배열 형태 결과 처리`, { materialCode, arrayLength: results.length, firstElementType: typeof results[0], firstElementIsArray: Array.isArray(results[0]), firstElementKeys: results[0] && typeof results[0] === 'object' ? Object.keys(results[0]) : null }); // results가 데이터 행들의 배열인지 확인 if (results.length > 0 && typeof results[0] === 'object' && !Array.isArray(results[0]) && results[0].PROJ_NO) { // results = [{PROJ_NO: '...', POS_NO: '...', ...}, ...] - 바로 데이터 행들 rows = results; } else { // [rows, metaData] 형태 - 첫 번째 요소가 실제 데이터 rows = results[0] || []; } } else if (results && typeof results === 'object' && results.rows) { debugLog(`🔍 객체 형태 결과 처리`, { materialCode, hasRows: !!results.rows, rowsType: typeof results.rows, rowsIsArray: Array.isArray(results.rows), rowsLength: Array.isArray(results.rows) ? results.rows.length : null }); // { rows: [...], metaData: [...] } 형태 rows = results.rows || []; } else { debugLog(`🔍 기타 형태 결과 처리`, { materialCode, resultValue: results }); // 직접 배열인 경우 rows = results || []; } debugLog(`📊 최종 rows 추출 결과`, { materialCode, rowsType: typeof rows, isRowsArray: Array.isArray(rows), rowCount: Array.isArray(rows) ? rows.length : 0, firstRow: Array.isArray(rows) && rows.length > 0 ? rows[0] : null, firstRowType: Array.isArray(rows) && rows.length > 0 ? typeof 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, }; }