2.3 KiB
2.3 KiB
架构决策:真实预约容量模型
日期:2026-08-01
状态:Accepted
范围:单店 SaaS 真实试点
决策
- 服务项目配置
duration_minutes,范围 30~480 分钟且按 30 分钟递增。 - 预约保存
duration_minutes快照,后续修改服务项目不会改变已承诺号源。 - 门店配置
booking_capacity(1~10),表示同一半小时容量桶可并行服务的顾客数。 - 可约性必须检查服务从开始到结束覆盖的每个半小时桶;有效预约和
walk_in各消耗一个名额,blocked关闭覆盖范围内全部名额。 - 创建预约或手动占用时,对门店行使用悲观写锁,在同一事务内重新读取占用并判定,避免两个并发请求同时通过可用性检查。
booking_last_slot_start保留兼容语义:它是最后一个 30 分钟容量桶的开始时间,营业容量结束时刻为其后 30 分钟;服务必须在结束时刻前完成。
为什么先做门店容量
现有预约在开始服务时才绑定 assigned_user_id,宠主下单也不选择技师。在这种数据结构下宣称已经具备“技师排班”会制造假精度。试点阶段先由老板配置门店可真实兑现的并发接待数,足以阻止长服务跨档冲突和同店并发超卖。
个人技师日历延后到预约前可分配技师、员工可维护可工作时段、服务项目可声明技师技能之后再引入。届时门店容量仍作为总上限,不会推翻本决策。
兼容与迁移
- 旧接口未传
serviceType查询号源时采用 60 分钟安全默认值;创建预约必须解析到本店有效服务项目。 - 历史系统默认与预约按稳定名称映射回填:洗澡 60、美容 120、洗澡+美容 150、剪指甲/驱虫 30,未知服务 60 分钟。
- 旧手动占用回填为 30 分钟;旧门店并发接待数回填为 1。
- 生产不自动执行迁移,发布前按
backend/db/migrations/README.md备份、测试和人工执行。
验收
- 120 分钟服务会占用连续四个半小时桶。
- 容量为 2 时,同一桶允许两个有效占用,第三个被拒绝。
walk_in消耗一个名额;blocked覆盖处全部不可约。- 候选服务结束晚于营业容量结束时刻时不可约。
- 并发创建不会突破门店容量。