package cn.iocoder.yudao.module.srm.service.tender;
|
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmSupplierQuoteSaveReqVO;
|
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.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.dal.mysql.SrmTenderProjectMapper;
|
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 cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
|
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.List;
|
|
/**
|
* SRM 投标管理 Service 实现类
|
*/
|
@Service
|
@Validated
|
public class SrmTenderBidServiceImpl implements SrmTenderBidService {
|
|
@Resource
|
private SrmTenderBidMapper tenderBidMapper;
|
|
@Resource
|
private SrmSupplierQuoteMapper supplierQuoteMapper;
|
|
@Resource
|
private SrmTenderProjectMapper tenderProjectMapper;
|
|
@Resource
|
private SrmSupplierApplyMapper supplierApplyMapper;
|
|
// ========== 投标管理 ==========
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long createBid(SrmTenderBidSaveReqVO createReqVO) {
|
// 校验招标项目是否存在且状态正确
|
validateTenderStatus(createReqVO.getTenderProjectId());
|
// 校验供应商是否已通过准入审批
|
if (!supplierApplyMapper.existsApprovedBySupplierId(createReqVO.getSupplierId())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_SUPPLIER_NOT_APPROVED);
|
}
|
// 校验供应商是否已参与投标
|
SrmTenderBidDO existing = tenderBidMapper.selectByTenderAndSupplier(createReqVO.getTenderProjectId(), createReqVO.getSupplierId());
|
if (existing != null) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_SUPPLIER_EXISTS);
|
}
|
SrmTenderBidDO bid = BeanUtils.toBean(createReqVO, SrmTenderBidDO.class);
|
bid.setBidStatus(BidStatusEnum.REGISTERED.getCode());
|
bid.setBidTime(LocalDateTime.now());
|
tenderBidMapper.insert(bid);
|
return bid.getId();
|
}
|
|
@Override
|
public SrmTenderBidDO getBid(Long id) {
|
return tenderBidMapper.selectById(id);
|
}
|
|
@Override
|
public List<SrmTenderBidDO> getBidListByProject(Long tenderProjectId) {
|
return tenderBidMapper.selectListByTenderProjectId(tenderProjectId);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void withdrawBid(Long id) {
|
SrmTenderBidDO bid = validateBidExists(id);
|
bid.setBidStatus(BidStatusEnum.WITHDRAWN.getCode());
|
tenderBidMapper.updateById(bid);
|
// 删除报价
|
supplierQuoteMapper.deleteByBidId(id);
|
}
|
|
// ========== 报价管理 ==========
|
|
@Override
|
public Long createQuote(SrmSupplierQuoteSaveReqVO createReqVO) {
|
// 校验投标状态(撤标后不允许报价)
|
SrmTenderBidDO bid = validateBidNotWithdrawn(createReqVO.getBidId());
|
// 校验同一投标下物料不可重复报价
|
if (supplierQuoteMapper.existsByBidAndMaterial(createReqVO.getBidId(), createReqVO.getTenderMaterialId())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_MATERIAL_DUPLICATE);
|
}
|
SrmSupplierQuoteDO quote = BeanUtils.toBean(createReqVO, SrmSupplierQuoteDO.class);
|
// 从投标记录中获取招标项目ID和供应商ID,避免前端遗漏导致数据库约束失败
|
quote.setTenderProjectId(bid.getTenderProjectId());
|
quote.setSupplierId(bid.getSupplierId());
|
supplierQuoteMapper.insert(quote);
|
return quote.getId();
|
}
|
|
@Override
|
public void updateQuote(SrmSupplierQuoteSaveReqVO updateReqVO) {
|
// 校验投标状态(撤标后不允许报价)
|
validateBidNotWithdrawn(updateReqVO.getBidId());
|
// 校验同一投标下物料不可重复报价(排除自身)
|
SrmSupplierQuoteDO existing = supplierQuoteMapper.selectById(updateReqVO.getId());
|
if (existing != null && !existing.getTenderMaterialId().equals(updateReqVO.getTenderMaterialId())) {
|
if (supplierQuoteMapper.existsByBidAndMaterial(updateReqVO.getBidId(), updateReqVO.getTenderMaterialId())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.QUOTE_MATERIAL_DUPLICATE);
|
}
|
}
|
SrmSupplierQuoteDO updateObj = BeanUtils.toBean(updateReqVO, SrmSupplierQuoteDO.class);
|
supplierQuoteMapper.updateById(updateObj);
|
}
|
|
@Override
|
public List<SrmSupplierQuoteDO> getQuoteList(Long bidId) {
|
return supplierQuoteMapper.selectListByBidId(bidId);
|
}
|
|
// ========== 校验方法 ==========
|
|
private SrmTenderBidDO validateBidExists(Long id) {
|
SrmTenderBidDO bid = tenderBidMapper.selectById(id);
|
if (bid == null) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_NOT_EXISTS);
|
}
|
return bid;
|
}
|
|
private SrmTenderBidDO validateBidNotWithdrawn(Long bidId) {
|
SrmTenderBidDO bid = validateBidExists(bidId);
|
if (BidStatusEnum.WITHDRAWN.getCode().equals(bid.getBidStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_WITHDRAWN_CANNOT_QUOTE);
|
}
|
return bid;
|
}
|
|
private void validateTenderStatus(Long tenderProjectId) {
|
if (tenderProjectMapper.selectById(tenderProjectId) == null) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_NOT_EXISTS);
|
}
|
}
|
}
|