package cn.iocoder.yudao.module.srm.service.tender;
|
|
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmTenderMaterialSaveReqVO;
|
import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmTenderProjectPageReqVO;
|
import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmTenderProjectPartialUpdateReqVO;
|
import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.SrmTenderProjectSaveReqVO;
|
import cn.iocoder.yudao.module.srm.dal.dataobject.SrmBidAwardDO;
|
import cn.iocoder.yudao.module.srm.dal.dataobject.SrmTenderMaterialDO;
|
import cn.iocoder.yudao.module.srm.dal.dataobject.SrmTenderProjectDO;
|
import cn.iocoder.yudao.module.srm.dal.mysql.SrmBidAwardMapper;
|
import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderBidMapper;
|
import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderMaterialMapper;
|
import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderProjectMapper;
|
import cn.iocoder.yudao.module.srm.enums.AwardStatusEnum;
|
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.validation.annotation.Validated;
|
|
import java.util.List;
|
import java.util.Map;
|
import java.util.function.Function;
|
import java.util.stream.Collectors;
|
|
import static cn.iocoder.yudao.module.srm.enums.LogRecordConstants.*;
|
|
@Service
|
@Validated
|
public class SrmTenderProjectServiceImpl implements SrmTenderProjectService {
|
|
@Resource
|
private SrmTenderProjectMapper tenderProjectMapper;
|
@Resource
|
private SrmTenderMaterialMapper tenderMaterialMapper;
|
@Resource
|
private SrmBidAwardMapper bidAwardMapper;
|
@Resource
|
private SrmTenderBidMapper tenderBidMapper;
|
|
@Override
|
public Long createTenderProject(SrmTenderProjectSaveReqVO createReqVO) {
|
SrmTenderProjectDO project = BeanUtils.toBean(createReqVO, SrmTenderProjectDO.class);
|
project.setTenderStatus(TenderStatusEnum.DRAFT.getCode());
|
tenderProjectMapper.insert(project);
|
return project.getId();
|
}
|
|
@Override
|
@LogRecord(type = LOG_TENDER_TYPE, subType = LOG_TENDER_UPDATE_SUB_TYPE,
|
bizNo = "{{#updateReqVO.id}}", success = LOG_TENDER_UPDATE_SUCCESS)
|
public void updateTenderProject(SrmTenderProjectSaveReqVO updateReqVO) {
|
SrmTenderProjectDO project = validateTenderExists(updateReqVO.getId());
|
Integer status = project.getTenderStatus();
|
|
// 草稿状态:全字段可编辑
|
if (TenderStatusEnum.canEditFullProject(status)) {
|
SrmTenderProjectDO updateObj = BeanUtils.toBean(updateReqVO, SrmTenderProjectDO.class);
|
updateObj.setTenderStatus(status); // 状态不允许前端传入覆盖
|
tenderProjectMapper.updateById(updateObj);
|
LogRecordContext.putVariable("tenderName", project.getTenderName());
|
LogRecordContext.putVariable("oldTenderDesc", project.getTenderDesc());
|
LogRecordContext.putVariable("newTenderDesc", updateReqVO.getTenderDesc());
|
LogRecordContext.putVariable("oldQualification", project.getQualificationRequirements());
|
LogRecordContext.putVariable("newQualification", updateReqVO.getQualificationRequirements());
|
return;
|
}
|
|
// 发布中/投标中:仅允许修改招标说明和资质要求
|
if (TenderStatusEnum.canEditPartialProject(status)) {
|
SrmTenderProjectDO updateObj = new SrmTenderProjectDO();
|
updateObj.setId(updateReqVO.getId());
|
updateObj.setTenderDesc(updateReqVO.getTenderDesc());
|
updateObj.setQualificationRequirements(updateReqVO.getQualificationRequirements());
|
tenderProjectMapper.updateById(updateObj);
|
LogRecordContext.putVariable("tenderName", project.getTenderName());
|
LogRecordContext.putVariable("oldTenderDesc", project.getTenderDesc());
|
LogRecordContext.putVariable("newTenderDesc", updateReqVO.getTenderDesc());
|
LogRecordContext.putVariable("oldQualification", project.getQualificationRequirements());
|
LogRecordContext.putVariable("newQualification", updateReqVO.getQualificationRequirements());
|
return;
|
}
|
|
// 其他状态:不允许编辑
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_PROJECT_LOCKED);
|
}
|
|
@Override
|
public void deleteTenderProject(Long id) {
|
SrmTenderProjectDO project = validateTenderExists(id);
|
if (!TenderStatusEnum.DRAFT.getCode().equals(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_STATUS_NOT_DRAFT);
|
}
|
// 检查是否已有投标数据
|
if (tenderBidMapper.countByTenderProjectId(id) > 0) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_HAS_BIDS_CANNOT_DELETE);
|
}
|
tenderMaterialMapper.deleteByTenderProjectId(id);
|
tenderProjectMapper.deleteById(id);
|
}
|
|
@Override
|
public SrmTenderProjectDO getTenderProject(Long id) {
|
SrmTenderProjectDO project = tenderProjectMapper.selectById(id);
|
if (project != null) {
|
SrmBidAwardDO award = bidAwardMapper.selectByTenderProjectId(id);
|
if (award != null) {
|
project.setAwardId(award.getId());
|
project.setPurchaseOrderNo(award.getPurchaseOrderNo());
|
}
|
}
|
return project;
|
}
|
|
@Override
|
public PageResult<SrmTenderProjectDO> getTenderProjectPage(SrmTenderProjectPageReqVO pageReqVO) {
|
PageResult<SrmTenderProjectDO> pageResult = tenderProjectMapper.selectPage(pageReqVO);
|
// 批量查询定标信息,填充 awardId 和 purchaseOrderNo
|
List<Long> projectIds = pageResult.getList().stream()
|
.map(SrmTenderProjectDO::getId).collect(Collectors.toList());
|
if (!projectIds.isEmpty()) {
|
List<SrmBidAwardDO> awards = bidAwardMapper.selectListByTenderProjectIds(projectIds);
|
Map<Long, SrmBidAwardDO> awardMap = awards.stream().collect(Collectors.toMap(
|
SrmBidAwardDO::getTenderProjectId, Function.identity(), (a, b) -> a));
|
pageResult.getList().forEach(project -> {
|
SrmBidAwardDO award = awardMap.get(project.getId());
|
if (award != null) {
|
project.setAwardId(award.getId());
|
project.setPurchaseOrderNo(award.getPurchaseOrderNo());
|
// 防御:如果定标已生成订单但项目状态未更新,同步状态
|
if (AwardStatusEnum.ORDER_GENERATED.getCode().equals(award.getAwardStatus())) {
|
project.setTenderStatus(TenderStatusEnum.CLOSED.getCode());
|
}
|
}
|
});
|
}
|
return pageResult;
|
}
|
|
@Override
|
public void publishTender(Long id) {
|
SrmTenderProjectDO project = validateTenderExists(id);
|
if (!TenderStatusEnum.DRAFT.getCode().equals(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_STATUS_NOT_DRAFT);
|
}
|
project.setTenderStatus(TenderStatusEnum.PUBLISHED.getCode());
|
tenderProjectMapper.updateById(project);
|
}
|
|
@Override
|
public void closeTender(Long id) {
|
SrmTenderProjectDO project = validateTenderExists(id);
|
if (TenderStatusEnum.CLOSED.getCode().equals(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_STATUS_ALREADY_CLOSED);
|
}
|
// 草稿状态不允许直接关闭
|
if (TenderStatusEnum.DRAFT.getCode().equals(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_PROJECT_LOCKED);
|
}
|
project.setTenderStatus(TenderStatusEnum.CLOSED.getCode());
|
tenderProjectMapper.updateById(project);
|
}
|
|
@Override
|
public void startBidding(Long id) {
|
SrmTenderProjectDO project = validateTenderExists(id);
|
if (!TenderStatusEnum.PUBLISHED.getCode().equals(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_STATUS_NOT_PUBLISHED);
|
}
|
project.setTenderStatus(TenderStatusEnum.BIDDING.getCode());
|
tenderProjectMapper.updateById(project);
|
}
|
|
@Override
|
public void startEvaluation(Long id) {
|
SrmTenderProjectDO project = validateTenderExists(id);
|
if (!TenderStatusEnum.BIDDING.getCode().equals(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_STATUS_NOT_BIDDING);
|
}
|
project.setTenderStatus(TenderStatusEnum.EVALUATING.getCode());
|
tenderProjectMapper.updateById(project);
|
}
|
|
@Override
|
@LogRecord(type = LOG_TENDER_TYPE, subType = LOG_TENDER_UPDATE_SUB_TYPE,
|
bizNo = "{{#updateReqVO.id}}", success = LOG_TENDER_UPDATE_SUCCESS)
|
public void updateTenderProjectPartial(SrmTenderProjectPartialUpdateReqVO updateReqVO) {
|
SrmTenderProjectDO project = validateTenderExists(updateReqVO.getId());
|
if (!TenderStatusEnum.canEditPartialProject(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_PROJECT_LOCKED);
|
}
|
SrmTenderProjectDO updateObj = new SrmTenderProjectDO();
|
updateObj.setId(updateReqVO.getId());
|
updateObj.setTenderDesc(updateReqVO.getTenderDesc());
|
updateObj.setQualificationRequirements(updateReqVO.getQualificationRequirements());
|
tenderProjectMapper.updateById(updateObj);
|
LogRecordContext.putVariable("tenderName", project.getTenderName());
|
LogRecordContext.putVariable("oldTenderDesc", project.getTenderDesc());
|
LogRecordContext.putVariable("newTenderDesc", updateReqVO.getTenderDesc());
|
LogRecordContext.putVariable("oldQualification", project.getQualificationRequirements());
|
LogRecordContext.putVariable("newQualification", updateReqVO.getQualificationRequirements());
|
}
|
|
// ========== 物料子表 ==========
|
|
@Override
|
public void createMaterial(SrmTenderMaterialSaveReqVO createReqVO) {
|
SrmTenderProjectDO project = validateTenderExists(createReqVO.getTenderProjectId());
|
if (!TenderStatusEnum.canEditMaterial(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_MATERIAL_LOCKED);
|
}
|
SrmTenderMaterialDO material = BeanUtils.toBean(createReqVO, SrmTenderMaterialDO.class);
|
tenderMaterialMapper.insert(material);
|
}
|
|
@Override
|
public void updateMaterial(SrmTenderMaterialSaveReqVO updateReqVO) {
|
SrmTenderMaterialDO existing = tenderMaterialMapper.selectById(updateReqVO.getId());
|
if (existing != null) {
|
SrmTenderProjectDO project = tenderProjectMapper.selectById(existing.getTenderProjectId());
|
if (project != null && !TenderStatusEnum.canEditMaterial(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_MATERIAL_LOCKED);
|
}
|
}
|
SrmTenderMaterialDO updateObj = BeanUtils.toBean(updateReqVO, SrmTenderMaterialDO.class);
|
tenderMaterialMapper.updateById(updateObj);
|
}
|
|
@Override
|
public void deleteMaterial(Long id) {
|
SrmTenderMaterialDO material = tenderMaterialMapper.selectById(id);
|
if (material != null) {
|
SrmTenderProjectDO project = tenderProjectMapper.selectById(material.getTenderProjectId());
|
if (project != null && !TenderStatusEnum.canEditMaterial(project.getTenderStatus())) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_MATERIAL_LOCKED);
|
}
|
}
|
tenderMaterialMapper.deleteById(id);
|
}
|
|
@Override
|
public List<SrmTenderMaterialDO> getMaterialList(Long tenderProjectId) {
|
return tenderMaterialMapper.selectListByTenderProjectId(tenderProjectId);
|
}
|
|
private SrmTenderProjectDO validateTenderExists(Long id) {
|
SrmTenderProjectDO project = tenderProjectMapper.selectById(id);
|
if (project == null) {
|
throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_NOT_EXISTS);
|
}
|
return project;
|
}
|
|
}
|