summaryrefslogtreecommitdiff
path: root/lib/rfqs-tech/service.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-07-07 01:44:45 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-07-07 01:44:45 +0000
commit90f79a7a691943a496f67f01c1e493256070e4de (patch)
tree37275fde3ae08c2bca384fbbc8eb378de7e39230 /lib/rfqs-tech/service.ts
parentfbb3b7f05737f9571b04b0a8f4f15c0928de8545 (diff)
(대표님) 변경사항 20250707 10시 43분 - unstaged 변경사항 추가
Diffstat (limited to 'lib/rfqs-tech/service.ts')
-rw-r--r--lib/rfqs-tech/service.ts142
1 files changed, 17 insertions, 125 deletions
diff --git a/lib/rfqs-tech/service.ts b/lib/rfqs-tech/service.ts
index fac18a43..6989188b 100644
--- a/lib/rfqs-tech/service.ts
+++ b/lib/rfqs-tech/service.ts
@@ -10,9 +10,6 @@ import { getErrorMessage } from "@/lib/handle-error";
import { GetRfqsSchema, CreateRfqSchema, UpdateRfqSchema, CreateRfqItemSchema, GetMatchedVendorsSchema, UpdateRfqVendorSchema, GetTBESchema, GetCBESchema, createCbeEvaluationSchema } from "./validations";
import { asc, desc, ilike, inArray, and, or, sql, eq, isNull, ne, isNotNull, count } from "drizzle-orm";
import path from "path";
-import fs from "fs/promises";
-import { randomUUID } from "crypto";
-import { writeFile, mkdir } from 'fs/promises'
import { join } from 'path'
import { vendorResponses, vendorResponsesView, Rfq, rfqs, rfqAttachments, rfqItems, rfqComments, rfqEvaluations, vendorRfqView, vendorTbeView, rfqsView, vendorResponseAttachments, vendorTechnicalResponses, cbeEvaluations, vendorCommercialResponses, vendorResponseCBEView, RfqViewWithItems } from "@/db/schema/rfq";
@@ -27,6 +24,7 @@ import { headers } from 'next/headers';
// DRM 복호화 관련 유틸 import
import { decryptWithServerAction } from "@/components/drm/drmUtils";
+import { deleteFile, saveDRMFile, saveFile } from "../file-stroage";
interface InviteVendorsInput {
rfqId: number
@@ -364,50 +362,21 @@ export async function processRfqAttachments(args: {
// 1-3) 파일 삭제
for (const row of rows) {
- // filePath: 예) "/rfq/123/...xyz"
- const absolutePath = path.join(
- process.cwd(),
- "public",
- row.filePath.replace(/^\/+/, "") // 슬래시 제거
- );
- try {
- await fs.unlink(absolutePath);
- } catch (err) {
- console.error("File remove error:", err);
- }
+ await deleteFile(row.filePath)
}
}
// 2) 새 파일 업로드
if (newFiles.length > 0) {
- const rfqDir = path.join("public", "rfq", String(rfqId));
- // 폴더 없으면 생성
- await fs.mkdir(rfqDir, { recursive: true });
-
for (const file of newFiles) {
- // 2-1) DRM 복호화 시도 ----------------------------------------------------------------------
- // decryptWithServerAction 함수는 오류 처리 및 원본 반환 로직을 포함하고 있음 (해제 실패시 원본 반환)
- // 이후 코드가 buffer로 작업하므로 buffer로 전환한다.
- const decryptedData = await decryptWithServerAction(file);
- const buffer = Buffer.from(decryptedData);
- // -----------------------------------------------------------------------------------------
-
-
- // 2-2) 고유 파일명
- const uniqueName = `${randomUUID()}-${file.name}`;
- // 예) "rfq/123/xxx"
- const relativePath = path.join("rfq", String(rfqId), uniqueName);
- const absolutePath = path.join("public", relativePath);
-
- // 2-3) 파일 저장
- await fs.writeFile(absolutePath, buffer);
+ const saveResult = await saveDRMFile(file, decryptWithServerAction, `rfqTech/${rfqId}`)
// 2-4) DB Insert
await db.insert(rfqAttachments).values({
rfqId,
vendorId,
fileName: file.name,
- filePath: "/" + relativePath.replace(/\\/g, "/"),
+ filePath: saveResult.publicPath!,
// (Windows 경로 대비)
});
}
@@ -1410,15 +1379,6 @@ export async function inviteTbeVendorsAction(formData: FormData) {
throw new Error("Invalid input or no files attached.")
}
- // /public/rfq/[rfqId] 경로
- const uploadDir = path.join(process.cwd(), "public", "rfq", String(rfqId))
-
- // 디렉토리가 없다면 생성
- try {
- await fs.mkdir(uploadDir, { recursive: true })
- } catch (err) {
- console.error("디렉토리 생성 실패:", err)
- }
// DB 트랜잭션
await db.transaction(async (tx) => {
@@ -1466,21 +1426,14 @@ export async function inviteTbeVendorsAction(formData: FormData) {
// 여기서는 "모든 파일"을 RFQ-DIR에 저장 + "각 협력업체"에는 동일 파일 목록을 첨부한다는 예시.
const savedFiles = []
for (const file of tbeFiles) {
- const originalName = file.name || "tbe-sheet.xlsx"
- // 파일명 충돌 방지를 위한 타임스탬프 추가
- const timestamp = new Date().getTime()
- const fileName = `${timestamp}-${originalName}`
- const savePath = path.join(uploadDir, fileName)
- // 파일 ArrayBuffer → Buffer 변환 후 저장
- const arrayBuffer = await file.arrayBuffer()
- await fs.writeFile(savePath, Buffer.from(arrayBuffer))
+ const saveResult = await saveDRMFile(file, decryptWithServerAction, `rfqTech/${rfqId}`)
// 저장 경로 & 파일명 기록
savedFiles.push({
- fileName: originalName, // 원본 파일명으로 첨부
- filePath: `/rfq/${rfqId}/${fileName}`, // public 이하 경로
- absolutePath: savePath,
+ fileName: file.name, // 원본 파일명으로 첨부
+ filePath: saveResult.publicPath, // public 이하 경로
+ absolutePath: saveResult.publicPath,
})
}
@@ -1652,22 +1605,9 @@ export async function createRfqCommentWithAttachments(params: {
// 2) 첨부파일 처리
if (files && files.length > 0) {
- const rfqDir = path.join(process.cwd(), "public", "rfq", String(rfqId));
- // 폴더 없으면 생성
- await fs.mkdir(rfqDir, { recursive: true });
-
for (const file of files) {
- const ab = await file.arrayBuffer();
- const buffer = Buffer.from(ab);
- // 2-2) 고유 파일명
- const uniqueName = `${randomUUID()}-${file.name}`;
- // 예) "rfq/123/xxx"
- const relativePath = path.join("rfq", String(rfqId), uniqueName);
- const absolutePath = path.join(process.cwd(), "public", relativePath);
-
- // 2-3) 파일 저장
- await fs.writeFile(absolutePath, buffer);
+ const saveResult = await saveDRMFile(file, decryptWithServerAction, `rfqTech/${rfqId}`)
// DB에 첨부파일 row 생성
await db.insert(rfqAttachments).values({
@@ -1677,7 +1617,7 @@ export async function createRfqCommentWithAttachments(params: {
cbeId: cbeId || null,
commentId: insertedComment.id, // 새 코멘트와 연결
fileName: file.name,
- filePath: "/" + relativePath.replace(/\\/g, "/"),
+ filePath: saveResult.publicPath!,
})
}
}
@@ -2045,37 +1985,14 @@ export async function uploadTbeResponseFile(formData: FormData) {
}
}
- // 타임스탬프 기반 고유 파일명 생성
- const timestamp = Date.now()
- const originalName = file.name
- const fileExtension = originalName.split(".").pop()
- const fileName = `${originalName.split(".")[0]}-${timestamp}.${fileExtension}`
-
- // 업로드 디렉토리 및 경로 정의
- const uploadDir = join(process.cwd(), "public", "rfq", "tbe-responses")
-
- // 디렉토리가 없으면 생성
- try {
- await mkdir(uploadDir, { recursive: true })
- } catch (error) {
- // 이미 존재하면 무시
- }
-
- const filePath = join(uploadDir, fileName)
-
- // 파일을 버퍼로 변환
- const bytes = await file.arrayBuffer()
- const buffer = Buffer.from(bytes)
-
- // 파일을 서버에 저장
- await writeFile(filePath, buffer)
+ const saveResult = await saveFile({file, directory:`rfqTech/${rfqId}/tbe-responses`})
// 먼저 vendorTechnicalResponses 테이블에 엔트리 생성
const technicalResponse = await db.insert(vendorTechnicalResponses)
.values({
responseId: vendorResponseId,
summary: "TBE 응답 파일 업로드", // 필요에 따라 수정
- notes: `파일명: ${originalName}`,
+ notes: `파일명: ${file.name}`,
responseStatus:"SUBMITTED"
})
.returning({ id: vendorTechnicalResponses.id });
@@ -2083,9 +2000,6 @@ export async function uploadTbeResponseFile(formData: FormData) {
// 생성된 기술 응답 ID 가져오기
const technicalResponseId = technicalResponse[0].id;
- // 파일 정보를 데이터베이스에 저장
- const dbFilePath = `rfq/tbe-responses/${fileName}`
-
// vendorResponseAttachments 테이블 스키마에 맞게 데이터 삽입
await db.insert(vendorResponseAttachments)
.values({
@@ -2096,8 +2010,8 @@ export async function uploadTbeResponseFile(formData: FormData) {
// vendorId와 evaluationId 필드가 테이블에 있다면 포함, 없다면 제거
// vendorId: vendorId,
// evaluationId: evaluationId,
- fileName: originalName,
- filePath: dbFilePath,
+ fileName: file.name,
+ filePath: saveResult.publicPath!,
uploadedAt: new Date(),
});
@@ -2902,18 +2816,6 @@ export async function createCbeEvaluation(formData: FormData) {
const files = formData.getAll("files") as File[]
const hasFiles = files && files.length > 0 && files[0].size > 0
- // 파일 저장을 위한 디렉토리 생성 (파일이 있는 경우에만)
- let uploadDir = ""
- if (hasFiles) {
- uploadDir = path.join(process.cwd(), "public", "rfq", String(rfqId))
- try {
- await fs.mkdir(uploadDir, { recursive: true })
- } catch (err) {
- console.error("디렉토리 생성 실패:", err)
- return { error: "파일 업로드를 위한 디렉토리 생성에 실패했습니다." }
- }
- }
-
// 첨부 파일 정보를 저장할 배열
const attachments: { filename: string; path: string }[] = []
@@ -2921,23 +2823,13 @@ export async function createCbeEvaluation(formData: FormData) {
if (hasFiles) {
for (const file of files) {
if (file.size > 0) {
- const originalFilename = file.name
- const fileExtension = path.extname(originalFilename)
- const timestamp = new Date().getTime()
- const safeFilename = `cbe-${rfqId}-${timestamp}${fileExtension}`
- const filePath = path.join("rfq", String(rfqId), safeFilename)
- const fullPath = path.join(process.cwd(), "public", filePath)
-
try {
- // File을 ArrayBuffer로 변환하여 파일 시스템에 저장
- const arrayBuffer = await file.arrayBuffer()
- const buffer = Buffer.from(arrayBuffer)
- await fs.writeFile(fullPath, buffer)
+ const saveResult = await saveDRMFile(file, decryptWithServerAction, `rfqTech/${rfqId}`)
// 첨부 파일 정보 추가
attachments.push({
- filename: originalFilename,
- path: fullPath, // 이메일 첨부를 위한 전체 경로
+ filename: file.name,
+ path: saveResult.publicPath!, // 이메일 첨부를 위한 전체 경로
})
} catch (err) {
console.error(`파일 저장 실패:`, err)