Răsfoiți Sursa

docs: 锁定活动管理整改决策(D1-D4)并更新方案

依据用户 2026-10-22 拍板的 4 项决策更新 docs/整改方案-活动管理差异修复-2026-10-22.md:(D1)签到审核按活动级 requireCheckinReview 落地功能;(D2)活动总结清理死代码(删 summarizing 死值);(D3)删除 guide_activities 与 activity_provisions 两子系统并整合进主活动(前置依赖审计);(D4)报名审核改为活动级 requireReview 默认 false(免审即占名额、需审审过才占),撤销免费强制审核。方案已具备分批改实现条件。
zxyj-web 3 săptămâni în urmă
părinte
comite
5266f70044
1 a modificat fișierele cu 117 adăugiri și 87 ștergeri
  1. 117 87
      docs/整改方案-活动管理差异修复-2026-10-22.md

+ 117 - 87
docs/整改方案-活动管理差异修复-2026-10-22.md

@@ -2,113 +2,135 @@
 
 - **日期**:2026-10-22
 - **关联调研**:`docs/调研报告-活动管理实现vs需求-2026-10-22.html`
-- **范围**:cfc-backend 主活动(activities)全流程差异修复
-- **状态**:方案稿(待产品/架构确认后分批改)
+- **范围**:cfc-backend 活动域全流程差异修复
+- **状态**:✅ 决策已锁定(2026-10-22 用户拍板),待分批改实现
+
+---
+
+## 〇、决策锁定记录(2026-10-22)
+
+| # | 议题 | 决策 |
+|---|------|------|
+| D1 | 签到是否要审核 | **在活动里定义**(活动级开关 `requireCheckinReview`),开启时签到进入"待审核",由管理端/规划师端审核通过后生效。→ 落地功能(原方案 A)|
+| D2 | 活动总结能力 | **清理死代码**:不做自动聚合/AI 总结,删除 DTO 的 `summarizing` 死值声明与注释、清理 `applyDisplayState` 中不可能产出的分支。→ 原方案 B |
+| D3 | 规划师活动 / 履约活动 | **删除**两套独立子系统(`guide_activities`、`activity_provisions`),其能力并入主活动 `activities`;删除前先做依赖影响面审计。→ 原方案 P2-2 升级为"删除+整合" |
+| D4 | 报名是否需要审核 | **默认免审核**:活动级开关 `requireReview`(默认 false)。仅当活动显式开启"需审核"时,报名进入 pending,审核通过(approve)才占用名额;免审核活动报名即 approved,立即占用名额。原"免费活动强制审核"逻辑撤销。 |
+
+> 关键语义统一:**"是否需审核"是活动级开关**(报名审核 `requireReview`、签到审核 `requireCheckinReview`),两开关默认均关闭。名额占用统一发生在"状态变为 approved"时点。
 
 ---
 
 ## 一、目标与原则
 
-1. **先修阻断正确性的项(P0)**:名额失控、取消报名主路径断裂、无退款、签到审核字段失效——这四项直接影响业务正确性与用户信任,优先落地。
-2. **再修一致性与完整性(P1)**:计数口径、发布范式、评价门槛、总结能力。
-3. **低优收口(P2)**:定时化、子系统整合决策。
-4. **最小侵入**:每个修复点尽量收敛在既有 Service 方法内,避免跨模块重构;涉及支付/退款的改动必须走回归测试。
-5. **可回滚**:每个修复独立提交,便于按项回退。
+1. **先修阻断正确性的项(P0)**:名额失控、取消报名主路径断裂、无退款、签到审核字段失效——四项直接影响业务正确性与用户信任。
+2. **再修一致性与完整性(P1)**:计数口径、发布范式、评价门槛、总结死代码清理。
+3. **收口架构(P2)**:删除规划师活动/履约活动子系统,整合进主活动;过期结束定时化。
+4. **最小侵入 + 可回滚**:每个修复独立提交,便于按项回退;涉及支付/退款与删表改动必须做影响面评估与回归。
 
 ---
 
