From 3c25f0e0cca347370f7551b694dd17ec0d21d102 Mon Sep 17 00:00:00 2001 From: yinq Date: Mon, 9 Mar 2026 18:04:54 +0800 Subject: [PATCH] =?UTF-8?q?1.0.80=20=E5=90=88=E5=90=8C=E5=8F=98=E6=9B=B4?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E6=B5=81=E5=AE=8C=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ErpContractChangeController.java | 11 + .../domain/bo/ErpContractChangeSaveBo.java | 33 ++ .../service/IErpContractChangeService.java | 10 +- .../impl/ErpContractChangeServiceImpl.java | 289 +++++++++++++----- 4 files changed, 261 insertions(+), 82 deletions(-) diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractChangeController.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractChangeController.java index d227d74f..ce0d67df 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractChangeController.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/controller/ErpContractChangeController.java @@ -94,6 +94,17 @@ public class ErpContractChangeController extends BaseController { return R.ok(erpContractChangeService.saveContractChange(bo)); } + /** + * 提交合同变更并提交流程 + */ + @SaCheckPermission("oa/erp:contractChange:add") + @Log(title = "合同变更", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping("/contractChangeSubmitAndFlowStart") + public R contractChangeSubmitAndFlowStart(@RequestBody ErpContractChangeSaveBo bo) { + return R.ok(erpContractChangeService.contractChangeSubmitAndFlowStart(bo)); + } + /** * 新增合同变更 */ diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractChangeSaveBo.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractChangeSaveBo.java index d4994ac1..52584c22 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractChangeSaveBo.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/domain/bo/ErpContractChangeSaveBo.java @@ -1,6 +1,7 @@ package org.dromara.oa.erp.domain.bo; import lombok.Data; +import org.dromara.workflow.api.domain.RemoteFlowInstanceBizExt; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -8,6 +9,8 @@ import jakarta.validation.constraints.NotNull; import java.math.BigDecimal; import java.util.Date; import java.util.List; +import java.util.Map; +import java.util.Objects; /** * 合同变更保存业务对象(主表+信息快照+物料快照+付款方式快照 一次提交) @@ -115,4 +118,34 @@ public class ErpContractChangeSaveBo { * 合同变更付款方式快照列表(内容变更时使用) */ private List changePaymentMethodList; + + /** + * 流程定义编码(提交审批时必填) + */ + private String flowCode; + + /** + * 流程变量(提交审批时使用) + */ + private Map variables; + + /** + * 流程实例业务扩展(提交审批时使用) + */ + private RemoteFlowInstanceBizExt bizExt; + + public Map getVariables() { + if (variables == null) { + return new java.util.HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } + + public RemoteFlowInstanceBizExt getBizExt() { + if (bizExt == null) { + bizExt = new RemoteFlowInstanceBizExt(); + } + return bizExt; + } } diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractChangeService.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractChangeService.java index 64ab5b58..5238d909 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractChangeService.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/IErpContractChangeService.java @@ -90,5 +90,13 @@ public interface IErpContractChangeService { * * @param contractChangeId 合同变更ID */ - void writeBackToContract(Long contractChangeId); + void writeBackToContract(ErpContractChange contractChangeId); + + /** + * 提交合同变更并提交流程 + * + * @param bo 保存数据 + flowCode、variables、bizExt + * @return 合同变更主表 VO + */ + ErpContractChangeVo contractChangeSubmitAndFlowStart(ErpContractChangeSaveBo bo); } diff --git a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractChangeServiceImpl.java b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractChangeServiceImpl.java index 71044f39..9a764353 100644 --- a/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractChangeServiceImpl.java +++ b/ruoyi-modules/ruoyi-oa/src/main/java/org/dromara/oa/erp/service/impl/ErpContractChangeServiceImpl.java @@ -1,8 +1,11 @@ package org.dromara.oa.erp.service.impl; import cn.hutool.core.convert.Convert; +import cn.hutool.core.map.MapUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.enums.BusinessStatusEnum; +import org.dromara.common.core.enums.OAStatusEnum; import org.dromara.common.tenant.helper.TenantHelper; import org.dromara.oa.erp.domain.bo.ErpContractChangeMaterialBo; import org.dromara.oa.erp.domain.bo.ErpContractChangePaymentMethodBo; @@ -25,24 +28,34 @@ import org.dromara.oa.erp.domain.vo.*; import org.dromara.oa.erp.mapper.*; import org.dromara.oa.erp.service.IErpContractChangeService; import org.dromara.system.api.RemoteCodeRuleService; +import org.dromara.workflow.api.RemoteWorkflowService; +import org.dromara.workflow.api.domain.RemoteStartProcess; +import org.dromara.common.core.exception.ServiceException; +import org.apache.seata.spring.annotation.GlobalTransactional; import org.apache.dubbo.config.annotation.DubboReference; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Objects; +import java.util.*; /** - * 合同变更Service业务层处理 + * 合同变更 Service 业务层实现。 + *

+ * 职责:合同变更主表及子表(变更信息快照、物料快照、付款方式快照)的增删改查、 + * 保存/提交并发起审批流程、审批通过后回写原合同及流程状态同步。 + *

+ *

+ * 删除说明:本类中所有删除均为逻辑删除。依赖实体上的 {@code @TableLogic},Mapper 的 delete 会转换为 UPDATE del_flag,不物理删行。 + *

* * @author Yinq * @date 2026-03-07 */ @RequiredArgsConstructor @Service +@Slf4j public class ErpContractChangeServiceImpl implements IErpContractChangeService { + // ---------- 主表及子表 Mapper ---------- private final ErpContractChangeMapper baseMapper; private final ErpContractChangeInfoMapper changeInfoMapper; private final ErpContractChangeMaterialMapper changeMaterialMapper; @@ -54,50 +67,55 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { @DubboReference private RemoteCodeRuleService remoteCodeRuleService; - /** 合同变更流程编码 */ + @DubboReference(timeout = 30000) + private RemoteWorkflowService remoteWorkflowService; + + /** 合同变更流程定义编码(与流程引擎中 flowCode 一致) */ public static final String FLOW_CODE_CONTRACT_CHANGE = "HTBG"; - /** 变更编号编码规则 */ + /** 变更单编号规则编码(调用编码规则服务生成变更编号) */ private static final String CONTRACT_CHANGE_CODE_RULE = "1021"; - /** 变更类型:1内容变更 2解除合同 */ + /** 变更类型:1-内容变更(需维护变更后信息/物料/付款方式快照) */ private static final String CHANGE_TYPE_CONTENT = "1"; + /** 变更类型:2-解除合同(仅更新原合同激活标识) */ private static final String CHANGE_TYPE_TERMINATE = "2"; - /** 未回写 */ + /** 回写标识:0-未回写 */ private static final String WRITE_BACK_NO = "0"; - /** 已回写/可用 */ + /** 回写标识:1-已回写(审批通过并已写回原合同后不再允许修改回写相关字段) */ private static final String WRITE_BACK_YES = "1"; + /** 变更状态:3-可用(审批完成且已回写后的终态) */ private static final String CHANGE_STATUS_AVAILABLE = "3"; /** - * 查询合同变更 + * 根据主键查询合同变更(仅主表) * * @param contractChangeId 主键 - * @return 合同变更 + * @return 合同变更 VO,不存在则 null */ @Override - public ErpContractChangeVo queryById(Long contractChangeId){ + public ErpContractChangeVo queryById(Long contractChangeId) { return baseMapper.selectVoById(contractChangeId); } - /** - * 分页查询合同变更列表 - * - * @param bo 查询条件 - * @param pageQuery 分页参数 - * @return 合同变更分页列表 - */ - @Override - public TableDataInfo queryPageList(ErpContractChangeBo bo, PageQuery pageQuery) { - MPJLambdaWrapper lqw = buildQueryWrapper(bo); - Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); - return TableDataInfo.build(result); - } + /** + * 分页查询合同变更列表(条件同 queryList,带分页) + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 分页结果 + */ + @Override + public TableDataInfo queryPageList(ErpContractChangeBo bo, PageQuery pageQuery) { + MPJLambdaWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } /** - * 查询符合条件的合同变更列表 + * 根据条件查询合同变更列表(不分页,用于下拉等) * * @param bo 查询条件 - * @return 合同变更列表 + * @return 列表,未逻辑删除的数据 */ @Override public List queryList(ErpContractChangeBo bo) { @@ -105,38 +123,43 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { return baseMapper.selectVoList(lqw); } + /** + * 构建列表/分页查询条件:仅查未删除,其余条件按 bo 非空字段等值/模糊匹配 + */ private MPJLambdaWrapper buildQueryWrapper(ErpContractChangeBo bo) { return JoinWrappers.lambda(ErpContractChange.class) - .selectAll(ErpContractChange.class) - .eq(ErpContractChange::getDelFlag, "0") - .eq(bo.getContractId() != null, ErpContractChange::getContractId, bo.getContractId()) - .eq(StringUtils.isNotBlank(bo.getChangeCode()), ErpContractChange::getChangeCode, bo.getChangeCode()) - .eq(StringUtils.isNotBlank(bo.getChangeType()), ErpContractChange::getChangeType, bo.getChangeType()) - .eq(StringUtils.isNotBlank(bo.getChangeContractCode()), ErpContractChange::getChangeContractCode, bo.getChangeContractCode()) - .like(StringUtils.isNotBlank(bo.getChangeContractName()), ErpContractChange::getChangeContractName, bo.getChangeContractName()) - .like(StringUtils.isNotBlank(bo.getCustomerName()), ErpContractChange::getCustomerName, bo.getCustomerName()) - .eq(bo.getChangeContractAmount() != null, ErpContractChange::getChangeContractAmount, bo.getChangeContractAmount()) - .eq(StringUtils.isNotBlank(bo.getContractCode()), ErpContractChange::getContractCode, bo.getContractCode()) - .like(StringUtils.isNotBlank(bo.getContractName()), ErpContractChange::getContractName, bo.getContractName()) - .like(StringUtils.isNotBlank(bo.getOriginalCustomerName()), ErpContractChange::getOriginalCustomerName, bo.getOriginalCustomerName()) - .eq(bo.getOriginalContractAmount() != null, ErpContractChange::getOriginalContractAmount, bo.getOriginalContractAmount()) - .eq(StringUtils.isNotBlank(bo.getChangeReason()), ErpContractChange::getChangeReason, bo.getChangeReason()) - .eq(bo.getApplyTime() != null, ErpContractChange::getApplyTime, bo.getApplyTime()) - .eq(bo.getUndertakeDeptId() != null, ErpContractChange::getUndertakeDeptId, bo.getUndertakeDeptId()) - .eq(bo.getUndertakeBy() != null, ErpContractChange::getUndertakeBy, bo.getUndertakeBy()) - .eq(StringUtils.isNotBlank(bo.getIndustryRegion()), ErpContractChange::getIndustryRegion, bo.getIndustryRegion()) - .eq(StringUtils.isNotBlank(bo.getSealLegalEntity()), ErpContractChange::getSealLegalEntity, bo.getSealLegalEntity()) - .eq(StringUtils.isNotBlank(bo.getChangeStatus()), ErpContractChange::getChangeStatus, bo.getChangeStatus()) - .eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpContractChange::getFlowStatus, bo.getFlowStatus()) - .eq(StringUtils.isNotBlank(bo.getWriteBackFlag()), ErpContractChange::getWriteBackFlag, bo.getWriteBackFlag()) - .eq(bo.getWriteBackTime() != null, ErpContractChange::getWriteBackTime, bo.getWriteBackTime()) - .eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpContractChange::getActiveFlag, bo.getActiveFlag()); + .selectAll(ErpContractChange.class) + .eq(ErpContractChange::getDelFlag, "0") + .eq(bo.getContractId() != null, ErpContractChange::getContractId, bo.getContractId()) + .eq(StringUtils.isNotBlank(bo.getChangeCode()), ErpContractChange::getChangeCode, bo.getChangeCode()) + .eq(StringUtils.isNotBlank(bo.getChangeType()), ErpContractChange::getChangeType, bo.getChangeType()) + .eq(StringUtils.isNotBlank(bo.getChangeContractCode()), ErpContractChange::getChangeContractCode, bo.getChangeContractCode()) + .like(StringUtils.isNotBlank(bo.getChangeContractName()), ErpContractChange::getChangeContractName, bo.getChangeContractName()) + .like(StringUtils.isNotBlank(bo.getCustomerName()), ErpContractChange::getCustomerName, bo.getCustomerName()) + .eq(bo.getChangeContractAmount() != null, ErpContractChange::getChangeContractAmount, bo.getChangeContractAmount()) + .eq(StringUtils.isNotBlank(bo.getContractCode()), ErpContractChange::getContractCode, bo.getContractCode()) + .like(StringUtils.isNotBlank(bo.getContractName()), ErpContractChange::getContractName, bo.getContractName()) + .like(StringUtils.isNotBlank(bo.getOriginalCustomerName()), ErpContractChange::getOriginalCustomerName, bo.getOriginalCustomerName()) + .eq(bo.getOriginalContractAmount() != null, ErpContractChange::getOriginalContractAmount, bo.getOriginalContractAmount()) + .eq(StringUtils.isNotBlank(bo.getChangeReason()), ErpContractChange::getChangeReason, bo.getChangeReason()) + .eq(bo.getApplyTime() != null, ErpContractChange::getApplyTime, bo.getApplyTime()) + .eq(bo.getUndertakeDeptId() != null, ErpContractChange::getUndertakeDeptId, bo.getUndertakeDeptId()) + .eq(bo.getUndertakeBy() != null, ErpContractChange::getUndertakeBy, bo.getUndertakeBy()) + .eq(StringUtils.isNotBlank(bo.getIndustryRegion()), ErpContractChange::getIndustryRegion, bo.getIndustryRegion()) + .eq(StringUtils.isNotBlank(bo.getSealLegalEntity()), ErpContractChange::getSealLegalEntity, bo.getSealLegalEntity()) + .eq(StringUtils.isNotBlank(bo.getChangeStatus()), ErpContractChange::getChangeStatus, bo.getChangeStatus()) + .eq(StringUtils.isNotBlank(bo.getFlowStatus()), ErpContractChange::getFlowStatus, bo.getFlowStatus()) + .eq(StringUtils.isNotBlank(bo.getWriteBackFlag()), ErpContractChange::getWriteBackFlag, bo.getWriteBackFlag()) + .eq(bo.getWriteBackTime() != null, ErpContractChange::getWriteBackTime, bo.getWriteBackTime()) + .eq(StringUtils.isNotBlank(bo.getActiveFlag()), ErpContractChange::getActiveFlag, bo.getActiveFlag()); } + // ======================= 主表增删改(单表) ======================= + /** - * 新增合同变更 + * 新增合同变更(仅主表,不包含子表快照) * - * @param bo 合同变更 + * @param bo 合同变更 BO,成功后回写主键到 bo * @return 是否新增成功 */ @Override @@ -151,9 +174,9 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { } /** - * 修改合同变更 + * 修改合同变更(仅主表) * - * @param bo 合同变更 + * @param bo 合同变更 BO * @return 是否修改成功 */ @Override @@ -164,7 +187,7 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { } /** - * 保存前的数据校验 + * 保存前校验:原合同ID、变更类型必填(主表与保存接口共用) */ private void validEntityBeforeSave(ErpContractChange entity) { if (entity.getContractId() == null) { @@ -176,20 +199,34 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { } /** - * 校验并批量删除合同变更信息 + * 按主键批量逻辑删除合同变更(依赖 ErpContractChange 的 @TableLogic,实际执行 UPDATE del_flag)。 + * isValid 为 true 时预留业务校验扩展点。 * - * @param ids 待删除的主键集合 - * @param isValid 是否进行有效性校验 + * @param ids 主键集合 + * @param isValid 是否执行有效性校验(当前为预留) * @return 是否删除成功 */ @Override public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { - if(isValid){ - //TODO 做一些业务上的校验,判断是否需要校验 + if (isValid) { + // TODO 按业务需要补充:如已回写、审批中等不允许删除等 } return baseMapper.deleteByIds(ids) > 0; } + // ======================= 保存与提交流程 ======================= + + /** + * 保存合同变更(主表 + 内容变更时的信息/物料/付款方式快照),新增与修改统一入口。 + *
    + *
  • 修改且为「内容变更」时:先物理删除原子表再按 bo 重新插入(保证与前端提交一致)
  • + *
  • 已回写的记录:回写标识与回写时间不允许被覆盖
  • + *
  • 新增时:若未传变更编号则通过编码规则生成
  • + *
+ * + * @param bo 主表字段 + changeInfo / changeMaterialList / changePaymentMethodList(内容变更时) + * @return 合同变更主表主键 + */ @Override @Transactional(rollbackFor = Exception.class) public Long saveContractChange(ErpContractChangeSaveBo bo) { @@ -198,12 +235,14 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { validEntityBeforeSave(main); if (isUpdate) { + // 已回写的数据不允许覆盖回写相关字段 ErpContractChange existing = baseMapper.selectById(main.getContractChangeId()); if (existing != null && StringUtils.isNotBlank(existing.getWriteBackFlag()) && WRITE_BACK_YES.equals(existing.getWriteBackFlag())) { main.setWriteBackFlag(existing.getWriteBackFlag()); main.setWriteBackTime(existing.getWriteBackTime()); } baseMapper.updateById(main); + // 内容变更时子表采用「先逻辑删除后新增」,保证与前端提交一致(子表实体带 @TableLogic) if (CHANGE_TYPE_CONTENT.equals(bo.getChangeType())) { deleteChangeSubByChangeId(main.getContractChangeId()); } @@ -217,6 +256,7 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { bo.setChangeCode(main.getChangeCode()); } + // 内容变更时写入/更新:变更信息快照、物料快照、付款方式快照(子表主键置空表示新增) if (CHANGE_TYPE_CONTENT.equals(bo.getChangeType())) { Long changeId = main.getContractChangeId(); if (bo.getChangeInfo() != null) { @@ -245,6 +285,36 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { return main.getContractChangeId(); } + /** + * 提交合同变更并后端发起审批流程(与合同 contractSubmitAndFlowStart 一致)。 + * 先保存再调用流程「启动并完成首节点」,不打开前端提交校验弹窗。 + * + * @param bo 保存数据 + flowCode、variables、bizExt(流程所需) + * @return 保存并发起流程后的合同变更主表 VO + */ + @Override + @GlobalTransactional(rollbackFor = Exception.class) + public ErpContractChangeVo contractChangeSubmitAndFlowStart(ErpContractChangeSaveBo bo) { + Long changeId = saveContractChange(bo); + bo.setContractChangeId(changeId); + // 后端发起时忽略权限校验 + bo.getVariables().put("ignore", true); + RemoteStartProcess startProcess = new RemoteStartProcess(); + startProcess.setBusinessId(changeId.toString()); + startProcess.setFlowCode(bo.getFlowCode()); + startProcess.setVariables(bo.getVariables()); + startProcess.setBizExt(bo.getBizExt()); + bo.getBizExt().setBusinessId(startProcess.getBusinessId()); + boolean flag = remoteWorkflowService.startCompleteTask(startProcess); + if (!flag) { + throw new ServiceException("流程发起异常"); + } + return baseMapper.selectVoById(changeId); + } + + /** + * 从 SaveBo 组装主表实体(不包含子表),新增时默认未回写、变更状态 1、激活 1 + */ private ErpContractChange buildMainEntity(ErpContractChangeSaveBo bo) { ErpContractChange e = new ErpContractChange(); e.setContractChangeId(bo.getContractChangeId()); @@ -275,15 +345,27 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { return e; } + /** + * 按合同变更ID逻辑删除子表:变更信息、变更物料、变更付款方式(保存时「先删后增」用)。 + * 各实体带 @TableLogic,Mapper.delete 实际为 UPDATE del_flag,不物理删行。 + */ private void deleteChangeSubByChangeId(Long contractChangeId) { changeInfoMapper.delete(new LambdaQueryWrapper() - .eq(ErpContractChangeInfo::getContractChangeId, contractChangeId)); + .eq(ErpContractChangeInfo::getContractChangeId, contractChangeId)); changeMaterialMapper.delete(new LambdaQueryWrapper() - .eq(ErpContractChangeMaterial::getContractChangeId, contractChangeId)); + .eq(ErpContractChangeMaterial::getContractChangeId, contractChangeId)); changePaymentMethodMapper.delete(new LambdaQueryWrapper() - .eq(ErpContractChangePaymentMethod::getContractChangeId, contractChangeId)); + .eq(ErpContractChangePaymentMethod::getContractChangeId, contractChangeId)); } + // ======================= 详情与回写 ======================= + + /** + * 查询合同变更详情:主表 + 变更信息快照(单条)+ 物料快照列表 + 付款方式快照列表 + * + * @param contractChangeId 合同变更主键 + * @return 详情 VO,主表不存在时 main 为 null + */ @Override public ContractChangeDetailVo queryDetailById(Long contractChangeId) { ContractChangeDetailVo vo = new ContractChangeDetailVo(); @@ -292,19 +374,24 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { return vo; } List infoList = changeInfoMapper.selectVoList( - new LambdaQueryWrapper().eq(ErpContractChangeInfo::getContractChangeId, contractChangeId)); + new LambdaQueryWrapper().eq(ErpContractChangeInfo::getContractChangeId, contractChangeId)); vo.setChangeInfo(infoList.isEmpty() ? null : infoList.get(0)); vo.setChangeMaterialList(changeMaterialMapper.selectVoList( - new LambdaQueryWrapper().eq(ErpContractChangeMaterial::getContractChangeId, contractChangeId))); + new LambdaQueryWrapper().eq(ErpContractChangeMaterial::getContractChangeId, contractChangeId))); vo.setChangePaymentMethodList(changePaymentMethodMapper.selectVoList( - new LambdaQueryWrapper().eq(ErpContractChangePaymentMethod::getContractChangeId, contractChangeId))); + new LambdaQueryWrapper().eq(ErpContractChangePaymentMethod::getContractChangeId, contractChangeId))); return vo; } + /** + * 审批通过后将变更结果回写至原合同(仅未回写记录执行一次)。 + * 解除合同:将原合同激活标识置为 0;内容变更:用变更快照覆盖原合同信息/物料/付款方式,并更新本变更单状态与回写标识。 + * + * @param change 合同变更主表实体(需已查库,含 contractId、changeType 等) + */ @Override @Transactional(rollbackFor = Exception.class) - public void writeBackToContract(Long contractChangeId) { - ErpContractChange change = baseMapper.selectById(contractChangeId); + public void writeBackToContract(ErpContractChange change) { if (change == null || !WRITE_BACK_NO.equals(change.getWriteBackFlag())) { return; } @@ -312,7 +399,7 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { if (CHANGE_TYPE_TERMINATE.equals(change.getChangeType())) { doWriteBackTerminate(contractId); } else { - doWriteBackContent(contractChangeId, contractId); + doWriteBackContent(change.getContractChangeId(), contractId); } change.setChangeStatus(CHANGE_STATUS_AVAILABLE); change.setFlowStatus(BusinessStatusEnum.FINISH.getStatus()); @@ -321,6 +408,7 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { baseMapper.updateById(change); } + /** 解除合同回写:将原合同激活标识置为 0 */ private void doWriteBackTerminate(Long contractId) { ErpContractInfo info = contractInfoMapper.selectById(contractId); if (info != null) { @@ -329,9 +417,12 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { } } + /** + * 内容变更回写:用变更信息快照更新原合同主表;原合同物料/付款方式先逻辑删除后按变更快照插入(逻辑删除,实体带 @TableLogic)。 + */ private void doWriteBackContent(Long contractChangeId, Long contractId) { List infoList = changeInfoMapper.selectVoList( - new LambdaQueryWrapper().eq(ErpContractChangeInfo::getContractChangeId, contractChangeId)); + new LambdaQueryWrapper().eq(ErpContractChangeInfo::getContractChangeId, contractChangeId)); if (!infoList.isEmpty()) { ErpContractInfo contractInfo = contractInfoMapper.selectById(contractId); if (contractInfo != null) { @@ -339,35 +430,67 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { contractInfoMapper.updateById(contractInfo); } } + // 逻辑删除原合同下物料(@TableLogic) LambdaQueryWrapper materialDel = new LambdaQueryWrapper().eq(ErpContractMaterial::getContractId, contractId); contractMaterialMapper.delete(materialDel); List materials = changeMaterialMapper.selectList( - new LambdaQueryWrapper().eq(ErpContractChangeMaterial::getContractChangeId, contractChangeId)); + new LambdaQueryWrapper().eq(ErpContractChangeMaterial::getContractChangeId, contractChangeId)); for (ErpContractChangeMaterial m : materials) { contractMaterialMapper.insert(copyChangeMaterialToContract(m, contractId)); } + // 逻辑删除原合同下付款方式(@TableLogic) LambdaQueryWrapper paymentDel = new LambdaQueryWrapper().eq(ErpContractPaymentMethod::getContractId, contractId); contractPaymentMethodMapper.delete(paymentDel); List payments = changePaymentMethodMapper.selectList( - new LambdaQueryWrapper().eq(ErpContractChangePaymentMethod::getContractChangeId, contractChangeId)); + new LambdaQueryWrapper().eq(ErpContractChangePaymentMethod::getContractChangeId, contractChangeId)); for (ErpContractChangePaymentMethod p : payments) { contractPaymentMethodMapper.insert(copyChangePaymentToContract(p, contractId)); } } + // ======================= 流程监听 ======================= + /** - * 合同变更流程监听:审批通过后回写合同表 + * 合同变更流程事件监听(flowCode=HTBG):根据流程状态同步变更单 flowStatus/changeStatus,审批完成时触发回写。 + *
    + *
  • WAITING -> 审批中
  • + *
  • FINISH -> 已完成,并执行 writeBackToContract
  • + *
  • INVALID/TERMINATION -> 无效
  • + *
  • BACK/CANCEL -> 草稿
  • + *
*/ - @EventListener(condition = "#processEvent.flowCode == T(org.dromara.oa.erp.service.impl.ErpContractChangeServiceImpl).FLOW_CODE_CONTRACT_CHANGE") + @EventListener(condition = "#processEvent.flowCode =='HTBG'") public void processHandler(ProcessEvent processEvent) { TenantHelper.dynamic(processEvent.getTenantId(), () -> { - if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) { - Long contractChangeId = Convert.toLong(processEvent.getBusinessId()); - writeBackToContract(contractChangeId); + log.info("当前任务执行了{}", processEvent.toString()); + ErpContractChange contractChange = baseMapper.selectById(Convert.toLong(processEvent.getBusinessId())); + contractChange.setFlowStatus(processEvent.getStatus()); + Map params = processEvent.getParams(); + if (MapUtil.isNotEmpty(params)) { + // 预留:办理人等信息可按需从 params 取用 + String handler = Convert.toStr(params.get("handler")); } + if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.WAITING.getStatus())) { + contractChange.setChangeStatus(OAStatusEnum.APPROVING.getStatus()); + } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.FINISH.getStatus())) { + contractChange.setChangeStatus(OAStatusEnum.COMPLETED.getStatus()); + writeBackToContract(contractChange); + } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.INVALID.getStatus()) + || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.TERMINATION.getStatus())) { + contractChange.setChangeStatus(OAStatusEnum.INVALID.getStatus()); + } else if (Objects.equals(processEvent.getStatus(), BusinessStatusEnum.BACK.getStatus()) + || Objects.equals(processEvent.getStatus(), BusinessStatusEnum.CANCEL.getStatus())) { + contractChange.setChangeStatus(OAStatusEnum.DRAFT.getStatus()); + } + baseMapper.updateById(contractChange); }); } + // ======================= 回写时的数据拷贝 ======================= + + /** + * 将变更信息快照字段拷贝到原合同主表(回写内容变更时用) + */ private void copyChangeInfoToContract(ErpContractChangeInfoVo snap, ErpContractInfo contract) { contract.setContractFlag(snap.getContractFlag()); contract.setCustomerContractCode(snap.getCustomerContractCode()); @@ -408,7 +531,9 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { contract.setRemark(snap.getRemark()); } - /** 变更物料快照转合同物料(回写)*/ + /** + * 将单条变更物料快照转为原合同下的合同物料实体(回写时插入 erp_contract_material) + */ private ErpContractMaterial copyChangeMaterialToContract(ErpContractChangeMaterial m, Long contractId) { ErpContractMaterial cm = new ErpContractMaterial(); cm.setContractId(contractId); @@ -429,7 +554,9 @@ public class ErpContractChangeServiceImpl implements IErpContractChangeService { return cm; } - /** 变更付款方式快照转合同付款方式(回写) */ + /** + * 将单条变更付款方式快照转为原合同下的合同付款方式实体(回写时插入 erp_contract_payment_method) + */ private ErpContractPaymentMethod copyChangePaymentToContract(ErpContractChangePaymentMethod p, Long contractId) { ErpContractPaymentMethod cpm = new ErpContractPaymentMethod(); cpm.setContractId(contractId);