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.

140 lines
5.0 KiB

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