云
2026-10-25 d54fbc9d4f8981fa0f7f613b33a28a8cd4f764ea
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java
@@ -5,6 +5,9 @@
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi;
import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskStatusEnum;
import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO;
import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO;
@@ -50,6 +53,11 @@
     */
    private static final String FINANCE_PAYMENT_APPROVE_BIZ_TYPE = "erp_finance_payment_approve";
    /**
     * 付款单审批的 BPM 流程定义 Key
     */
    private static final String FINANCE_PAYMENT_PROCESS_KEY = "erp-finance-payment-audit";
    @Resource
    private ErpFinancePaymentMapper financePaymentMapper;
    @Resource
@@ -73,6 +81,9 @@
    @Resource
    private ApprovalConfigApi approvalConfigApi;
    @Resource
    private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -177,7 +188,14 @@
        // 2. 校验审批配置已启用且配置了有效审批人
        approvalConfigApi.validateApprovalEnabledAndGetApprovers(FINANCE_PAYMENT_APPROVE_BIZ_TYPE);
        // 3. 状态置为审批中,并清空上一轮审核结果
        financePaymentMapper.submitAndResetAuditInfo(id, ErpAuditStatus.APPROVING.getStatus());
        if (financePaymentMapper.submitAndResetAuditInfo(id, ErpAuditStatus.APPROVING.getStatus()) != 1) {
            throw exception(FINANCE_PAYMENT_SUBMIT_FAIL_NOT_ALLOWED);
        }
        // 4. 创建 BPM 流程实例,使审批出现在「协同办公 - 我的流程」
        bpmProcessInstanceApi.createProcessInstance(getLoginUserId(),
                new BpmProcessInstanceCreateReqDTO()
                        .setProcessDefinitionKey(FINANCE_PAYMENT_PROCESS_KEY)
                        .setBusinessKey(String.valueOf(id)));
    }
    @Override
@@ -202,13 +220,50 @@
            if (StrUtil.isBlank(reviewRemark)) {
                throw exception(FINANCE_PAYMENT_AUDIT_REJECT_REASON_REQUIRED);
            }
            financePaymentMapper.auditFinancePayment(id, ErpAuditStatus.PROCESS.getStatus(),
                    userId, getUserNickname(userId), reviewRemark);
            if (financePaymentMapper.auditFinancePayment(id, ErpAuditStatus.PROCESS.getStatus(),
                    userId, getUserNickname(userId), reviewRemark) != 1) {
                throw exception(FINANCE_PAYMENT_AUDIT_FAIL_NOT_PROCESS);
            }
            return;
        }
        // 5. 审核通过:记录审核人与审核意见,状态置为已审核
        financePaymentMapper.auditFinancePayment(id, ErpAuditStatus.APPROVE.getStatus(),
                userId, getUserNickname(userId), reviewRemark);
        if (financePaymentMapper.auditFinancePayment(id, ErpAuditStatus.APPROVE.getStatus(),
                userId, getUserNickname(userId), reviewRemark) != 1) {
            throw exception(FINANCE_PAYMENT_AUDIT_FAIL_NOT_PROCESS);
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateFinancePaymentAuditStatus(Long id, Integer bpmStatus, String reason) {
        // 1. BPM 审批结果映射为付款单状态:通过=已审核;不通过/取消=未审核(退回后可修改并重新提交)
        Integer newStatus = convertBpmResultToStatus(bpmStatus);
        if (newStatus == null) {
            return;
        }
        // 2. 仅当仍处于「审批中」时回写,避免重复覆盖
        if (financePaymentMapper.updateAuditStatusByBpm(id, newStatus, reason) != 1) {
            log.warn("[updateFinancePaymentAuditStatus] 付款单({}) 不处于审批中状态,忽略 BPM 结果({})", id, bpmStatus);
        }
    }
    /**
     * 转换 BPM 审批结果为付款单状态
     *
     * 付款单仅有「未审核 / 审批中 / 已审核 / 已作废」,无独立的「审核不通过」状态,
     * 故驳回或撤销时回退到「未审核」,便于修改后重新提交(与原有轻量审批一致)。
     */
    private Integer convertBpmResultToStatus(Integer bpmStatus) {
        if (BpmTaskStatusEnum.APPROVE.getStatus().equals(bpmStatus)) {
            return ErpAuditStatus.APPROVE.getStatus();
        }
        if (BpmTaskStatusEnum.REJECT.getStatus().equals(bpmStatus)) {
            return ErpAuditStatus.PROCESS.getStatus();
        }
        if (BpmTaskStatusEnum.CANCEL.getStatus().equals(bpmStatus)) {
            return ErpAuditStatus.PROCESS.getStatus();
        }
        return null;
    }
    /**