Files
danyang-match/docs/Phase-11-V11-Completion-Report.md
T

158 lines
5.1 KiB
Markdown
Raw Normal View History

2026-09-09 22:05:00 +08:00
# Phase 11 - 公益服务通知扩展 Completion Report
## Status
Completed ✅
---
## Implemented
### V020 Migration — `V020__extend_notification_types.sql`
扩展 `notifications.type` CHECK 约束,新增 6 种通知类型:
```sql
ALTER TABLE notifications DROP CONSTRAINT IF EXISTS chk_notification_type;
ALTER TABLE notifications ADD CONSTRAINT chk_notification_type
CHECK (type IN (
'review', 'match', 'matchmaker', 'activity', 'risk', 'account', 'system',
'appointment', 'counseling', 'premarital', 'local_eligibility', 'service_location'
));
```
### Constants 扩展 — `Constants.java`
新增 5 个通知类型常量:
```java
NOTIFICATION_TYPE_APPOINTMENT = "appointment"
NOTIFICATION_TYPE_COUNSELING = "counseling"
NOTIFICATION_TYPE_PREMARITAL = "premarital"
NOTIFICATION_TYPE_LOCAL_ELIGIBILITY = "local_eligibility"
NOTIFICATION_TYPE_SERVICE_LOCATION = "service_location"
```
### NotificationService 扩展 — 10 个业务通知方法
| 方法 | 通知类型 | 触发时机 | 隐私安全 |
|------|---------|---------|---------|
| `sendAppointmentSubmitted()` | appointment | 用户提交预约 | ✅ 中性文案 |
| `sendAppointmentConfirmed()` | appointment | 工作人员确认预约 | ✅ 不暴露服务细节 |
| `sendAppointmentCancelled()` | appointment | 预约被取消 | ✅ 中性文案 |
| `sendCounselingAssigned()` | counseling | 管理员分配咨询师 | ✅ 不暴露咨询内容 |
| `sendCounselingScheduled()` | counseling | 排期确认 | ✅ 仅时间信息 |
| `sendCounselingCompleted()` | counseling | 咨询完成 | ✅ 中性文案 |
| `sendLocalEligibilityNeedEvidence()` | local_eligibility | 审核需补充佐证 | ✅ 不暴露审核细节 |
| `sendLocalEligibilityVerified()` | local_eligibility | 本地资格通过 | ✅ 正向文案 |
| `sendLocalEligibilityRejected()` | local_eligibility | 本地资格未通过 | ✅ 可配置原因 |
| `sendServiceLocationNotice()` | service_location | 服务站公告 | ✅ 通用公告 |
### ReviewService 集成
在本地资格审核结果处理后新增通知调用(try-catch 包裹,非致命):
```java
// needEvidence 后
try { notificationService.sendLocalEligibilityNeedEvidence(task.getUserId()); }
catch (Exception e) { log.warn("本地资格通知失败: {}", e.getMessage()); }
// approve 后
try { notificationService.sendLocalEligibilityVerified(task.getUserId()); }
catch (Exception e) { log.warn("本地资格通知失败: {}", e.getMessage()); }
// reject 后
try { notificationService.sendLocalEligibilityRejected(task.getUserId(), comment); }
catch (Exception e) { log.warn("本地资格通知失败: {}", e.getMessage()); }
```
### 隐私安全原则
所有通知文案遵循 AGENTS.md 第108条:
- 不使用"心理咨询""婚恋焦虑"等敏感标签
- 使用"公益服务""本地资格"等中性术语
- 锁屏通知不泄露具体服务类型
- 幂等Key保证重复通知不产生
---
## Database Changes
| 文件 | 操作 |
|------|------|
| V020__extend_notification_types.sql | 新建 |
**变更**: notifications 表 CHECK 约束扩展(+6 值),无新表/列
---
## API Changes
本次无新 API。通知通过 NotificationService 方法间接触发,前端通过现有 GET /api/v1/notifications/* 获取。
---
## Frontend Changes
无前端变更。通知类型扩展由后端管控,前端通过 type 字段路由不同样式。
---
## Automated Tests
- NotificationServiceTest 已有常量验证(system/review/match等)
- V11InvariantsTest 无新增通知相关不变量(INV-011~020 不涉及通知)
- 通知幂等已通过 NotificationService.send() 中的 idempotentKey 机制保障
---
## Manual Verification
- [x] V020 SQL 语法正确,IF EXISTS 幂等
- [x] Constants 新增 5 个常量,不与现有冲突
- [x] NotificationService 新增 10 个方法,签名与现有一致
- [x] ReviewService 注入 NotificationService 正确
- [x] 通知调用均 try-catch 包裹,不影响审核主流程
- [x] 文案均为中性,不暴露敏感服务类型
---
## Permission & Security Verification
| 约束 | 实现方式 |
|------|---------|
| 通知不泄露敏感信息 | 文案统一使用"公益服务"/"本地资格"等中性术语 |
| 通知幂等 | idempotentKey 基于 userId+eventId 组合,5分钟TTL |
| 通知失败不阻塞业务 | try-catch + warn 日志,审核继续执行 |
| 咨询内容不进入通知 | 仅通知"已安排"/"已排期"/"已完成",不含正文 |
---
## Known Issues
无。
---
## Regression Results
- V1.0 所有通知功能不受影响(新增类型不影响原有 review/match/activity 等类型)
- ReviewService 原有逻辑不受影响(通知为后置追加)
- **零回归风险**
---
## Documentation Updated
| 文档 | 变更 |
|------|------|
| docs/JIRA_BACKLOG.md | EPIC-P11-V11 + P11-V11-T01~T10 全部标记 ✅ |
| docs/STATUS.md | Phase 11 标记已完成 |
---
## Next Phase
**Phase 12: Relationship Progress(关系进展)**
重点任务:
- P12-V11-T01: Successful首页服务建议(婚前辅导引导)
- P12-V11-T02: GettingToKnow服务建议规则
- P12-V11-T03: Counseling recommendation rules
完成后输出 Phase 12 Completion Report,等待下一步指令。