-## 二、整改项清单
+## 二、整改项清单(已锁定)
 
-| 编号 | 级别 | 问题 | 涉及文件 | 方案要点 |
-|------|------|------|----------|----------|
-| P0-1 | 🔴 高 | 名额 maxParticipants 报名时不校验,允许超额 | `ActivityRegistrationService`、实体 `Activity` | 名额占用发生在"变为 approved"时点,用原子自增+上限约束防超卖 |
-| P0-2 | 🔴 高 | 取消报名仅支持 pending;无退款、无名额回滚 | `ActivityRegistrationService.cancel`、`ActivityOrderService`、`PaymentService` | 支持 approved 取消;付费活动联动退款;原子回退名额 |
-| P0-3 | 🔴 高 | 签到审核字段 requireCheckinReview 失效 | `ActivityService.checkin`、新增审核端点 | 落地"待审核"中间态;或移除字段(二选一) |
-| P1-1 | 🟡 中 | currentParticipants 实为签到计数,与名额口径错位 | `Activity` 实体、`ActivityService` | 拆分"报名人数"与"签到人数"两个口径 |
-| P1-2 | 🟡 中 | 两套发布范式不一致(直发不校验维度 / 审核强制权重100%) | `ActivityService.publish`、`ActivityAdminService` | 统一维度校验规则,消除状态歧义 |
-| P1-3 | 🟡 中 | 评价无门槛、无去重、status 恒 0 | `ActivityFeedbackService.submit` | 校验"已报名且已签到",按 child 去重 |
-| P1-4 | 🟡 中 | 活动总结无聚合/AI 生成;DTO summarizing 死值 | `ActivityService`、`ActivityDTO` | 新增 summary 端点聚合;或清理死代码 |
-| P2-1 | 🟢 低 | 过期自动结束仅查询触发+延迟7天 | `ActivityService.autoEndExpiredActivities` | 改为 Spring @Scheduled 定时任务 |
-| P2-2 | 🟢 低 | 三套活动子系统并存且互不相通 | 架构层 | 决策是否抽象统一 Activity 内核 |
+| 编号 | 级别 | 问题 | 涉及文件 | 方案要点 | 决策 |
+|------|------|------|----------|----------|------|
+| P0-1 | 🔴 高 | 名额 maxParticipants 报名时不校验 | `ActivityRegistrationService`、`Activity` | 名额占用发生在"变 approved"时点;活动级 `requireReview` 默认 false(免审即报即占,需审审过才占),原子自增+上限约束防超卖 | D4 |
+| P0-2 | 🔴 高 | 取消报名仅支持 pending;无退款、无名额回滚 | `cancel`、`ActivityOrderService`、`PaymentService` | 支持 approved 取消;付费联动退款;原子回退名额 | — |
+| P0-3 | 🔴 高 | 签到审核字段 requireCheckinReview 失效 | `checkin`、新增审核端点 | **落地功能**:按活动级开关,开启时签到进"待审核",审核通过生效并发积分 | D1 |
+| P1-1 | 🟡 中 | currentParticipants 实为签到计数 | `Activity`、`ActivityService` | 拆分报名人数/签到人数字段,统一口径 | — |
+| P1-2 | 🟡 中 | 发布范式不一致 | `publish`、`ActivityAdminService` | 两路统一要求 `dimensionCode` 非空 | — |
+| P1-3 | 🟡 中 | 评价无门槛、无去重、status 恒 0 | `ActivityFeedbackService.submit` | 校验已报名且已签到;按 child 去重 | — |
+| P1-4 | 🟡 中 | 总结死代码 | `ActivityDTO`、`ActivityService` | **清理死代码**:删 `summarizing` 声明与不可能分支 | D2 |
+| P2-1 | 🟢 低 | 过期结束仅查询触发+延迟7天 | `autoEndExpiredActivities` | 改为 Spring @Scheduled 定时任务 | — |
+| P2-2 | 🟢 低→中 | 三套子系统并存 | 架构层 | **删除** `guide_activities`、`activity_provisions`,整合进主活动(删除前做依赖审计) | D3 |
 
 ---
 
 ## 三、详细方案
 
