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.
 
 
 
 
 
 

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 定稿)

  1. claim_rule:池为 CLAIM_RULE_ADMIN_ONLY 时销售不可自领(claimLead 已有,复核批量领取路径是否同守)。
  2. hold_limit(个人持有上限):COUNT(lead) WHERE owner_user_id=? AND pool_id=? AND status IN (已领取,跟进中) ≥ hold_limit → 拒。计数口径仅已领取+跟进中(已转商机/过期失效/作废不占名额)。
  3. 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 零依赖契约
  • 注入+加校验 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,单条校验自动继承,超限由 runBatchLeadBatchFailReason.fromCode() 自动映射 OVER_HOLD_LIMIT/OVER_DAILY_LIMIT

  • 单测

    • ClaimLimitCheckerTest 7 例(hold 达/超/未达/0=字面0;daily 达/0=跳过/未达)
    • LeadServiceImplTest 5 例(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 扫描:全部通过