這期說下狀態以及對應事件的相關設計,這部份內容是後續狀態機相關的配置的基礎,其中有些設計在實現的時候來回修改了幾版,仍是挺考驗細節設計的。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