-### P0-1 名额原子校验(防超卖)
+### P0-1 名额原子校验 + 报名审核活动级开关(防超卖)
 
-**现状**:`register`(:75) / `batchRegister`(:39) 与 `checkRegistrationGate`(:318) 均不读 `maxParticipants`;名额只在 `getRegistrationRoster`(:225) 展示时计算"剩余"。
+**现状**:`register`(:75) / `batchRegister`(:39) 与 `checkRegistrationGate`(:318) 均不读 `maxParticipants`;且当前免费活动默认强制审核,与"默认免审"诉求不符。
 
-**问题本质**:名额应占用在"审核通过 / 支付成功(即状态变为 approved)"的时点,而非报名(pending)时点。因此校验点应在**写入 approved** 处,而非 register 处。
+**决策(D4)**:报名是否需审核由活动级开关 `requireReview`(默认 false)决定:
+- `requireReview = false`(默认):报名即 `approved`,**立即占用名额**;
+- `requireReview = true`:报名进入 `pending`,**仅审核通过(approve)才占用名额**;审核拒绝则释放/不占。
 
 **方案**:
-1. 在实体 `Activity` 增加字段 `signedUpCount`(已通过报名人数,区别于签到计数),或直接复用原子更新保证上限。
-2. 在以下两处"变为 approved"的逻辑加原子上限约束(推荐使用 `UPDATE … SET current_participants = current_participants + 1 WHERE id = ? AND current_participants < max_participants`,以 affected rows 判断是否成功):
-   - `ActivityRegistrationService.approve`(:105)
-   - `ActivityOrderService.writeRegistrations`(支付成功写 approved 处)
-3. 若名额已满,approve 返回"名额已满,无法通过";支付成功写报名时若满员则触发退款并提示。
-4. `getRegistrationRoster` 的"剩余名额"改为读取同一计数,去掉 `Math.max(0,…)` 兜底的误导。
-
-**影响**:报名(pending)不受限、审核/支付通过时受限于名额——符合"满员截止"的业务语义;需处理并发(原子 SQL 已解决)。
-**测试**:并发 20 请求同时通过审核,名额=10 时仅 10 条 approved;支付回调并发同理。
+1. 实体 `Activity` 增加 `requireReview`(tinyint,默认 0)。`requireCheckinReview` 沿用既有字段(D1)。
+2. `register`/`batchRegister` 中:若 `requireReview`,`status=pending`;否则 `status=approved` 并走名额占用。
+3. 名额占用统一在"变 approved"处用原子 SQL 约束:
+   `UPDATE activities SET current_participants = current_participants + 1 WHERE id = ? AND current_participants < max_participants`
+   以 affected rows 判断是否成功;失败返回"名额已满"。
+   涉及两处:
+   - `ActivityRegistrationService.approve`(:105)(需审活动审过)
+   - `ActivityOrderService.writeRegistrations`(付费活动支付成功写 approved)
+4. 撤销"免费活动强制审核"旧逻辑(`checkRegistrationGate`/register 中对免费即 pending 的强制),改为读 `requireReview`。
+5. `getRegistrationRoster`(:225) 的"剩余名额"读取同一计数,去掉 `Math.max(0,…)` 兜底误导。
+
+**影响**:免费活动默认改为免审即过;需审活动才进审核流——符合 D4。需处理并发(原子 SQL 已解决)。
+**测试**:并发 20 通过审核/支付,名额=10 时仅 10 条 approved;免审活动报名即满员受限额约束。
 
 ---
 
 ### P0-2 取消报名支持 approved + 退款/名额回滚
 
