import { NextRequest, NextResponse } from "next/server"; import { getServerSession } from 'next-auth'; import { authOptions } from '@/app/api/auth/[...nextauth]/route'; import db from "@/db/db"; import { eq } from "drizzle-orm"; import { rfqLastAttachments, rfqLastAttachmentRevisions } from "@/db/schema"; import { saveFile, deleteFile } from "@/lib/file-storage"; export async function POST(request: NextRequest) { try { const session = await getServerSession(authOptions); if (!session?.user?.id) { return NextResponse.json( { success: false, message: "인증이 필요합니다" }, { status: 401 } ); } const formData = await request.formData(); const attachmentId = parseInt(formData.get("attachmentId") as string); const revisionComment = formData.get("revisionComment") as string; const file = formData.get("file") as File; if (!file || file.size === 0) { return NextResponse.json( { success: false, message: "파일이 없습니다" }, { status: 400 } ); } // 파일 크기 검증 (100MB) if (file.size > 100 * 1024 * 1024) { return NextResponse.json( { success: false, message: "파일 크기는 100MB를 초과할 수 없습니다" }, { status: 400 } ); } // 트랜잭션 시작 const result = await db.transaction(async (tx) => { // 1. 기존 첨부파일 정보 조회 const [existingAttachment] = await tx .select() .from(rfqLastAttachments) .where(eq(rfqLastAttachments.id, attachmentId)); if (!existingAttachment) { throw new Error("첨부파일을 찾을 수 없습니다"); } // 2. 현재 리비전 번호 계산 const currentRevision = existingAttachment.currentRevision || "A"; const nextRevision = String.fromCharCode(currentRevision.charCodeAt(0) + 1); // 3. 공용 파일 저장 함수 사용 const saveResult = await saveFile({ file, directory: `uploads/rfq-attachments/rfq-${existingAttachment.rfqId}`, originalName: file.name, userId: session.user.id, }); if (!saveResult.success) { throw new Error(saveResult.error || "파일 저장 실패"); } // 4. 기존 latest 플래그 해제 if (existingAttachment.latestRevisionId) { await tx .update(rfqLastAttachmentRevisions) .set({ isLatest: false }) .where(eq(rfqLastAttachmentRevisions.id, existingAttachment.latestRevisionId)); } // 5. 새 리비전 생성 const [revision] = await tx .insert(rfqLastAttachmentRevisions) .values({ attachmentId, revisionNo: nextRevision, fileName: saveResult.fileName!, originalFileName: saveResult.originalName!, filePath: saveResult.publicPath!, fileSize: saveResult.fileSize!, fileType: file.type || "unknown", isLatest: true, revisionComment, uploadedBy: parseInt(session.user.id), uploadedAt: new Date(), }) .returning(); // 6. 첨부파일 정보 업데이트 await tx .update(rfqLastAttachments) .set({ currentRevision: nextRevision, latestRevisionId: revision.id, updatedAt: new Date(), }) .where(eq(rfqLastAttachments.id, attachmentId)); return { attachment: existingAttachment, revision }; }); return NextResponse.json({ success: true, message: `새 버전이 업로드되었습니다 (Rev. ${result.revision.revisionNo})`, data: result.revision, }); } catch (error) { console.error("Update revision error:", error); return NextResponse.json( { success: false, message: error instanceof Error ? error.message : "리비전 업데이트 실패" }, { status: 500 } ); } }