| | |
| | | import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmTenderBidSaveReqVO; |
| | | import cn.iocoder.yudao.module.srm.dal.dataobject.SrmSupplierQuoteDO; |
| | | import cn.iocoder.yudao.module.srm.dal.dataobject.SrmTenderBidDO; |
| | | import cn.iocoder.yudao.module.srm.dal.dataobject.SrmTenderProjectDO; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmSupplierApplyMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmSupplierQuoteMapper; |
| | | import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderBidMapper; |
| | |
| | | import cn.iocoder.yudao.module.srm.enums.ErrorCodeConstants; |
| | | import cn.iocoder.yudao.module.srm.enums.TenderStatusEnum; |
| | | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| | | import com.mzt.logapi.context.LogRecordContext; |
| | | import com.mzt.logapi.starter.annotation.LogRecord; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.module.srm.enums.LogRecordConstants.*; |
| | | |
| | | /** |
| | | * SRM 投标管理 Service 实现类 |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @LogRecord(type = LOG_BID_TYPE, subType = LOG_BID_CREATE_SUB_TYPE, |
| | | bizNo = "{{#createReqVO.bidNo}}", success = LOG_BID_CREATE_SUCCESS) |
| | | public Long createBid(SrmTenderBidSaveReqVO createReqVO) { |
| | | // 校验招标项目是否存在且状态正确 |
| | | validateTenderStatus(createReqVO.getTenderProjectId()); |
| | | // 校验招标项目状态(PUBLISHED/BIDDING 才允许投标) |
| | | SrmTenderProjectDO project = validateTenderStatus(createReqVO.getTenderProjectId()); |
| | | // 检查投标截止时间 |
| | | if (project.getEndTime() != null && LocalDateTime.now().isAfter(project.getEndTime())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_END_TIME_PASSED); |
| | | } |
| | | // 校验供应商是否已通过准入审批 |
| | | if (!supplierApplyMapper.existsApprovedBySupplierId(createReqVO.getSupplierId())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_SUPPLIER_NOT_APPROVED); |
| | | } |
| | | // 校验投标编号是否重复 |
| | | if (tenderBidMapper.existsByBidNo(createReqVO.getBidNo())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_NO_EXISTS); |
| | | } |
| | | // 校验供应商是否已参与投标 |
| | | SrmTenderBidDO existing = tenderBidMapper.selectByTenderAndSupplier(createReqVO.getTenderProjectId(), createReqVO.getSupplierId()); |
| | |
| | | bid.setBidStatus(BidStatusEnum.REGISTERED.getCode()); |
| | | bid.setBidTime(LocalDateTime.now()); |
| | | tenderBidMapper.insert(bid); |
| | | LogRecordContext.putVariable("bidNo", bid.getBidNo()); |
| | | LogRecordContext.putVariable("tenderName", project.getTenderName()); |
| | | return bid.getId(); |
| | | } |
| | | |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | @LogRecord(type = LOG_BID_TYPE, subType = LOG_BID_WITHDRAW_SUB_TYPE, |
| | | bizNo = "{{#id}}", success = LOG_BID_WITHDRAW_SUCCESS) |
| | | public void withdrawBid(Long id) { |
| | | SrmTenderBidDO bid = validateBidExists(id); |
| | | // 检查招标项目状态:仅 PUBLISHED/BIDDING 允许撤标 |
| | | SrmTenderProjectDO project = tenderProjectMapper.selectById(bid.getTenderProjectId()); |
| | | if (project == null || !TenderStatusEnum.canCreateOrUpdateQuote(project.getTenderStatus())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_BID_FORBIDDEN_WITHDRAW); |
| | | } |
| | | bid.setBidStatus(BidStatusEnum.WITHDRAWN.getCode()); |
| | | tenderBidMapper.updateById(bid); |
| | | // 删除报价 |
| | | supplierQuoteMapper.deleteByBidId(id); |
| | | LogRecordContext.putVariable("bidNo", bid.getBidNo()); |
| | | } |
| | | |
| | | // ========== 报价管理 ========== |
| | | |
| | | @Override |
| | | @LogRecord(type = LOG_QUOTE_TYPE, subType = LOG_QUOTE_CREATE_SUB_TYPE, |
| | | bizNo = "{{#createReqVO.bidId}}", success = LOG_QUOTE_CREATE_SUCCESS) |
| | | public Long createQuote(SrmSupplierQuoteSaveReqVO createReqVO) { |
| | | // 校验投标状态(撤标后不允许报价) |
| | | SrmTenderBidDO bid = validateBidNotWithdrawn(createReqVO.getBidId()); |
| | | // 校验招标项目状态:仅 PUBLISHED/BIDDING 允许报价 |
| | | SrmTenderProjectDO project = tenderProjectMapper.selectById(bid.getTenderProjectId()); |
| | | if (project == null || !TenderStatusEnum.canCreateOrUpdateQuote(project.getTenderStatus())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_QUOTE_FORBIDDEN); |
| | | } |
| | | // 校验同一投标下物料不可重复报价 |
| | | if (supplierQuoteMapper.existsByBidAndMaterial(createReqVO.getBidId(), createReqVO.getTenderMaterialId())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_MATERIAL_DUPLICATE); |
| | |
| | | @Override |
| | | public void updateQuote(SrmSupplierQuoteSaveReqVO updateReqVO) { |
| | | // 校验投标状态(撤标后不允许报价) |
| | | validateBidNotWithdrawn(updateReqVO.getBidId()); |
| | | SrmTenderBidDO bid = validateBidNotWithdrawn(updateReqVO.getBidId()); |
| | | // 校验招标项目状态:仅 PUBLISHED/BIDDING 允许报价 |
| | | SrmTenderProjectDO project = tenderProjectMapper.selectById(bid.getTenderProjectId()); |
| | | if (project == null || !TenderStatusEnum.canCreateOrUpdateQuote(project.getTenderStatus())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_QUOTE_FORBIDDEN); |
| | | } |
| | | // 校验同一投标下物料不可重复报价(排除自身) |
| | | SrmSupplierQuoteDO existing = supplierQuoteMapper.selectById(updateReqVO.getId()); |
| | | if (existing != null && !existing.getTenderMaterialId().equals(updateReqVO.getTenderMaterialId())) { |
| | |
| | | return bid; |
| | | } |
| | | |
| | | private void validateTenderStatus(Long tenderProjectId) { |
| | | if (tenderProjectMapper.selectById(tenderProjectId) == null) { |
| | | private SrmTenderProjectDO validateTenderStatus(Long tenderProjectId) { |
| | | SrmTenderProjectDO project = tenderProjectMapper.selectById(tenderProjectId); |
| | | if (project == null) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_NOT_EXISTS); |
| | | } |
| | | if (!TenderStatusEnum.canCreateBid(project.getTenderStatus())) { |
| | | throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_BID_FORBIDDEN); |
| | | } |
| | | return project; |
| | | } |
| | | } |