diff options
Diffstat (limited to 'lib/bidding/detail/service.ts')
| -rw-r--r-- | lib/bidding/detail/service.ts | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/bidding/detail/service.ts b/lib/bidding/detail/service.ts index 92be2eee..df8427da 100644 --- a/lib/bidding/detail/service.ts +++ b/lib/bidding/detail/service.ts @@ -2529,3 +2529,104 @@ export async function getBiddingDocumentsForPartners(biddingId: number) { } )() } + +// ================================================= +// 입찰가 비교 분석 함수들 +// ================================================= + +// 벤더별 입찰가 정보 조회 (캐시 적용) +export async function getVendorPricesForBidding(biddingId: number) { + return unstable_cache( + async () => { + try { + // 각 회사의 입찰가 정보를 조회 - 본입찰 참여 업체들 + const vendorPrices = await db + .select({ + companyId: biddingCompanies.companyId, + companyName: vendors.vendorName, + biddingCompanyId: biddingCompanies.id, + currency: sql<string>`'KRW'`, // 기본값 KRW + finalQuoteAmount: biddingCompanies.finalQuoteAmount, + isBiddingParticipated: biddingCompanies.isBiddingParticipated, + }) + .from(biddingCompanies) + .leftJoin(vendors, eq(biddingCompanies.companyId, vendors.id)) + .where(and( + eq(biddingCompanies.biddingId, biddingId), + eq(biddingCompanies.isBiddingParticipated, true), // 본입찰 참여 업체만 + sql`${biddingCompanies.finalQuoteAmount} IS NOT NULL` // 입찰가를 제출한 업체만 + )) + + console.log(`Found ${vendorPrices.length} vendors for bidding ${biddingId}`) + + const result: any[] = [] + + for (const vendor of vendorPrices) { + try { + // 해당 회사의 품목별 입찰가 조회 (본입찰 데이터) + const itemPrices = await db + .select({ + prItemId: companyPrItemBids.prItemId, + itemName: prItemsForBidding.itemInfo, // itemInfo 사용 + itemNumber: prItemsForBidding.itemNumber, // itemNumber도 포함 + quantity: prItemsForBidding.quantity, + quantityUnit: prItemsForBidding.quantityUnit, + weight: prItemsForBidding.totalWeight, // totalWeight 사용 + weightUnit: prItemsForBidding.weightUnit, + unitPrice: companyPrItemBids.bidUnitPrice, + amount: companyPrItemBids.bidAmount, + proposedDeliveryDate: companyPrItemBids.proposedDeliveryDate, + }) + .from(companyPrItemBids) + .leftJoin(prItemsForBidding, eq(companyPrItemBids.prItemId, prItemsForBidding.id)) + .where(and( + eq(companyPrItemBids.biddingCompanyId, vendor.biddingCompanyId), + eq(companyPrItemBids.isPreQuote, false) // 본입찰 데이터만 + )) + .orderBy(prItemsForBidding.id) + + console.log(`Vendor ${vendor.companyName}: Found ${itemPrices.length} item prices`) + + // 총 금액은 biddingCompanies.finalQuoteAmount 사용 + const totalAmount = parseFloat(vendor.finalQuoteAmount || '0') + + result.push({ + companyId: vendor.companyId, + companyName: vendor.companyName || `Vendor ${vendor.companyId}`, + biddingCompanyId: vendor.biddingCompanyId, + totalAmount, + currency: vendor.currency, + itemPrices: itemPrices.map(item => ({ + prItemId: item.prItemId, + itemName: item.itemName || item.itemNumber || `Item ${item.prItemId}`, + quantity: parseFloat(item.quantity || '0'), + quantityUnit: item.quantityUnit || 'ea', + weight: item.weight ? parseFloat(item.weight) : null, + weightUnit: item.weightUnit, + unitPrice: parseFloat(item.unitPrice || '0'), + amount: parseFloat(item.amount || '0'), + proposedDeliveryDate: item.proposedDeliveryDate ? + (typeof item.proposedDeliveryDate === 'string' + ? item.proposedDeliveryDate + : item.proposedDeliveryDate.toISOString().split('T')[0]) + : null, + })) + }) + } catch (vendorError) { + console.error(`Error processing vendor ${vendor.companyId}:`, vendorError) + // 벤더 처리 중 에러가 발생해도 다른 벤더들은 계속 처리 + } + } + + return result + } catch (error) { + console.error('Failed to get vendor prices for bidding:', error) + return [] + } + }, + [`bidding-vendor-prices-${biddingId}`], + { + tags: [`bidding-${biddingId}`, 'quotation-vendors', 'pr-items'] + } + )() +} |
