| | |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmSupplierQuoteMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderBidMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderProjectMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderMaterialMapper; |
| | | 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 org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.validation.annotation.Validated; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | import static cn.iocoder.yudao.module.srm.enums.LogRecordConstants.*; |
| | | |
| | |
| | | |
| | | @Resource |
| | | private SrmSupplierMapper supplierMapper; |
| | | @Resource |
| | | private SrmTenderMaterialMapper tenderMaterialMapper; |
| | | |
| | | // ========== 投标管理 ========== |
| | | |
| | |
| | | // ========== 报价管理 ========== |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @LogRecord(type = LOG_QUOTE_TYPE, subType = LOG_QUOTE_CREATE_SUB_TYPE, |
| | | bizNo = "{{#createReqVO.bidId}}", success = LOG_QUOTE_CREATE_SUCCESS) |
| | | public Long createQuote(SrmSupplierQuoteSaveReqVO createReqVO) { |
| | |
| | | if (project == null || !TenderStatusEnum.canCreateOrUpdateQuote(project.getTenderStatus())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_QUOTE_FORBIDDEN); |
| | | } |
| | | validateQuoteMaterial(createReqVO.getTenderMaterialId(), bid.getTenderProjectId()); |
| | | // 校验同一投标下物料不可重复报价 |
| | | if (supplierQuoteMapper.existsByBidAndMaterial(createReqVO.getBidId(), createReqVO.getTenderMaterialId())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_MATERIAL_DUPLICATE); |
| | |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void updateQuote(SrmSupplierQuoteSaveReqVO updateReqVO) { |
| | | // 校验投标状态(撤标后不允许报价) |
| | | SrmTenderBidDO bid = validateBidNotWithdrawn(updateReqVO.getBidId()); |
| | |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_QUOTE_FORBIDDEN); |
| | | } |
| | | // 校验同一投标下物料不可重复报价(排除自身) |
| | | SrmSupplierQuoteDO existing = supplierQuoteMapper.selectById(updateReqVO.getId()); |
| | | if (existing != null && !existing.getTenderMaterialId().equals(updateReqVO.getTenderMaterialId())) { |
| | | SrmSupplierQuoteDO existing = updateReqVO.getId() == null ? null : supplierQuoteMapper.selectById(updateReqVO.getId()); |
| | | if (existing == null) throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_NOT_EXISTS); |
| | | if (!Objects.equals(existing.getBidId(), bid.getId())) throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_BID_MISMATCH); |
| | | validateQuoteMaterial(updateReqVO.getTenderMaterialId(), bid.getTenderProjectId()); |
| | | if (!Objects.equals(existing.getTenderMaterialId(), updateReqVO.getTenderMaterialId())) { |
| | | if (supplierQuoteMapper.existsByBidAndMaterial(updateReqVO.getBidId(), updateReqVO.getTenderMaterialId())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_MATERIAL_DUPLICATE); |
| | | } |
| | | } |
| | | SrmSupplierQuoteDO updateObj = BeanUtils.toBean(updateReqVO, SrmSupplierQuoteDO.class); |
| | | updateObj.setTenderProjectId(bid.getTenderProjectId()); |
| | | updateObj.setSupplierId(bid.getSupplierId()); |
| | | supplierQuoteMapper.updateById(updateObj); |
| | | } |
| | | |
| | | private void validateQuoteMaterial(Long materialId, Long projectId) { |
| | | var material = materialId == null ? null : tenderMaterialMapper.selectById(materialId); |
| | | if (material == null || !Objects.equals(material.getTenderProjectId(), projectId)) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_MATERIAL_NOT_IN_PROJECT); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | return supplierQuoteMapper.selectListByBidId(bidId); |
| | | } |
| | | |
| | | // ========== 投标总金额(人工维护,可自动带出报价合计后调整) ========== |
| | | |
| | | @Override |
| | | public void updateBidTotal(Long bidId, BigDecimal bidTotalAmount) { |
| | | // 校验投标状态(撤标后不允许修改) |
| | | SrmTenderBidDO bid = validateBidNotWithdrawn(bidId); |
| | | // 校验招标项目状态:仅允许维护报价的招标状态下可修改 |
| | | SrmTenderProjectDO project = tenderProjectMapper.selectById(bid.getTenderProjectId()); |
| | | if (project == null || !TenderStatusEnum.canCreateOrUpdateQuote(project.getTenderStatus())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_QUOTE_FORBIDDEN); |
| | | } |
| | | // 仅在传入非 null 时更新(MyBatis-Plus updateById 会忽略 null 字段,null 视为不改) |
| | | if (bidTotalAmount != null) { |
| | | bid.setBidTotalAmount(bidTotalAmount); |
| | | tenderBidMapper.updateById(bid); |
| | | } |
| | | } |
| | | |
| | | // ========== 校验方法 ========== |
| | | |
| | | private SrmTenderBidDO validateBidExists(Long id) { |