11 小时以前 db46314b9c56256a31c9114bd45d9bd63368cbd8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
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);
        }
        // 校验投标编号是否重复
        if (tenderBidMapper.existsByBidNo(createReqVO.getBidNo())) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_NO_EXISTS);
        }
        // 校验供应商是否已参与投标
        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);
        }
    }
}