summaryrefslogtreecommitdiff
path: root/lib/pos/get-pos.ts
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-09-26 14:13:20 +0900
committerjoonhoekim <26rote@gmail.com>2025-09-26 14:13:20 +0900
commitf8fc02e175f93466cd7693eb6e549c45362e785b (patch)
tree1037ec1f9225b0a0142defd6a27c68c3e6a47009 /lib/pos/get-pos.ts
parent11bc8239ad474a8f31c1c73de51f7d0f101594df (diff)
(김준회) POS 및 구매 피드백 처리
- 요구사항 28.(0.1) 24번 행 (prItem번호 별도 표기) - pos nfs 경로에서 가져오도록 수정개발
Diffstat (limited to 'lib/pos/get-pos.ts')
-rw-r--r--lib/pos/get-pos.ts238
1 files changed, 235 insertions, 3 deletions
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<AccessNfsFileResult> {
+ 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',
+ };
+ }
+}