# 架构决策:BusinessEvent 业务事件落库 > 日期:2026-08-01 > > 状态:已采纳,待生产数据迁移 > > Owner Agent:Backend Core(报告/留资写入点联动 Report Media Backend) > > Service Lock:`BusinessEvent*`、预约/报告/留资事件调用点、工作台报告漏斗 > > Paired QA:Core Flow QA + Report Share QA > > Data Model Review Required:Yes > > Access / Privacy Review Required:Yes ## 1. 决策背景 此前本体中的 Event 多数只表达“动作发生后应存在的事实”,并没有统一事件表。报告打开仅写应用日志,工作台只能由前端临时拼预约、报告和留资,无法可靠支持经营漏斗、StoreCustomer 时间线、回访归因和复购统计。 ## 2. 冻结模型 `BusinessEvent` 是不可变事实,不是业务对象当前状态,也不是消息队列。 | 字段 | 语义 | |---|---| | `event_id` | 随机事件 ID;不使用数据库自增 ID 做外部关联 | | `event_type` / `event_version` | 过去时事件名与 schema 版本 | | `store_id` | 强制门店数据范围 | | `store_customer_id` | 可选门店客户稳定关系,供客户时间线使用 | | `aggregate_type` / `aggregate_id` | 事件对应的 Appointment、Report 或 ReportLead | | `actor_user_id` / `actor_role` | 操作人快照;匿名公开事件可空 | | `source` | customer / admin / public_report / system / migration | | `occurred_at` | 业务事实发生时间 | | `metadata_json` | 服务端白名单低敏维度,不接受原始请求体 | | `idempotency_key` | 可选稳定键,保证一个业务结果只落一条 | | `create_time` | 事件入库时间 | 事件表只追加,不提供更新、软删除或通用明细 API。 ## 3. 第一批真实事件 | 事件 | 可靠触发点 | 幂等口径 | |---|---|---| | `appointment_created` | 预约保存成功 | appointment ID | | `appointment_status_changed` | 合法状态迁移保存成功 | appointment ID + 目标状态 | | `service_started` | `new -> doing` | appointment ID | | `service_completed` | `doing -> done` | appointment ID | | `report_submitted` | 报告及图片保存成功 | report ID | | `report_opened` / `report_reopened` | 公开报告打开埋点 | 每次有效打开;统计按 report ID 去重 | | `lead_submitted` | 每次留资提交成功 | 可重复记录;漏斗按 lead ID 去重 | `report_sent`、`follow_up_completed`、`rebook_created` 尚无可靠状态机或归因字段,本阶段明确不伪造;对应工作台指标返回 `null + trackingReady=false`。 ## 4. 隐私边界 - 事件表不得保存手机号、报告 token 或 token hash、媒体 URL、IP、openid/unionid、备注、内容全文、密码、密钥或任意请求体。 - 报告打开接口只用 token 在服务端定位 Report,事件仅保存内部 report ID;日志继续只记 SHA-256 前 8 位 hex。 - 管理端只开放按当前会话 `storeId` 聚合的漏斗结果,不开放事件明细。 ## 5. 一致性与迁移 - 预约、状态迁移、报告提交与事件写入处于同一数据库事务。 - 留资沿用现有并发幂等事务边界;重复提交可产生动作事件,漏斗按 lead ID 去重,不放大转化数。 - 历史迁移只回填可从数据库确定的预约创建、报告提交、由报告确认的服务完成和留资提交。 - 历史报告打开与开始服务时间无法可靠恢复,不做猜测性回填。 迁移顺序: 1. `20260801_split_service_identity.sql` 2. `20260801_create_store_customer.sql` 3. `20260801_create_business_event.sql` ## 6. BusinessEvent 与 AuditLog 边界 BusinessEvent 记录“经营上发生了什么”;AuditLog 记录“谁对受保护配置或数据做了什么变更”。本阶段先完成服务闭环事实,后续在门店开通、员工权限、设置修改和敏感操作进入生产化时建立独立 AuditLog,不把安全审计字段混入经营事件。 ## 7. 验收 - `mvn test` 全绿,迁移 SQL 集成测试通过。 - `npm run build`(admin)通过,工作台“已打开”来自事件汇总。 - customer 访问工作台事件汇总为 403;boss/staff 只能读取本店。 - 事件 metadata 隐私单测证明不含原始 token、手机号或 IP。 - 本体校验通过且 controller/entity 0 漂移。