You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
5.0 KiB
139 lines
5.0 KiB
package com.crm.lead.state;
|
|
|
|
import com.crm.lead.constant.LeadConstants;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* 线索状态迁移命令——sealed 类型体系,每条迁移边一个子类型。
|
|
*
|
|
* <p>调用方负责预计算所有字段值(快照、deadline 等),
|
|
* {@link LeadTransition} 不查外部服务,保持对 crm-rule / crm-auth 零依赖。</p>
|
|
*
|
|
* <p>每条命令自带守卫声明——{@link #allowedFromStatuses()}(合法起始态集合)与
|
|
* {@link #requiresOwner()}(是否要求操作人==领取人)。{@link LeadTransition#execute}
|
|
* 分派前统一读这两项跑一次守卫(ADR-0021 CAS 之上的友好前置)。目标态计算、
|
|
* 「起始态×命令内容」组合子规则仍由各 apply 实现负责。</p>
|
|
*/
|
|
public sealed interface TransitionCmd
|
|
permits TransitionCmd.ClaimCmd,
|
|
TransitionCmd.AssignToPoolCmd,
|
|
TransitionCmd.AssignToUserCmd,
|
|
TransitionCmd.FeedbackCmd,
|
|
TransitionCmd.ConvertCmd,
|
|
TransitionCmd.ReleaseCmd,
|
|
TransitionCmd.ActivateCmd {
|
|
|
|
/** 操作人 ID——守卫做持有人校验时用。 */
|
|
Long operatorId();
|
|
|
|
/** 这条迁移边的合法起始态集合(守卫层)。 */
|
|
Set<Integer> allowedFromStatuses();
|
|
|
|
/** 这条边是否要求「操作人 == 领取人」。默认否。 */
|
|
default boolean requiresOwner() {
|
|
return false;
|
|
}
|
|
|
|
/** 领取:待领取(2) → 已领取(3) */
|
|
record ClaimCmd(
|
|
Long operatorId,
|
|
String ownerNameSnapshot,
|
|
Long ownerDeptIdSnapshot,
|
|
LocalDateTime recycleDeadline
|
|
) implements TransitionCmd {
|
|
@Override public Set<Integer> allowedFromStatuses() {
|
|
return Set.of(LeadConstants.STATUS_PENDING);
|
|
}
|
|
}
|
|
|
|
/** 分配到公海池:未分发(1) → 待领取(2) */
|
|
record AssignToPoolCmd(
|
|
Long operatorId,
|
|
Long poolId,
|
|
String poolNameSnapshot,
|
|
Long deptId,
|
|
Long teamDeptId,
|
|
LocalDateTime expireDeadline
|
|
) implements TransitionCmd {
|
|
@Override public Set<Integer> allowedFromStatuses() {
|
|
return Set.of(LeadConstants.STATUS_UNDISTRIBUTED);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 分配到销售:未分发(1)/待领取(2) → 已领取(3);线索作废(7) → 线索作废(7)(更新 owner)。
|
|
* 作废状态下 recycleDeadline 为 null。
|
|
*/
|
|
record AssignToUserCmd(
|
|
Long operatorId,
|
|
Long userId,
|
|
String ownerNameSnapshot,
|
|
Long ownerDeptIdSnapshot,
|
|
LocalDateTime recycleDeadline
|
|
) implements TransitionCmd {
|
|
@Override public Set<Integer> allowedFromStatuses() {
|
|
return Set.of(LeadConstants.STATUS_UNDISTRIBUTED,
|
|
LeadConstants.STATUS_PENDING, LeadConstants.STATUS_VOID);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 提交反馈:已领取(3)/跟进中(4) → 跟进中(4)/线索作废(7);线索作废(7) → 已领取(3)(作废恢复)。
|
|
* recycleDeadline 为 null 表示目标状态为线索作废(清 owner,不设 deadline)。
|
|
*/
|
|
record FeedbackCmd(
|
|
Long operatorId,
|
|
int feedbackStatus,
|
|
String content,
|
|
String productCode,
|
|
String attachmentIds,
|
|
LocalDateTime recycleDeadline
|
|
) implements TransitionCmd {
|
|
@Override public Set<Integer> allowedFromStatuses() {
|
|
return Set.of(LeadConstants.STATUS_CLAIMED,
|
|
LeadConstants.STATUS_FOLLOWING, LeadConstants.STATUS_VOID);
|
|
}
|
|
@Override public boolean requiresOwner() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/** 转商机:已领取(3)/跟进中(4) → 已转商机(5)(outbound port 已被 service 调通) */
|
|
record ConvertCmd(
|
|
Long operatorId,
|
|
Long opportunityId,
|
|
String opportunityName
|
|
) implements TransitionCmd {
|
|
@Override public Set<Integer> allowedFromStatuses() {
|
|
return Set.of(LeadConstants.STATUS_CLAIMED, LeadConstants.STATUS_FOLLOWING);
|
|
}
|
|
@Override public boolean requiresOwner() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/** 释放:已领取(3)/跟进中(4) → 待领取(2),清 owner,保留反馈快照 */
|
|
record ReleaseCmd(
|
|
Long operatorId
|
|
) implements TransitionCmd {
|
|
@Override public Set<Integer> allowedFromStatuses() {
|
|
return Set.of(LeadConstants.STATUS_CLAIMED, LeadConstants.STATUS_FOLLOWING);
|
|
}
|
|
@Override public boolean requiresOwner() {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
/** 激活:过期失效(6) → 恢复失效前态,重置回收计时 N 和失效计时 M */
|
|
record ActivateCmd(
|
|
Long operatorId,
|
|
LocalDateTime newExpireDeadline,
|
|
LocalDateTime newRecycleDeadline
|
|
) implements TransitionCmd {
|
|
@Override public Set<Integer> allowedFromStatuses() {
|
|
return Set.of(LeadConstants.STATUS_EXPIRED);
|
|
}
|
|
}
|
|
}
|
|
|