2026-08-03 f0c9b593769315001591cb4a759650a76b71cb8f
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmTenderProjectServiceImpl.java
@@ -4,17 +4,21 @@
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;
@@ -23,6 +27,8 @@
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
@@ -34,6 +40,8 @@
    private SrmTenderMaterialMapper tenderMaterialMapper;
    @Resource
    private SrmBidAwardMapper bidAwardMapper;
    @Resource
    private SrmTenderBidMapper tenderBidMapper;
    @Override
    public Long createTenderProject(SrmTenderProjectSaveReqVO createReqVO) {
@@ -44,13 +52,42 @@
    }
    @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());
        if (!TenderStatusEnum.DRAFT.getCode().equals(project.getTenderStatus())) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.TENDER_STATUS_NOT_DRAFT);
        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;
        }
        SrmTenderProjectDO updateObj = BeanUtils.toBean(updateReqVO, SrmTenderProjectDO.class);
        tenderProjectMapper.updateById(updateObj);
        // 发布中/投标中:仅允许修改招标说明和资质要求
        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
@@ -58,6 +95,10 @@
        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);
@@ -117,6 +158,10 @@
        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);
    }
@@ -141,22 +186,60 @@
        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);
    }