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.SrmBidEvaluationSaveReqVO;
|
import cn.iocoder.yudao.module.srm.dal.dataobject.SrmBidEvaluationDO;
|
import cn.iocoder.yudao.module.srm.dal.dataobject.SrmBidOpenDO;
|
import cn.iocoder.yudao.module.srm.dal.dataobject.SrmTenderProjectDO;
|
import cn.iocoder.yudao.module.srm.dal.mysql.SrmBidEvaluationMapper;
|
import cn.iocoder.yudao.module.srm.dal.mysql.SrmBidOpenMapper;
|
import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderProjectMapper;
|
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.math.BigDecimal;
|
import java.math.RoundingMode;
|
import java.time.LocalDateTime;
|
import java.util.Comparator;
|
import java.util.List;
|
|
/**
|
* SRM 评标管理 Service 实现类
|
*/
|
@Service
|
@Validated
|
public class SrmBidEvaluationServiceImpl implements SrmBidEvaluationService {
|
|
@Resource
|
private SrmBidEvaluationMapper bidEvaluationMapper;
|
|
@Resource
|
private SrmBidOpenMapper bidOpenMapper;
|
|
@Resource
|
private SrmTenderProjectMapper tenderProjectMapper;
|
|
// ========== 评标管理 ==========
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long createEvaluation(SrmBidEvaluationSaveReqVO createReqVO) {
|
SrmBidEvaluationDO evaluation = BeanUtils.toBean(createReqVO, SrmBidEvaluationDO.class);
|
// 强制置空 id,避免前端传入已有 id 导致主键冲突,由数据库序列自动生成
|
evaluation.setId(null);
|
// 计算综合评分: 价格*0.4 + 技术*0.3 + 交付*0.2 + 服务*0.1
|
BigDecimal price = nvl(evaluation.getPriceScore());
|
BigDecimal tech = nvl(evaluation.getTechScore());
|
BigDecimal delivery = nvl(evaluation.getDeliveryScore());
|
BigDecimal service = nvl(evaluation.getServiceScore());
|
BigDecimal composite = price.multiply(new BigDecimal("0.4"))
|
.add(tech.multiply(new BigDecimal("0.3")))
|
.add(delivery.multiply(new BigDecimal("0.2")))
|
.add(service.multiply(new BigDecimal("0.1")))
|
.setScale(2, RoundingMode.HALF_UP);
|
evaluation.setCompositeScore(composite);
|
evaluation.setEvaluationTime(LocalDateTime.now());
|
bidEvaluationMapper.insert(evaluation);
|
// 首次评标时更新招标项目状态为评标中
|
SrmTenderProjectDO project = tenderProjectMapper.selectById(createReqVO.getTenderProjectId());
|
if (project != null && TenderStatusEnum.BIDDING.getCode().equals(project.getTenderStatus())) {
|
project.setTenderStatus(TenderStatusEnum.EVALUATING.getCode());
|
tenderProjectMapper.updateById(project);
|
}
|
return evaluation.getId();
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void updateEvaluation(SrmBidEvaluationSaveReqVO updateReqVO) {
|
SrmBidEvaluationDO existing = bidEvaluationMapper.selectById(updateReqVO.getId());
|
if (existing == null) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.EVALUATION_NOT_EXISTS_TENDER);
|
}
|
SrmBidEvaluationDO evaluation = BeanUtils.toBean(updateReqVO, SrmBidEvaluationDO.class);
|
BigDecimal price = nvl(evaluation.getPriceScore());
|
BigDecimal tech = nvl(evaluation.getTechScore());
|
BigDecimal delivery = nvl(evaluation.getDeliveryScore());
|
BigDecimal service = nvl(evaluation.getServiceScore());
|
BigDecimal composite = price.multiply(new BigDecimal("0.4"))
|
.add(tech.multiply(new BigDecimal("0.3")))
|
.add(delivery.multiply(new BigDecimal("0.2")))
|
.add(service.multiply(new BigDecimal("0.1")))
|
.setScale(2, RoundingMode.HALF_UP);
|
evaluation.setCompositeScore(composite);
|
evaluation.setEvaluationTime(LocalDateTime.now());
|
bidEvaluationMapper.updateById(evaluation);
|
}
|
|
@Override
|
public List<SrmBidEvaluationDO> getEvaluationList(Long tenderProjectId) {
|
return bidEvaluationMapper.selectListByTenderProjectId(tenderProjectId);
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public void calculateRanking(Long tenderProjectId) {
|
List<SrmBidEvaluationDO> list = bidEvaluationMapper.selectListByTenderProjectId(tenderProjectId);
|
// 按综合评分降序排名
|
list.sort(Comparator.comparing(e -> e.getCompositeScore() != null ? e.getCompositeScore() : BigDecimal.ZERO, Comparator.reverseOrder()));
|
for (int i = 0; i < list.size(); i++) {
|
SrmBidEvaluationDO evaluation = list.get(i);
|
evaluation.setRanking(i + 1);
|
bidEvaluationMapper.updateById(evaluation);
|
}
|
}
|
|
// ========== 开标管理 ==========
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public Long createBidOpen(Long tenderProjectId) {
|
if (bidOpenMapper.selectByTenderProjectId(tenderProjectId) != null) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_STATUS_NOT_PUBLISHED);
|
}
|
// 开标后自动更新招标项目状态为投标中
|
SrmTenderProjectDO project = tenderProjectMapper.selectById(tenderProjectId);
|
if (project != null && TenderStatusEnum.PUBLISHED.getCode().equals(project.getTenderStatus())) {
|
project.setTenderStatus(TenderStatusEnum.BIDDING.getCode());
|
tenderProjectMapper.updateById(project);
|
}
|
SrmBidOpenDO open = new SrmBidOpenDO();
|
open.setTenderProjectId(tenderProjectId);
|
open.setOpenTime(LocalDateTime.now());
|
bidOpenMapper.insert(open);
|
return open.getId();
|
}
|
|
@Override
|
public SrmBidOpenDO getBidOpen(Long id) {
|
return bidOpenMapper.selectById(id);
|
}
|
|
private static BigDecimal nvl(BigDecimal value) {
|
return value != null ? value : BigDecimal.ZERO;
|
}
|
|
}
|