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.
52 lines
4.3 KiB
52 lines
4.3 KiB
|
3 weeks ago
|
# 07 修复:P0-6/7 公海混合展示 + 新增线索归属约束
|
||
|
|
|
||
|
|
Type: task
|
||
|
|
Status: resolved
|
||
|
|
Blocked by: 02, 06
|
||
|
|
|
||
|
|
## Question
|
||
|
|
|
||
|
|
按 ticket 02 的裁决修复(注意与 06 串行——同改 `LeadServiceImpl`):
|
||
|
|
|
||
|
|
**P0-6 公海混合展示**(PRD §7 已定稿(E)):
|
||
|
|
- `LeadViewQueryImpl.buildViewWrapper()` PUBLIC_POOL 分支不再硬编码 `status=PENDING`,改为**"公海可见状态集"参数驱动**,默认 `{待领取, 已领取, 跟进中}`,不硬编码(后续可能收窄/按池细分——留参数化缝)。
|
||
|
|
- 参数放哪(常量类 / 配置项 / LeadPageParam 可选覆盖)由本 ticket 定,遵循"改规则不改代码"的定稿意图并写清注释。
|
||
|
|
- 已被领走的行只读属前端职责;后端保证列表含这些行 + "领取人"字段回填正确。
|
||
|
|
- `LeadViewQueryImplTest` 同步更新(现有 PUBLIC_POOL 断言会变)。
|
||
|
|
|
||
|
|
**P0-7 新增线索归属约束**(PRD §6.1 grill #6 定稿):
|
||
|
|
- 销售新增:**强制回填本人主部门的池**(不给选、不可编辑),忽略前端传入 poolId;兼职部门有池也只落主部门池。
|
||
|
|
- 主部门无池 → 报错拦截("本部门尚未配置公海池,请联系管理员"),不允许销售建挂空池线索。
|
||
|
|
- 管理员新增:可指定任意池,或 poolId=null 建"未分发"(管理员导入专属中间态)。
|
||
|
|
- **需要"当前用户是否管理员"判定**:先查本仓既有实践(角色/权限点判定机制,参照 crm-auth 能力与既有 Controller 用法)再落地,不发明新机制。
|
||
|
|
|
||
|
|
**验收**:新增单测(销售回填主部门池/主部门无池拒绝/管理员可建未分发/公海视图含已领取跟进中行)+ `mvn test`(crm-lead)全绿 + BOM 扫描。
|
||
|
|
|
||
|
|
## Answer
|
||
|
|
|
||
|
|
### P0-6 公海混合展示
|
||
|
|
- `LeadConstants` 新增常量 `PUBLIC_POOL_VISIBLE_STATUSES = List.of(STATUS_PENDING, STATUS_CLAIMED, STATUS_FOLLOWING)`(参数化缝——后续可按池细分或收窄,改常量不改代码)。
|
||
|
|
- `LeadViewQueryImpl` PUBLIC_POOL 分支从 `wrapper.eq(Lead::getStatus, STATUS_PENDING)` 改为 `wrapper.in(Lead::getStatus, LeadConstants.PUBLIC_POOL_VISIBLE_STATUSES)`。
|
||
|
|
- 新增 `LeadViewQueryImplTest.pageLeads_publicPoolView_usesInClause`——验证 wrapper SQL 含 IN 子句。
|
||
|
|
|
||
|
|
### P0-7 新增线索归属约束
|
||
|
|
- `SecurityUtils` 新增 `hasRole(String roleCode)` 方法——遍历 `Authentication.getAuthorities()` 匹配角色码,不硬编码角色名;调用方传 `AuthConstants.ROLE_CODE_ADMIN`。
|
||
|
|
- `ILeadService` 新增 4 参 `createLead(dto, claimOnCreate, followOnCreate, Long assignToUserId)` 抽象方法;3 参版本改为 default 委托(assignToUserId=null)。
|
||
|
|
- `LeadServiceImpl.createLead` 重构为 4 分支:
|
||
|
|
1. **非管理员**:`ownerSnapshotResolver.of(userId)` 取主部门 → `getPoolByDept(deptId)` 强制回填池(忽略前端 poolId);无池→65001 拒;claimOnCreate 时校验 claim_rule + 额度,设置 CLAIMED;否则 PENDING。
|
||
|
|
2. **管理员 + assignToUserId != null**(选人即分配):`getPoolByIdOrThrow(poolId)` 取池 → `ownerSnapshotResolver.of(assignToUserId)` → 额度校验归属=被指派人 → CLAIMED + owner=被指派人。
|
||
|
|
3. **管理员 + poolId=null**:建未分发(UNDISTRIBUTED)。
|
||
|
|
4. **管理员 + poolId 指定(不选人)**:`getPoolByIdOrThrow(poolId)` 取池 → claimOnCreate 时校验 claim_rule + 额度。
|
||
|
|
- `LeadController.create` 端点加 `@RequestParam(value = "assignToUserId", required = false) Long assignToUserId` 参数。
|
||
|
|
|
||
|
|
### 单测(LeadServiceImplTest +3, LeadViewQueryImplTest +1)
|
||
|
|
- `createLead_salesUser_deptNoPool_rejected`——主部门无池→65001 拒、不写库。
|
||
|
|
- `createLead_adminNoPool_undistributed`——管理员不指定池→UNDISTRIBUTED。
|
||
|
|
- `createLead_adminAssignToUser_claimedOnCreate`——选人即分配→CLAIMED + owner=被指派人 + 额度归属=被指派人 + ADMIN_ONLY 池不阻拦管理员分配。
|
||
|
|
- `pageLeads_publicPoolView_usesInClause`——PUBLIC_POOL 视图 wrapper 用 IN 子句(非 eq 单值)。
|
||
|
|
- 修复 4 个既有 createLead 测试(followOnCreate/noFollow/adminOnlyPool_rejected/limitExceeded)——适配非管理员路径的 `stubUserLookup` + `getPoolByDept` stub。
|
||
|
|
|
||
|
|
### 验证
|
||
|
|
- BOM 扫描:8 个修改文件全部无 BOM。
|
||
|
|
- `mvn test -pl crm-base,crm-lead -am`:86 tests, 0 failures, 0 errors, BUILD SUCCESS。
|