24282 2 роки тому
батько
коміт
83ea8e2e1d

+ 83 - 0
bladex-saas-project/saas-business-tradeerp/src/main/java/com/fjhx/purchase/controller/PurchaseContractChangeFlowControllerV2.java

@@ -0,0 +1,83 @@
+/*
+ *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions are met:
+ *
+ *  Redistributions of source code must retain the above copyright notice,
+ *  this list of conditions and the following disclaimer.
+ *  Redistributions in binary form must reproduce the above copyright
+ *  notice, this list of conditions and the following disclaimer in the
+ *  documentation and/or other materials provided with the distribution.
+ *  Neither the name of the dreamlu.net developer nor the names of its
+ *  contributors may be used to endorse or promote products derived from
+ *  this software without specific prior written permission.
+ *  Author: Chill 庄骞 (smallchill@163.com)
+ */
+package com.fjhx.purchase.controller;
+
+import com.fjhx.activiti.SubmitFlowCondition;
+import com.fjhx.contract.entity.Contract;
+import com.fjhx.purchase.entity.PurchaseContract;
+import com.fjhx.purchase.service.IPurchaseContractChangeFlowService;
+import org.springblade.common.constant.ApiConstant;
+import org.springblade.core.boot.ctrl.BladeController;
+import org.springblade.core.tool.api.R;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 采购合同表变更-流程 控制器
+ *
+ * @author linqt
+ * @since 2022-02-09
+ */
+@RestController
+@RequestMapping(ApiConstant.Project.SAAS_BUSINESS_TRADEERP_REQUEST_PREFIX + "/purchase/contract/change/flow/v2")
+public class PurchaseContractChangeFlowControllerV2 extends BladeController {
+
+    @Autowired
+    private IPurchaseContractChangeFlowService iPurchaseContractChangeFlowService;
+
+    /**
+     * 开始流程
+     *
+     * @param contract
+     * @return
+     */
+    @PostMapping(value = "/start")
+    public R start(@RequestBody PurchaseContract contract) {
+        iPurchaseContractChangeFlowService.startV2(contract);
+        return R.success();
+    }
+
+
+    /**
+     * 审核
+     *
+     * @param condition
+     * @return
+     */
+    @PostMapping(value = "/examine")
+    public R examine(@RequestBody SubmitFlowCondition condition) {
+        iPurchaseContractChangeFlowService.examineV2(condition);
+        return R.success();
+    }
+
+
+    /**
+     * 删除流程
+     *
+     * @param entity
+     * @return
+     */
+    @PostMapping(value = "/delete")
+    public R delete(@RequestBody Contract entity) {
+        iPurchaseContractChangeFlowService.deleteV2(entity);
+        return R.success();
+    }
+
+}

+ 8 - 0
bladex-saas-project/saas-business-tradeerp/src/main/java/com/fjhx/purchase/service/IPurchaseContractChangeFlowService.java

@@ -1,6 +1,7 @@
 package com.fjhx.purchase.service;
 
 import com.fjhx.activiti.SubmitFlowCondition;
+import com.fjhx.contract.entity.Contract;
 import com.fjhx.purchase.entity.PurchaseContract;
 
 /**
@@ -39,4 +40,11 @@ public interface IPurchaseContractChangeFlowService {
      * @return
      */
     void delete(SubmitFlowCondition condition);
+
+    void startV2(PurchaseContract contract);
+
+    void examineV2(SubmitFlowCondition condition);
+
+    void deleteV2(Contract entity);
+
 }

+ 318 - 22
bladex-saas-project/saas-business-tradeerp/src/main/java/com/fjhx/purchase/service/impl/PurchaseContractChangeFlowServiceImpl.java

@@ -1,6 +1,8 @@
 package com.fjhx.purchase.service.impl;
 
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import com.fjhx.activiti.ProcessTaskReferBuilder;
 import com.fjhx.activiti.ProcessTaskResult;
 import com.fjhx.activiti.SubmitFlowCondition;
@@ -16,27 +18,18 @@ import com.fjhx.message.constant.MessageNoticeConstant;
 import com.fjhx.message.enums.MessageNoticeEnum;
 import com.fjhx.message.service.IMessageNoticeService;
 import com.fjhx.purchase.constant.PurchaseContractConstant;