-**现状**:`cancel`(:97) 用 `findRegistration(...,"pending")` 过滤,已 approved/已支付报名无法取消,且全程无退款、无名额回滚。
+**现状**:`cancel`(:97) 用 `findRegistration(...,"pending")` 过滤,已 approved/已支付报名无法取消,且全程无退款、无名额回滚。D4 落地后绝大多数报名为 approved,本问题影响面更大,**必修**。
 
 **方案**:
 1. `cancel` 放宽到 `status IN ('pending','approved')`;`findRegistration` 去掉仅 pending 限制(或新增重载)。
-2. 判定是否付费:`hasPaidOrder(activityId, userId)`(已存在,:333)。若命中已支付订单:
-   - 调用 `PaymentService.refund(orderNo, amount)` 原路退款;
-   - 退款成功后置 `ActivityOrder.status = 'refunded'`,原报名记录置 `cancelled`。
-3. 名额回滚:在 approve 占用名额的前提下,取消 approved 时原子 `current_participants = current_participants - 1 WHERE id = ? AND current_participants > 0`。
-4. 记录 `cancelledAt` 与可选 `cancelReason`(实体需加 `cancelledAt` 字段)。
-5. 退款为异步/外部调用,需加失败重试与告警;退款失败时不置 cancelled,返回"退款处理中/失败"。
+2. 判定付费:`hasPaidOrder(activityId, userId)`(:333)。命中已支付订单则:
+   - 调 `PaymentService.refund(orderNo, amount)` 原路退款;
+   - 成功后 `ActivityOrder.status='refunded'`,报名记录置 `cancelled`。
+3. 名额回滚:取消 approved 时原子 `current_participants = current_participants - 1 WHERE id = ? AND current_participants > 0`。
+4. 实体加 `cancelledAt`、`cancelReason`(可选)字段。
+5. 退款为外部异步调用,加失败重试与告警;退款失败时不置 cancelled,返回"退款处理中/失败"。
 
-**影响**:触及支付资金流,必须回归;建议先在非生产环境用小额订单验证退款链路。
-**测试**:免费活动 approved→取消成功、名额-1;付费活动 approved→取消触发退款、订单置 refunded、名额-1;pending→取消不变更资金。
+**影响**:触及支付资金流,必须回归;建议先小额订单验证退款链路(D4 已明确"需审才占名额",但付费报名通常免审即占,取消即触发退款,务必验证)。
+**测试**:免费 approved→取消成功、名额-1;付费 approved→取消触发退款、订单 refunded、名额-1;pending→取消不变更资金。
 
 ---
 
-### P0-3 签到审核字段落地(或移除)
+### P0-3 签到审核字段落地(按活动级开关)
 
-**现状**:实体有 `requireCheckinReview`,`checkin`(:198) 从不读取,一律直接 `Task.status="completed"`。
+**现状**:实体有 `requireCheckinReview`(D1 确认在活动里定义),但 `checkin`(:198) 从不读取,一律直接 `Task.status="completed"`。
 
-**方案(二选一,建议 A)**:
-- **A 落地功能**:`checkin` 中若 `requireCheckinReview == 1`,生成 `Task.status = 'pending_review'`(待审核),返回 `needReview=true`;新增管理端/规划师端端点 `POST /api/admin/activity/checkin/review {taskId, action}` 审核通过后置 `completed` 并发积分/能量;不通过则删除 Task 或置 `rejected`。需同步 `applyDisplayState` 识别"已签到待审核"展示态。
-- **B 移除**:若业务确认不需要签到审核,从实体、建表、`ActivityDTO` 与后台配置表单中移除该字段,避免误导运营。
+**方案(已锁定 A)**:
+1. `checkin`(:198) 中读取活动 `requireCheckinReview`:
+   - `=1`:生成 `Task.status='pending_review'`(待审核),返回 `needReview=true`;不立即发积分/能量。
+   - `=0`(默认):行为同现状,`Task.status='completed'` 并发积分/能量。
+2. 新增端点 `POST /api/admin/activity/checkin/review {taskId, action}`:
+   - `action=approve` → `Task.status='completed'` 并发积分/能量;
+   - `action=reject` → `Task.status='rejected'`(或删除 Task),不发积分。
+3. `applyDisplayState`(:527) 识别"已签到待审核"展示态(如 `checked_in_pending_review`),前端据 `needReview` 提示。
+4. 规划师端若需自审,复用同一审核端点(权限按角色放开)。
 
