| | |
| | | award.setBidId(bidId); |
| | | award.setAwardNo("SMP" + System.currentTimeMillis()); |
| | | award.setAwardStatus(AwardStatusEnum.AWARDED.getCode()); |
| | | // 投标金额为空时,回退到该投标下所有报价之和,避免 award_amount 为空导致入库失败 |
| | | award.setAwardAmount(resolveAwardAmount(bidId, bid.getBidTotalAmount())); |
| | | // 投标金额为空时,回退到该投标下所有报价行金额之和 = Σ(报价单价 × 物料数量),避免 award_amount 为空导致入库失败 |
| | | award.setAwardAmount(resolveAwardAmount(id, bidId, bid.getBidTotalAmount())); |
| | | award.setAwardTime(LocalDateTime.now()); |
| | | award.setApprovalTime(LocalDateTime.now()); |
| | | bidAwardMapper.insert(award); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 解析中标金额:投标金额为空时,汇总该投标下所有报价 |
| | | * 解析中标金额:投标金额为空时,汇总该投标下所有报价行金额 = Σ(报价单价 × 物料数量) |
| | | */ |
| | | private BigDecimal resolveAwardAmount(Long bidId, BigDecimal bidTotalAmount) { |
| | | private BigDecimal resolveAwardAmount(Long tenderProjectId, Long bidId, BigDecimal bidTotalAmount) { |
| | | if (bidTotalAmount != null) { |
| | | return bidTotalAmount; |
| | | } |
| | | List<SrmSupplierQuoteDO> quotes = supplierQuoteMapper.selectListByBidId(bidId); |
| | | return quotes.stream() |
| | | .map(SrmSupplierQuoteDO::getQuotePrice) |
| | | .filter(Objects::nonNull) |
| | | List<SrmTenderMaterialDO> materials = tenderMaterialMapper.selectListByTenderProjectId(tenderProjectId); |
| | | Map<Long, BigDecimal> quantityMap = materials.stream() |
| | | .collect(Collectors.toMap(SrmTenderMaterialDO::getId, |
| | | material -> material.getQuantity() == null ? BigDecimal.ZERO : material.getQuantity())); |
| | | return supplierQuoteMapper.selectListByBidId(bidId).stream() |
| | | .filter(quote -> quote.getQuotePrice() != null && quote.getTenderMaterialId() != null) |
| | | .map(quote -> quote.getQuotePrice() |
| | | .multiply(quantityMap.getOrDefault(quote.getTenderMaterialId(), BigDecimal.ZERO))) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | } |
| | | |
| | |
| | | Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemList(productIds).getCheckedData() |
| | | .stream().collect(Collectors.toMap(MdmItemRespDTO::getId, Function.identity())); |
| | | |
| | | // 计算价格 |
| | | BigDecimal totalQuoteAmount = quotes.stream() |
| | | .map(SrmSupplierQuoteDO::getQuotePrice) |
| | | .filter(Objects::nonNull) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | // 计算价格(报价为“单价”口径:行金额 = 报价单价 × 数量; |
| | | // 定标金额与报价合计不一致时按行金额比例分摊,订单行单价仍取报价单价) |
| | | BigDecimal totalQuoteAmount = BigDecimal.ZERO; |
| | | for (SrmTenderMaterialDO material : materials) { |
| | | SrmSupplierQuoteDO quote = quoteMap.get(material.getId()); |
| | | BigDecimal quantity = material.getQuantity(); |
| | | if (quote == null || quote.getQuotePrice() == null |
| | | || quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | continue; |
| | | } |
| | | totalQuoteAmount = totalQuoteAmount.add(quote.getQuotePrice().multiply(quantity)); |
| | | } |
| | | BigDecimal awardAmount = award.getAwardAmount() != null ? award.getAwardAmount() : totalQuoteAmount; |
| | | BigDecimal ratio = totalQuoteAmount.compareTo(BigDecimal.ZERO) > 0 |
| | | ? awardAmount.divide(totalQuoteAmount, 8, RoundingMode.HALF_UP) |
| | |
| | | if (mdmItem == null) { |
| | | continue; |
| | | } |
| | | BigDecimal materialTotal = quotePrice.multiply(ratio); |
| | | BigDecimal unitPrice = materialTotal.divide(quantity, 4, RoundingMode.HALF_UP); |
| | | BigDecimal unitPrice = quotePrice.multiply(ratio).setScale(4, RoundingMode.HALF_UP); |
| | | ErpPurchaseOrderCreateReqDTO.Item item = new ErpPurchaseOrderCreateReqDTO.Item(); |
| | | item.setProductId(material.getProductId()); |
| | | item.setProductUnitId(mdmItem.getUnitMeasureId()); |