diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-22 02:57:00 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-22 02:57:00 +0000 |
| commit | ee57cc221ff2edafd3c0f12a181214c602ed257e (patch) | |
| tree | 148f552f503798f7a350d6eff936b889f16be49f /lib/vendor-document-list/import-service.ts | |
| parent | 14f61e24947fb92dd71ec0a7196a6e815f8e66da (diff) | |
(대표님, 최겸) 이메일 템플릿, 벤더데이터 변경사항 대응, 기술영업 변경요구사항 구현
Diffstat (limited to 'lib/vendor-document-list/import-service.ts')
| -rw-r--r-- | lib/vendor-document-list/import-service.ts | 287 |
1 files changed, 160 insertions, 127 deletions
diff --git a/lib/vendor-document-list/import-service.ts b/lib/vendor-document-list/import-service.ts index bc384ea2..c7ba041a 100644 --- a/lib/vendor-document-list/import-service.ts +++ b/lib/vendor-document-list/import-service.ts @@ -1332,156 +1332,189 @@ class ImportService { /** * 가져오기 상태 조회 */ - async getImportStatus( - contractId: number, - sourceSystem: string = 'DOLCE' - ): Promise<ImportStatus> { - try { - // 마지막 가져오기 시간 조회 - const [lastImport] = await db - .select({ - lastSynced: sql<string>`MAX(${documents.externalSyncedAt})` - }) - .from(documents) - .where(and( - eq(documents.contractId, contractId), - eq(documents.externalSystemType, sourceSystem) - )) + /** + * 가져오기 상태 조회 - 에러 시 안전한 기본값 반환 + */ +async getImportStatus( + contractId: number, + sourceSystem: string = 'DOLCE' +): Promise<ImportStatus> { + try { + // 마지막 가져오기 시간 조회 + const [lastImport] = await db + .select({ + lastSynced: sql<string>`MAX(${documents.externalSyncedAt})` + }) + .from(documents) + .where(and( + eq(documents.contractId, contractId), + eq(documents.externalSystemType, sourceSystem) + )) - // 프로젝트 코드와 벤더 코드 조회 - const contractInfo = await this.getContractInfoById(contractId) + // 프로젝트 코드와 벤더 코드 조회 + const contractInfo = await this.getContractInfoById(contractId) - if (!contractInfo?.projectCode || !contractInfo?.vendorCode) { - throw new Error(`Project code or vendor code not found for contract ${contractId}`) + // 🔥 계약 정보가 없으면 기본 상태 반환 (에러 throw 하지 않음) + if (!contractInfo?.projectCode || !contractInfo?.vendorCode) { + console.warn(`Project code or vendor code not found for contract ${contractId}`) + return { + lastImportAt: lastImport?.lastSynced ? new Date(lastImport.lastSynced).toISOString() : undefined, + availableDocuments: 0, + newDocuments: 0, + updatedDocuments: 0, + availableRevisions: 0, + newRevisions: 0, + updatedRevisions: 0, + availableAttachments: 0, + newAttachments: 0, + updatedAttachments: 0, + importEnabled: false, // 🔥 계약 정보가 없으면 import 비활성화 + error: `Contract ${contractId}에 대한 프로젝트 코드 또는 벤더 코드를 찾을 수 없습니다.` // 🔥 에러 메시지 추가 } + } - let availableDocuments = 0 - let newDocuments = 0 - let updatedDocuments = 0 - let availableRevisions = 0 - let newRevisions = 0 - let updatedRevisions = 0 - let availableAttachments = 0 - let newAttachments = 0 - let updatedAttachments = 0 + let availableDocuments = 0 + let newDocuments = 0 + let updatedDocuments = 0 + let availableRevisions = 0 + let newRevisions = 0 + let updatedRevisions = 0 + let availableAttachments = 0 + let newAttachments = 0 + let updatedAttachments = 0 - try { - // 각 drawingKind별로 확인 - const drawingKinds = ['B3', 'B4', 'B5'] + try { + // 각 drawingKind별로 확인 + const drawingKinds = ['B3', 'B4', 'B5'] - for (const drawingKind of drawingKinds) { - try { - const externalDocs = await this.fetchFromDOLCE( - contractInfo.projectCode, - contractInfo.vendorCode, - drawingKind - ) - availableDocuments += externalDocs.length - - // 신규/업데이트 문서 수 계산 - for (const externalDoc of externalDocs) { - const existing = await db - .select({ id: documents.id, updatedAt: documents.updatedAt }) - .from(documents) - .where(and( - eq(documents.contractId, contractId), - eq(documents.docNumber, externalDoc.DrawingNo) - )) - .limit(1) - - if (existing.length === 0) { - newDocuments++ - } else { - // DOLCE의 CreateDt와 로컬 updatedAt 비교 - if (externalDoc.CreateDt && existing[0].updatedAt) { - const externalModified = new Date(externalDoc.CreateDt) - const localModified = new Date(existing[0].updatedAt) - if (externalModified > localModified) { - updatedDocuments++ - } + for (const drawingKind of drawingKinds) { + try { + const externalDocs = await this.fetchFromDOLCE( + contractInfo.projectCode, + contractInfo.vendorCode, + drawingKind + ) + availableDocuments += externalDocs.length + + // 신규/업데이트 문서 수 계산 + for (const externalDoc of externalDocs) { + const existing = await db + .select({ id: documents.id, updatedAt: documents.updatedAt }) + .from(documents) + .where(and( + eq(documents.contractId, contractId), + eq(documents.docNumber, externalDoc.DrawingNo) + )) + .limit(1) + + if (existing.length === 0) { + newDocuments++ + } else { + // DOLCE의 CreateDt와 로컬 updatedAt 비교 + if (externalDoc.CreateDt && existing[0].updatedAt) { + const externalModified = new Date(externalDoc.CreateDt) + const localModified = new Date(existing[0].updatedAt) + if (externalModified > localModified) { + updatedDocuments++ } } + } - // revisions 및 attachments 상태도 확인 - try { - const detailDocs = await this.fetchDetailFromDOLCE( - externalDoc.ProjectNo, - externalDoc.DrawingNo, - externalDoc.Discipline, - externalDoc.DrawingKind - ) - availableRevisions += detailDocs.length - - for (const detailDoc of detailDocs) { - const existingRevision = await db - .select({ id: revisions.id }) - .from(revisions) - .where(eq(revisions.registerId, detailDoc.RegisterId)) - .limit(1) - - if (existingRevision.length === 0) { - newRevisions++ - } else { - updatedRevisions++ - } + // revisions 및 attachments 상태도 확인 + try { + const detailDocs = await this.fetchDetailFromDOLCE( + externalDoc.ProjectNo, + externalDoc.DrawingNo, + externalDoc.Discipline, + externalDoc.DrawingKind + ) + availableRevisions += detailDocs.length + + for (const detailDoc of detailDocs) { + const existingRevision = await db + .select({ id: revisions.id }) + .from(revisions) + .where(eq(revisions.registerId, detailDoc.RegisterId)) + .limit(1) + + if (existingRevision.length === 0) { + newRevisions++ + } else { + updatedRevisions++ + } - // FS Category 문서의 첨부파일 확인 - if (detailDoc.Category === 'FS' && detailDoc.UploadId) { - try { - const fileInfos = await this.fetchFileInfoFromDOLCE(detailDoc.UploadId) - availableAttachments += fileInfos.filter(f => f.UseYn === 'Y').length - - for (const fileInfo of fileInfos) { - if (fileInfo.UseYn !== 'Y') continue - - const existingAttachment = await db - .select({ id: documentAttachments.id }) - .from(documentAttachments) - .where(eq(documentAttachments.fileId, fileInfo.FileId)) - .limit(1) - - if (existingAttachment.length === 0) { - newAttachments++ - } else { - updatedAttachments++ - } + // FS Category 문서의 첨부파일 확인 + if (detailDoc.Category === 'FS' && detailDoc.UploadId) { + try { + const fileInfos = await this.fetchFileInfoFromDOLCE(detailDoc.UploadId) + availableAttachments += fileInfos.filter(f => f.UseYn === 'Y').length + + for (const fileInfo of fileInfos) { + if (fileInfo.UseYn !== 'Y') continue + + const existingAttachment = await db + .select({ id: documentAttachments.id }) + .from(documentAttachments) + .where(eq(documentAttachments.fileId, fileInfo.FileId)) + .limit(1) + + if (existingAttachment.length === 0) { + newAttachments++ + } else { + updatedAttachments++ } - } catch (error) { - console.warn(`Failed to check files for ${detailDoc.UploadId}:`, error) } + } catch (error) { + console.warn(`Failed to check files for ${detailDoc.UploadId}:`, error) } } - } catch (error) { - console.warn(`Failed to check revisions for ${externalDoc.DrawingNo}:`, error) } + } catch (error) { + console.warn(`Failed to check revisions for ${externalDoc.DrawingNo}:`, error) } - } catch (error) { - console.warn(`Failed to check ${drawingKind} for status:`, error) } + } catch (error) { + console.warn(`Failed to check ${drawingKind} for status:`, error) } - } catch (error) { - console.warn(`Failed to fetch external data for status: ${error}`) } + } catch (error) { + console.warn(`Failed to fetch external data for status: ${error}`) + // 🔥 외부 API 호출 실패 시에도 기본값 반환 + } - return { - lastImportAt: lastImport?.lastSynced ? new Date(lastImport.lastSynced).toISOString() : undefined, - availableDocuments, - newDocuments, - updatedDocuments, - availableRevisions, - newRevisions, - updatedRevisions, - availableAttachments, - newAttachments, - updatedAttachments, - importEnabled: this.isImportEnabled(sourceSystem) - } + return { + lastImportAt: lastImport?.lastSynced ? new Date(lastImport.lastSynced).toISOString() : undefined, + availableDocuments, + newDocuments, + updatedDocuments, + availableRevisions, + newRevisions, + updatedRevisions, + availableAttachments, + newAttachments, + updatedAttachments, + importEnabled: this.isImportEnabled(sourceSystem) + } - } catch (error) { - console.error('Failed to get import status:', error) - throw error + } catch (error) { + // 🔥 최종적으로 모든 에러를 catch하여 안전한 기본값 반환 + console.error('Failed to get import status:', error) + return { + lastImportAt: undefined, + availableDocuments: 0, + newDocuments: 0, + updatedDocuments: 0, + availableRevisions: 0, + newRevisions: 0, + updatedRevisions: 0, + availableAttachments: 0, + newAttachments: 0, + updatedAttachments: 0, + importEnabled: false, + error: error instanceof Error ? error.message : 'Unknown error occurred' } } +} /** * 가져오기 활성화 여부 확인 |
