summaryrefslogtreecommitdiff
path: root/lib/soap
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-10-30 10:35:26 +0900
committerjoonhoekim <26rote@gmail.com>2025-10-30 10:35:26 +0900
commit284f9f40d9494168f3e68eedd9af067c38362eea (patch)
treeac26b3e9fab46b996c16bfa7a7add8f26ddb5042 /lib/soap
parent88f13ab89d2250e52c3375b077328a933a5762ec (diff)
(김준회) refactor: POS: 온디맨드로 다운로드받도록 변경, 매핑로직에선 pos 관련 로직 제거
Diffstat (limited to 'lib/soap')
-rw-r--r--lib/soap/ecc/mapper/bidding-and-pr-mapper.ts180
-rw-r--r--lib/soap/ecc/mapper/rfq-and-pr-mapper.ts42
2 files changed, 25 insertions, 197 deletions
diff --git a/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts b/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts
index 5f3c7e78..af4cecdc 100644
--- a/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts
+++ b/lib/soap/ecc/mapper/bidding-and-pr-mapper.ts
@@ -1,7 +1,13 @@
/**
- * pr 발행 후, pr을 묶어서 rfq, bidding 을 sap ecc에서 생성한 경우
- * ZBSART = AB인 경우, 즉 bidding인 경우 해당 케이스를 soap으로 수신한 뒤 이 함수에서 헤더는 biddings 테이블에, 아이템은 prItemsForBidding 테이블에 매핑
- * ZBSART = AN인 경우, 즉 rfq인 경우 해당 케이스를 soap으로 수신한 뒤 rfq-and-pr-mapper.ts 파일에서 매핑
+ * SAP ECC에서 PR을 묶어 Bidding을 생성한 경우 SOAP으로 수신하여 처리하는 매퍼
+ *
+ * ZBSART = AB (Bidding)인 경우 이 파일에서 처리하여 biddings, prItemsForBidding 테이블에 매핑합니다.
+ * ZBSART = AN (RFQ)인 경우는 rfq-and-pr-mapper.ts 파일에서 매핑합니다.
+ *
+ * 주요 변경사항:
+ * - POS 파일 자동 다운로드 로직 제거됨 (온디맨드 방식으로 변경)
+ * - syncBiddingPosFiles 함수 제거됨
+ * - 사용자가 필요할 때만 POS 파일을 다운로드하도록 개선
*/
import { debugLog, debugSuccess, debugError } from '@/lib/debug-utils';
@@ -23,11 +29,8 @@ import {
parseSAPDateTime,
parseSAPDateToString,
} from './common-mapper-utils';
-import {
- getDcmtmIdByMaterialCode,
- getEncryptDocumentumFile,
- downloadPosFile
-} from '@/lib/pos';
+// Note: POS 파일은 온디맨드 방식으로 다운로드됩니다.
+// 자동 동기화 관련 import는 제거되었습니다.
// ECC 데이터 타입 정의
export type ECCBidHeader = typeof PR_INFORMATION_T_BID_HEADER.$inferInsert;
@@ -37,116 +40,8 @@ export type ECCBidItem = typeof PR_INFORMATION_T_BID_ITEM.$inferInsert;
export type BiddingData = typeof biddings.$inferInsert;
export type PrItemForBiddingData = typeof prItemsForBidding.$inferInsert;
-/**
- * Bidding용 POS 파일 동기화 함수
- * 자재코드 기준으로 POS 파일을 찾아서 prDocuments 테이블에 저장
- */
-async function syncBiddingPosFiles(
- biddingId: number,
- materialCodes: string[],
- userId: string = '1'
-): Promise<{
- success: boolean;
- successCount: number;
- failedCount: number;
- errors: string[];
-}> {
- debugLog('Bidding POS 파일 동기화 시작', { biddingId, materialCodes });
-
- let successCount = 0;
- let failedCount = 0;
- const errors: string[] = [];
-
- // 중복 제거된 자재코드로 처리
- const uniqueMaterialCodes = [...new Set(materialCodes.filter(code => code && code.trim() !== ''))];
-
- for (const materialCode of uniqueMaterialCodes) {
- try {
- debugLog(`자재코드 ${materialCode} POS 파일 조회 시작`);
-
- // 1. 자재코드로 DCMTM_ID 조회
- const dcmtmResult = await getDcmtmIdByMaterialCode({ materialCode });
-
- if (!dcmtmResult.success || !dcmtmResult.files || dcmtmResult.files.length === 0) {
- debugLog(`자재코드 ${materialCode}: POS 파일 없음`);
- continue; // 에러로 카운트하지 않고 스킵
- }
-
- // 첫 번째 파일만 처리
- const posFile = dcmtmResult.files[0];
-
- // 2. POS API로 파일 경로 가져오기
- const posResult = await getEncryptDocumentumFile({
- objectID: posFile.dcmtmId
- });
-
- if (!posResult.success || !posResult.result) {
- errors.push(`${materialCode}: POS 파일 경로 조회 실패`);
- failedCount++;
- continue;
- }
-
- // 3. 파일 다운로드
- const downloadResult = await downloadPosFile({
- relativePath: posResult.result
- });
-
- if (!downloadResult.success || !downloadResult.fileBuffer) {
- errors.push(`${materialCode}: 파일 다운로드 실패`);
- failedCount++;
- continue;
- }
-
- // 4. 서버에 파일 저장 (uploads/bidding-pos 디렉토리)
- const path = await import('path');
- const fs = await import('fs/promises');
-
- const uploadDir = path.join(process.cwd(), 'uploads', 'bidding-pos');
- try {
- await fs.access(uploadDir);
- } catch {
- await fs.mkdir(uploadDir, { recursive: true });
- }
-
- const timestamp = Date.now();
- const sanitizedFileName = (downloadResult.fileName || `${materialCode}.pdf`).replace(/[^a-zA-Z0-9.-]/g, '_');
- const fileName = `${timestamp}_${sanitizedFileName}`;
- const filePath = path.join(uploadDir, fileName);
-
- await fs.writeFile(filePath, downloadResult.fileBuffer);
-
- // 5. prDocuments 테이블에 저장
- await db.insert(prDocuments).values({
- biddingId,
- documentName: `${materialCode} 설계문서`,
- fileName,
- originalFileName: posFile.fileName,
- fileSize: downloadResult.fileBuffer.length,
- mimeType: downloadResult.mimeType || 'application/pdf',
- filePath: `uploads/bidding-pos/${fileName}`,
- registeredBy: userId,
- description: `POS 시스템에서 자동 동기화됨 (DCMTM_ID: ${posFile.dcmtmId}, 자재코드: ${materialCode})`,
- version: 'Rev.0'
- });
-
- successCount++;
- debugSuccess(`자재코드 ${materialCode} POS 파일 동기화 완료`);
-
- } catch (error) {
- const errorMessage = error instanceof Error ? error.message : '알 수 없는 오류';
- errors.push(`${materialCode}: ${errorMessage}`);
- failedCount++;
- debugError(`자재코드 ${materialCode} POS 파일 동기화 실패`, error);
- }
- }
-
- return {
- success: successCount > 0,
- successCount,
- failedCount,
- errors
- };
-}
+// Note: syncBiddingPosFiles 함수는 제거되었습니다.
+// POS 파일은 온디맨드 방식으로 사용자가 필요할 때 다운로드됩니다.
/**
@@ -501,53 +396,8 @@ export async function mapAndSaveECCBiddingData(
processedCount: result.processedCount,
});
- // 7) 각 Bidding에 대해 POS 파일 자동 동기화 (비동기로 실행하여 메인 플로우 블록하지 않음)
- debugLog('Bidding POS 파일 자동 동기화 시작', { biddingCount: result.insertedBiddings.length });
-
- // 비동기로 각 Bidding의 POS 파일 동기화 실행 (결과를 기다리지 않음)
- result.insertedBiddings.forEach(async (bidding) => {
- try {
- // 해당 Bidding과 관련된 모든 자재코드 추출
- const relatedMaterialCodes = result.allEccItems
- .filter(item => item.ANFNR === bidding.ANFNR)
- .map(item => item.MATNR)
- .filter(Boolean) as string[];
-
- if (relatedMaterialCodes.length === 0) {
- debugLog(`Bidding ${bidding.biddingNumber}: 자재코드 없음`);
- return;
- }
-
- debugLog(`Bidding ${bidding.biddingNumber} POS 파일 동기화 시작`, {
- biddingId: bidding.id,
- materialCodes: relatedMaterialCodes
- });
-
- const syncResult = await syncBiddingPosFiles(
- bidding.id,
- relatedMaterialCodes,
- bidding.createdBy || '1'
- );
-
- if (syncResult.success) {
- debugSuccess(`Bidding ${bidding.biddingNumber} POS 파일 동기화 완료`, {
- biddingId: bidding.id,
- successCount: syncResult.successCount,
- failedCount: syncResult.failedCount
- });
- } else {
- debugError(`Bidding ${bidding.biddingNumber} POS 파일 동기화 실패`, {
- biddingId: bidding.id,
- errors: syncResult.errors
- });
- }
- } catch (error) {
- debugError(`Bidding ${bidding.biddingNumber} POS 파일 동기화 중 예외 발생`, {
- biddingId: bidding.id,
- error: error instanceof Error ? error.message : '알 수 없는 오류'
- });
- }
- });
+ // Note: POS 파일은 온디맨드 방식으로 사용자가 필요할 때 다운로드됩니다.
+ // 자동 다운로드는 더 이상 수행하지 않습니다.
return {
success: true,
diff --git a/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts b/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
index f2683213..cc241aa6 100644
--- a/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
+++ b/lib/soap/ecc/mapper/rfq-and-pr-mapper.ts
@@ -1,7 +1,12 @@
/**
- * pr 발행 후, pr을 묶어서 rfq, bidding 을 sap ecc에서 생성한 경우
- * ZBSART = AN인 경우, 즉 rfq인 경우 해당 케이스를 soap으로 수신한 뒤 이 함수에서 rqfLast, rfqPrItems 테이블에 매핑
- * bidding인 경우는 bidding-and-pr-mapper.ts 파일에서 매핑
+ * SAP ECC에서 PR을 묶어 RFQ를 생성한 경우 SOAP으로 수신하여 처리하는 매퍼
+ *
+ * ZBSART = AN (RFQ)인 경우 이 파일에서 처리하여 rfqsLast, rfqPrItems 테이블에 매핑합니다.
+ * ZBSART = AB (Bidding)인 경우는 bidding-and-pr-mapper.ts 파일에서 매핑합니다.
+ *
+ * 주요 변경사항:
+ * - POS 파일 자동 다운로드 로직 제거됨 (온디맨드 방식으로 변경)
+ * - 사용자가 필요할 때만 POS 파일을 다운로드하도록 개선
*/
import { debugLog, debugSuccess, debugError } from '@/lib/debug-utils';
@@ -20,7 +25,6 @@ import {
findProjectInfoByPSPID,
parseSAPDateTime,
} from './common-mapper-utils';
-import { syncRfqPosFiles } from '@/lib/pos';
// ECC 데이터 타입 정의
export type ECCBidHeader = typeof PR_INFORMATION_T_BID_HEADER.$inferInsert;
@@ -374,34 +378,8 @@ export async function mapAndSaveECCRfqDataToRfqLast(
processedCount: result.processedCount,
});
- // 6) 각 RFQ에 대해 POS 파일 자동 동기화 (비동기로 실행하여 메인 플로우 블록하지 않음)
- debugLog('RFQ POS 파일 자동 동기화 시작', { rfqCount: result.insertedRfqs.length });
-
- // 비동기로 각 RFQ의 POS 파일 동기화 실행 (결과를 기다리지 않음)
- result.insertedRfqs.forEach(async (rfq) => {
- try {
- debugLog(`RFQ ${rfq.rfqCode} POS 파일 동기화 시작`, { rfqId: rfq.id });
- const syncResult = await syncRfqPosFiles(rfq.id, 1); // 시스템 사용자 ID = 1
-
- if (syncResult.success) {
- debugSuccess(`RFQ ${rfq.rfqCode} POS 파일 동기화 완료`, {
- rfqId: rfq.id,
- successCount: syncResult.successCount,
- failedCount: syncResult.failedCount
- });
- } else {
- debugError(`RFQ ${rfq.rfqCode} POS 파일 동기화 실패`, {
- rfqId: rfq.id,
- errors: syncResult.errors
- });
- }
- } catch (error) {
- debugError(`RFQ ${rfq.rfqCode} POS 파일 동기화 중 예외 발생`, {
- rfqId: rfq.id,
- error: error instanceof Error ? error.message : '알 수 없는 오류'
- });
- }
- });
+ // Note: POS 파일은 온디맨드 방식으로 사용자가 필요할 때 다운로드됩니다.
+ // 자동 다운로드는 더 이상 수행하지 않습니다.
return {
success: true,