diff options
Diffstat (limited to 'lib/vendor-document-list/enhanced-document-service.ts')
| -rw-r--r-- | lib/vendor-document-list/enhanced-document-service.ts | 233 |
1 files changed, 232 insertions, 1 deletions
diff --git a/lib/vendor-document-list/enhanced-document-service.ts b/lib/vendor-document-list/enhanced-document-service.ts index 7464b13f..43eea6eb 100644 --- a/lib/vendor-document-list/enhanced-document-service.ts +++ b/lib/vendor-document-list/enhanced-document-service.ts @@ -24,6 +24,7 @@ import { contracts, users, vendors } from "@/db/schema" import { getServerSession } from "next-auth/next" import { authOptions } from "@/app/api/auth/[...nextauth]/route" import { countDocumentStagesOnly, selectDocumentStagesOnly } from "./repository" +import { saveFile } from "../file-stroage" // 스키마 타입 정의 export interface GetEnhancedDocumentsSchema { @@ -1468,4 +1469,234 @@ export async function getDocumentDetails(documentId: number) { error: error instanceof Error ? error.message : "Failed to delete revision" } } - }
\ No newline at end of file + } + + + interface UploadResult { + docNumber: string + revision: string + success: boolean + message?: string + error?: string + } + + interface BulkUploadResult { + success: boolean + successCount?: number + failCount?: number + results?: UploadResult[] + error?: string + } + + export async function bulkUploadB4Documents(formData: FormData): Promise<BulkUploadResult> { + try { + const session = await getServerSession(authOptions) + if (!session?.user) { + return { success: false, error: "인증이 필요합니다" } + } + + const projectId = formData.get("projectId") as string + const fileCount = parseInt(formData.get("fileCount") as string) + + if (!projectId) { + return { success: false, error: "프로젝트를 선택해주세요" } + } + + const results: UploadResult[] = [] + let successCount = 0 + let failCount = 0 + + // 문서번호별로 그룹화 + const fileGroups = new Map<string, Array<{ + file: File + revision: string + index: number + }>>() + + // 파일들을 문서번호별로 그룹화 + for (let i = 0; i < fileCount; i++) { + const file = formData.get(`file_${i}`) as File + const docNumber = formData.get(`docNumber_${i}`) as string + const revision = formData.get(`revision_${i}`) as string + + if (!file || !docNumber) continue + + if (!fileGroups.has(docNumber)) { + fileGroups.set(docNumber, []) + } + + fileGroups.get(docNumber)!.push({ + file, + revision: revision || "00", + index: i + }) + } + + // 각 문서번호 그룹 처리 + for (const [docNumber, files] of fileGroups.entries()) { + try { + // 문서가 존재하는지 확인 + const existingDoc = await db.query.documents.findFirst({ + where: and( + eq(documents.docNumber, docNumber), + eq(documents.projectId, parseInt(projectId)) + ) + }) + + if (!existingDoc) { + // 문서가 없으면 모든 파일 스킵 + for (const fileInfo of files) { + results.push({ + docNumber, + revision: fileInfo.revision, + success: false, + error: `문서번호 ${docNumber}가 존재하지 않습니다` + }) + failCount++ + } + continue + } + + // 기존 스테이지 조회 + const existingStages = await db.query.issueStages.findMany({ + where: eq(issueStages.documentId, existingDoc.id) + }) + + const preStage = existingStages.find(s => s.stageName === 'GTT → SHI (For Pre.DWG)') + const workStage = existingStages.find(s => s.stageName === 'GTT → SHI (For Work.DWG)') + + // 파일별 처리 (첫 번째 리비전은 Pre.DWG, 나머지는 Work.DWG) + for (let fileIndex = 0; fileIndex < files.length; fileIndex++) { + const fileInfo = files[fileIndex] + let targetStageId: number + + try { + // 스테이지 결정 및 생성 + if (fileIndex === 0) { + // 첫 번째 리비전 - Pre.DWG 스테이지 + if (preStage) { + targetStageId = preStage.id + } else { + // Pre.DWG 스테이지 생성 + const [newStage] = await db.insert(issueStages).values({ + documentId: existingDoc.id, + stageName: 'GTT → SHI (For Pre.DWG)', + stageOrder: 1, + stageStatus: 'PLANNED', + }).returning() + targetStageId = newStage.id + } + } else { + // 나머지 리비전 - Work.DWG 스테이지 + if (workStage) { + targetStageId = workStage.id + } else { + // Work.DWG 스테이지 생성 + const [newStage] = await db.insert(issueStages).values({ + documentId: existingDoc.id, + stageName: 'GTT → SHI (For Work.DWG)', + stageOrder: 2, + stageStatus: 'PLANNED', + }).returning() + targetStageId = newStage.id + } + } + + // 같은 리비전이 이미 있는지 확인 + const existingRevision = await db.query.revisions.findFirst({ + where: and( + eq(revisions.issueStageId, targetStageId), + eq(revisions.revision, fileInfo.revision) + ) + }) + + let revisionId: number + + if (existingRevision) { + // 기존 리비전 사용 + revisionId = existingRevision.id + } else { + // 새 리비전 생성 + const [newRevision] = await db.insert(revisions).values({ + issueStageId: targetStageId, + revision: fileInfo.revision, + uploaderType: "vendor", + uploaderName: session.user.name || "System", + uploadedAt: new Date().toISOString().split('T')[0], + submittedDate: new Date().toISOString().split('T')[0], + revisionStatus: 'SUBMITTED', + }).returning() + revisionId = newRevision.id + } + + // 파일 저장 + const saveResult = await saveFile({ + file: fileInfo.file, + directory: `documents/${existingDoc.id}/revisions/${revisionId}`, + originalName: fileInfo.file.name, + userId: session.user.id + }) + + if (!saveResult.success) { + throw new Error(saveResult.error || "파일 저장 실패") + } + + // 첨부파일 정보 저장 + await db.insert(documentAttachments).values({ + revisionId, + fileName: fileInfo.file.name, + filePath: saveResult.publicPath!, + fileType: fileInfo.file.type, + fileSize: fileInfo.file.size, + }) + + results.push({ + docNumber, + revision: fileInfo.revision, + success: true, + message: `${fileIndex === 0 ? 'Pre.DWG' : 'Work.DWG'} 스테이지에 업로드 완료` + }) + successCount++ + + } catch (fileError) { + results.push({ + docNumber, + revision: fileInfo.revision, + success: false, + error: fileError instanceof Error ? fileError.message : "파일 처리 실패" + }) + failCount++ + } + } + + } catch (docError) { + // 문서 그룹 전체 에러 + for (const fileInfo of files) { + results.push({ + docNumber, + revision: fileInfo.revision, + success: false, + error: docError instanceof Error ? docError.message : "문서 처리 실패" + }) + failCount++ + } + } + } + + revalidatePath('/documents') + + return { + success: true, + successCount, + failCount, + results + } + + } catch (error) { + console.error("Bulk upload error:", error) + return { + success: false, + error: error instanceof Error ? error.message : "업로드 중 오류가 발생했습니다" + } + } + } |