-import com.fjhx.purchase.entity.PurchaseContract;
-import com.fjhx.purchase.entity.PurchaseContractChange;
-import com.fjhx.purchase.entity.PurchaseContractProduct;
-import com.fjhx.purchase.entity.PurchaseContractProductChange;
-import com.fjhx.purchase.entity.PurchaseContractProject;
-import com.fjhx.purchase.entity.PurchaseContractProjectChange;
+import com.fjhx.purchase.entity.*;
 import com.fjhx.purchase.enums.PurchaseCycleEnum;
 import com.fjhx.purchase.enums.PurchaseStatusEnum;
-import com.fjhx.purchase.service.IPurchaseContractChangeFlowService;
-import com.fjhx.purchase.service.IPurchaseContractChangeService;
-import com.fjhx.purchase.service.IPurchaseContractPdfService;
-import com.fjhx.purchase.service.IPurchaseContractProductChangeService;
-import com.fjhx.purchase.service.IPurchaseContractProductService;
-import com.fjhx.purchase.service.IPurchaseContractProjectChangeService;
-import com.fjhx.purchase.service.IPurchaseContractProjectService;
-import com.fjhx.purchase.service.IPurchaseContractService;
+import com.fjhx.purchase.service.*;
 import com.fjhx.shipmentdetailed.entity.ShipmentDetailed;
 import com.fjhx.shipmentdetailed.entity.ShipmentDetailedChange;
 import com.fjhx.shipmentdetailed.service.IShipmentDetailedChangeService;
 import com.fjhx.shipmentdetailed.service.IShipmentDetailedService;
 import com.fjhx.utils.CodeRuleUtil;
+import com.fjhx.utils.ExampleAbstract;
+import com.fjhx.utils.ExampleResult;
+import com.fjhx.utils.FlowConstructor;
 import com.fjhx.wms.due.entity.Due;
 import com.fjhx.wms.due.enums.DuePaymentItemsEnum;
 import com.fjhx.wms.warehouse.IWmsDueApi;
@@ -63,13 +56,7 @@ import org.springframework.transaction.annotation.Transactional;
 import java.math.BigDecimal;
 import java.text.MessageFormat;
 import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -485,10 +472,319 @@ public class PurchaseContractChangeFlowServiceImpl implements IPurchaseContractC
 
         // 删除
 //        iPurchaseContractService.removeById(condition.getId());
-        //修改状态999
+        // 修改状态999
         iPurchaseContractService.updateStatusById(Arrays.asList(condition.getId()), PurchaseStatusEnum.INVALID.getKey());
     }
 
