4.2 KiB
06 修复:P0-2/3/4/5 领取上限与规则校验链
Type: task Status: resolved Blocked by: 02
Question
按 ticket 02 的裁决修复领取/分配/新增即领取的规则校验链(P0-5 若判误报则跳过,仅复核批量路径):
校验链规格(PRD §6.2/§6.3 定稿):
- claim_rule:池为
CLAIM_RULE_ADMIN_ONLY时销售不可自领(claimLead 已有,复核批量领取路径是否同守)。 - hold_limit(个人持有上限):
COUNT(lead) WHERE owner_user_id=? AND pool_id=? AND status IN (已领取,跟进中)≥ hold_limit → 拒。计数口径仅已领取+跟进中(已转商机/过期失效/作废不占名额)。 - daily_claim_limit(每日领取上限):当日该用户从该池领取计数 ≥ daily_claim_limit → 拒;0=无限跳过;"每日"=自然日。计数的落库依据自选(lead_history CLAIM 行 op_time 或 lead.claim_time),写进 ADR/注释。
落点:
claimLead():进链校验,超限抛CODE_HOLD_LIMIT_EXCEEDED(65007)/CODE_DAILY_LIMIT_EXCEEDED(65006)(以LeadConstants/ResultCode既有定义为准,先查后用)。assignToUser():同一套校验,额度归属=被指派销售(不是操作管理员),按目标线索所属池的上限值算(grill #7)。createLead(claimOnCreate=true):复用同一校验链。语义已由用户定稿(2026-08-19):勾选"是否领取"但超上限(持有/每日)或池 claim_rule 禁自领时,整个新增失败报错,用户只能改选"否"再提交。- 批量路径
claim-batch/assign-user-batch:逐条走同一守卫,超限记LeadBatchFailReason.OVER_HOLD_LIMIT/OVER_DAILY_LIMIT(枚举已存在),部分成功不拖垮整批。
验收:单测覆盖各边界(达上限拒/未达放行/limit=0 跳过/额度归属正确/claimOnCreate 超限整体失败)+ mvn test(crm-lead)全绿 + BOM 扫描。若校验逻辑可抽公共组件(如 ClaimLimitChecker),注意与 LeadTransition 对 crm-rule 零依赖契约的边界(查 crm-rule 侧的前置留在 LeadServiceImpl,参照 CONTEXT.md「状态机守卫」条目)。
Answer
已实施完毕(2026-08-19):
-
ClaimLimitChecker 组件
crm-lead/src/main/java/com/crm/lead/service/ClaimLimitChecker.java——@Component,查 leadMapper:- hold_limit:
COUNT(lead) WHERE owner_user_id=? AND pool_id=? AND status IN (3,4)≥ hold_limit → 抛 65007;hold_limit=0 = 字面 0(0 ≥ 0 恒真 → 拒) - daily_claim_limit:当日
claim_time ≥ 今日 0 时计数 ≥ daily_claim_limit → 抛 65006;0=无限跳过 - 计数依据 =
lead.claim_time(claim/assign 均写,release 不清),反映领取次数非当前持有 - 架构边界:crm-lead 内组件,pool 的 limit 值由 LeadServiceImpl 从 crm-rule 取 LeadPool 后传入,不侵入 LeadTransition 的 crm-rule 零依赖契约
- hold_limit:
-
注入+加校验
LeadServiceImpl——构造器加ClaimLimitChecker,三处调用:claimLead():claim_rule 检查后、transition 前,调check(userId, poolId, holdLimit, dailyLimit)assignToUser():UNDISTRIBUTED/PENDING 路径,取 pool 后调check(userId=被指派销售, ...)(额度归属=被指派销售)createLead(claimOnCreate=true):claim_rule 禁自领 → 抛 65005;额度超限 → 抛 65007/65006,整个新增失败不写库
-
validatePool 修正
LeadPoolServiceImpl——holdLimit < 1改为< 0(允许 0=字面 0) -
批量路径:
claimBatch/assignToUserBatch委派self::claimLead/self.assignToUser,单条校验自动继承,超限由runBatch的LeadBatchFailReason.fromCode()自动映射OVER_HOLD_LIMIT/OVER_DAILY_LIMIT -
单测:
ClaimLimitCheckerTest7 例(hold 达/超/未达/0=字面0;daily 达/0=跳过/未达)LeadServiceImplTest5 例(claimLead hold/daily 超限拒;assignToUser 额度归属=被指派销售;createLead ADMIN_ONLY 拒/额度超限整体失败)LeadPoolServiceImplTest修正 Q10(holdLimit=0 合法,-1 拒)
-
mvn test:crm-rule 26 tests 0 failures / crm-lead 82 tests 0 failures / BUILD SUCCESS
-
BOM 扫描:全部通过