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 lombok.extern.slf4j.Slf4j;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.validation.annotation.Validated;
|
|
import java.math.BigDecimal;
|
import java.time.LocalDateTime;
|
import java.util.*;
|
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
|
/**
|
* SRM 定标管理 Service 实现类
|
*/
|
@Service
|
@Validated
|
@Slf4j
|
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
|
public SrmBidAwardDO getAwardByProjectId(Long tenderProjectId) {
|
return bidAwardMapper.selectByTenderProjectId(tenderProjectId);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void deleteAward(Long id) {
|
SrmBidAwardDO award = validateAwardExists(id);
|
bidAwardMapper.deleteById(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<SrmTenderMaterialDO> materials = tenderMaterialMapper
|
.selectListByTenderProjectId(award.getTenderProjectId());
|
if (CollUtil.isEmpty(materials)) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_NOT_EXISTS);
|
}
|
|
// 4. 查中标报价列表
|
List<SrmSupplierQuoteDO> quotes = supplierQuoteMapper.selectListByBidId(award.getBidId());
|
if (CollUtil.isEmpty(quotes)) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_QUOTE_NOT_EXISTS);
|
}
|
Map<Long, SrmSupplierQuoteDO> quoteMap = quotes.stream()
|
.collect(Collectors.toMap(
|
SrmSupplierQuoteDO::getTenderMaterialId,
|
Function.identity(),
|
(a, b) -> a));
|
|
// 5. 批量查 MDM 物料,获取计量单位
|
Set<Long> productIds = materials.stream()
|
.map(SrmTenderMaterialDO::getProductId)
|
.collect(Collectors.toSet());
|
Map<Long, MdmItemRespDTO> itemMap = mdmItemApi.getItemList(productIds).getCheckedData()
|
.stream().collect(Collectors.toMap(MdmItemRespDTO::getId, Function.identity()));
|
|
// 6. 构建订单项
|
List<ErpPurchaseOrderCreateReqDTO.Item> 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.setDepositPrice(BigDecimal.ZERO);
|
createReq.setItems(orderItems);
|
createReq.setRemark("SRM 定标自动生成, 定标编号: " + award.getAwardNo());
|
|
Long purchaseOrderId = erpPurchaseOrderApi.createPurchaseOrder(createReq).getCheckedData();
|
|
// 获取采购订单号
|
String purchaseOrderNo = null;
|
try {
|
purchaseOrderNo = erpPurchaseOrderApi.getPurchaseOrder(purchaseOrderId)
|
.getCheckedData().getNo();
|
} catch (Exception e) {
|
log.warn("[generatePurchaseOrder] 获取采购订单号失败,purchaseOrderId={}", purchaseOrderId, e);
|
}
|
|
// 8. 更新定标记录
|
award.setPurchaseOrderId(purchaseOrderId);
|
award.setPurchaseOrderNo(purchaseOrderNo);
|
award.setAwardStatus(AwardStatusEnum.ORDER_GENERATED.getCode());
|
bidAwardMapper.updateById(award);
|
|
// 9. 更新招标项目状态
|
SrmTenderProjectDO project = tenderProjectMapper.selectById(award.getTenderProjectId());
|
if (project != null) {
|
project.setTenderStatus(TenderStatusEnum.CLOSED.getCode());
|
tenderProjectMapper.updateById(project);
|
}
|
}
|
|
private SrmBidAwardDO validateAwardExists(Long id) {
|
SrmBidAwardDO award = bidAwardMapper.selectById(id);
|
if (award == null) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.AWARD_NOT_EXISTS);
|
}
|
return award;
|
}
|
|
}
|