summaryrefslogtreecommitdiff
path: root/app/api/vendor-investigations
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 00:17:56 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 00:17:56 +0000
commit9e280704988fdeffa05c1d8cbb731722f666c6af (patch)
treebbf57b3c882502dc7afd2ff770d95aca69fca0d9 /app/api/vendor-investigations
parent44356f1b203da5169db42950a42a8146f612c674 (diff)
(대표님) 앱 라우터 api 파트 커밋
Diffstat (limited to 'app/api/vendor-investigations')
-rw-r--r--app/api/vendor-investigations/[investigationId]/attachments/route.ts158
1 files changed, 158 insertions, 0 deletions
diff --git a/app/api/vendor-investigations/[investigationId]/attachments/route.ts b/app/api/vendor-investigations/[investigationId]/attachments/route.ts
new file mode 100644
index 00000000..80513e28
--- /dev/null
+++ b/app/api/vendor-investigations/[investigationId]/attachments/route.ts
@@ -0,0 +1,158 @@
+// app/api/vendor-investigations/[investigationId]/attachments/route.ts
+import { NextRequest, NextResponse } from "next/server"
+import { promises as fs } from "fs"
+import path from "path"
+import { v4 as uuidv4 } from "uuid"
+import db from "@/db/db"
+import { vendorInvestigationAttachments } from "@/db/schema"
+import { eq } from "drizzle-orm";
+
+export async function POST(
+ req: NextRequest,
+ { params }: { params: { investigationId: string } }
+) {
+ try {
+ const investigationId = parseInt(params.investigationId)
+ if (!investigationId) {
+ return NextResponse.json({ error: "Invalid investigation ID" }, { status: 400 })
+ }
+
+ const formData = await req.formData()
+ const file = formData.get("file") as File
+
+ if (!file || file.size === 0) {
+ return NextResponse.json({ error: "No file provided" }, { status: 400 })
+ }
+
+ // 파일 크기 제한 (10MB)
+ const maxSize = 10 * 1024 * 1024
+ if (file.size > maxSize) {
+ return NextResponse.json({
+ error: `파일 크기가 ${maxSize / 1024 / 1024}MB를 초과합니다.`
+ }, { status: 400 })
+ }
+
+ // 지원하는 파일 타입 검증
+ const allowedTypes = [
+ 'application/pdf',
+ 'application/msword',
+ 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
+ 'application/vnd.ms-excel',
+ 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
+ 'image/png',
+ 'image/jpeg',
+ 'image/jpg',
+ 'image/gif'
+ ]
+
+ if (!allowedTypes.includes(file.type)) {
+ return NextResponse.json({
+ error: "지원하지 않는 파일 형식입니다."
+ }, { status: 400 })
+ }
+
+ // 파일 저장
+ const arrayBuffer = await file.arrayBuffer()
+ const buffer = Buffer.from(arrayBuffer)
+
+ // 고유한 파일명 생성
+ const ext = path.extname(file.name)
+ const uniqueName = `${uuidv4()}${ext}`
+
+ // 업로드 디렉토리 생성
+ const uploadDir = path.join(process.cwd(), "public", "vendor-investigation", String(investigationId))
+ await fs.mkdir(uploadDir, { recursive: true })
+
+ const filePath = path.join(uploadDir, uniqueName)
+ await fs.writeFile(filePath, buffer)
+
+ // 파일 타입 결정
+ let attachmentType = "OTHER"
+ if (file.type.includes("pdf")) {
+ attachmentType = "REPORT"
+ } else if (file.type.includes("image")) {
+ attachmentType = "PHOTO"
+ } else if (
+ file.type.includes("word") ||
+ file.type.includes("document") ||
+ file.name.toLowerCase().includes("report")
+ ) {
+ attachmentType = "DOCUMENT"
+ }
+
+ // DB에 파일 정보 저장
+ const [attachment] = await db.insert(vendorInvestigationAttachments).values({
+ investigationId,
+ fileName: file.name,
+ filePath: `/vendor-investigation/${investigationId}/${uniqueName}`,
+ fileSize: file.size,
+ mimeType: file.type,
+ attachmentType: attachmentType as "REPORT" | "PHOTO" | "DOCUMENT" | "CERTIFICATE" | "OTHER",
+ // uploadedBy: currentUserId, // 실제 사용자 ID로 설정
+ }).returning()
+
+ return NextResponse.json({
+ success: true,
+ attachment: {
+ id: attachment.id,
+ fileName: attachment.fileName,
+ filePath: attachment.filePath,
+ fileSize: attachment.fileSize,
+ attachmentType: attachment.attachmentType
+ }
+ })
+
+ } catch (error) {
+ console.error("파일 업로드 오류:", error)
+ return NextResponse.json({
+ error: "파일 업로드 중 오류가 발생했습니다."
+ }, { status: 500 })
+ }
+}
+
+// 첨부파일 삭제
+export async function DELETE(
+ req: NextRequest,
+ { params }: { params: { investigationId: string } }
+) {
+ try {
+ const { searchParams } = new URL(req.url)
+ const attachmentId = searchParams.get("attachmentId")
+
+ if (!attachmentId) {
+ return NextResponse.json({ error: "Attachment ID required" }, { status: 400 })
+ }
+
+ // DB에서 파일 정보 조회
+ const attachment = await db.query.vendorInvestigationAttachments.findFirst({
+ where: (attachments, { eq, and }) => and(
+ eq(attachments.id, parseInt(attachmentId)),
+ eq(attachments.investigationId, parseInt(params.investigationId))
+ )
+ })
+
+ if (!attachment) {
+ return NextResponse.json({ error: "Attachment not found" }, { status: 404 })
+ }
+
+ // 실제 파일 삭제
+ const fullPath = path.join(process.cwd(), "public", attachment.filePath)
+ try {
+ await fs.unlink(fullPath)
+ } catch (error) {
+ console.warn("파일 삭제 실패 (파일이 존재하지 않을 수 있음):", error)
+ }
+
+ // DB에서 레코드 삭제
+ await db.delete(vendorInvestigationAttachments)
+ .where(eq(vendorInvestigationAttachments.id, parseInt(attachmentId)))
+
+ return NextResponse.json({ success: true })
+
+ } catch (error) {
+ console.error("파일 삭제 오류:", error)
+ return NextResponse.json({
+ error: "파일 삭제 중 오류가 발생했습니다."
+ }, { status: 500 })
+ }
+} \ No newline at end of file