From fce4f29a64affbaf7cfd4af12256f1bcf504b812 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=AE=B6=E8=AE=AD?= Date: Fri, 1 May 2026 09:55:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../disburse/bo/StateTransitionResult.java | 27 +-- .../DisburseStatusTransitionContext.java | 38 ++-- .../disburse/enums/DisburseActionEnum.java | 12 +- .../enums/DisburseActionRuleEnum.java | 172 ------------------ .../executor/StateTransitionExecutor.java | 117 ++++-------- 5 files changed, 72 insertions(+), 294 deletions(-) delete mode 100644 src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionRuleEnum.java diff --git a/src/main/java/com/example/workutils/demo/disburse/bo/StateTransitionResult.java b/src/main/java/com/example/workutils/demo/disburse/bo/StateTransitionResult.java index 1cd69a8..5d19eca 100644 --- a/src/main/java/com/example/workutils/demo/disburse/bo/StateTransitionResult.java +++ b/src/main/java/com/example/workutils/demo/disburse/bo/StateTransitionResult.java @@ -1,58 +1,59 @@ package com.example.workutils.demo.disburse.bo; +import com.example.workutils.demo.disburse.enums.DisburseRevokeStatusEnum; import com.example.workutils.demo.disburse.enums.DisburseStateEnum; -import lombok.Data; +import lombok.Getter; /** * @desc: 状态机流转结果 * @author: zhaoyuhang * @date: 2026-04-28 10:01:13 */ -@Data +@Getter public class StateTransitionResult { /** * 状态流转是否成功 */ - public final boolean success; + private final boolean success; /** * 流转后的放款状态 */ - public final DisburseStateEnum transitionAfterState; + private final DisburseStateEnum transitionAfterState; /** * 挂起标识 * false:未挂起,true:已挂起 */ - public final Boolean suspendedFlag; + private final Boolean suspendedFlag; /** - * 撤销标识 - * false:未撤销,true:已撤销 + * 撤销状态 */ - public final Boolean revokeFlag; + private final DisburseRevokeStatusEnum revokeStatus; /** * 操作拒绝原因 */ - public final String failReason; + private final String failReason; private StateTransitionResult(boolean success, DisburseStateEnum transitionAfterState, - Boolean suspendedFlag, Boolean revokeFlag, String failReason) { + Boolean suspendedFlag, DisburseRevokeStatusEnum revokeStatus, + String failReason) { this.success = success; this.transitionAfterState = transitionAfterState; this.suspendedFlag = suspendedFlag; - this.revokeFlag = revokeFlag; + this.revokeStatus = revokeStatus; this.failReason = failReason; } public static StateTransitionResult allow(DisburseStateEnum transitionAfterState, Boolean suspended, - Boolean canceled) { - return new StateTransitionResult(true, transitionAfterState, suspended, canceled, null); + DisburseRevokeStatusEnum revokeStatus) { + return new StateTransitionResult(true, transitionAfterState, suspended, revokeStatus, null); } public static StateTransitionResult deny(String reason) { diff --git a/src/main/java/com/example/workutils/demo/disburse/context/DisburseStatusTransitionContext.java b/src/main/java/com/example/workutils/demo/disburse/context/DisburseStatusTransitionContext.java index 564aff1..0596ac5 100644 --- a/src/main/java/com/example/workutils/demo/disburse/context/DisburseStatusTransitionContext.java +++ b/src/main/java/com/example/workutils/demo/disburse/context/DisburseStatusTransitionContext.java @@ -1,64 +1,48 @@ package com.example.workutils.demo.disburse.context; +import com.example.workutils.demo.disburse.enums.DisburseRevokeStatusEnum; import com.example.workutils.demo.disburse.enums.DisburseStateEnum; -import lombok.Data; +import lombok.Getter; /** * @desc: 放款状态流转上下文类 * @author: zhaoyuhang * @date: 2026-04-28 10:06:37 */ -@Data +@Getter public class DisburseStatusTransitionContext { /** * 放款状态枚举 */ - public DisburseStateEnum currentDisburseState; + private final DisburseStateEnum currentDisburseState; /** * 挂起标识 * false:未挂起,true:已挂起 */ - public boolean suspendedFlag; + private final boolean suspendedFlag; /** - * 撤销标识 - * false:未撤销,true:已撤销 + * 撤销状态 */ - public boolean revokeFlag; + private final DisburseRevokeStatusEnum revokeStatus; /** * 达到冷静期标识 * false:未达到冷静期,true:已达到冷静期 */ - public boolean coolingReachedFlag; - - /** - * 自动确认标识 - * false:不自动确认,true:自动确认 - */ - public boolean autoConfirmFlag; - - /** - * 自动审核标识 - * false:不自动审核,true:自动审核 - */ - public boolean autoAuditFlag; + private final boolean coolingReachedFlag; public DisburseStatusTransitionContext(DisburseStateEnum currentDisburseState, boolean suspendedFlag, - boolean revokeFlag, - boolean coolingReachedFlag, - boolean autoConfirmFlag, - boolean autoAuditFlag) { + DisburseRevokeStatusEnum revokeStatus, + boolean coolingReachedFlag) { this.currentDisburseState = currentDisburseState; this.suspendedFlag = suspendedFlag; - this.revokeFlag = revokeFlag; + this.revokeStatus = revokeStatus; this.coolingReachedFlag = coolingReachedFlag; - this.autoConfirmFlag = autoConfirmFlag; - this.autoAuditFlag = autoAuditFlag; } } diff --git a/src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionEnum.java b/src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionEnum.java index 2e46184..a4af01b 100644 --- a/src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionEnum.java +++ b/src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionEnum.java @@ -50,7 +50,17 @@ public enum DisburseActionEnum { /** * 撤销 */ - REVOKE("撤销"); + REVOKE("撤销"), + + /** + * 撤销成功 + */ + REVOKE_SUCCESS("撤销成功"), + + /** + * 撤销失败 + */ + REVOKE_FAIL("撤销失败"); /** * 描述 diff --git a/src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionRuleEnum.java b/src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionRuleEnum.java deleted file mode 100644 index 9a53689..0000000 --- a/src/main/java/com/example/workutils/demo/disburse/enums/DisburseActionRuleEnum.java +++ /dev/null @@ -1,172 +0,0 @@ -package com.example.workutils.demo.disburse.enums; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * @Description: 放款操作规则枚举(决策表) - * @Author:zhaoyuhang - * @Date: 2026/4/28 - **/ -@Getter -@AllArgsConstructor -public enum DisburseActionRuleEnum { - - /** - * 挂起:初始化/待确认/待审核 + 未挂起 → 挂起标识置true,状态不变 - * - * 操作:挂起 - * 允许操作的放款状态:初始化、待确认、 - */ - SUSPEND(DisburseActionEnum.SUSPEND, - Arrays.asList(DisburseStateEnum.INIT, - DisburseStateEnum.PENDING_CONFIRM, - DisburseStateEnum.PENDING_AUDIT), - false, - null, - null, - null, - "初始化/待确认/待审核可挂起"), - - /** - * 挂起恢复:已挂起 → 挂起标识置false,状态不变 - */ - SUSPEND_RESUME(DisburseActionEnum.SUSPEND_RESUME, - null, - true, - null, - null, - null, - "已挂起可恢复"), - - /** - * 提交:初始化 + 未挂起 + 未撤销 + 已达到冷静期 → 待确认 - */ - COMMIT(DisburseActionEnum.COMMIT, - Arrays.asList(DisburseStateEnum.INIT), - false, - false, - true, - DisburseStateEnum.PENDING_CONFIRM, - "全部条件必须满足"), - - /** - * 确认:待确认 + 未挂起 + 未撤销 → 待审核 - */ - CONFIRM(DisburseActionEnum.CONFIRM, - Arrays.asList(DisburseStateEnum.PENDING_CONFIRM), - false, - false, - null, - DisburseStateEnum.PENDING_AUDIT, - "全部条件必须满足"), - - /** - * 审核:待审核 + 未挂起 + 未撤销 → 放款中 - */ - AUDIT(DisburseActionEnum.AUDIT, - Arrays.asList(DisburseStateEnum.PENDING_AUDIT), - false, - false, - null, - DisburseStateEnum.DISBURSING, - "全部条件必须匹配"), - - /** - * 放款成功:放款中 → 放款成功 - */ - DISBURSE_SUCCESS(DisburseActionEnum.DISBURSE_SUCCESS, - Arrays.asList(DisburseStateEnum.DISBURSING), - null, - null, - null, - DisburseStateEnum.DISBURSE_SUCCESS, - "放款中→放款成功"), - - /** - * 放款失败:放款中 → 放款失败 - */ - DISBURSE_FAIL(DisburseActionEnum.DISBURSE_FAIL, - Arrays.asList(DisburseStateEnum.DISBURSING), - null, - null, - null, - DisburseStateEnum.DISBURSE_FAILED, - "放款中→放款失败"), - - /** - * 撤销(放款前):初始化/待确认/待审核 + 未撤销 → 放款失败 - */ - REVOKE_BEFORE_DISBURSE(DisburseActionEnum.REVOKE, - Arrays.asList(DisburseStateEnum.INIT, DisburseStateEnum.PENDING_CONFIRM, DisburseStateEnum.PENDING_AUDIT), - null, - false, - null, - DisburseStateEnum.DISBURSE_FAILED, - "未发起交易前撤销直接阻止放款"), - - /** - * 撤销(放款后):放款中/放款成功 + 未撤销 → 状态不变 - */ - REVOKE_AFTER_DISBURSE(DisburseActionEnum.REVOKE, - Arrays.asList(DisburseStateEnum.DISBURSING, DisburseStateEnum.DISBURSE_SUCCESS), - null, - false, - null, - null, - "发起结算后轧差处理"), - - ; - - /** - * 放款操作枚举 - */ - private final DisburseActionEnum disburseActionEnum; - - /** - * 允许的当前放款状态列表,null表示任意状态 - */ - private final List allowDisburseStates; - - /** - * 期望挂起状态 - * false:未挂起,true:已挂起,null:不检查 - */ - private final Boolean expectSuspended; - - /** - * 期望撤销状态 - * false:未撤销,true:已撤销,null:不检查 - */ - private final Boolean expectRevoked; - - /** - * 期望达到冷静期 - * false:未达到冷静期,true:已达到冷静期,null:不检查 - */ - private final Boolean expectCoolingReached; - - /** - * 目标放款状态,null表示保持当前状态不变 - */ - private final DisburseStateEnum targetDisburseState; - - /** - * 约束说明 - */ - private final String constraintDesc; - - - /** - * 根据操作枚举获取匹配的规则列表(同一操作可能有多条规则) - */ - public static List getRulesByAction(DisburseActionEnum action) { - return Arrays.stream(values()) - .filter(rule -> rule.getDisburseActionEnum() == action) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/com/example/workutils/demo/disburse/executor/StateTransitionExecutor.java b/src/main/java/com/example/workutils/demo/disburse/executor/StateTransitionExecutor.java index da2481f..862cf23 100644 --- a/src/main/java/com/example/workutils/demo/disburse/executor/StateTransitionExecutor.java +++ b/src/main/java/com/example/workutils/demo/disburse/executor/StateTransitionExecutor.java @@ -2,8 +2,10 @@ package com.example.workutils.demo.disburse.executor; import com.example.workutils.demo.disburse.bo.StateTransitionResult; import com.example.workutils.demo.disburse.context.DisburseStatusTransitionContext; +import com.example.workutils.demo.disburse.enums.DisburseActionAllowRuleEnum; import com.example.workutils.demo.disburse.enums.DisburseActionEnum; -import com.example.workutils.demo.disburse.enums.DisburseActionRuleEnum; +import com.example.workutils.demo.disburse.enums.DisburseDenyReasonEnum; +import com.example.workutils.demo.disburse.enums.DisburseRevokeStatusEnum; import com.example.workutils.demo.disburse.enums.DisburseStateEnum; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; @@ -21,122 +23,75 @@ public class StateTransitionExecutor { public StateTransitionResult transitionState(DisburseStatusTransitionContext context, DisburseActionEnum action) { - // 1. 查找该操作的所有规则 - List rules = DisburseActionRuleEnum.getRulesByAction(action); + // 1. 查找该操作的所有允许规则 + List rules = DisburseActionAllowRuleEnum.getRulesByAction(action); if (rules.isEmpty()) { log.error("放款操作未命中任何决策规则,放款操作:{}不合法!", action.name()); - return StateTransitionResult.deny("放款操作未命中任何决策规则!"); + return StateTransitionResult.deny(DisburseDenyReasonEnum.NO_RULE_MATCHED.getReason()); } - // 2. 前置条件检查(挂起/撤销/冷静期),同一操作的所有规则前置条件一致,取第一条校验即可 - DisburseActionRuleEnum referenceRule = rules.get(0); - StateTransitionResult preCheckResult = checkPreConditions(context, referenceRule); - if (preCheckResult != null) { - return preCheckResult; - } - - // 3. 状态匹配:遍历规则,找到allowDisburseStates匹配的规则 - for (DisburseActionRuleEnum rule : rules) { - if (isStateAllowed(rule, context.getCurrentDisburseState())) { + // 2. 根据上下文参数匹配唯一规则:放款状态 + 挂起 + 撤销 + 冷静期 + for (DisburseActionAllowRuleEnum rule : rules) { + if (isConditionMatched(rule, context)) { return executeRule(context, rule); } } - // 4. 无匹配规则 → 拒绝 - return handleNoMatchedRule(context, action); + // 3. 无匹配规则 → 拼接允许规则说明 + String reason = "当前状态不允许执行" + action.getDesc() + + ",允许的放款状态:" + DisburseActionAllowRuleEnum.buildAllowedStatesDesc(rules); + log.info(reason); + return StateTransitionResult.deny(reason); } /** - * 前置条件检查:挂起/撤销/冷静期 + * 检查规则的所有条件是否与上下文匹配 */ - private StateTransitionResult checkPreConditions(DisburseStatusTransitionContext context, - DisburseActionRuleEnum rule) { - // 挂起状态检查 + private boolean isConditionMatched(DisburseActionAllowRuleEnum rule, + DisburseStatusTransitionContext context) { + if (!isStateAllowed(rule, context.getCurrentDisburseState())) { + return false; + } if (rule.getExpectSuspended() != null && !rule.getExpectSuspended().equals(context.isSuspendedFlag())) { - log.info("期望挂起状态:{},实际挂起状态:{},状态不可推进!", - rule.getExpectSuspended(), context.isSuspendedFlag()); - return context.isSuspendedFlag() - ? StateTransitionResult.deny("挂起时不可推进") - : StateTransitionResult.deny("未挂起不可执行该操作"); + return false; } - - // 撤销状态检查 - if (rule.getExpectRevoked() != null - && !rule.getExpectRevoked().equals(context.isRevokeFlag())) { - log.info("期望撤销状态:{},实际撤销状态:{},状态不可推进!", - rule.getExpectRevoked(), context.isRevokeFlag()); - return context.isRevokeFlag() - ? StateTransitionResult.deny("撤销后不可推进") - : StateTransitionResult.deny("未撤销不可执行该操作"); + if (rule.getExpectRevokeStatus() != null + && !rule.getExpectRevokeStatus().equals(context.getRevokeStatus())) { + return false; } - - // 冷静期检查 if (rule.getExpectCoolingReached() != null && !rule.getExpectCoolingReached().equals(context.isCoolingReachedFlag())) { - log.info("期望达到冷静期:{},实际达到冷静期状态:{},冷静期未到!", - rule.getExpectCoolingReached(), context.isCoolingReachedFlag()); - return StateTransitionResult.deny("冷静期未到"); + return false; } - - return null; + return true; } /** * 判断当前状态是否在规则的允许状态列表中 */ - private boolean isStateAllowed(DisburseActionRuleEnum rule, DisburseStateEnum currentState) { + private boolean isStateAllowed(DisburseActionAllowRuleEnum rule, DisburseStateEnum currentState) { return rule.getAllowDisburseStates() == null || rule.getAllowDisburseStates().contains(currentState); } /** - * 执行匹配的规则,计算目标状态 + * 执行匹配的允许规则,计算目标状态 */ private StateTransitionResult executeRule(DisburseStatusTransitionContext context, - DisburseActionRuleEnum rule) { + DisburseActionAllowRuleEnum rule) { DisburseStateEnum targetState = rule.getTargetDisburseState() != null ? rule.getTargetDisburseState() : context.getCurrentDisburseState(); - // 目标挂起标识从操作类型推导:SUSPEND→true,SUSPEND_RESUME→false,其余保持当前 - Boolean targetSuspended = resolveTargetSuspended(context, rule.getDisburseActionEnum()); + Boolean targetSuspended = rule.getTargetSuspended() != null + ? rule.getTargetSuspended() + : context.isSuspendedFlag(); - // 目标撤销标识从操作类型推导:REVOKE→true,其余保持当前 - Boolean targetRevoke = rule.getDisburseActionEnum() == DisburseActionEnum.REVOKE - ? true - : context.isRevokeFlag(); + DisburseRevokeStatusEnum targetRevokeStatus = rule.getTargetRevokeStatus() != null + ? rule.getTargetRevokeStatus() + : context.getRevokeStatus(); - return StateTransitionResult.allow(targetState, targetSuspended, targetRevoke); - } - - /** - * 根据操作类型推导目标挂起标识 - */ - private Boolean resolveTargetSuspended(DisburseStatusTransitionContext context, - DisburseActionEnum action) { - if (action == DisburseActionEnum.SUSPEND) { - return true; - } - if (action == DisburseActionEnum.SUSPEND_RESUME) { - return false; - } - return context.isSuspendedFlag(); - } - - /** - * 无匹配规则时的拒绝处理 - */ - private StateTransitionResult handleNoMatchedRule(DisburseStatusTransitionContext context, - DisburseActionEnum action) { - // 撤销 + 放款失败 → 特殊提示 - if (action == DisburseActionEnum.REVOKE - && context.getCurrentDisburseState() == DisburseStateEnum.DISBURSE_FAILED) { - log.info("放款状态:{}已经放款失败,无需撤销!", context.getCurrentDisburseState()); - return StateTransitionResult.deny("放款单据已经放款失败,无需撤销"); - } - - log.info("当前放款状态:{}不允许执行操作:{}", context.getCurrentDisburseState(), action.getDesc()); - return StateTransitionResult.deny("当前状态不允许该操作"); + return StateTransitionResult.allow(targetState, targetSuspended, targetRevokeStatus); } }