本地生活服务系统预约场景里,进度通知不宜与状态写入口强耦合。状态变更发 domain event,通知渠道(App push、短信)订阅失败可重试,避免「更新了状态但用户没收到」。

结论
appointment status 变更 → outbox → notifier 消费;用户端查询仍读 order/appointment 表为准。
python
def start_service(appointment_id: str, worker_id: str):
appt = repo.get(appointment_id)
appt.status = "in_service"
appt.started_at = now()
repo.save(appt)
outbox.publish("AppointmentStarted", appt.to_event())
AppointmentStarted 事件写入 outbox,notifier 异步;读以 appointments 为准。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。
一、状态枚举
建议:booked → dispatched → in_service → completed → cancelled。每步 timestamp 落库,导出用 completed_at。
status 枚举带 timestamp;completed_at 供 export。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。
二、通知幂等与补发
notification_log 记录 (appointment_id, event_type, channel)。失败重试指数退避;用户打开 App 拉详情以 DB 为准,不完全依赖 push。
sql
SELECT status, started_at, completed_at
FROM appointments WHERE id = ?;
notification_log 幂等;push 失败可补发。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。
三、改约并发
改约乐观锁 version 字段,冲突返回让用户刷新。旧时段 slot 释放回库存。
改约乐观锁 version;冲突提示刷新。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。
四、验收附件
完成时可上传 photo_urls JSON,存对象存储,导出只存 URL 列。权限:用户与客服可读,公开 CDN 需鉴权。
photo_urls 存对象存储,export 存 URL。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。
五、与外卖共平台
business_line = local_service,共用 user_id。列表 API filter by line。
business_line=local_service filter。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。
六、光合同城边界
国内综合版支持预约扩展;深度 SLA、第三方 CRM 对接单列。商务结算规则由客户确定。
SLA 引擎深度定制单列。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。
七、进度通知与客服视图
客服后台宜提供按 appointment_id 查询全链路 timestamp 的只读视图,包含 booked/dispatched/in_service/completed 与 notification_log 最后一条状态。用户投诉「进度不动」时,先查 DB 再查 push,而不是先怀疑用户手机。导出增加 service_duration_minutes 列,由 completed_at-started_at 计算,供财务与 SLA 核对。
改约冲突返回明确错误码,前端提示刷新时段。师傅端 offline 时 dispatch 应 retry 或转人工池,避免 silent 挂起。完成上传照片 virus scan 失败应允许重传,不应卡在 completed 之前。
八、小结
拆通知与状态,保证 DB 真相单一;outbox 保投递。试跑 booked→completed 全链,查用户端与 export 一致。
师傅拒单应回退 dispatched 并通知用户,避免 silent 挂起。取消策略写进 snapshot,纠纷读快照而非口头规则。
拒单回退 dispatched 并通知用户。
实施时建议固定 golden 样本单号,在预发与生产各留用户端、后台、导出三处截图;列名或状态枚举变更走书面版本号,避免财务周结时才发现对不上历史单。