-**影响**:A 改动签到与 Task 状态机、新增端点;B 为清理型改动。
-**测试**:开启审核后签到→状态 pending_review→审核通过发积分/未通过不发;关闭时行为同现状。
+**影响**:改动签到与 Task 状态机、新增端点;属需求内功能落地,非新需求。
+**测试**:开启审核→签到状态 pending_review→审核通过发积分/未通过不发;关闭时同现状。
 
 ---
 
 ### P1-1 currentParticipants 语义修正
 
-**现状**:`checkin`(:354) 中 `currentParticipants+1`,实为"签到人数",与 `maxParticipants`(报名名额)非同一口径,导致满员判断失真。
+**现状**:`checkin`(:354) 中 `currentParticipants+1` 实为"签到人数",与 `maxParticipants`(报名名额)非同一口径。
 
 **方案**:
-- 新增字段 `signedCount`(签到人数),`checkin` 时 `+1` 到 `signedCount`;
-- 报名名额占用(P0-1)使用独立的 `approvedCount`/`currentParticipants` 语义字段;
-- 对外展示与统计明确区分:报名人数(approved 计数)、签到人数(signedCount)。
-- 若不想新增字段,至少将 `currentParticipants` 明确命名为"签到人数",名额比较统一用 approved 实时统计,前端文案同步。
+- 新增字段 `signedCount`(签到人数),`checkin` 时 `+1`;
+- 报名名额占用(P0-1)使用独立计数(`currentParticipants` 明确为"已通过报名人数");
+- 对外明确区分:报名人数(approved 计数)、签到人数(signedCount)。
 
-**测试**:报名 10 人、签到 6 人时,报名人数=10、签到人数=6、剩余名额=max-10。
+**测试**:报名 10、签到 6 时,报名人数=10、签到人数=6、剩余名额=max-10。
 
 ---
 
 ### P1-2 发布范式统一
 
-**现状**:C 端 `ActivityService.publish`(:173) 不校验维度;管理端审核流 `auditActivity` 强制五维权重合计=100%。
+**现状**:C 端 `publish`(:173) 不校验维度;管理端 `auditActivity` 强制五维权重=100%。
 
 **方案**:
-- 明确两类入口语义:**管理后台直发**(角色已受信任)与**规划师/需审核提交**(走审核流)。
-- 统一维度校验:**两路都要求 `dimensionCode` 非空**(最低一致性);审核流的"权重合计=100%"作为审核专属强校验保留,直发不强要求权重但必须有 dimensionCode。
-- 在 `publish` 增加 `if (dimensionCode == null) return error("请先设置活动维度")`。
+- 明确两类入口语义:**管理后台直发**(受信任角色)与**需审核提交**(走审核流)。
+- 统一维度校验:**两路都要求 `dimensionCode` 非空**;审核流的"权重合计=100%"作为审核专属强校验保留,直发不强要求权重但须有 dimensionCode。
+- `publish` 增加 `if (dimensionCode == null) return error("请先设置活动维度")`。
 
-**影响**:小改动,消除"绕过审核直接 published 且维度缺失"的数据质量问题。
 **测试**:直发无 dimensionCode 被拒;审核流权重≠100% 被拒。
 
 ---
@@ -118,24 +140,25 @@
 **现状**:`ActivityFeedbackService.submit`(:20) 直接 insert,无门槛、无去重,`status` 恒 0。
 
 **方案**:
