summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/vendor-document-list/dolce-upload-service.ts184
1 files changed, 143 insertions, 41 deletions
diff --git a/lib/vendor-document-list/dolce-upload-service.ts b/lib/vendor-document-list/dolce-upload-service.ts
index 35058a65..8c66f234 100644
--- a/lib/vendor-document-list/dolce-upload-service.ts
+++ b/lib/vendor-document-list/dolce-upload-service.ts
@@ -1,9 +1,8 @@
// lib/vendor-document-list/dolce-upload-service.ts
import db from "@/db/db"
import { documents, revisions, documentAttachments, contracts, projects, vendors, issueStages } from "@/db/schema"
-import { eq, and, desc, sql, inArray, min } from "drizzle-orm"
+import { eq, and, inArray, min } from "drizzle-orm"
import { v4 as uuidv4 } from "uuid"
-import path from "path"
import * as crypto from "crypto"
import { getServerSession } from "next-auth/next"
import { authOptions } from "@/app/api/auth/[...nextauth]/route"
@@ -59,13 +58,65 @@ interface DOLCEDocument {
RegCompanyCode: string
}
+interface RevisionAttachment {
+ id: number
+ uploadId: string | null
+ fileId: string | null
+ fileName: string
+ filePath: string
+ fileType: string | null
+ fileSize: number | null
+ createdAt: Date
+}
+
+interface RevisionWithAttachments {
+ id: number
+ registerId: string | number | null
+ revision: string
+ revisionStatus: string | null
+ uploaderId: string | number | null
+ uploaderName: string | null
+ submittedDate: string | null
+ comment: string | null
+ usage: string | null
+ usageType: string | null
+ externalUploadId: string | null
+ externalRegisterId: number
+ externalSentAt: string | null
+ serialNo: number | null
+ issueStageId: number
+ stageName: string | null
+ documentId: number
+ documentNo: string
+ documentName: string
+ drawingKind: string | null
+ drawingMoveGbn: string | null
+ discipline: string | null
+ registerGroupId: number | null
+ category?: string | null
+ cGbn: string | null
+ dGbn: string | null
+ degreeGbn: string | null
+ deptGbn: string | null
+ jGbn: string | null
+ sGbn: string | null
+ manager: string | null
+ managerENM: string | null
+ managerNo: string | null
+ shiDrawingNo: string | null
+ externalDocumentId: string | null
+ externalSystemType: string | null
+ externalSyncedAt: Date | null
+ attachments: RevisionAttachment[]
+}
+
interface DOLCEFileMapping {
- CGbn?: string
- Category?: string
+ CGbn?: string | null
+ Category?: string | null
CheckBox: string
- DGbn?: string
- DegreeGbn?: string
- DeptGbn?: string
+ DGbn?: string | null
+ DegreeGbn?: string | null
+ DeptGbn?: string | null
Discipline: string
DrawingKind: string
DrawingMoveGbn: string
@@ -73,7 +124,7 @@ interface DOLCEFileMapping {
DrawingNo: string
DrawingUsage: string
FileNm: string
- JGbn?: string
+ JGbn?: string | null
Manager: string
MappingYN: string
NewOrNot: string
@@ -82,8 +133,8 @@ interface DOLCEFileMapping {
RegisterGroupId: number
RegisterKindCode: string
RegisterSerialNo: number
- RevNo?: string
- SGbn?: string
+ RevNo?: string | null
+ SGbn?: string | null
UploadId: string
}
@@ -115,19 +166,24 @@ class DOLCEUploadService {
async uploadToDoLCE(
projectId: number,
revisionIds: number[],
- userId: string,
- userName?: string
+ userId: string
): Promise<DOLCEUploadResult> {
try {
console.log(`Starting DOLCE upload for contract ${projectId}, revisions: ${revisionIds.join(', ')}`)
- // 1. 계약 정보 조회 (프로젝트 코드, 벤더 코드 등)
+ // 1. 사용자 정보 조회 (DOLCE API에 필요한 정보)
+ const userInfo = await this.getUserInfo(userId)
+ if (!userInfo) {
+ throw new Error(`User info not found for ID: ${userId}`)
+ }
+
+ // 2. 계약 정보 조회 (프로젝트 코드, 벤더 코드 등)
const contractInfo = await this.getContractInfo(projectId)
if (!contractInfo) {
throw new Error(`Contract info not found for ID: ${projectId}`)
}
- // 2. 업로드할 리비전 정보 조회
+ // 3. 업로드할 리비전 정보 조회
const revisionsToUpload = await this.getRevisionsForUpload(revisionIds)
if (revisionsToUpload.length === 0) {
return {
@@ -138,7 +194,7 @@ class DOLCEUploadService {
}
let uploadedDocuments = 0
- let uploadedFiles = 0
+ const uploadedFiles = 0
const errors: string[] = []
const results: any = {
documentResults: [],
@@ -146,19 +202,19 @@ class DOLCEUploadService {
mappingResults: []
}
- // 3. 각 리비전별로 처리
+ // 4. 각 리비전별로 처리
for (const revision of revisionsToUpload) {
try {
console.log(`Processing revision ${revision.revision} for document ${revision.documentNo}`)
- // 3-1. UploadId 미리 생성 (파일이 있는 경우에만)
+ // 4-1. UploadId 미리 생성 (파일이 있는 경우에만)
let uploadId: string | undefined
if (revision.attachments && revision.attachments.length > 0) {
uploadId = uuidv4() // 문서 업로드 시 사용할 UploadId 미리 생성
console.log(`Generated UploadId for document upload: ${uploadId}`)
}
- // 3-2. 문서 정보 업로드 (UploadId 포함)
+ // 4-2. 문서 정보 업로드 (UploadId 포함)
const dolceDoc = this.transformToDoLCEDocument(
revision,
contractInfo,
@@ -166,7 +222,13 @@ class DOLCEUploadService {
contractInfo.vendorCode,
)
- const docResult = await this.uploadDocument([dolceDoc], userId)
+ const docResult = await this.uploadDocument(
+ [dolceDoc],
+ userInfo.userId,
+ userInfo.userName,
+ userInfo.vendorCode,
+ userInfo.userEmail
+ )
if (!docResult.success) {
errors.push(`Document upload failed for ${revision.documentNo}: ${docResult.error}`)
continue // 문서 업로드 실패 시 다음 리비전으로 넘어감
@@ -176,11 +238,11 @@ class DOLCEUploadService {
results.documentResults.push(docResult)
console.log(`✅ Document uploaded successfully: ${revision.documentNo}`)
- // 3-3. 파일 업로드 (이미 생성된 UploadId 사용)
+ // 4-3. 파일 업로드 (이미 생성된 UploadId 사용)
if (uploadId && revision.attachments && revision.attachments.length > 0) {
try {
// 파일 업로드 시 이미 생성된 UploadId 사용
- const fileUploadResults = await this.uploadFiles(
+ await this.uploadFiles(
revision.attachments,
userId,
uploadId // 이미 생성된 UploadId 전달
@@ -192,7 +254,7 @@ class DOLCEUploadService {
}
}
- // 3-5. 성공한 리비전의 상태 업데이트
+ // 4-4. 성공한 리비전의 상태 업데이트
await this.updateRevisionStatus(revision.id, 'SUBMITTED', uploadId)
} catch (error) {
@@ -245,6 +307,41 @@ class DOLCEUploadService {
: null
}
+ /**
+ * 사용자 정보 조회 (DOLCE 업로드에 필요한 정보)
+ */
+ private async getUserInfo(userId: string): Promise<{
+ userId: string;
+ userName: string;
+ userEmail: string;
+ vendorCode: string;
+ } | null> {
+ const { users, vendors } = await import("@/db/schema")
+
+ const [result] = await db
+ .select({
+ userId: users.id,
+ userName: users.name,
+ userEmail: users.email,
+ vendorCode: vendors.vendorCode
+ })
+ .from(users)
+ .innerJoin(vendors, eq(users.companyId, vendors.id))
+ .where(eq(users.id, Number(userId)))
+ .limit(1)
+
+ if (!result) {
+ return null
+ }
+
+ return {
+ userId: String(result.userId),
+ userName: result.userName,
+ userEmail: result.userEmail,
+ vendorCode: result.vendorCode || ""
+ }
+ }
+
/**
* 각 issueStageId별로 첫 번째 revision 정보를 조회
@@ -272,7 +369,7 @@ class DOLCEUploadService {
/**
* 업로드할 리비전 정보 조회 (문서 정보 및 첨부파일 포함)
*/
- private async getRevisionsForUpload(revisionIds: number[]) {
+ private async getRevisionsForUpload(revisionIds: number[]): Promise<RevisionWithAttachments[]> {
// revisions → issueStages → documents 순서로 join하여 정보 조회
const revisionResults = await db
.select({
@@ -333,7 +430,7 @@ class DOLCEUploadService {
.where(inArray(revisions.id, revisionIds))
// 각 리비전의 첨부파일 정보도 조회
- const revisionsWithAttachments = []
+ const revisionsWithAttachments: RevisionWithAttachments[] = []
for (const revision of revisionResults) {
const attachments = await db
.select({
@@ -365,11 +462,11 @@ class DOLCEUploadService {
* @param uploadId 이미 생성된 UploadId (문서 업로드 시 생성됨)
*/
private async uploadFiles(
- attachments: any[],
+ attachments: RevisionAttachment[],
userId: string,
uploadId: string // 이미 생성된 UploadId를 매개변수로 받음
): Promise<Array<{ uploadId: string, fileId: string, filePath: string }>> {
- const uploadResults = []
+ const uploadResults: Array<{ uploadId: string, fileId: string, filePath: string }> = []
const resultDataArray: ResultData[] = []
for (let i = 0; i < attachments.length; i++) {
@@ -516,7 +613,7 @@ class DOLCEUploadService {
private async getFileStats(filePath: string): Promise<{ size: number, birthtime: Date, mtime: Date }> {
try {
// Node.js 환경이라면 fs.stat 사용
- const fs = require('fs').promises
+ const fs = await import('fs/promises')
const stats = await fs.stat(filePath)
return {
@@ -524,7 +621,7 @@ class DOLCEUploadService {
birthtime: stats.birthtime,
mtime: stats.mtime
}
- } catch (error) {
+ } catch {
console.warn(`Could not get file stats for ${filePath}, using defaults`)
// 파일 정보를 가져올 수 없는 경우 기본값 사용
const now = new Date()
@@ -539,13 +636,22 @@ class DOLCEUploadService {
/**
* 문서 정보 업로드 (DetailDwgReceiptMgmtEdit)
*/
- private async uploadDocument(dwgList: DOLCEDocument[], userId: string): Promise<{ success: boolean, error?: string, data?: any }> {
+ private async uploadDocument(
+ dwgList: DOLCEDocument[],
+ userId: string,
+ userName: string,
+ vendorCode: string,
+ email: string
+ ): Promise<{ success: boolean, error?: string, data?: any }> {
try {
const endpoint = `${this.BASE_URL}/Services/VDCSWebService.svc/DetailDwgReceiptMgmtEdit`
const requestBody = {
DwgList: dwgList,
- UserID: userId
+ UserID: userId,
+ UserNM: userName,
+ VENDORCODE: vendorCode,
+ EMAIL: email
}
console.log('Uploading documents to DOLCE:', JSON.stringify(requestBody, null, 2))
@@ -623,12 +729,9 @@ class DOLCEUploadService {
/**
* 리비전 데이터를 DOLCE 문서 형태로 변환 (업데이트된 스키마 사용)
*/
- /**
- * 리비전 데이터를 DOLCE 문서 형태로 변환 (업데이트된 스키마 사용)
- */
private transformToDoLCEDocument(
- revision: any,
- contractInfo: any,
+ revision: RevisionWithAttachments,
+ contractInfo: { projectCode: string; vendorCode: string },
uploadId?: string,
vendorCode?: string,
): DOLCEDocument {
@@ -750,7 +853,7 @@ class DOLCEUploadService {
Mode: mode,
// Status: revision.revisionStatus || "Standby",
Status: "Standby",
- RegisterId: revision.registerId || 0, // registerId가 없으면 0 (ADD 모드)
+ RegisterId: revision.registerId ? (typeof revision.registerId === 'string' ? parseInt(revision.registerId) : revision.registerId) : 0, // registerId가 없으면 0 (ADD 모드)
ProjectNo: contractInfo.projectCode,
Discipline: revision.discipline || "DL",
DrawingKind: revision.drawingKind || "B3",
@@ -772,8 +875,8 @@ class DOLCEUploadService {
* 파일 매핑 데이터 변환
*/
private transformToFileMapping(
- revision: any,
- contractInfo: any,
+ revision: RevisionWithAttachments,
+ contractInfo: { projectCode: string; vendorCode: string },
uploadId: string,
fileName: string
): DOLCEFileMapping {
@@ -1008,8 +1111,7 @@ export const dolceUploadService = new DOLCEUploadService()
export async function uploadRevisionsToDOLCE(
projectId: number,
revisionIds: number[],
- userId: string,
- userName?: string
+ userId: string
): Promise<DOLCEUploadResult> {
- return dolceUploadService.uploadToDoLCE(projectId, revisionIds, userId, userName)
+ return dolceUploadService.uploadToDoLCE(projectId, revisionIds, userId)
} \ No newline at end of file