diff options
Diffstat (limited to 'lib/bidding/detail/service.ts')
| -rw-r--r-- | lib/bidding/detail/service.ts | 62 |
1 files changed, 41 insertions, 21 deletions
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts index 956c1798..d9bcb255 100644 --- a/lib/bidding/detail/service.ts +++ b/lib/bidding/detail/service.ts @@ -71,7 +71,7 @@ export interface QuotationVendor { quotationAmount: number // 견적금액 currency: string submissionDate: string // 제출일 - isWinner: boolean // 낙찰여부 + isWinner: boolean | null // 낙찰여부 (null: 미정, true: 낙찰, false: 탈락) awardRatio: number | null // 발주비율 isBiddingParticipated: boolean | null // 본입찰 참여여부 status: 'pending' | 'submitted' | 'selected' | 'rejected' @@ -262,7 +262,7 @@ export async function getQuotationVendors(biddingId: number): Promise<QuotationV quotationAmount: Number(vendor.quotationAmount) || 0, currency: vendor.currency, submissionDate: vendor.submissionDate ? (vendor.submissionDate instanceof Date ? vendor.submissionDate.toISOString().split('T')[0] : String(vendor.submissionDate).split('T')[0]) : '', - isWinner: vendor.isWinner || false, + isWinner: vendor.isWinner, awardRatio: vendor.awardRatio ? Number(vendor.awardRatio) : null, isBiddingParticipated: vendor.isBiddingParticipated, status: vendor.status as 'pending' | 'submitted' | 'selected' | 'rejected', @@ -1208,7 +1208,7 @@ export async function uploadAwardDocument(biddingId: number, file: File, userId: originalFileName: file.name, filePath: saveResult.filePath, fileSize: file.size, - documentType: 'award', + documentType: 'other', title: '낙찰 관련 문서', description: '낙찰 관련 첨부파일', uploadedBy: userId, @@ -1347,7 +1347,7 @@ export async function awardBidding(biddingId: number, selectionReason: string, u eq(biddingCompanies.biddingId, biddingId), eq(biddingCompanies.isWinner, true) )) - + if (awardedCompanies.length === 0) { return { success: false, error: '낙찰된 업체가 없습니다. 먼저 발주비율을 산정해주세요.' } } @@ -1373,27 +1373,40 @@ export async function awardBidding(biddingId: number, selectionReason: string, u // 2. 선정 사유 저장 (첫 번째 낙찰 업체 기준으로 저장) const firstAwardedCompany = awardedCompanies[0] - await tx - .insert(vendorSelectionResults) - .values({ - biddingId, - selectedCompanyId: firstAwardedCompany.companyId, - selectionReason, - selectedBy: userId, - selectedAt: new Date(), - createdAt: new Date(), - updatedAt: new Date() - }) - .onConflictDoUpdate({ - target: [vendorSelectionResults.biddingId], - set: { + + // 기존 선정 결과 확인 + const existingResult = await tx + .select() + .from(vendorSelectionResults) + .where(eq(vendorSelectionResults.biddingId, biddingId)) + .limit(1) + + if (existingResult.length > 0) { + // 업데이트 + await tx + .update(vendorSelectionResults) + .set({ selectedCompanyId: firstAwardedCompany.companyId, selectionReason, selectedBy: userId, selectedAt: new Date(), updatedAt: new Date() - } - }) + }) + .where(eq(vendorSelectionResults.biddingId, biddingId)) + } else { + // 삽입 + await tx + .insert(vendorSelectionResults) + .values({ + biddingId, + selectedCompanyId: firstAwardedCompany.companyId, + selectionReason, + selectedBy: userId, + selectedAt: new Date(), + createdAt: new Date(), + updatedAt: new Date() + }) + } }) @@ -1644,12 +1657,14 @@ export interface PartnersBiddingListItem { isWinner: boolean | null isAttendingMeeting: boolean | null isPreQuoteSelected: boolean | null + isPreQuoteParticipated: boolean | null + preQuoteDeadline: Date | null isBiddingInvited: boolean | null notes: string | null createdAt: Date updatedAt: Date // updatedBy: string | null - + hasSpecificationMeeting: boolean | null // biddings 정보 biddingId: number biddingNumber: string @@ -1688,6 +1703,8 @@ export async function getBiddingListForPartners(companyId: number): Promise<Part isWinner: biddingCompanies.isWinner, isAttendingMeeting: biddingCompanies.isAttendingMeeting, isPreQuoteSelected: biddingCompanies.isPreQuoteSelected, + isPreQuoteParticipated: biddingCompanies.isPreQuoteParticipated, + preQuoteDeadline: biddingCompanies.preQuoteDeadline, isBiddingInvited: biddingCompanies.isBiddingInvited, notes: biddingCompanies.notes, createdAt: biddingCompanies.createdAt, @@ -1712,6 +1729,7 @@ export async function getBiddingListForPartners(companyId: number): Promise<Part managerPhone: biddings.managerPhone, currency: biddings.currency, budget: biddings.budget, + hasSpecificationMeeting: biddings.hasSpecificationMeeting, }) .from(biddingCompanies) .innerJoin(biddings, eq(biddingCompanies.biddingId, biddings.id)) @@ -1791,6 +1809,8 @@ export async function getBiddingDetailsForPartners(biddingId: number, companyId: isAttendingMeeting: biddingCompanies.isAttendingMeeting, isPreQuoteSelected: biddingCompanies.isPreQuoteSelected, isBiddingParticipated: biddingCompanies.isBiddingParticipated, + isPreQuoteParticipated: biddingCompanies.isPreQuoteParticipated, + hasSpecificationMeeting: biddings.hasSpecificationMeeting, // 응답한 조건들 (company_condition_responses) - 제시된 조건과 응답 모두 여기서 관리 paymentTermsResponse: companyConditionResponses.paymentTermsResponse, taxConditionsResponse: companyConditionResponses.taxConditionsResponse, |
