summaryrefslogtreecommitdiff
path: root/lib/vendor-document-list/import-service.ts
diff options
context:
space:
mode:
Diffstat (limited to 'lib/vendor-document-list/import-service.ts')
-rw-r--r--lib/vendor-document-list/import-service.ts288
1 files changed, 247 insertions, 41 deletions
diff --git a/lib/vendor-document-list/import-service.ts b/lib/vendor-document-list/import-service.ts
index 4a152299..d2a14980 100644
--- a/lib/vendor-document-list/import-service.ts
+++ b/lib/vendor-document-list/import-service.ts
@@ -37,10 +37,23 @@ interface DOLCEDocument {
DrawingNo: string
GTTInput_PlanDate?: string
GTTInput_ResultDate?: string
+ AppDwg_PlanDate?: string
+ AppDwg_ResultDate?: string
+ WorDwg_PlanDate?: string
+ WorDwg_ResultDate?: string
+
+
GTTPreDwg_PlanDate?: string
GTTPreDwg_ResultDate?: string
GTTWorkingDwg_PlanDate?: string
GTTWorkingDwg_ResultDate?: string
+
+ FMEAFirst_PlanDate?: string
+ FMEAFirst_ResultDate?: string
+ FMEASecond_PlanDate?: string
+ FMEASecond_ResultDate?: string
+
+
JGbn?: string
Manager: string
ManagerENM: string
@@ -72,12 +85,12 @@ class ImportService {
// 2. 각 drawingKind별로 데이터 조회
const allDocuments: DOLCEDocument[] = []
const drawingKinds = ['B3', 'B4', 'B5']
-
+
for (const drawingKind of drawingKinds) {
try {
const documents = await this.fetchFromDOLCE(
- contractInfo.projectCode,
- contractInfo.vendorCode,
+ contractInfo.projectCode,
+ contractInfo.vendorCode,
drawingKind
)
allDocuments.push(...documents)
@@ -87,7 +100,7 @@ class ImportService {
// 개별 drawingKind 실패는 전체 실패로 처리하지 않음
}
}
-
+
if (allDocuments.length === 0) {
return {
success: true,
@@ -107,13 +120,22 @@ class ImportService {
for (const dolceDoc of allDocuments) {
try {
const result = await this.syncSingleDocument(contractId, dolceDoc, sourceSystem)
-
+
if (result === 'NEW') {
newCount++
// B4 문서의 경우 이슈 스테이지 자동 생성
if (dolceDoc.DrawingKind === 'B4') {
await this.createIssueStagesForB4Document(dolceDoc.DrawingNo, contractId, dolceDoc)
}
+
+ if (dolceDoc.DrawingKind === 'B3') {
+ await this.createIssueStagesForB3Document(dolceDoc.DrawingNo, contractId, dolceDoc)
+ }
+
+
+ if (dolceDoc.DrawingKind === 'B5') {
+ await this.createIssueStagesForB5Document(dolceDoc.DrawingNo, contractId, dolceDoc)
+ }
} else if (result === 'UPDATED') {
updatedCount++
} else {
@@ -151,7 +173,7 @@ class ImportService {
vendorCode: string;
} | null> {
const [result] = await db
- .select({
+ .select({
projectCode: projects.code,
vendorCode: vendors.vendorCode
})
@@ -162,7 +184,7 @@ class ImportService {
.limit(1)
- return result?.projectCode && result?.vendorCode
+ return result?.projectCode && result?.vendorCode
? { projectCode: result.projectCode, vendorCode: result.vendorCode }
: null
}
@@ -172,15 +194,15 @@ class ImportService {
*/
private async fetchFromDOLCE(
projectCode: string,
- vendorCode: string,
+ vendorCode: string,
drawingKind: string
): Promise<DOLCEDocument[]> {
const endpoint = process.env.DOLCE_DOC_LIST_API_URL || 'http://60.100.99.217:1111/Services/VDCSWebService.svc/DwgReceiptMgmt'
-
+
const requestBody = {
project: projectCode,
drawingKind: drawingKind, // B3, B4, B5
- drawingMoveGbn: "",
+ drawingMoveGbn: "",
drawingNo: "",
drawingName: "",
drawingVendor: vendorCode
@@ -204,14 +226,32 @@ class ImportService {
}
const data = await response.json()
-
- // 응답 구조에 따라 조정 필요 (실제 API 응답 구조 확인 후)
- if (Array.isArray(data)) {
- return data as DOLCEDocument[]
- } else if (data.documents && Array.isArray(data.documents)) {
- return data.documents as DOLCEDocument[]
- } else if (data.data && Array.isArray(data.data)) {
- return data.data as DOLCEDocument[]
+
+ // DOLCE API 응답 구조에 맞게 처리
+ if (data.DwgReceiptMgmtResult) {
+ const result = data.DwgReceiptMgmtResult
+
+ // drawingKind에 따라 적절한 배열에서 데이터 추출
+ let documents: DOLCEDocument[] = []
+
+ switch (drawingKind) {
+ case 'B3':
+ documents = result.VendorDwgList || []
+ break
+ case 'B4':
+ documents = result.GTTDwgList || []
+ break
+ case 'B5':
+ documents = result.FMEADwgList || []
+ break
+ default:
+ console.warn(`Unknown drawingKind: ${drawingKind}`)
+ documents = []
+ }
+
+ console.log(`Found ${documents.length} documents for ${drawingKind} in ${drawingKind === 'B3' ? 'VendorDwgList' : drawingKind === 'B4' ? 'GTTDwgList' : 'FMEADwgList'}`)
+ return documents as DOLCEDocument[]
+
} else {
console.warn(`Unexpected DOLCE response structure:`, data)
return []
@@ -222,7 +262,6 @@ class ImportService {
throw error
}
}
-
/**
* 단일 문서 동기화
*/
@@ -247,17 +286,17 @@ class ImportService {
docNumber: dolceDoc.DrawingNo,
title: dolceDoc.DrawingName,
status: 'ACTIVE',
-
+
// DOLCE 전용 필드들
drawingKind: dolceDoc.DrawingKind,
drawingMoveGbn: dolceDoc.DrawingMoveGbn,
discipline: dolceDoc.Discipline,
-
+
// 외부 시스템 정보
externalDocumentId: dolceDoc.DrawingNo, // DOLCE에서는 DrawingNo가 ID 역할
externalSystemType: sourceSystem,
externalSyncedAt: new Date(),
-
+
// B4 전용 필드들
cGbn: dolceDoc.CGbn,
dGbn: dolceDoc.DGbn,
@@ -265,7 +304,7 @@ class ImportService {
deptGbn: dolceDoc.DeptGbn,
jGbn: dolceDoc.JGbn,
sGbn: dolceDoc.SGbn,
-
+
// 추가 정보
shiDrawingNo: dolceDoc.SHIDrawingNo,
manager: dolceDoc.Manager,
@@ -273,19 +312,19 @@ class ImportService {
managerNo: dolceDoc.ManagerNo,
registerGroup: dolceDoc.RegisterGroup,
registerGroupId: dolceDoc.RegisterGroupId,
-
+
// 생성자 정보
createUserNo: dolceDoc.CreateUserNo,
createUserId: dolceDoc.CreateUserId,
createUserENM: dolceDoc.CreateUserENM,
-
+
updatedAt: new Date()
}
if (existingDoc.length > 0) {
// 업데이트 필요 여부 확인
const existing = existingDoc[0]
- const hasChanges =
+ const hasChanges =
existing.title !== documentData.title ||
existing.drawingMoveGbn !== documentData.drawingMoveGbn ||
existing.manager !== documentData.manager
@@ -316,6 +355,36 @@ class ImportService {
}
}
+ private convertDolceDateToDate(dolceDate: string | undefined | null): Date | null {
+ if (!dolceDate || dolceDate.trim() === '') {
+ return null
+ }
+
+ // "20250204" 형태의 문자열을 "2025-02-04" 형태로 변환
+ if (dolceDate.length === 8 && /^\d{8}$/.test(dolceDate)) {
+ const year = dolceDate.substring(0, 4)
+ const month = dolceDate.substring(4, 6)
+ const day = dolceDate.substring(6, 8)
+
+ try {
+ const date = new Date(`${year}-${month}-${day}`)
+ // 유효한 날짜인지 확인
+ if (isNaN(date.getTime())) {
+ console.warn(`Invalid date format: ${dolceDate}`)
+ return null
+ }
+ return date
+ } catch (error) {
+ console.warn(`Failed to parse date: ${dolceDate}`, error)
+ return null
+ }
+ }
+
+ console.warn(`Unexpected date format: ${dolceDate}`)
+ return null
+}
+
+
/**
* B4 문서용 이슈 스테이지 자동 생성
*/
@@ -353,23 +422,25 @@ class ImportService {
if (!existingStageNames.includes('For Pre')) {
await db.insert(issueStages).values({
documentId: documentId,
- stageName: 'For Pre',
- planDate: dolceDoc.GTTPreDwg_PlanDate ? dolceDoc.GTTPreDwg_PlanDate : null,
- actualDate: dolceDoc.GTTPreDwg_ResultDate ? dolceDoc.GTTPreDwg_ResultDate : null,
- stageStatus: dolceDoc.GTTPreDwg_ResultDate ? 'COMPLETED' : 'PLANNED',
+ stageName: 'GTT → SHI (For Pre.DWG)',
+ planDate: this.convertDolceDateToDate(dolceDoc.GTTPreDwg_PlanDate),
+ actualDate: this.convertDolceDateToDate(dolceDoc.GTTPreDwg_ResultDate),
+ stageStatus: 'PLANNED',
stageOrder: 1,
+ priority: 'MEDIUM', // 기본값
+ reminderDays: 3, // 기본값
description: 'GTT 예비 도면 단계'
})
}
// For Working 스테이지 생성 (GTTWorkingDwg)
- if (!existingStageNames.includes('For Working')) {
+ if (!existingStageNames.includes('For Work')) {
await db.insert(issueStages).values({
documentId: documentId,
- stageName: 'For Working',
- planDate: dolceDoc.GTTWorkingDwg_PlanDate ? dolceDoc.GTTWorkingDwg_PlanDate : null,
- actualDate: dolceDoc.GTTWorkingDwg_ResultDate ? dolceDoc.GTTWorkingDwg_ResultDate : null,
- stageStatus: dolceDoc.GTTWorkingDwg_ResultDate ? 'COMPLETED' : 'PLANNED',
+ stageName: 'GTT → SHI (For Work.DWG)',
+ planDate: this.convertDolceDateToDate(dolceDoc.GTTWorkingDwg_PlanDate),
+ actualDate: this.convertDolceDateToDate(dolceDoc.GTTWorkingDwg_ResultDate),
+ stageStatus: 'PLANNED',
stageOrder: 2,
description: 'GTT 작업 도면 단계'
})
@@ -383,6 +454,141 @@ class ImportService {
}
}
+ private async createIssueStagesForB3Document(
+ drawingNo: string,
+ contractId: number,
+ dolceDoc: DOLCEDocument
+ ): Promise<void> {
+ try {
+ // 문서 ID 조회
+ const [document] = await db
+ .select({ id: documents.id })
+ .from(documents)
+ .where(and(
+ eq(documents.contractId, contractId),
+ eq(documents.docNumber, drawingNo)
+ ))
+ .limit(1)
+
+ if (!document) {
+ throw new Error(`Document not found: ${drawingNo}`)
+ }
+
+ const documentId = document.id
+
+ // 기존 이슈 스테이지 확인
+ const existingStages = await db
+ .select()
+ .from(issueStages)
+ .where(eq(issueStages.documentId, documentId))
+
+ const existingStageNames = existingStages.map(stage => stage.stageName)
+
+ // For Pre 스테이지 생성 (GTTPreDwg)
+ if (!existingStageNames.includes('Approval')) {
+ await db.insert(issueStages).values({
+ documentId: documentId,
+ stageName: 'Vendor → SHI (For Approval)',
+
+ planDate: this.convertDolceDateToDate(dolceDoc.AppDwg_PlanDate),
+ actualDate: this.convertDolceDateToDate(dolceDoc.AppDwg_ResultDate),
+
+ stageStatus: 'PLANNED',
+ stageOrder: 1,
+ description: 'Vendor 승인 도면 단계'
+ })
+ }
+
+ // For Working 스테이지 생성 (GTTWorkingDwg)
+ if (!existingStageNames.includes('Working')) {
+ await db.insert(issueStages).values({
+ documentId: documentId,
+ stageName: 'Vendor → SHI (For Working)',
+
+ planDate: this.convertDolceDateToDate(dolceDoc.WorDwg_PlanDate),
+ actualDate: this.convertDolceDateToDate(dolceDoc.WorDwg_ResultDate),
+
+ stageStatus: 'PLANNED',
+ stageOrder: 2,
+ description: 'Vendor 작업 도면 단계'
+ })
+ }
+
+ console.log(`Created issue stages for B4 document: ${drawingNo}`)
+
+ } catch (error) {
+ console.error(`Failed to create issue stages for ${drawingNo}:`, error)
+ // 이슈 스테이지 생성 실패는 전체 문서 생성을 막지 않음
+ }
+ }
+
+ private async createIssueStagesForB5Document(
+ drawingNo: string,
+ contractId: number,
+ dolceDoc: DOLCEDocument
+ ): Promise<void> {
+ try {
+ // 문서 ID 조회
+ const [document] = await db
+ .select({ id: documents.id })
+ .from(documents)
+ .where(and(
+ eq(documents.contractId, contractId),
+ eq(documents.docNumber, drawingNo)
+ ))
+ .limit(1)
+
+ if (!document) {
+ throw new Error(`Document not found: ${drawingNo}`)
+ }
+
+ const documentId = document.id
+
+ // 기존 이슈 스테이지 확인
+ const existingStages = await db
+ .select()
+ .from(issueStages)
+ .where(eq(issueStages.documentId, documentId))
+
+ const existingStageNames = existingStages.map(stage => stage.stageName)
+
+ // For Pre 스테이지 생성 (GTTPreDwg)
+ if (!existingStageNames.includes('Approval')) {
+ await db.insert(issueStages).values({
+ documentId: documentId,
+ stageName: 'Vendor → SHI (For Approval)',
+
+ planDate: this.convertDolceDateToDate(dolceDoc.FMEAFirst_PlanDate),
+ actualDate: this.convertDolceDateToDate(dolceDoc.FMEAFirst_ResultDate),
+
+ stageStatus: 'PLANNED',
+ stageOrder: 1,
+ description: 'FMEA 예비 도면 단계'
+ })
+ }
+
+ // For Working 스테이지 생성 (GTTWorkingDwg)
+ if (!existingStageNames.includes('Working')) {
+ await db.insert(issueStages).values({
+ documentId: documentId,
+ stageName: 'Vendor → SHI (For Working)',
+ planDate: dolceDoc.FMEASecond_PlanDate ? dolceDoc.FMEASecond_PlanDate : null,
+ actualDate: dolceDoc.FMEASecond_ResultDate ? dolceDoc.FMEASecond_ResultDate : null,
+ stageStatus: 'PLANNED',
+ stageOrder: 2,
+ description: 'FMEA 작업 도면 단계'
+ })
+ }
+
+ console.log(`Created issue stages for B4 document: ${drawingNo}`)
+
+ } catch (error) {
+ console.error(`Failed to create issue stages for ${drawingNo}:`, error)
+ // 이슈 스테이지 생성 실패는 전체 문서 생성을 막지 않음
+ }
+ }
+
+
/**
* 가져오기 상태 조회
*/
@@ -393,8 +599,8 @@ class ImportService {
try {
// 마지막 가져오기 시간 조회
const [lastImport] = await db
- .select({
- lastSynced: sql<string>`MAX(${documents.externalSyncedAt})`
+ .select({
+ lastSynced: sql<string>`MAX(${documents.externalSyncedAt})`
})
.from(documents)
.where(and(
@@ -405,7 +611,7 @@ class ImportService {
// 프로젝트 코드와 벤더 코드 조회
const contractInfo = await this.getContractInfoById(contractId)
- console.log(contractInfo,"contractInfo")
+ console.log(contractInfo, "contractInfo")
if (!contractInfo?.projectCode || !contractInfo?.vendorCode) {
throw new Error(`Project code or vendor code not found for contract ${contractId}`)
@@ -418,12 +624,12 @@ class ImportService {
try {
// 각 drawingKind별로 확인
const drawingKinds = ['B3', 'B4', 'B5']
-
+
for (const drawingKind of drawingKinds) {
try {
const externalDocs = await this.fetchFromDOLCE(
- contractInfo.projectCode,
- contractInfo.vendorCode,
+ contractInfo.projectCode,
+ contractInfo.vendorCode,
drawingKind
)
availableDocuments += externalDocs.length