diff options
Diffstat (limited to 'lib/bidding/pre-quote/service.ts')
| -rw-r--r-- | lib/bidding/pre-quote/service.ts | 163 |
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 |
