企业 网站租赁

Odoo 企业版网站租赁为什么不是“库存够就能下单”:资源日历、排班占用与可租区间投影讲透

website_sale_renting_planning 真正解决的不是“网页显示几件可租”,而是把网站租期、排班资源、员工日历与库存语义折成同一份 availability 投影。

企业 网站
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 5 阅读

很多人看到 Odoo 企业版网站租赁页,会天然把“可租”理解成库存问题:

  • 仓里有货,就能租;
  • 仓里没货,就不能租。

website_sale_renting_planning 的实现不是这个思路。它把 网站日期选择、租赁订单、资源排班、员工日历 几层信息折到一起,最后才投影成前台的 availability。也就是说,前端看到的“这段时间还能租几个”,并不是单纯算库存,而是算:

在这段时间里,有多少资源既没被已有租单占掉,又符合排班/工作日历约束。

这就是它为什么是一个跨模块链路题,而不是“库存显示优化”。

主要参考:

  • enterprise/website_sale_renting_planning/controllers/main.py
  • enterprise/website_sale_renting/models/sale_order.py
  • enterprise/sale_renting_planning/models/planning_slot.py

一、先说结论:网站上的 availability 是“投影值”,不是底层唯一真相

网站租赁页对访客展示的是一个相对友好的结果:某个产品在某段时间内还能不能租、还能租多少。

但后端并不会把这个结果直接存成一个长期字段,而是在请求时按当前日期区间动态计算:

  1. 先看产品是不是 service + rent_ok + planning_enabled
  2. 再找这个产品背后的 planning_role 与可用 resource
  3. 再把已有 planning.slot、员工日历、请假/停工区间折成 unavailable intervals;
  4. 最后才把这些 unavailable 区间映射成网站端可显示的 availability 段。

所以它不是“库存字段透传到网站”,而是 网站 → 排班 → 资源 → 日历 的一条投影链。

二、入口在网站控制器,但真正决定数量的是 planning 资源层

website_sale_renting_planning/controllers/main.py 覆盖了 renting_product_availabilities()

这里有个关键判断:只有当产品满足以下条件时,才会走资源排班版逻辑:

  • type == 'service'
  • rent_ok
  • planning_enabled
  • planning_role_id.sync_shift_rental

这说明一个重要边界:

  • 普通租赁产品 可以按库存/租出数量去算;
  • 启用了排班同步的服务型租赁,则必须把资源可用性也算进去。

这一步实际上是在前台请求和后端资源模型之间插了一道门:不是所有租赁都进入排班世界,只有明确配置成“排班驱动租赁”的产品才会。

三、已有排班槽位不是“背景数据”,而是网站 availability 的直接约束

控制器里会先取出相关 planning.slot,并按 resource_id 分组,再把每个资源已有的占用区间整理成 Intervals()

这意味着网站前台看到的 availability,不只是“已存在销售订单”的结果,还会受到 已经排进去但未必显式展示在网站上的 shift 影响。

换句话说:

  • 销售单只是业务承诺;
  • planning.slot 才是资源真正被占掉的时间事实;
  • 网站 availability 必须以这个事实为基础投影。

这就是为什么它不是“只看 sale.order 的租期”。

四、员工/资源日历也会反向压缩网站可租区间

更有意思的是,这个控制器不只看已存在的 planning.slot,还会继续看 human_resourcescalendar_id

如果某天资源本来就不上班,或者有 leave interval,系统会把这些区间也并进 unavailable intervals。

所以它不是说:

  • 只要这个资源没被租出去,就算可用。

而是说:

  • 这个资源要同时满足:
  • 没被其他 slot 占用;
  • 在工作日历里可工作;
  • 没处于 leave / unavailable 时间段;
  • 才会被算进网站 availability。

这一步直接把 HR/资源日历语义 引进了网站租赁页。对于用户来说只是“今天还能订吗”,但源码层面其实是“资源今天有没有资格被算作可服务容量”。

五、为什么不能只看 qty_available

website_sale_renting/models/sale_order.py 里的 _get_cart_and_free_qty() 已经说明:租赁商品的可下单数量不是普通库存逻辑。

它会考虑:

  • 当前订单本身在同时间段里已经租了多少;
  • 其他订单在相同区间里占了多少;
  • 准备时间 preparation_time
  • qty_in_rent 与期间内的最小可用量。

而到了 website_sale_renting_planning,还要再叠一层“资源排班”约束。也就是说,网站租赁产品在企业版里至少有两层语义:

  1. 库存/租赁量语义:这件东西在这段时间物理上够不够;
  2. 资源/排班语义:有没有合适资源在这段时间提供它。

如果只看 qty_available,你会得到一个过于乐观的答案。

六、排班侧回写租赁订单,前台 availability 也会因此变化

sale_renting_planning/models/planning_slot.py 里,slot 在 write() 时如果改了开始/结束时间,会反向更新租赁订单的:

  • rental_start_date
  • rental_return_date

这意味着网站 availability 不是一个只读投影,它的底层事实会被排班修改反向改变。

链路是这样的:

  • 网站最初创建租赁语境;
  • 排班槽位承接这个订单;
  • 后台有人改 slot;
  • 租赁订单时间边界跟着变;
  • 下一次网站 availability 再计算时,结果也会变。

这就是一个完整的双向链路:

网站选期 → 订单/排班落地 → 排班改期 → 订单边界回写 → 网站 availability 重投影

七、新手最容易误解的 4 个点

1)以为网站上显示“available”就一定能下单

不是。那只是当前区间、当前资源、当前日历条件下的投影结果,结账前仍可能被进一步校验。

2)以为排班只是交付阶段的事

也不是。只要产品启用了 planning_enabled + sync_shift_rental,排班资源从网站选期那一刻就已经参与决策。

3)以为人力资源日历和网站租赁无关

恰恰相反。员工不上班、资源休假、日历不工作,都会直接压缩网站端看到的可租区间。

4)以为改 slot 只影响后台

不对。改 slot 会回写租赁订单时间边界,进而影响下一轮网站 availability 计算。

八、实战建议

  1. 不要把服务型租赁和纯库存型租赁混着理解。前者受资源排班约束,后者偏库存约束。
  2. 如果前台 availability 看起来“偏少”,优先查资源日历和 leave,而不只是查库存。
  3. 如果后台改过 planning slot,要意识到它可能已经悄悄改变了网站前台的可租判断。
  4. 给业务同事讲清“网站 availability 是投影,不是承诺本身”,避免把前台提示当成最终合同口径。

九、结论

Odoo 企业版网站租赁不是“库存够就能下单”。一旦接上 website_sale_renting_planning,网站看到的 availability 就变成一份跨模块投影:前台日期选择只是入口,真正决定结果的是租赁订单、排班槽位、资源日历和不可用区间的联合计算。它值钱的地方,不在于多显示一个数量,而在于把“可卖”和“可服务”这两件事在网站层面提前对齐。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。