From c4a98bdfe1ed9a54d103c5729d83b64bb53cc28f Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期二, 25 八月 2026 09:08:07 +0800
Subject: [PATCH] feat(erp): 采购订单审批接入协同办公(BPM)
---
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java | 3 +
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java | 18 ++++++++-
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java | 20 ++++++++++
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/listener/ErpPurchaseOrderStatusListener.java | 54 +++++++++++++++++++++++++++
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java | 4 ++
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java | 8 ++++
6 files changed, 104 insertions(+), 3 deletions(-)
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java
index df706ac..f779a39 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java
@@ -13,6 +13,7 @@
import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO;
+import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
import cn.iocoder.yudao.module.erp.enums.ErpPurchaseOrderSourceTypeEnum;
import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi;
import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO;
@@ -40,7 +41,9 @@
import java.util.Map;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@@ -170,6 +173,23 @@
return success(purchaseOrderService.confirmReceipt(id));
}
+ @PostMapping("/reverse-approve")
+ @Operation(summary = "鍙嶅鎵癸紙鍗忓悓鍔炲叕宸插姙浠诲姟涓挙鍥炲凡瀹℃牳璁㈠崟锛岀洿鎺ラ噸鏂拌繘鍏ュ緟鍔炲鎵癸級")
+ @Parameter(name = "processInstanceId", description = "娴佺▼瀹炰緥缂栧彿", required = true)
+ @PreAuthorize("@ss.hasPermission('erp:purchase-order:update-status')")
+ public CommonResult<Boolean> reverseApprove(@RequestParam("processInstanceId") String processInstanceId) {
+ // 1. 鏍规嵁娴佺▼瀹炰緥缂栧彿鎵惧埌閲囪喘璁㈠崟
+ ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.getPurchaseOrderByProcessInstanceId(processInstanceId);
+ if (purchaseOrder == null) {
+ throw exception(PURCHASE_ORDER_NOT_EXISTS);
+ }
+ // 2. 鍙嶅鏍革細宸插鏍� -> 鏈鏍革紙鍚叆搴�/閫�璐ф牎楠岋級
+ purchaseOrderService.updatePurchaseOrderStatus(purchaseOrder.getId(), ErpAuditStatus.PROCESS.getStatus());
+ // 3. 鑷姩閲嶆柊鎻愪氦瀹℃壒 -> 璁㈠崟鐩存帴鍥炲埌鍗忓悓鍔炲叕寰呭姙浠诲姟
+ purchaseOrderService.submitPurchaseOrder(purchaseOrder.getId(), "purchase_order_approve", getLoginUserId());
+ return success(true);
+ }
+
private PageResult<ErpPurchaseOrderRespVO> buildPurchaseOrderVOPageResult(PageResult<ErpPurchaseOrderDO> pageResult) {
if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal());
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java
index 9f7aca0..1caa99f 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java
@@ -74,6 +74,10 @@
return selectOne(ErpPurchaseOrderDO::getNo, no);
}
+ default ErpPurchaseOrderDO selectByProcessInstanceId(String processInstanceId) {
+ return selectOne(ErpPurchaseOrderDO::getProcessInstanceId, processInstanceId);
+ }
+
default List<ErpPurchaseOrderDO> selectList(Long supplierId, Integer status) {
return selectList(new LambdaQueryWrapperX<ErpPurchaseOrderDO>()
.eqIfPresent(ErpPurchaseOrderDO::getSupplierId, supplierId)
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java
index 849625d..db7bbee 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java
@@ -20,7 +20,8 @@
PROCESS(10, "鏈鏍�"), // 鏈鏍�/鑽夌
APPROVING(15, "瀹℃壒涓�"), // 瀹℃壒涓�
APPROVE(20, "宸插鏍�"), // 瀹℃牳閫氳繃
- CANCEL(30, "宸蹭綔搴�"); // 宸蹭綔搴�/宸叉挙閿�
+ CANCEL(30, "宸蹭綔搴�"), // 宸蹭綔搴�/宸叉挙閿�
+ REJECT(35, "宸查┏鍥�"); // 瀹℃壒琚┏鍥�
public static final Integer[] ARRAYS = Arrays.stream(values()).map(ErpAuditStatus::getStatus).toArray(Integer[]::new);
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java
index 120cbd2..d5c204f 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java
@@ -98,6 +98,14 @@
ErpPurchaseOrderDO getPurchaseOrder(Long id);
/**
+ * 鏍规嵁 BPM 娴佺▼瀹炰緥缂栧彿鏌ヨ閲囪喘璁㈠崟锛堢敤浜庡崗鍚屽姙鍏弽瀹℃壒锛�
+ *
+ * @param processInstanceId 娴佺▼瀹炰緥缂栧彿
+ * @return 閲囪喘璁㈠崟
+ */
+ ErpPurchaseOrderDO getPurchaseOrderByProcessInstanceId(String processInstanceId);
+
+ /**
* 鏍¢獙閲囪喘璁㈠崟锛屽凡缁忓鏍搁�氳繃
*
* @param id 缂栧彿
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
index 083095f..8809791 100644
--- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java
@@ -41,6 +41,7 @@
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
+import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
/**
@@ -56,7 +57,11 @@
/**
* BPM 閲囪喘璁㈠崟瀹℃壒鍒嗙被缂栫爜
*/
- private static final String PURCHASE_ORDER_APPROVE_CATEGORY_CODE = "purchase_request_approve";
+ private static final String PURCHASE_ORDER_APPROVE_CATEGORY_CODE = "purchase_order_approve";
+ /**
+ * BPM 閲囪喘璁㈠崟瀹℃壒娴佺▼瀹氫箟 Key锛堝垱寤鸿鍗曞悗鑷姩鎻愪氦鍒板崗鍚屽姙鍏鎵癸級
+ */
+ private static final String PURCHASE_ORDER_APPROVE_PROCESS_DEFINITION_KEY = "purchase_order_approve";
@Resource
private ErpPurchaseOrderMapper purchaseOrderMapper;
@@ -119,6 +124,10 @@
// 2.3 缁戝畾闄勪欢
storageAttachmentApi.bindAttachments("file", "erp_purchase_order",
purchaseOrder.getId(), createReqVO.getBlobIds());
+
+ // 3. 鍒涘缓鍚庤嚜鍔ㄦ彁浜ゅ鎵瑰埌鍗忓悓鍔炲叕锛堝鎵瑰湪鍗忓悓鍔炲叕瀹屾垚锛屼笉鍦ㄦ湰椤甸潰瀹℃壒锛�
+ submitPurchaseOrder(purchaseOrder.getId(), PURCHASE_ORDER_APPROVE_PROCESS_DEFINITION_KEY, getLoginUserId());
+
return purchaseOrder.getId();
}
@@ -288,7 +297,7 @@
if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmResult)) {
return ErpAuditStatus.APPROVE.getStatus();
} else if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmResult)) {
- return ErpAuditStatus.PROCESS.getStatus();
+ return ErpAuditStatus.REJECT.getStatus();
} else if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmResult)) {
return ErpAuditStatus.CANCEL.getStatus();
}
@@ -406,6 +415,11 @@
}
@Override
+ public ErpPurchaseOrderDO getPurchaseOrderByProcessInstanceId(String processInstanceId) {
+ return purchaseOrderMapper.selectByProcessInstanceId(processInstanceId);
+ }
+
+ @Override
public ErpPurchaseOrderDO validatePurchaseOrder(Long id) {
ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id);
if (ObjectUtil.notEqual(purchaseOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) {
diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/listener/ErpPurchaseOrderStatusListener.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/listener/ErpPurchaseOrderStatusListener.java
new file mode 100644
index 0000000..62fdb1d
--- /dev/null
+++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/listener/ErpPurchaseOrderStatusListener.java
@@ -0,0 +1,54 @@
+package cn.iocoder.yudao.module.erp.service.purchase.listener;
+
+import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent;
+import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEventListener;
+import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseOrderService;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+/**
+ * 閲囪喘璁㈠崟瀹℃壒鐘舵�佺洃鍚櫒
+ *
+ * 鐩戝惉 BPM 娴佺▼瀹炰緥鐘舵�佸彉鏇翠簨浠讹紝鏇存柊閲囪喘璁㈠崟鐨勫鎵圭姸鎬侊紙鍗忓悓鍔炲叕瀹℃壒鍚庡洖鍐欙級
+ *
+ * @author 瓒呯骇绠$悊鍛�
+ */
+@Component
+@Slf4j
+public class ErpPurchaseOrderStatusListener extends BpmProcessInstanceStatusEventListener {
+
+ /**
+ * 閲囪喘璁㈠崟瀹℃壒娴佺▼瀹氫箟 Key
+ */
+ private static final String PROCESS_DEFINITION_KEY = "purchase_order_approve";
+
+ @Resource
+ private ErpPurchaseOrderService purchaseOrderService;
+
+ @Override
+ protected String getProcessDefinitionKey() {
+ return PROCESS_DEFINITION_KEY;
+ }
+
+ @Override
+ protected void onEvent(BpmProcessInstanceStatusEvent event) {
+ Long orderId;
+ try {
+ orderId = Long.parseLong(event.getBusinessKey());
+ } catch (NumberFormatException e) {
+ log.warn("[onEvent] businessKey({}) 涓嶆槸鏈夋晥鐨勯噰璐鍗曠紪鍙�", event.getBusinessKey());
+ return;
+ }
+
+ log.info("[onEvent] 鏀跺埌BPM瀹℃壒浜嬩欢锛宱rderId={}, status={}", orderId, event.getStatus());
+
+ try {
+ purchaseOrderService.updatePurchaseOrderAuditStatus(orderId, event.getStatus());
+ log.info("[onEvent] 閲囪喘璁㈠崟({}) 瀹℃壒鐘舵�佹洿鏂板畬鎴�", orderId);
+ } catch (Exception e) {
+ log.error("[onEvent] 鏇存柊閲囪喘璁㈠崟瀹℃壒鐘舵�佸け璐ワ紝orderId={}", orderId, e);
+ }
+ }
+
+}
--
Gitblit v1.9.3