+
+    /**
+     * 初始化流程
+     *
+     * @return
+     */
+    private FlowConstructor flowConstructor() {
+        return FlowConstructor.init(
+                new ExampleAbstract() {
+                    @Override
+                    public String getCode() {
+                        return MessageNoticeEnum.MESSAGE_NOTICE_TYPE_20.getValue();
+                    }
+
+                    /**
+                     * 结束
+                     *  @param flowLinkNo    流程关联编码
+                     */
+                    @Transactional(rollbackFor = {Exception.class})
+                    @Override
+                    public void end(String flowLinkNo) {
+
+                        String id = getCacheData(String.class);
+
+                        // 查询采购合同信息
+                        QueryWrapper<PurchaseContract> wrapper = new QueryWrapper<>();
+                        wrapper.lambda().eq(PurchaseContract::getId, id).or().eq(PurchaseContract::getProcessInstanceId, id);
+                        PurchaseContract purchaseContract = iPurchaseContractService.getOne(wrapper);
+                        if (Func.isEmpty(purchaseContract)) {
+                            throw new ServiceException("采购合同不存在");
+                        } else if (purchaseContract.getPurchaseStatus() == PurchaseStatusEnum.INVALID.getKey()) {
+                            throw new ServiceException("采购合同已作废");
+                        }
+
+                        // 采购状态:采购中
+                        PurchaseContract update = new PurchaseContract();
+                        update.setId(purchaseContract.getId());
+                        update.setPurchaseStatus(PurchaseStatusEnum.IN_PROCUREMENT.getKey());
+                        iPurchaseContractService.updateById(update);
+
+                        // 修改合同表状态,合同状态:采购中
+                        // 合同ID
+                        String contractId = purchaseContract.getContractId();
+                        String[] contractIds = StringUtils.split(contractId, ",");
+                        if (ArrayUtils.isNotEmpty(contractIds)) {
+                            iContractService.updateStatusById(Arrays.stream(contractIds).collect(Collectors.toList()), ContractStatusEnum.PURCHASE.getKey());
+                        }
+
+                        // 添加账单数据
+                        if (ObjectUtil.isNotEmpty(purchaseContract.getPaymentCycleType())) {
+                            Due due = new Due();
+                            due.setId(IdUtils.fastSimpleUUID());
+                            due.setPurchaseContractId(purchaseContract.getId());
+                            if (purchaseContract.getPaymentCycleType() == PurchaseCycleEnum.FULL_PREPAYMENT.getKey()) {
+                                // 添加一条全款预付得账单数据
+                                String promptDate = DateUtil.dateAddASub(purchaseContract.getCreateTime(), purchaseContract.getPaymentCyclePrescribe());
+                                due.setPromptDate(promptDate);
+                                due.setDueMoney(purchaseContract.getPurchasePrice());
+                                due.setPaymentItemsType(DuePaymentItemsEnum.FULL_PREPAYMENT.getKey());
+                            } else if (purchaseContract.getPaymentCycleType() == PurchaseCycleEnum.BALANCE_PAYMENT.getKey()) {
+                                // 添加一条账期尾款数据
+                                due.setPaymentItemsType(DuePaymentItemsEnum.BALANCE_PAYMENT.getKey());
+                                due.setDueMoney(purchaseContract.getPurchasePrice().subtract(purchaseContract.getPaymentFull()));
+                            } else if (purchaseContract.getPaymentCycleType() == PurchaseCycleEnum.TOP_PERIOD.getKey()) {
+                                // 添加一条小账期款数据
+                                String promptDate = DateUtil.dateAddASub(purchaseContract.getCreateTime(), purchaseContract.getPaymentDays());
+                                due.setPromptDate(promptDate);
+                                due.setPaymentItemsType(DuePaymentItemsEnum.TOP_PERIOD.getKey());
+                                due.setDueMoney(BigDecimal.ZERO);
+                            }
+                            iWmsDueApi.saveDue(due);
+                            if (purchaseContract.getPaymentFull().compareTo(BigDecimal.ZERO) == 1 &&
+                                    purchaseContract.getPaymentCycleType() != PurchaseCycleEnum.FULL_PREPAYMENT.getKey()) {
+                                String promptDate = DateUtil.dateAddASub(purchaseContract.getCreateTime(), purchaseContract.getPaymentCyclePrescribe());
+                                // 添加一条预付款得账单数据
+                                due.setId(IdUtils.fastSimpleUUID());
+                                due.setPromptDate(promptDate);
+                                due.setPaymentItemsType(DuePaymentItemsEnum.ADVANCE.getKey());
+                                due.setDueMoney(purchaseContract.getPaymentFull());
+                                iWmsDueApi.saveDue(due);
+                            }
+                        }
+
+                        try {
+                            // 添加日志
+                            iContractTrackLogService.addLog(purchaseContract.getContractId(), ContractTrackTypeEnum.PURCHASE.getKey(), ContractTrackLogConstant.Status.END, new Date());
+                            iContractTrackLogService.addLog(purchaseContract.getContractId(), ContractTrackTypeEnum.PRODUCTION.getKey(), ContractTrackLogConstant.Status.SEND, new Date());
+
+                            // 生成采购合同PDF
+                            purchaseContractPdfService.generate(purchaseContract.getId());
+                            // 发送消息通知
+                            sendMessageNotice(purchaseContract);
+                        } catch (Exception e) {
+                            e.printStackTrace();
+                        }
+                    }
+
+                    /**
+                     * 删除流程
+                     *
+                     * @param flowLinkNo 流程关联编码
+                     * @return
+                     */
+                    @Transactional(rollbackFor = {Exception.class})
+                    @Override
+                    public boolean deleteLogic(String flowLinkNo) {
+                        String id = getCacheData(String.class);
+
+                        iWmsDueApi.deleteDue(id);
+
+                        // 删除
+                        // iPurchaseContractService.removeById(condition.getId());
+                        // 修改状态999
+                        iPurchaseContractService.updateStatusById(Collections.singletonList(id), PurchaseStatusEnum.INVALID.getKey());
+                        return true;
+                    }
+
+                }
+        );
+    }
+
+
+    @Override
+    public void startV2(PurchaseContract contract) {
+        // 获取分布式锁key
+        String lockKey = CodeRuleUtil.getLockKey(AuthUtil.getTenantId(), CodeRuleTypeEnum.CODE_RULE_TYPE_4.getKey());
+        RLock lock = redisLockClient.lockFair(lockKey, 0, -1L);
+
+        try {
+            // 加锁,阻塞
+            lock.lock();
+
+            // 获取当前的租户id
+            String tenantId = AuthUtil.getTenantId();
+            if (StringUtils.isBlank(tenantId)) {
+                throw new ServiceException("获取不到当前租户");
+            }
+
+            // if (StringUtils.isBlank(contract.getId())) {
+            //     // 此处设为null,是防止复制采购合同时把复制对象的值携带过来
+            //     contract.setProcessInstanceId(null);
+            //     contract.setProcessInstanceName(null);
+            //     contract.setProcessInstanceUserId(null);
+            //     contract.setProcessInstanceUserName(null);
+            // }
+
+
+            // try {
+            // 查询采购合同旧数据
+            PurchaseContract oldContract = iPurchaseContractService.getById(contract.getId());
+            if (Func.isEmpty(oldContract)) {
+                throw new ServiceException("采购信息不存在!!!");
+            }
+            PurchaseContractChange contractChange = new PurchaseContractChange();
+            BeanUtils.copyProperties(oldContract, contractChange);
+            contractChange.setId(IdUtils.fastSimpleUUID());
+            contractChange.setOldId(oldContract.getId());
+            // 保存采购变更历史记录
+            iPurchaseContractChangeService.save(contractChange);
+
+            // 新、旧采购产品ID关联map
+            Map<String, String> newAndOldIdMap = new HashMap<>();
+
+            // 查询采购产品旧数据
+            List<PurchaseContractProduct> products = iPurchaseContractProductService.lambdaQuery().eq(PurchaseContractProduct::getPurchaseContractId, contract.getId()).list();
+            if (CollectionUtils.isNotEmpty(products)) {
+                List<PurchaseContractProductChange> productChanges = new ArrayList<>();
+                for (PurchaseContractProduct product : products) {
+                    PurchaseContractProductChange productChange = new PurchaseContractProductChange();
+                    BeanUtils.copyProperties(product, productChange);
+                    productChange.setId(IdUtils.fastSimpleUUID());
+                    productChange.setOldId(product.getId());
+                    productChange.setPurchaseContractId(contractChange.getId());
+                    // 记录新旧采购产品ID
+                    newAndOldIdMap.put(productChange.getOldId(), productChange.getId());
+                    // 配件辅材父类ID替换成新父类ID
+                    if (StringUtils.isNotBlank(product.getParentId()) && !StringUtils.equals(product.getParentId(), "0")) {
+                        productChange.setParentId(newAndOldIdMap.get(product.getParentId()));
+                    }
+
+                    productChanges.add(productChange);
+                }
+                // 保存采购产品变更历史记录
+                iPurchaseContractProductChangeService.saveBatch(productChanges);
+            }
+
+            // 查询采购收费项目旧数据
+            List<PurchaseContractProject> projects = iPurchaseContractProjectService.lambdaQuery().eq(PurchaseContractProject::getPurchaseContractId, contract.getId()).list();
+            if (CollectionUtils.isNotEmpty(projects)) {
+                List<PurchaseContractProjectChange> projectChanges = new ArrayList<>();
+                for (PurchaseContractProject project : projects) {
+                    PurchaseContractProjectChange projectChange = new PurchaseContractProjectChange();
+                    BeanUtils.copyProperties(project, projectChange);
+                    projectChange.setId(IdUtils.fastSimpleUUID());
+                    projectChange.setOldId(project.getId());
+                    projectChange.setPurchaseContractId(contractChange.getId());
+                    projectChanges.add(projectChange);
+                }
+                // 保存采购收费项目变更历史记录
+                iPurchaseContractProjectChangeService.saveBatch(projectChanges);
+            }
+
+            // 查询采购出货明细旧数据
+            List<ShipmentDetailed> detaileds = iShipmentDetailedService.lambdaQuery().eq(ShipmentDetailed::getBusinessId, contract.getId()).list();
+            if (CollectionUtils.isNotEmpty(detaileds)) {
+                List<ShipmentDetailedChange> detailedChanges = new ArrayList<>();
+                for (ShipmentDetailed detailed : detaileds) {
+                    ShipmentDetailedChange detailedChange = new ShipmentDetailedChange();
+                    BeanUtils.copyProperties(detailed, detailedChange);
+                    detailedChange.setId(IdUtils.fastSimpleUUID());
+                    detailedChange.setOldId(detailed.getId());
+                    detailedChange.setBusinessId(contractChange.getId());
+                    // 赋值新采购合同产品ID
+                    detailedChange.setProductId(newAndOldIdMap.get(detailed.getProductId()));
+                    detailedChanges.add(detailedChange);
+                }
+                // 保存采购出货明细变更历史记录
+                iShipmentDetailedChangeService.saveBatch(detailedChanges);
+            }
+
+            // 状态:审批中
+            contract.setPurchaseStatus(PurchaseStatusEnum.UNDER_REVIEW.getKey());
+            // 版本号+1
+            contract.setVersion(contract.getVersion() + 1);
+            // 存在变更数据(表示该条合同被发起变更)
+            contract.setIsChange(PurchaseContractConstant.IsChange.EXIST_CHANGE);
+            // 数据来源:变更新增
+            contract.setSource(PurchaseContractConstant.Source.PURCHASE_CHANGE);
+
+            // 设置流程字段
+            // contract.setProcessInstanceId(processTaskResult.getProcessInstanceId());
+            // contract.setProcessInstanceName(processTaskResult.getName());
+            // contract.setProcessInstanceUserId(processTaskResult.getAssignee());
+            // contract.setProcessInstanceUserName(processTaskResult.getAssigneeName());
+
+            // 更新数据
+            iPurchaseContractService.saveOrUpdate(contract);
+            // } catch (Exception e) {
+            //     //手动处理事务回滚
+            //     // activitiApi.deleteFlow(contract.getProcessInstanceId());
+            //
+            //
+            //     throw e;
+            // }
+
+            // 添加日志
+            Date startTime = Optional.ofNullable(contract.getStartTime()).orElse(new Date());
+            iContractTrackLogService.addLog(contract.getContractId(), ContractTrackTypeEnum.PURCHASE.getKey(), ContractTrackLogConstant.Status.SEND, startTime);
+
+            // 启动流程
+            // ProcessTaskResult processTaskResult = startUpFlow(contract);
+
+            String title = AuthUtil.getUserName() + " 在" + LocalDate.now() + "日发起了 采购变更审批流程(单号" + contract.getCode() + ")";
+            flowConstructor().create(contract.getId(), title, contract.getFlowRemark(), contract.getId());
+
+        } catch (Exception e) {
+            throw e;
+        } finally {
+            try {
+                // 解锁
+                lock.unlock();
+            } catch (Exception e) {
+
+            }
+        }
+    }
+
+    @Override
+    public void examineV2(SubmitFlowCondition condition) {
+
+        if (StringUtils.isAnyBlank(condition.getId(), condition.getProcessInstanceId())) {
+            throw new ServiceException("参数缺失");
+        }
+        // 查询采购合同信息
+        QueryWrapper<PurchaseContract> wrapper = new QueryWrapper<>();
+        wrapper.lambda().eq(PurchaseContract::getId, condition.getId()).or().eq(PurchaseContract::getProcessInstanceId, condition.getId());
+        PurchaseContract purchaseContract = iPurchaseContractService.getOne(wrapper);
+        if (Func.isEmpty(purchaseContract)) {
+            throw new ServiceException("采购合同不存在");
+        } else if (purchaseContract.getPurchaseStatus() == PurchaseStatusEnum.INVALID.getKey()) {
+            throw new ServiceException("采购合同已作废");
+        }
+
+
+        //审批操作
+        ExampleResult exampleResult = flowConstructor().jump(condition.getId(), condition.getButtonId(), condition.getFlowRemark());
+        // exampleResult.after(() -> {
+        //     //获取下一节点处理人信息
+        //     JSONObject nextNodeHandleUserInfo = new JSONObject();
+        //     getNextNodeHandleUserInfo(exampleResult, nextNodeHandleUserInfo);
+        //
+        //     //设置流程字段
+        //     UpdateWrapper<Contract> wrapper = new UpdateWrapper<>();
+        //     wrapper.lambda().set(Contract::getProcessInstanceId, nextNodeHandleUserInfo.getString("processInstanceId"));
+        //     wrapper.lambda().set(Contract::getProcessInstanceUserId, nextNodeHandleUserInfo.getString("processInstanceUserId"));
+        //     wrapper.lambda().set(Contract::getProcessInstanceUserName, nextNodeHandleUserInfo.getString("processInstanceUserName"));
+        //     wrapper.lambda().eq(Contract::getId, entity.getId());
+        //
+        //     //修改外销合同表
+        //     contractService.update(wrapper);
+        // });
+    }
+
+    @Override
+    public void deleteV2(Contract entity) {
+        //旧审批数据做伪删除,并同时处理业务数据
+        flowConstructor().deleteLogic(entity.getProcessInstanceId(), entity.getId());
+    }
+
     /**
      * 发送消息通知
      *

+ 7 - 3
bladex-saas-project/saas-business-tradeerp/src/main/resources/templates/contract_GOLDSUN.html

@@ -161,6 +161,7 @@
             <td style="width: 70px; padding-right: 10px; vertical-align: middle">
                 <!-- 企业logo -->
                 <img th:src="${huaWeiUrl}+${company.logo}" alt="" fit="scale-down" style="height: 60px; width: 60px;" />
+
             </td>
             <td style="text-align: center;vertical-align: middle">
                 <!-- 企业英文名称 -->
@@ -192,7 +193,8 @@
         </tr>
     </table>
     <!-- 第一个表格 -->
-    <div class="putImg">
+    <div class="putImg"  style="position: relative">
+        <div style="position: absolute;top:0px;left: 10px"><img style="width: 200px; height: 200px;" th:src="${huaWeiUrl}+${company.companySeal}" alt="" srcset="" /></div>
         <table class="one" cellspacing="0" cellpadding="0">
             <thead>
             <tr>
@@ -203,11 +205,13 @@
             </tr>
             </thead>
             <tbody>
-            <tr>
+            <tr  style="position: relative">
                 <td>
                     <!-- 卖方名称 -->
                     <span th:text="${company.nameEnglish}" />
+
                 </td>
+
                 <td>
                     <!-- 买方名称 -->
                     <span th:text="${contract.customerCompanyName}" />
@@ -596,7 +600,7 @@
                 <!-- 卖方:企业中英文名称 -->
                 <span th:text="${company.nameEnglish}" />
                 <div style="padding: 10px 0 0 10px; position: absolute; top: -160px">
-                    <img style="width: 200px; height: 200px;" th:src="${huaWeiUrl}+${company.companySeal}" alt="" srcset="" />
+
                 </div>
             </td>
             <td style="width: 50%; vertical-align: top">

+ 2 - 0
bladex-saas-project/saas-entity/src/main/java/com/fjhx/message/enums/MessageNoticeEnum.java

@@ -42,6 +42,8 @@ public enum MessageNoticeEnum {
     MESSAGE_NOTICE_TYPE_28(28, "FUNDS_EHSD2"), // ERP 请款审批
     MESSAGE_NOTICE_TYPE_29(29, "FUNDS_EHSD3"), // ERP 请款审批
     MESSAGE_NOTICE_TYPE_30(30, "FUNDS_EHSD4"), // ERP 请款审批
+
+    MESSAGE_NOTICE_TYPE_31(31, "ALTERATION_PURCHASE_CONTRACT"), // 采购合同变更
     ;
 
     private int key;

+ 6 - 2
bladex-saas-project/service-flow/src/main/java/com/fjhx/service/example/impl/ExampleInfoServiceImpl.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.fjhx.base.NewBaseEntity;
 import com.fjhx.constants.StatusConstant;
 import com.fjhx.flow.entity.example.ExampleDetails;
 import com.fjhx.flow.entity.example.ExampleInfo;
@@ -25,7 +26,6 @@ import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.MapUtils;
 import org.springblade.common.enums.YesOrNoEnum;
 import org.springblade.core.launch.constant.FlowConstant;
-import org.springblade.core.mp.base.BaseEntity;
 import org.springblade.core.secure.BladeUser;
 import org.springblade.core.secure.utils.AuthUtil;
 import org.springblade.core.tool.utils.Convert;
@@ -127,7 +127,11 @@ public class ExampleInfoServiceImpl extends ServiceImpl<ExampleInfoMapper, Examp
         Assert.notEmpty(flowLinkNo, "业务关联编码不能为空");
 
         // 流程实例
-        ExampleInfo exampleInfo = getOne(ExampleInfo::getFlowLinkNo, flowLinkNo);
+        ExampleInfo exampleInfo = getOne(Wrappers.<ExampleInfo>lambdaQuery()
+                .eq(ExampleInfo::getFlowLinkNo, flowLinkNo)
+                .orderByDesc(NewBaseEntity::getCreateTime)
+                .last("limit 1")
+        );
 
         // 查询已处理节点
         List<Map<String, Object>> result = exampleDetailsService.listMaps(