summaryrefslogtreecommitdiff
path: root/lib/bidding/pre-quote/service.ts
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-09-05 03:46:21 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-09-05 03:46:21 +0000
commit66d64b482f2b6b52b0dd396ef998f27d491c70dd (patch)
treee616fa2782f26480e8a3c67663f78b8d681a7510 /lib/bidding/pre-quote/service.ts
parentc05596247bf396260375f3e193300650b731ee61 (diff)
(최겸) 구매 입찰 내 견적 첨부파일, PR 견적가 조회 기능 추가
Diffstat (limited to 'lib/bidding/pre-quote/service.ts')
-rw-r--r--lib/bidding/pre-quote/service.ts163
1 files changed, 145 insertions, 18 deletions
diff --git a/lib/bidding/pre-quote/service.ts b/lib/bidding/pre-quote/service.ts
index c34f6f9e..7f0a9083 100644
--- a/lib/bidding/pre-quote/service.ts
+++ b/lib/bidding/pre-quote/service.ts
@@ -5,6 +5,8 @@ import { biddingCompanies, companyConditionResponses, biddings, prItemsForBiddin
import { vendors } from '@/db/schema/vendors'
import { sendEmail } from '@/lib/mail/sendEmail'
import { eq, inArray, and } from 'drizzle-orm'
+import { saveFile } from '@/lib/file-stroage'
+import { downloadFile } from '@/lib/file-download'
interface CreateBiddingCompanyInput {
biddingId: number
@@ -524,17 +526,17 @@ export async function submitPreQuoteResponse(
majorApplicableRawMaterial: responseData.priceAdjustmentForm.majorApplicableRawMaterial,
adjustmentFormula: responseData.priceAdjustmentForm.adjustmentFormula,
rawMaterialPriceIndex: responseData.priceAdjustmentForm.rawMaterialPriceIndex,
- referenceDate: responseData.priceAdjustmentForm.referenceDate ? new Date(responseData.priceAdjustmentForm.referenceDate) : null,
- comparisonDate: responseData.priceAdjustmentForm.comparisonDate ? new Date(responseData.priceAdjustmentForm.comparisonDate) : null,
- adjustmentRatio: responseData.priceAdjustmentForm.adjustmentRatio,
+ referenceDate: responseData.priceAdjustmentForm.referenceDate as string || null,
+ comparisonDate: responseData.priceAdjustmentForm.comparisonDate as string || null,
+ adjustmentRatio: responseData.priceAdjustmentForm.adjustmentRatio || null,
notes: responseData.priceAdjustmentForm.notes,
adjustmentConditions: responseData.priceAdjustmentForm.adjustmentConditions,
majorNonApplicableRawMaterial: responseData.priceAdjustmentForm.majorNonApplicableRawMaterial,
adjustmentPeriod: responseData.priceAdjustmentForm.adjustmentPeriod,
contractorWriter: responseData.priceAdjustmentForm.contractorWriter,
- adjustmentDate: responseData.priceAdjustmentForm.adjustmentDate ? new Date(responseData.priceAdjustmentForm.adjustmentDate) : null,
+ adjustmentDate: responseData.priceAdjustmentForm.adjustmentDate as string || null,
nonApplicableReason: responseData.priceAdjustmentForm.nonApplicableReason,
- }
+ } as any
// 기존 연동제 정보가 있는지 확인
const existingPriceAdjustment = await tx
@@ -785,17 +787,17 @@ export async function savePreQuoteDraft(
majorApplicableRawMaterial: responseData.priceAdjustmentForm.majorApplicableRawMaterial,
adjustmentFormula: responseData.priceAdjustmentForm.adjustmentFormula,
rawMaterialPriceIndex: responseData.priceAdjustmentForm.rawMaterialPriceIndex,
- referenceDate: responseData.priceAdjustmentForm.referenceDate ? new Date(responseData.priceAdjustmentForm.referenceDate) : null,
- comparisonDate: responseData.priceAdjustmentForm.comparisonDate ? new Date(responseData.priceAdjustmentForm.comparisonDate) : null,
- adjustmentRatio: responseData.priceAdjustmentForm.adjustmentRatio,
+ referenceDate: responseData.priceAdjustmentForm.referenceDate as string || null,
+ comparisonDate: responseData.priceAdjustmentForm.comparisonDate as string || null,
+ adjustmentRatio: responseData.priceAdjustmentForm.adjustmentRatio || null,
notes: responseData.priceAdjustmentForm.notes,
adjustmentConditions: responseData.priceAdjustmentForm.adjustmentConditions,
majorNonApplicableRawMaterial: responseData.priceAdjustmentForm.majorNonApplicableRawMaterial,
adjustmentPeriod: responseData.priceAdjustmentForm.adjustmentPeriod,
contractorWriter: responseData.priceAdjustmentForm.contractorWriter,
- adjustmentDate: responseData.priceAdjustmentForm.adjustmentDate ? new Date(responseData.priceAdjustmentForm.adjustmentDate) : null,
+ adjustmentDate: responseData.priceAdjustmentForm.adjustmentDate as string || null,
nonApplicableReason: responseData.priceAdjustmentForm.nonApplicableReason,
- }
+ } as any
// 기존 연동제 정보가 있는지 확인
const existingPriceAdjustment = await tx
@@ -835,21 +837,37 @@ export async function savePreQuoteDraft(
export async function uploadPreQuoteDocument(
biddingId: number,
companyId: number,
- documentInfo: PreQuoteDocumentUpload,
+ file: File,
userId: string
) {
try {
+ // 파일 저장
+ const saveResult = await saveFile({
+ file,
+ directory: `bidding/${biddingId}/quotations`,
+ originalName: file.name,
+ userId
+ })
+
+ if (!saveResult.success) {
+ return {
+ success: false,
+ error: saveResult.error || '파일 저장에 실패했습니다.'
+ }
+ }
+
+ // 데이터베이스에 문서 정보 저장
const result = await db.insert(biddingDocuments)
.values({
biddingId,
companyId,
documentType: 'other', // 견적서 타입
- fileName: documentInfo.fileName,
- originalFileName: documentInfo.originalFileName,
- fileSize: documentInfo.fileSize,
- mimeType: documentInfo.mimeType,
- filePath: documentInfo.filePath,
- title: `견적서 - ${documentInfo.originalFileName}`,
+ fileName: saveResult.fileName!,
+ originalFileName: file.name,
+ fileSize: file.size,
+ mimeType: file.type,
+ filePath: saveResult.publicPath!, // publicPath 사용 (웹 접근 가능한 경로)
+ title: `견적서 - ${file.name}`,
description: '협력업체 제출 견적서',
isPublic: false,
isRequired: false,
@@ -884,7 +902,8 @@ export async function getPreQuoteDocuments(biddingId: number, companyId: number)
filePath: biddingDocuments.filePath,
title: biddingDocuments.title,
description: biddingDocuments.description,
- uploadedAt: biddingDocuments.uploadedAt
+ uploadedAt: biddingDocuments.uploadedAt,
+ uploadedBy: biddingDocuments.uploadedBy
})
.from(biddingDocuments)
.where(
@@ -934,4 +953,112 @@ export async function getSavedPrItemQuotations(biddingCompanyId: number) {
console.error('Failed to get saved PR item quotations:', error)
return []
}
+ }
+
+// 견적 문서 정보 조회 (다운로드용)
+export async function getPreQuoteDocumentForDownload(
+ documentId: number,
+ biddingId: number,
+ companyId: number
+) {
+ try {
+ const document = await db
+ .select({
+ fileName: biddingDocuments.fileName,
+ originalFileName: biddingDocuments.originalFileName,
+ filePath: biddingDocuments.filePath
+ })
+ .from(biddingDocuments)
+ .where(
+ and(
+ eq(biddingDocuments.id, documentId),
+ eq(biddingDocuments.biddingId, biddingId),
+ eq(biddingDocuments.companyId, companyId),
+ eq(biddingDocuments.documentType, 'other')
+ )
+ )
+ .limit(1)
+
+ if (document.length === 0) {
+ return {
+ success: false,
+ error: '문서를 찾을 수 없습니다.'
+ }
+ }
+
+ return {
+ success: true,
+ document: document[0]
+ }
+ } catch (error) {
+ console.error('Failed to get pre-quote document:', error)
+ return {
+ success: false,
+ error: '문서 정보 조회에 실패했습니다.'
+ }
+ }
+}
+
+// 견적 문서 삭제
+export async function deletePreQuoteDocument(
+ documentId: number,
+ biddingId: number,
+ companyId: number,
+ userId: string
+) {
+ try {
+ // 문서 존재 여부 및 권한 확인
+ const document = await db
+ .select({
+ id: biddingDocuments.id,
+ fileName: biddingDocuments.fileName,
+ filePath: biddingDocuments.filePath,
+ uploadedBy: biddingDocuments.uploadedBy
+ })
+ .from(biddingDocuments)
+ .where(
+ and(
+ eq(biddingDocuments.id, documentId),
+ eq(biddingDocuments.biddingId, biddingId),
+ eq(biddingDocuments.companyId, companyId),
+ eq(biddingDocuments.documentType, 'other')
+ )
+ )
+ .limit(1)
+
+ if (document.length === 0) {
+ return {
+ success: false,
+ error: '문서를 찾을 수 없습니다.'
+ }
+ }
+
+ const doc = document[0]
+
+ // 권한 확인 (업로드한 사용자만 삭제 가능)
+ if (doc.uploadedBy !== userId) {
+ return {
+ success: false,
+ error: '삭제 권한이 없습니다.'
+ }
+ }
+
+ // 데이터베이스에서 문서 정보 삭제
+ await db
+ .delete(biddingDocuments)
+ .where(eq(biddingDocuments.id, documentId))
+
+ // TODO: 실제 파일도 삭제하는 로직 추가 (필요시)
+
+ return {
+ success: true,
+ message: '문서가 성공적으로 삭제되었습니다.'
+ }
+ } catch (error) {
+ console.error('Failed to delete pre-quote document:', error)
+ return {
+ success: false,
+ error: '문서 삭제에 실패했습니다.'
+ }
+ }
} \ No newline at end of file