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.
50 lines
4.2 KiB
50 lines
4.2 KiB
|
3 weeks ago
|
# 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`,单条校验自动继承,超限由 `runBatch` 的 `LeadBatchFailReason.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 扫描**:全部通过
|