diff options
Diffstat (limited to 'lib/bidding/detail/service.ts')
| -rw-r--r-- | lib/bidding/detail/service.ts | 97 |
1 files changed, 96 insertions, 1 deletions
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts index 17ea8f28..4ef48d33 100644 --- a/lib/bidding/detail/service.ts +++ b/lib/bidding/detail/service.ts @@ -64,6 +64,12 @@ export async function getBiddingDetailData(biddingId: number): Promise<BiddingDe awardRatio: biddingCompanies.awardRatio, isBiddingParticipated: biddingCompanies.isBiddingParticipated, invitationStatus: biddingCompanies.invitationStatus, + // 연동제 관련 필드 + isPriceAdjustmentApplicableQuestion: biddingCompanies.isPriceAdjustmentApplicableQuestion, + priceAdjustmentResponse: companyConditionResponses.priceAdjustmentResponse, // 벤더가 응답한 연동제 적용 여부 + shiPriceAdjustmentApplied: biddingCompanies.shiPriceAdjustmentApplied, + priceAdjustmentNote: biddingCompanies.priceAdjustmentNote, + hasChemicalSubstance: biddingCompanies.hasChemicalSubstance, // Contact info from biddingCompaniesContacts contactPerson: biddingCompaniesContacts.contactName, contactEmail: biddingCompaniesContacts.contactEmail, @@ -75,6 +81,10 @@ export async function getBiddingDetailData(biddingId: number): Promise<BiddingDe eq(biddingCompaniesContacts.biddingId, biddingId), eq(biddingCompaniesContacts.vendorId, biddingCompanies.companyId) )) + .leftJoin(companyConditionResponses, and( + eq(companyConditionResponses.biddingCompanyId, biddingCompanies.id), + eq(companyConditionResponses.isPreQuote, false) // 본입찰 데이터만 + )) .where(and( eq(biddingCompanies.biddingId, biddingId), eq(biddingCompanies.isBiddingParticipated, true) @@ -102,6 +112,12 @@ export async function getBiddingDetailData(biddingId: number): Promise<BiddingDe awardRatio: curr.awardRatio ? Number(curr.awardRatio) : null, isBiddingParticipated: curr.isBiddingParticipated, invitationStatus: curr.invitationStatus, + // 연동제 관련 필드 + isPriceAdjustmentApplicableQuestion: curr.isPriceAdjustmentApplicableQuestion, + priceAdjustmentResponse: curr.priceAdjustmentResponse, // 벤더가 응답한 연동제 적용 여부 + shiPriceAdjustmentApplied: curr.shiPriceAdjustmentApplied, + priceAdjustmentNote: curr.priceAdjustmentNote, + hasChemicalSubstance: curr.hasChemicalSubstance, documents: [], }) } @@ -148,6 +164,12 @@ export interface QuotationVendor { awardRatio: number | null // 발주비율 isBiddingParticipated: boolean | null // 본입찰 참여여부 invitationStatus: 'pending' | 'pre_quote_sent' | 'pre_quote_accepted' | 'pre_quote_declined' | 'pre_quote_submitted' | 'bidding_sent' | 'bidding_accepted' | 'bidding_declined' | 'bidding_cancelled' | 'bidding_submitted' + // 연동제 관련 필드 + isPriceAdjustmentApplicableQuestion: boolean | null // SHI가 요청한 연동제 요청 여부 + priceAdjustmentResponse: boolean | null // 벤더가 응답한 연동제 적용 여부 (companyConditionResponses.priceAdjustmentResponse) + shiPriceAdjustmentApplied: boolean | null // SHI 연동제 적용여부 + priceAdjustmentNote: string | null // 연동제 Note + hasChemicalSubstance: boolean | null // 화학물질여부 documents: Array<{ id: number fileName: string @@ -818,11 +840,52 @@ export async function registerBidding(biddingId: number, userId: string) { await db.transaction(async (tx) => { debugLog('registerBidding: Transaction started') - // 1. 입찰 상태를 오픈으로 변경 + + // 0. 입찰서 제출기간 계산 (오프셋 기반) + const { submissionStartOffset, submissionDurationDays, submissionStartDate, submissionEndDate } = bidding + + let calculatedStartDate = bidding.submissionStartDate + let calculatedEndDate = bidding.submissionEndDate + + // 오프셋 값이 있으면 날짜 계산 + if (submissionStartOffset !== null && submissionDurationDays !== null) { + // 시간 추출 (기본값: 시작 09:00, 마감 18:00) + const startTime = submissionStartDate + ? { hours: submissionStartDate.getUTCHours(), minutes: submissionStartDate.getUTCMinutes() } + : { hours: 9, minutes: 0 } + const endTime = submissionEndDate + ? { hours: submissionEndDate.getUTCHours(), minutes: submissionEndDate.getUTCMinutes() } + : { hours: 18, minutes: 0 } + + // baseDate = 현재일 날짜만 (00:00:00) + const baseDate = new Date() + baseDate.setHours(0, 0, 0, 0) + + // 시작일 = baseDate + offset일 + 시작시간 + calculatedStartDate = new Date(baseDate) + calculatedStartDate.setDate(calculatedStartDate.getDate() + submissionStartOffset) + calculatedStartDate.setHours(startTime.hours, startTime.minutes, 0, 0) + + // 마감일 = 시작일(날짜만) + duration일 + 마감시간 + calculatedEndDate = new Date(calculatedStartDate) + calculatedEndDate.setHours(0, 0, 0, 0) + calculatedEndDate.setDate(calculatedEndDate.getDate() + submissionDurationDays) + calculatedEndDate.setHours(endTime.hours, endTime.minutes, 0, 0) + + debugLog('registerBidding: Submission dates calculated', { + baseDate: baseDate.toISOString(), + calculatedStartDate: calculatedStartDate.toISOString(), + calculatedEndDate: calculatedEndDate.toISOString(), + }) + } + + // 1. 입찰 상태를 오픈으로 변경 + 제출기간 업데이트 await tx .update(biddings) .set({ status: 'bidding_opened', + submissionStartDate: calculatedStartDate, + submissionEndDate: calculatedEndDate, updatedBy: userName, updatedAt: new Date() }) @@ -2617,3 +2680,35 @@ export async function setSpecificationMeetingParticipation(biddingCompanyId: num return { success: false, error: '사양설명회 참여상태 업데이트에 실패했습니다.' } } } + +// 연동제 정보 업데이트 +export async function updatePriceAdjustmentInfo(params: { + biddingCompanyId: number + shiPriceAdjustmentApplied: boolean | null + priceAdjustmentNote: string | null + hasChemicalSubstance: boolean | null +}): Promise<{ success: boolean; error?: string }> { + try { + const result = await db.update(biddingCompanies) + .set({ + shiPriceAdjustmentApplied: params.shiPriceAdjustmentApplied, + priceAdjustmentNote: params.priceAdjustmentNote, + hasChemicalSubstance: params.hasChemicalSubstance, + updatedAt: new Date(), + }) + .where(eq(biddingCompanies.id, params.biddingCompanyId)) + .returning({ biddingId: biddingCompanies.biddingId }) + + if (result.length > 0) { + const biddingId = result[0].biddingId + revalidateTag(`bidding-${biddingId}`) + revalidateTag('quotation-vendors') + revalidatePath(`/evcp/bid/${biddingId}`) + } + + return { success: true } + } catch (error) { + console.error('Failed to update price adjustment info:', error) + return { success: false, error: '연동제 정보 업데이트에 실패했습니다.' } + } +} |
