很多产品经理描述预约系统时,都会说一句话:把空闲时间列出来,让客户挑一个就好。可企业版 appointment 源码告诉你,“空闲时间”本身就是计算结果,而且它依赖用户模式、资源模式、容量规则和 booking line 约束共同得出。
一、预约类型先决定“按谁排班”
AppointmentType 里 _compute_assignment_method() 和 _compute_resource_ids() 很直白地说明:预约不是统一逻辑,它分成至少两条主路:
schedule_based_on == users:围绕员工/面试官等人员可用性排;schedule_based_on == resources:围绕设备、房间、材料等资源容量排。
这一步没想清楚,后面所有“为什么没时段”“为什么多占资源”的问题都会变成糊涂账。
二、资源模式下,不是看单个资源,而是算资源组合
AppointmentResource._get_possible_capacity_combinations() 会把主资源和 linked resources 组合起来,再由 _get_filtered_possible_capacity_combinations() 根据 asked_capacity 过滤出能承载这次预约的组合。
这很关键:企业版不是只问“某个房间空不空”,而是问“哪些资源组合起来,足够支撑这次预约需求”。
例如一个培训预约需要房间 + 设备 + 容量,系统考虑的是组合后总剩余能力,而不是单资源可用性。
三、booking line 是后端最后一道守门员
appointment_booking_line.py 的三个方法非常关键:
_check_user_or_resource_set():确保 booking line 在对应模式下必须有 user 或 resource;_check_user_or_resource_match_appointment_type():确保所挂的 user/resource 真属于这个 appointment type;_compute_capacity_used():在 shareable / 非 shareable、manage_capacity 开启与否等条件下,决定这条预约实际占了多少容量。
很多看似“前台选中了、为什么保存失败”的问题,其实都是这里在兜底。
四、真正的主链路是“类型定义 → 组合筛选 → booking 校验”
把后端逻辑串起来,大致是:
- appointment type 决定按用户还是按资源调度;
- 资源模式下计算可用组合和可承载容量;
- booking line 校验当前预约绑定对象是否合法;
- 再根据 capacity 规则计算这次预约真正占掉多少资源。
所以预约时段不是数据库里预先躺好的静态数据,而是在规则约束下即时推导出来的可分配结果。
五、新手误区
1. 以为空闲就是没人占用
在容量模式下,资源可能“没满”,但不是“完全空闲”;剩余容量才是关键。
2. 以为 linked resource 只是附加展示
不是。linked resource 会直接参与可用组合计算。
3. 以为 booking line 只是记录选了谁
它其实还承担一致性校验和容量口径落地职责。
六、实战注意事项
- 先确定业务属于用户调度还是资源调度,再设计前端;
- 资源容量和 shareable 规则要和业务讲清楚,否则用户会觉得“系统莫名其妙不给约”;
- 二开时不要跳过 booking line 约束,前端能选到不代表后端应接受;
- 涉及 linked resources 时,测试要覆盖组合爆炸和边界容量。
结语
企业版预约真正要解决的问题,不是“展示一个可点的日历”,而是把调度对象、资源组合、容量约束、保存校验一起收敛成一条可解释的预约链路。理解这一层,预约系统才不会越做越乱。
DISCUSSION
评论区