package cn.iocoder.yudao.module.srm.service.tender; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderCreateReqDTO; import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmBidAwardSaveReqVO; import cn.iocoder.yudao.module.srm.dal.dataobject.*; import cn.iocoder.yudao.module.srm.dal.mysql.*; import cn.iocoder.yudao.module.srm.enums.AwardStatusEnum; import cn.iocoder.yudao.module.srm.enums.BidStatusEnum; import cn.iocoder.yudao.module.srm.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.srm.enums.TenderStatusEnum; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; /** * SRM 定标管理 Service 实现类 */ @Service @Validated public class SrmBidAwardServiceImpl implements SrmBidAwardService { @Resource private SrmBidAwardMapper bidAwardMapper; @Resource private SrmTenderBidMapper tenderBidMapper; @Resource private SrmTenderProjectMapper tenderProjectMapper; @Resource private SrmSupplierMapper supplierMapper; @Resource private SrmTenderMaterialMapper tenderMaterialMapper; @Resource private SrmSupplierQuoteMapper supplierQuoteMapper; @Resource private MdmItemApi mdmItemApi; @Resource private ErpPurchaseOrderApi erpPurchaseOrderApi; @Override @Transactional(rollbackFor = Exception.class) public Long createAward(SrmBidAwardSaveReqVO createReqVO) { // 校验是否已存在定标 SrmBidAwardDO existing = bidAwardMapper.selectByTenderProjectId(createReqVO.getTenderProjectId()); if (existing != null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_SUPPLIER_EXISTS); } SrmBidAwardDO award = BeanUtils.toBean(createReqVO, SrmBidAwardDO.class); award.setAwardStatus(AwardStatusEnum.PENDING_APPROVAL.getCode()); award.setAwardTime(LocalDateTime.now()); bidAwardMapper.insert(award); // 更新投标状态为中标 SrmTenderBidDO bid = tenderBidMapper.selectById(createReqVO.getBidId()); if (bid != null) { bid.setBidStatus(BidStatusEnum.WIN.getCode()); tenderBidMapper.updateById(bid); } return award.getId(); } @Override public SrmBidAwardDO getAward(Long id) { return bidAwardMapper.selectById(id); } @Override @Transactional(rollbackFor = Exception.class) public void approveAward(Long id) { SrmBidAwardDO award = validateAwardExists(id); award.setAwardStatus(AwardStatusEnum.AWARDED.getCode()); award.setApprovalTime(LocalDateTime.now()); bidAwardMapper.updateById(award); // 更新招标项目状态为已定标 SrmTenderProjectDO project = tenderProjectMapper.selectById(award.getTenderProjectId()); if (project != null) { project.setTenderStatus(TenderStatusEnum.AWARDED.getCode()); tenderProjectMapper.updateById(project); } } @Override @Transactional(rollbackFor = Exception.class) public void generatePurchaseOrder(Long id) { // 1. 校验定标存在且状态为已定标 SrmBidAwardDO award = validateAwardExists(id); if (!AwardStatusEnum.AWARDED.getCode().equals(award.getAwardStatus())) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_STATUS_NOT_AWARDED); } // 2. 查 SRM 供应商 SrmSupplierDO srmSupplier = supplierMapper.selectById(award.getSupplierId()); if (srmSupplier == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_SUPPLIER_NOT_SYNCED); } // 3. 查招标物料列表 List materials = tenderMaterialMapper .selectListByTenderProjectId(award.getTenderProjectId()); if (CollUtil.isEmpty(materials)) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_NOT_EXISTS); } // 4. 查中标报价列表 List quotes = supplierQuoteMapper.selectListByBidId(award.getBidId()); if (CollUtil.isEmpty(quotes)) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_QUOTE_NOT_EXISTS); } Map quoteMap = quotes.stream() .collect(Collectors.toMap( SrmSupplierQuoteDO::getTenderMaterialId, Function.identity(), (a, b) -> a)); // 5. 批量查 MDM 物料,获取计量单位 Set productIds = materials.stream() .map(SrmTenderMaterialDO::getProductId) .collect(Collectors.toSet()); Map itemMap = mdmItemApi.getItemList(productIds).getCheckedData() .stream().collect(Collectors.toMap(MdmItemRespDTO::getId, Function.identity())); // 6. 构建订单项 List orderItems = new ArrayList<>(); for (SrmTenderMaterialDO material : materials) { SrmSupplierQuoteDO quote = quoteMap.get(material.getId()); if (quote == null) { continue; } MdmItemRespDTO mdmItem = itemMap.get(material.getProductId()); if (mdmItem == null) { continue; } ErpPurchaseOrderCreateReqDTO.Item item = new ErpPurchaseOrderCreateReqDTO.Item(); item.setProductId(material.getProductId()); item.setProductUnitId(mdmItem.getUnitMeasureId()); item.setProductPrice(quote.getQuotePrice()); item.setCount(material.getQuantity()); item.setTaxPercent(quote.getTaxRate()); item.setRemark("招标编号: " + award.getAwardNo()); orderItems.add(item); } // 7. 构建并调用 ERP 创建采购订单 ErpPurchaseOrderCreateReqDTO createReq = new ErpPurchaseOrderCreateReqDTO(); createReq.setSupplierId(srmSupplier.getId()); createReq.setOrderTime(LocalDateTime.now()); createReq.setItems(orderItems); createReq.setRemark("SRM 定标自动生成, 定标编号: " + award.getAwardNo()); Long purchaseOrderId = erpPurchaseOrderApi.createPurchaseOrder(createReq).getCheckedData(); // 8. 更新定标记录 award.setPurchaseOrderId(purchaseOrderId); award.setAwardStatus(AwardStatusEnum.ORDER_GENERATED.getCode()); bidAwardMapper.updateById(award); } private SrmBidAwardDO validateAwardExists(Long id) { SrmBidAwardDO award = bidAwardMapper.selectById(id); if (award == null) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_NOT_EXISTS); } return award; } }