-- 提交前校验:活动 `status=ended` 或 `now.after(endTime)`(已结束才可评);且 `isApproved` 且 `hasCheckedIn`(已报名且已签到),否则返回"仅参与活动的成员可评价"。
-- 去重:同一 `activityId + childId` 仅一条,重复提交时更新而非新增。
-- `status` 复用:若启用评价审核则 `pending/approved`;否则置 `approved`。
+- 提交前校验:活动已结束(`status=ended` 或 `now.after(endTime)`);且 `isApproved` 且 `hasCheckedIn`(已报名且已签到),否则"仅参与活动的成员可评价"。
+- 去重:同一 `activityId + childId` 仅一条,重复提交更新而非新增。
+- `status` 复用:启用评价审核则 `pending/approved`,否则 `approved`。
 
-**测试**:未报名/未签到用户提交被拒;同一 child 重复提交更新不新增。
+**测试**:未报名/未签到提交被拒;同一 child 重复提交更新不新增。
 
 ---
 
-### P1-4 活动总结能力(或清理死代码)
+### P1-4 活动总结死代码清理(已锁定 B)
 
-**现状**:无服务端聚合/AI 总结;`ActivityDTO` 注释声明 `summarizing` 但 `applyDisplayState`(:527) 从不产出。
+**现状**:无服务端聚合/AI 总结;`ActivityDTO` 注释声明 `summarizing` 但 `applyDisplayState`(:527) 从不产出(死代码)。
 
-**方案(二选一)**:
-- **A 落地总结**:新增 `POST /api/activity/summary {activityId}` 聚合 `approvedCount / pendingCount / signedCount / avgRating / feedbackList / 参与率`;可选接 LLM 生成一段自然语言总结,生成期间 DTO `displayStatus='summarizing'` 生效。
-- **B 清理**:若业务暂不需要"总结",删除 DTO 中 `summarizing` 死值声明与注释,避免前端误依赖。
+**方案(已锁定 B——清理)**:
+1. 删除 `ActivityDTO` 中 `summarizing` 相关声明与注释;
+2. 清理 `applyDisplayState`(:527) 中不可能产出的 `summarizing` 分支;
+3. 若前端有依赖"总结中"标签,同步移除或改为"已结束"展示。
 
-**影响**:A 为新增能力(需产品确认是否需要);B 为清理。
-**测试**:A 下 summary 返回正确聚合;B 下前端无"总结中"标签依赖。
+**影响**:纯清理,无功能损失(本就无总结能力)。
+**测试**:DTO/展示态无 `summarizing` 残留;编译通过、前端无报错依赖。
 
 ---
 
@@ -143,42 +166,49 @@
 
 **现状**:`autoEndExpiredActivities`(:402) 在 `list/detail` 调用时触发,且 `endTime` 早于"当前-7天"才结束。
 
-**方案**:改为 Spring `@Scheduled(cron = "0 0 2 * * ?")` 每日 02:00 执行;结束阈值改为 `endTime < now()`(或保留短暂宽限如 1 天),去掉"查询才触发"与 7 天延迟。`list/detail` 中保留轻量实时判断作为兜底即可。
+**方案**:改为 Spring `@Scheduled(cron = "0 0 2 * * ?")` 每日 02:00 执行;结束阈值改 `endTime < now()`(保留≤1天宽限),去掉"查询才触发"与 7 天延迟。`list/detail` 保留轻量实时判断兜底。
 
-**测试**:制造 endTime 昨天的活动,定时任务执行后状态=ended。
+**测试**:制造 endTime 昨天的活动,定时任务后状态=ended。
 
 ---
 
-### P2-2 三套子系统整合决策(架构)
+### P2-2 删除规划师活动与履约活动子系统(已锁定"删除+整合")
+
+**现状(D3 前)**:主活动 `activities`(报名/签到/评价)、规划师活动 `guide_activities`(仅创建/发布/取消,无报名签到)、商品履约 `activity_provisions`(购买活动商品后的另一套签到/核销)三者状态机/报名/签到互不相通。
 
