diff options
Diffstat (limited to 'lib/bidding/detail/service.ts')
| -rw-r--r-- | lib/bidding/detail/service.ts | 234 |
1 files changed, 233 insertions, 1 deletions
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts index 025b9eac..92be2eee 100644 --- a/lib/bidding/detail/service.ts +++ b/lib/bidding/detail/service.ts @@ -1701,6 +1701,7 @@ export interface PartnersBiddingListItem { managerPhone: string | null currency: string budget: number | null + isUrgent: boolean | null // 긴급여부 // 계산된 필드 responseDeadline: Date | null // 참여회신 마감일 (submissionStartDate 전 3일) @@ -1747,6 +1748,7 @@ export async function getBiddingListForPartners(companyId: number): Promise<Part managerPhone: biddings.managerPhone, currency: biddings.currency, budget: biddings.budget, + isUrgent: biddings.isUrgent, hasSpecificationMeeting: biddings.hasSpecificationMeeting, }) .from(biddingCompanies) @@ -1814,6 +1816,7 @@ export async function getBiddingDetailsForPartners(biddingId: number, companyId: // 상태 및 담당자 status: biddings.status, + isUrgent: biddings.isUrgent, managerName: biddings.managerName, managerEmail: biddings.managerEmail, managerPhone: biddings.managerPhone, @@ -2278,7 +2281,7 @@ export async function getPriceAdjustmentForm(companyConditionResponseId: number) } } -// 입찰업체 ID로 연동제 정보 조회 +// 입찰업체 ID로 연동제 정보 조회 export async function getPriceAdjustmentFormByBiddingCompanyId(biddingCompanyId: number) { try { const result = await db @@ -2297,3 +2300,232 @@ export async function getPriceAdjustmentFormByBiddingCompanyId(biddingCompanyId: return null } } + +// ================================================= +// 입찰 문서 관리 함수들 (발주처 문서용) +// ================================================= + +// 입찰 문서 업로드 (발주처 문서용 - companyId: null) +export async function uploadBiddingDocument( + biddingId: number, + file: File, + documentType: string, + title: string, + description: string, + userId: string +) { + try { + const userName = await getUserNameById(userId) + + // 파일 저장 + const saveResult = await saveFile({ + file, + directory: `bidding/${biddingId}/documents`, + originalName: file.name, + userId + }) + + if (!saveResult.success) { + return { + success: false, + error: saveResult.error || '파일 저장에 실패했습니다.' + } + } + + // 데이터베이스에 문서 정보 저장 (companyId는 null로 설정) + const result = await db.insert(biddingDocuments) + .values({ + biddingId, + companyId: null, // 발주처 문서 + documentType: documentType as any, + fileName: saveResult.fileName!, + originalFileName: file.name, + fileSize: file.size, + mimeType: file.type, + filePath: saveResult.publicPath!, // publicPath 사용 (웹 접근 가능한 경로) + title, + description, + isPublic: true, // 발주처 문서는 기본적으로 공개 + isRequired: false, + uploadedBy: userName, + uploadedAt: new Date() + }) + .returning() + + // 캐시 무효화 + revalidateTag(`bidding-${biddingId}`) + revalidateTag('bidding-documents') + + return { + success: true, + message: '문서가 성공적으로 업로드되었습니다.', + documentId: result[0].id + } + } catch (error) { + console.error('Failed to upload bidding document:', error) + return { + success: false, + error: error instanceof Error ? error.message : '문서 업로드에 실패했습니다.' + } + } +} + +// 업로드된 입찰 문서 목록 조회 (발주처 문서용) +export async function getBiddingDocuments(biddingId: number) { + try { + const documents = await db + .select({ + id: biddingDocuments.id, + biddingId: biddingDocuments.biddingId, + companyId: biddingDocuments.companyId, + documentType: biddingDocuments.documentType, + fileName: biddingDocuments.fileName, + originalFileName: biddingDocuments.originalFileName, + fileSize: biddingDocuments.fileSize, + filePath: biddingDocuments.filePath, + title: biddingDocuments.title, + description: biddingDocuments.description, + uploadedAt: biddingDocuments.uploadedAt, + uploadedBy: biddingDocuments.uploadedBy + }) + .from(biddingDocuments) + .where( + and( + eq(biddingDocuments.biddingId, biddingId), + sql`${biddingDocuments.companyId} IS NULL` // 발주처 문서만 + ) + ) + .orderBy(desc(biddingDocuments.uploadedAt)) + + return documents + } catch (error) { + console.error('Failed to get bidding documents:', error) + return [] + } +} + +// 입찰 문서 다운로드용 정보 조회 +export async function getBiddingDocumentForDownload(documentId: number, biddingId: number) { + try { + const documents = await db + .select() + .from(biddingDocuments) + .where( + and( + eq(biddingDocuments.id, documentId), + eq(biddingDocuments.biddingId, biddingId), + sql`${biddingDocuments.companyId} IS NULL` // 발주처 문서만 + ) + ) + .limit(1) + + if (documents.length === 0) { + return { + success: false, + error: '문서를 찾을 수 없습니다.' + } + } + + return { + success: true, + document: documents[0] + } + } catch (error) { + console.error('Failed to get bidding document for download:', error) + return { + success: false, + error: '문서 다운로드 준비에 실패했습니다.' + } + } +} + +// 입찰 문서 삭제 (발주처 문서용) +export async function deleteBiddingDocument(documentId: number, biddingId: number, userId: string) { + try { + const userName = await getUserNameById(userId) + + // 문서 정보 조회 (업로더 확인) + const documents = await db + .select() + .from(biddingDocuments) + .where( + and( + eq(biddingDocuments.id, documentId), + eq(biddingDocuments.biddingId, biddingId), + sql`${biddingDocuments.companyId} IS NULL`, // 발주처 문서만 + eq(biddingDocuments.uploadedBy, userName) + ) + ) + .limit(1) + + if (documents.length === 0) { + return { + success: false, + error: '삭제할 수 있는 문서가 없습니다.' + } + } + + // DB에서 삭제 + await db + .delete(biddingDocuments) + .where(eq(biddingDocuments.id, documentId)) + + // 캐시 무효화 + revalidateTag(`bidding-${biddingId}`) + revalidateTag('bidding-documents') + + return { + success: true, + message: '문서가 성공적으로 삭제되었습니다.' + } + } catch (error) { + console.error('Failed to delete bidding document:', error) + return { + success: false, + error: '문서 삭제에 실패했습니다.' + } + } +} + +// 협력업체용 발주처 문서 조회 (캐시 적용) +export async function getBiddingDocumentsForPartners(biddingId: number) { + return unstable_cache( + async () => { + try { + const documents = await db + .select({ + id: biddingDocuments.id, + biddingId: biddingDocuments.biddingId, + companyId: biddingDocuments.companyId, + documentType: biddingDocuments.documentType, + fileName: biddingDocuments.fileName, + originalFileName: biddingDocuments.originalFileName, + fileSize: biddingDocuments.fileSize, + filePath: biddingDocuments.filePath, + title: biddingDocuments.title, + description: biddingDocuments.description, + uploadedAt: biddingDocuments.uploadedAt, + uploadedBy: biddingDocuments.uploadedBy + }) + .from(biddingDocuments) + .where( + and( + eq(biddingDocuments.biddingId, biddingId), + sql`${biddingDocuments.companyId} IS NULL`, // 발주처 문서만 + eq(biddingDocuments.isPublic, true) // 공개 문서만 + ) + ) + .orderBy(desc(biddingDocuments.uploadedAt)) + + return documents + } catch (error) { + console.error('Failed to get bidding documents for partners:', error) + return [] + } + }, + [`bidding-documents-partners-${biddingId}`], + { + tags: [`bidding-${biddingId}`, 'bidding-documents'] + } + )() +} |
