From f8fc02e175f93466cd7693eb6e549c45362e785b Mon Sep 17 00:00:00 2001 From: joonhoekim <26rote@gmail.com> Date: Fri, 26 Sep 2025 14:13:20 +0900 Subject: (김준회) POS 및 구매 피드백 처리 - 요구사항 28.(0.1) 24번 행 (prItem번호 별도 표기) - pos nfs 경로에서 가져오도록 수정개발 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/pos/get-pos.ts | 238 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 235 insertions(+), 3 deletions(-) (limited to 'lib/pos/get-pos.ts') diff --git a/lib/pos/get-pos.ts b/lib/pos/get-pos.ts index c24c1dab..a77de247 100644 --- a/lib/pos/get-pos.ts +++ b/lib/pos/get-pos.ts @@ -2,14 +2,23 @@ import { XMLBuilder, XMLParser } from 'fast-xml-parser'; import { withSoapLogging } from '@/lib/soap/utils'; -import type { GetEncryptDocumentumFileParams } from './types'; -import { POS_SOAP_ENDPOINT } from './types'; +import fs from 'fs/promises'; +import path from 'path'; +import type { GetEncryptDocumentumFileParams, AccessNfsFileParams, AccessNfsFileResult } from './types'; +import { POS_SOAP_ENDPOINT, DOCUMENTUM_NFS_PATH } from './types'; import { debugLog, debugError, debugSuccess, debugProcess } from '@/lib/debug-utils'; /** * 문서 암호화 파일을 서버에 다운로드하고 경로를 반환하는 POS(Documentum) SOAP 액션 * 반환값은 서버 내 파일 다운로드 경로입니다. (예: "asd_as_2509131735233768_OP02\asd_as_2509131735233768_OP02.tif") - * 실제 파일은 \\60.100.99.123\ECM_NAS_PRM\Download\ 경로에 저장됩니다. + * + * 실제 파일은 DOCUMENTUM_NFS 환경변수로 지정된 NFS 마운트 경로에서 접근할 수 있습니다. + * - 환경변수: DOCUMENTUM_NFS (기본값: "/mnt/nfs-documentum/") + * - 실제 파일 경로: ${DOCUMENTUM_NFS}/Download/${반환된_상대_경로} + * + * 예시: + * - SOAP 반환값: "asd_as_2509131735233768_OP02\asd_as_2509131735233768_OP02.tif" + * - 실제 NFS 파일 경로: "/mnt/nfs-documentum/Download/asd_as_2509131735233768_OP02/asd_as_2509131735233768_OP02.tif" */ export async function getEncryptDocumentumFile( params: GetEncryptDocumentumFileParams @@ -173,3 +182,226 @@ export async function getEncryptDocumentumFile( }; } } + +/** + * NFS 마운트를 통해 POS 파일에 직접 접근하는 함수 + * POS API에서 반환된 상대 경로를 사용하여 NFS 마운트된 경로에서 파일을 읽습니다 + */ +export async function accessNfsFile( + params: AccessNfsFileParams +): Promise { + try { + const { relativePath } = params; + debugLog(`📁 NFS를 통한 POS 파일 접근 시작`, { + relativePath, + nfsBasePath: DOCUMENTUM_NFS_PATH + }); + + if (!relativePath) { + debugError(`❌ 파일 경로가 제공되지 않음`); + return { + success: false, + error: '파일 경로가 제공되지 않았습니다.', + }; + } + + // Windows 경로 구분자를 Unix 스타일로 정규화 + const normalizedRelativePath = relativePath.replace(/\\/g, '/'); + debugLog(`📁 경로 정규화`, { + original: relativePath, + normalized: normalizedRelativePath + }); + + // NFS 마운트 경로와 상대 경로를 결합 + // Download 폴더를 추가하여 전체 경로 구성 + const fullPath = path.posix.join(DOCUMENTUM_NFS_PATH, 'Download', normalizedRelativePath); + debugLog(`📍 NFS 전체 파일 경로 구성`, { fullPath }); + + // 경로 보안 검증 (디렉토리 탈출 방지) + const resolvedPath = path.resolve(fullPath); + const resolvedBasePath = path.resolve(DOCUMENTUM_NFS_PATH); + debugLog(`🔒 경로 보안 검증`, { + resolvedPath, + resolvedBasePath, + isValid: resolvedPath.startsWith(resolvedBasePath) + }); + + if (!resolvedPath.startsWith(resolvedBasePath)) { + debugError(`❌ 디렉토리 탈출 시도 감지`, { resolvedPath, resolvedBasePath }); + return { + success: false, + error: '잘못된 파일 경로입니다.', + }; + } + + // 파일 존재 여부 확인 + debugProcess(`🔍 NFS 파일 존재 여부 확인 중...`); + try { + await fs.access(resolvedPath); + debugSuccess(`✅ NFS 파일 접근 가능 확인`); + } catch (accessError) { + debugError(`❌ NFS 파일 접근 불가`, { + path: resolvedPath, + error: accessError instanceof Error ? accessError.message : 'Unknown error' + }); + return { + success: false, + error: `파일을 찾을 수 없습니다: ${resolvedPath}`, + }; + } + + // 파일 정보 확인 + debugProcess(`📊 NFS 파일 정보 확인 중...`); + const stats = await fs.stat(resolvedPath); + debugLog(`📊 NFS 파일 정보`, { + size: stats.size, + isFile: stats.isFile(), + modified: stats.mtime + }); + + if (!stats.isFile()) { + debugError(`❌ 대상이 파일이 아님`, { path: resolvedPath }); + return { + success: false, + error: '대상이 파일이 아닙니다.', + }; + } + + // 파일 크기 제한 (10000MB) + const maxSize = 10000 * 1024 * 1024; // 10000MB + if (stats.size > maxSize) { + debugError(`❌ 파일 크기 초과`, { + fileSize: stats.size, + maxSize, + path: resolvedPath + }); + return { + success: false, + error: `파일 크기가 너무 큽니다 (최대 10000MB). 현재 크기: ${Math.round(stats.size / 1024 / 1024)}MB`, + }; + } + + // 파일 읽기 + debugProcess(`📖 NFS 파일 읽기 중... (크기: ${stats.size} bytes)`); + const fileBuffer = await fs.readFile(resolvedPath); + debugSuccess(`✅ NFS 파일 읽기 완료 (${fileBuffer.length} bytes)`); + + // 파일명과 MIME 타입 추출 + const fileName = path.basename(resolvedPath); + const fileExtension = path.extname(fileName).toLowerCase(); + + // 확장자별 MIME 타입 설정 + let mimeType = 'application/octet-stream'; // 기본값 + switch (fileExtension) { + case '.pdf': + mimeType = 'application/pdf'; + break; + case '.tif': + case '.tiff': + mimeType = 'image/tiff'; + break; + case '.png': + mimeType = 'image/png'; + break; + case '.jpg': + case '.jpeg': + mimeType = 'image/jpeg'; + break; + case '.doc': + mimeType = 'application/msword'; + break; + case '.docx': + mimeType = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; + break; + case '.xls': + mimeType = 'application/vnd.ms-excel'; + break; + case '.xlsx': + mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; + break; + case '.dwg': + mimeType = 'application/acad'; + break; + case '.zip': + mimeType = 'application/zip'; + break; + } + + debugSuccess(`✅ NFS를 통한 POS 파일 접근 성공`, { + fileName, + mimeType, + fileSize: fileBuffer.length, + fullPath: resolvedPath + }); + + return { + success: true, + fileName, + fileBuffer, + mimeType, + fullPath: resolvedPath, + }; + + } catch (error) { + debugError('❌ NFS를 통한 POS 파일 접근 실패', { + relativePath: params.relativePath, + error: error instanceof Error ? error.message : 'Unknown error', + stack: error instanceof Error ? error.stack : undefined + }); + return { + success: false, + error: error instanceof Error ? error.message : 'Unknown error', + }; + } +} + +/** + * POS 파일 접근 방법을 테스트하는 함수 + * 개발/테스트 환경에서 NFS 마운트가 제대로 작동하는지 확인하는 용도 + */ +export async function testNfsAccess(): Promise<{ + success: boolean; + nfsPath: string; + accessible: boolean; + error?: string; +}> { + try { + debugLog(`🧪 NFS 접근 테스트 시작`, { nfsPath: DOCUMENTUM_NFS_PATH }); + + // NFS 마운트 기본 경로 접근 테스트 + const testPath = path.posix.join(DOCUMENTUM_NFS_PATH, 'Download'); + debugLog(`🔍 테스트 경로 확인`, { testPath }); + + try { + await fs.access(testPath); + debugSuccess(`✅ NFS 마운트 경로 접근 성공`, { testPath }); + return { + success: true, + nfsPath: DOCUMENTUM_NFS_PATH, + accessible: true, + }; + } catch (accessError) { + debugError(`❌ NFS 마운트 경로 접근 실패`, { + testPath, + error: accessError instanceof Error ? accessError.message : 'Unknown error' + }); + return { + success: false, + nfsPath: DOCUMENTUM_NFS_PATH, + accessible: false, + error: `NFS 마운트 경로에 접근할 수 없습니다: ${testPath}`, + }; + } + } catch (error) { + debugError('❌ NFS 접근 테스트 실패', { + error: error instanceof Error ? error.message : 'Unknown error', + stack: error instanceof Error ? error.stack : undefined + }); + return { + success: false, + nfsPath: DOCUMENTUM_NFS_PATH, + accessible: false, + error: error instanceof Error ? error.message : 'Unknown error', + }; + } +} -- cgit v1.2.3