-**现状**:主活动 `activities`(报名/签到/评价)、规划师活动 `guide_activities`(无报名签到)、商品履约 `activity_provisions`(另一套签到核销)三者状态机/报名/签到互不相通。
+**决策(D3)**:**删除** `guide_activities` 与 `activity_provisions` 两套独立子系统,其业务诉求并入主活动 `activities`:
+- "规划师活动"→ 复用主活动创建/发布,可由规划师角色持有/发起,统一走主活动报名/签到/评价;
+- "商品履约活动"→ 购买活动商品后生成的履约记录,复用主活动 Task 签到/核销,消除"双签到口径"。
 
-**建议**:作为**决策项**而非立即改代码。产品/架构需确认:
-- 规划师活动是否应复用主活动的报名/签到/评价能力(若需要,应合并或建立继承关系);
-- 商品履约签到是否应统一到主活动 Task 签到(避免同一活动双签到口径)。
+**实施步骤(删除前必做)**:
+1. **依赖影响面审计**:全局 grep `guide_activities` / `GuideActivity` / `activity_provisions` / `ActivityProvision` / `ActivityProvisionService` 的引用点(Controller、Service、Mapper、前端、定时任务、外部调用方),列清单。
+2. 确认是否有其他模块(如规划师认证闸门、商城履约、订单回调)强依赖这两套表;若有,先迁移依赖到主活动,再删表。
+3. 删除实体、Mapper、Service、Controller、建表/迁移 SQL 中对应定义;清理前端相关页面/路由。
+4. 单独立 PR、独立灰度,避免与 P0 资金改动混在一起。
 
-短期:在文档与代码注释中明确三者边界,避免后续误用。
+**影响**:属架构级清理,范围较大,建议作为独立任务推进,不阻塞 P0/P1 上线。
 
 ---
 
 ## 四、实施与上线策略
 
-1. **分批提交**:P0-1/2/3 各自独立 commit;P1/P2 随后。每批可独立回退。
-2. **依赖顺序**:P0-1(名额)应在 P0-2(退款回滚)之前,因为回滚逻辑依赖名额字段口径;P1-1 与 P0-1 最好合并处理计数口径。
+1. **分批提交**:P0-1/2/3、P1-1/2/3/4、P2-1 各自独立 commit;P2-2(删子系统)单独 PR。
+2. **依赖顺序**:P0-1(名额+审核开关)先于 P0-2(退款回滚,依赖名额字段口径);P1-1 与 P0-1 合并处理计数口径;P1-4 死代码清理可随时独立提交。
 3. **回归测试清单**:
-   - 报名满员拦截(并发)
+   - 报名满员拦截(并发,含免审即占与需审审过占两种)
+   - 免审/需审两条报名路径正确
    - 免费/付费取消报名(含退款)
    - 签到审核开关两种行为
    - 评价门槛/去重
    - 过期活动自动结束定时任务
-4. **上线策略**:P0 三项先在预发环境灰度(尤其退款链路用小额订单);确认无误再上生产。
-5. **回滚**:任一修复独立 commit,出问题 `git revert` 单笔即可。
+4. **上线策略**:P0 三项先在预发灰度(退款链路用小额订单);P2-2 删除子系统单独灰度。
+5. **回滚**:任一修复独立 commit,`git revert` 单笔即可。
 
 ---
 
-## 五、待确认决策点(请产品/架构拍板)
+## 五、已决事项(原"待确认"已锁定)
 
-1. P0-3:签到审核是**落地功能(A)**还是**移除字段(B)**?
-2. P1-4:是否需要"活动总结"自动聚合/AI 生成(A),还是**清理死代码(B)**?
-3. P2-2:规划师活动、商品履约活动是否纳入统一活动内核?(影响中长期架构)
-4. 名额占用时点采用"审核/支付通过即占名额"是否达成一致(影响候补/排队逻辑设计)?
+- ✅ D1 签到审核:按活动级 `requireCheckinReview` 落地功能。
+- ✅ D2 活动总结:清理死代码(不做聚合/AI)。
+- ✅ D3 规划师活动/履约活动:删除并整合进主活动(前置依赖审计)。
+- ✅ D4 报名审核:活动级 `requireReview` 默认 false,免审即占、需审审过才占;撤销免费强制审核。