diff options
Diffstat (limited to 'app/api/revision-attachment')
| -rw-r--r-- | app/api/revision-attachment/route.ts | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/app/api/revision-attachment/route.ts b/app/api/revision-attachment/route.ts new file mode 100644 index 00000000..12834085 --- /dev/null +++ b/app/api/revision-attachment/route.ts @@ -0,0 +1,153 @@ +import { NextRequest, NextResponse } from "next/server" +import { writeFile } from "fs/promises" +import { join } from "path" +import { v4 as uuidv4 } from "uuid" +import path from "path" +import { revalidateTag } from "next/cache" + +import db from "@/db/db" +import { + documents, + revisions, + documentAttachments, +} from "@/db/schema/vendorDocu" +import { eq } from "drizzle-orm" + +/* change log 유틸 */ +import { + logAttachmentChange, +} from "@/lib/vendor-document-list/sync-service" + +export async function POST(request: NextRequest) { + try { + const formData = await request.formData() + + /* ------- 파라미터 파싱 ------- */ + const revisionId = Number(formData.get("revisionId")) + const uploaderName = formData.get("uploaderName") as string | null + const targetSystem = (formData.get("targetSystem") as string | null) ?? "DOLCE" + const attachmentFiles = formData.getAll("attachments") as File[] + + /* ------- 검증 ------- */ + if (!revisionId || Number.isNaN(revisionId)) + return NextResponse.json({ error: "Invalid revisionId" }, { status: 400 }) + if (!attachmentFiles.length) + return NextResponse.json({ error: "No files provided" }, { status: 400 }) + + const MAX = 50 * 1024 * 1024 // 50MB + for (const f of attachmentFiles) + if (f.size > MAX) + return NextResponse.json( + { error: `${f.name} exceeds 50MB limit` }, + { status: 400 } + ) + + /* ------- 리비전 및 계약 정보 확보 ------- */ + const [revisionInfo] = await db + .select({ + id: revisions.id, + revision: revisions.revision, + usage: revisions.usage, + usageType: revisions.usageType, + issueStageId: revisions.issueStageId, + contractId: documents.contractId, + }) + .from(revisions) + .leftJoin(documents, eq(documents.id, revisions.issueStageId)) + .where(eq(revisions.id, revisionId)) + .limit(1) + + if (!revisionInfo) { + return NextResponse.json({ error: "Revision not found" }, { status: 404 }) + } + + /* ------- 트랜잭션 ------- */ + const result = await db.transaction(async (tx) => { + /* 첨부파일 처리 */ + const uploadedFiles: any[] = [] + const baseDir = join(process.cwd(), "public", "documents") + + for (const file of attachmentFiles) { + const ext = path.extname(file.name) + const fname = uuidv4() + ext + const dest = join(baseDir, fname) + + await writeFile(dest, Buffer.from(await file.arrayBuffer())) + + const [att] = await tx.insert(documentAttachments) + .values({ + revisionId, + fileName: file.name, + filePath: "/documents/" + fname, + fileSize: file.size, + fileType: ext.slice(1).toLowerCase() || undefined, + updatedAt: new Date(), + }) + .returning() + + uploadedFiles.push({ + id: att.id, + fileName: file.name, + fileSize: file.size, + filePath: att.filePath, + fileType: ext.slice(1).toLowerCase() || null, + }) + + // change_logs: attachment CREATE + await logAttachmentChange( + revisionInfo.contractId, + att.id, + "CREATE", + att, + undefined, + undefined, + uploaderName ?? undefined, + [targetSystem] + ) + } + + /* 리비전 updatedAt 업데이트 */ + await tx.update(revisions) + .set({ updatedAt: new Date() }) + .where(eq(revisions.id, revisionId)) + + return { + revisionId, + revision: revisionInfo.revision, + usage: revisionInfo.usage, + usageType: revisionInfo.usageType, + uploadedFiles, + contractId: revisionInfo.contractId + } + }) + + // 캐시 무효화 + try { + // revalidateTag(`enhanced-documents-${result.contractId}`) + revalidateTag(`sync-status-${result.contractId}`) + + console.log(`✅ Cache invalidated for contract ${result.contractId}`) + } catch (cacheError) { + console.warn('⚠️ Cache invalidation failed:', cacheError) + } + + return NextResponse.json({ + success: true, + message: `${result.uploadedFiles.length}개 첨부파일이 추가되었습니다`, + data: { + revisionId: result.revisionId, + revision: result.revision, + usage: result.usage, + usageType: result.usageType, + uploadedFiles: result.uploadedFiles, + filesCount: result.uploadedFiles.length + }, + }) + } catch (e) { + console.error("revision-attachment error:", e) + return NextResponse.json( + { error: "Failed to upload attachments", details: String(e) }, + { status: 500 }, + ) + } +}
\ No newline at end of file |
