这期说下状态以及对应事件的相关设计,这部份内容是后续状态机相关的配置的基础,其中有些设计在实现的时候来回修改了几版,仍是挺考验细节设计的。java
状态机是为了解决订单的状态变迁问题,为了方便理解,就须要有一个具体的状态变化图,下面是以前处理过的一个案例,先上其对应的状态变迁图:apache
说明:markdown
根据上图所示的状态,设计其对应的状态枚举以下:app
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Optional;
@AllArgsConstructor
@NoArgsConstructor
@Getter
public enum BizOrderStatusEnum {
CREATE("1", "建立"),
WYD_INITIAL_JUMP("2", "初始建立时可能为待实名校验,也可能为待发起借款,须要用guard判断"),
WAIT_REAL_NAME_AUTH("3", "待实名认证"),
WAIT_BORROW("4", "待发起借款"),
CANCEL("999", "用户取消"),
CLOSE("996", "订单关闭"),
SUCCESS("888", "成功,指已销帐,订单彻底终结"),
/**
* 审核相关状态定义-start
*/
AUDITING("100", "审核中"),
WAIT_BIZ_AUDIT("101", "待业务审核"),
BIZ_APPROVED("102", "业务审核经过"),
WAIT_COMPLEMENT("103", "待补全审核资料"),
CHECK_COMPLEMENT("104", "补全资料检查"),// --流程内部使用
WAIT_UPLOAD_IMG("105", "待上传影像资料"),
CHECK_UPLOAD("106", "上传影像检查"),// --- 流程内部使用
WAIT_BEF_DEAL_RISK_AUDIT("111", "待贷前额度评估"),
IN_DEAL_RISK_AUDITING("121", "贷中风控审核"),
WAIT_AF_DEAL_RISK_AUDIT("131", "待贷后审核"),
AF_DEAL_RISK_APPROVED("132", "贷后审核经过"),
APPROVED("198", "审核经过"),
/**
* 审核相关状态定义--end
*/
WAIT_SIGN("200", "待签约"),
SIGNED("288", "签约完成"),
LOANING("300", "放款中"),
LOANED("388", "放款完成"),
REFUNDING("401", "退款中"), // 对于消费贷,存在退款状况
REFUNDED("488", "退款完成"), // 对于消费贷,存在退款状况
BILL_GEN("501", "生成帐单"),
REPAYING("600", "还款中"), // 内部使用的中间瞬时状态,外部传入时不要使用,部分还款采用PART_REPAID类型
PART_REPAID("601", "部分还款"),
REPAID("688", "已还清"),
OVERDUE("700", "已逾期"),;
private String status;
private String desc;
/**
* status是否合法
*
* @param status
* @return
*/
public static boolean isIn(String status) {
return Arrays.asList(BizOrderStatusEnum.values()).parallelStream().
anyMatch(value -> StringUtils.equals(value.getStatus(), status));
}
/**
* 判断status是否相等
*
* @param status
* @param statusEnum
* @return
*/
public static boolean equals(String status, BizOrderStatusEnum statusEnum) {
return StringUtils.equalsIgnoreCase(status, statusEnum.getStatus());
}
/**
* status-->statusEnum
*
* @param status
* @return
*/
public static BizOrderStatusEnum getByStatus(String status) {
Optional<BizOrderStatusEnum> statusEnumOptional = Arrays.asList(BizOrderStatusEnum.values()).parallelStream()
.filter(statusEnum -> StringUtils.equalsIgnoreCase(status, statusEnum.getStatus())).findAny();
if (statusEnumOptional.isPresent()) {
return statusEnumOptional.get();
}
return null;
}
/**
* 判断status是否合法
*
* @param status
* @param statusEnums
* @return
*/
public static boolean isIn(String status, BizOrderStatusEnum... statusEnums) {
return Arrays.asList(statusEnums).parallelStream().
anyMatch(value -> StringUtils.equals(value.getStatus(), status));
}
/**
* 判断是否订单已终结,取消、关闭、成功、拒绝都属于终结状态
*
* @param status
* @return
*/
public static boolean isFinish(String status) {
return isIn(status, SUCCESS, CANCEL, CLOSE);
}
/**
* 判断订单是不是初始建立状态
* 对于: WAIT_REAL_NAME_AUTH, WAIT_BORROW 均可能是初始状态
* 对于其余:暂时为CREATE状态
*
* @param status
* @return
*/
public static boolean isInitialStatus(String status) {
return isIn(status, CREATE, WAIT_REAL_NAME_AUTH, WAIT_BORROW);
}
}复制代码
须要注意的是,这里面有些状态在一些业务场景是用不到的,好比退款,在当前业务场景并无用,这里的状态是全集。spa
事件会致使订单的状态发生变化(固然,不是绝对,有些事件是内部事件,并不会致使状态变化,这时就须要用withInternal来串联,详见下节配置),下面是本次的事件枚举设计
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.Optional;
@AllArgsConstructor
@NoArgsConstructor
@Getter
public enum BizOrderStatusChangeEventEnum {
EVT_CREATE("evt_create"),
EVT_CANCEL("evt_cancel"), // 取消
EVT_NAME_AUTH("evt_name_auth"), // 实名
EVT_SYS_CLOSE("evt_sys_close"), // 系统关单,如超时或风控关单等
EVT_AUDIT("evt_audit"), // 审核
EVT_COMPLEMENT("evt_complement"), // 补全材料
EVT_UPLOAD_IMG("evt_upload_img"), // 上传影像
EVT_APPROVED("evt_approved"), // 批准
EVT_REFUSE("evt_refuse"), // 拒绝
EVT_SIGN("evt_sign"), // 签约
EVT_LOAN("evt_loan"), // 放款
EVT_LOAN_FAILED("evt_loan_failed"),
EVT_REFUND("evt_refund"), // 退款
EVT_REPAY("evt_repay"), // 还款
EVT_GEN_BILL("evt_gen_bill"), // 生成帐单
EVT_TOSUCCESS("evt_tosuccess"), // 销帐
EVT_RETRY("evt_retry"), // 重试
EVT_OVERDUE("evt_overdue") // 逾期,用户无动做,由系统定时任务发起
,
EVT_LOAN_SUCC("evt_loan_succ"),
EVT_NEED_NAME_AUTH("evt_need_name_auth");
String event;
/**
* 判断
* @param eventName
* @return
*/
public static BizOrderStatusChangeEventEnum getEvent(String eventName) {
if (StringUtils.isBlank(eventName)) {
return null;
}
Optional<BizOrderStatusChangeEventEnum> resultOptional = Arrays.asList(BizOrderStatusChangeEventEnum.values()).parallelStream().filter(eventEnum ->
StringUtils.equals(eventName, eventEnum.getEvent())).findAny();
if (resultOptional.isPresent()) {
return resultOptional.get();
}
return null;
}
}复制代码
这里的状态就是StateMachine中的S,事件就是对应的E。code