先说结论
Odoo Fleet 的核心,不是一张车辆主档,而是一套把 当前责任人、历史分配、维修服务、里程读数、合同提醒和运营信号 聚合到车辆对象上的系统。
从 /home/ubuntu/odoo-temp/addons/fleet/models/fleet_vehicle.py、fleet_vehicle_assignation_log.py、fleet_vehicle_log_services.py 来看,fleet.vehicle 并不是孤立存在,而是被多条日志链持续“喂数据”。
所以它真正解决的问题不是“公司有几辆车”,而是:
每辆车现在由谁负责、过去给过谁、最近修了什么、跑了多少里程、下一步该关注什么。
第一层:为什么车辆对象上同时有当前司机和历史分配日志
fleet.vehicle 里既有:
driver_idfuture_driver_idnext_assignation_date
也有:
log_drivers→fleet.vehicle.assignation.log
而 fleet.vehicle.assignation.log 单独记录:
vehicle_iddriver_iddate_startdate_end
这说明官方区分得很清楚:
- 当前司机字段解决“现在谁在用”
- 分配日志解决“历史上谁用过、从什么时候到什么时候”
如果没有这层拆分,很多常见问题就无从回答:
- 某辆车事故发生时,那个时间段是谁在负责
- 某员工名下车辆是长期配车还是临时借调
- 一辆车未来是否已安排给下一个司机
所以 Fleet 不是简单地把 driver_id 改来改去,而是保留责任迁移的时间轴。
第二层:为什么服务日志里要同时挂车辆、里程和费用
fleet.vehicle.log.services 是 Fleet 里很容易被低估的一张表。
它不只记录维修项目名称,而是把:
vehicle_idservice_type_idamountvendor_iddateodometer_idodometerstatemanager_id
串在一起。
这表示 Odoo 不把保养当成“备注信息”,而是把它建模成一个带财务、履历和执行状态的服务事件。
尤其 odometer 的处理很有意思:
- 服务日志上可以直接录当前里程
- 逆向会自动创建
fleet.vehicle.odometer - 还禁止把里程清空为 0
这背后的逻辑非常务实:
一次保养发生时,“花了多少钱”和“当时跑了多少里程”通常是同一件运营事实。
第三层:为什么车辆首页会出现 service_activity
fleet.vehicle 上有个很关键但常被忽略的字段:service_activity。
它不是人工填写,而是从 log_services 上的活动状态聚合出来,结果只分成:
nonetodayoverdue
这说明官方不是想让你一层层钻日志,才知道哪辆车该处理;而是希望车辆对象本身能冒出一个当前需不需要关注的运营信号。
这种设计很像很多成熟运维系统里的 health badge:
- 不是把所有明细都摊开
- 而是先给你一个能快速排序和排查的主信号
对实际车队经理来说,这比单纯的台账字段更有价值。
第四层:为什么车型字段会自动“灌”到车辆上
fleet.vehicle 里很多字段并不要求手敲,而是从 model_id 自动加载:
- 变速箱
- 年款
- 颜色
- 座位数
- 车门数
- 燃料类型
- 功率
- 排放标准
- 续航
- 车辆类别
源码里 _load_fields_from_model() 会按映射批量把车型属性复制到车辆实例。
这说明官方把车型看作“标准模板”,把车辆看作“带具体身份的实例”。
这样做的好处很直接:
- 新建车辆更快
- 同车型数据更一致
- 统计维度不会因为人工录入漂移
同时车辆仍可叠加自己的:
- 牌照
- VIN
- 当前司机
- 当前状态
- 当前里程
- 当前合同与服务记录
第五层:为什么计数字段都在车辆对象上聚合
_compute_count_all() 会把车辆相关的:
- 里程数量
- 服务数量
- 合同数量
- 司机历史数量
一次聚合出来。
这类设计看起来普通,其实非常能体现产品取向:
Fleet 不是要你在很多菜单间来回跳,而是尽量让 fleet.vehicle 成为总入口。
所以一辆车在 Odoo 里更像“运营档案页”,而不是“基础资料卡”。
第六层:合同提醒为什么和车辆状态绑在一起
虽然本站之前已经写过合同提醒与司机里程边界,但源码里仍然能看出官方的一个明确判断:
- 车辆不是独立资产记录
- 它要持续承接合同到期、服务活动、司机切换这些外部节奏
contract_renewal_due_soon、contract_renewal_overdue、contract_state 这类字段之所以直接挂在 fleet.vehicle 上,就是为了让“下一步动作”贴着资产本身出现。
这也是很多实施项目真正需要的:不是保存历史,而是让待处理事项浮到最前面。
最容易误解的三个点
误区一:Fleet 只是车辆通讯录
不是。它的真正价值在于把车辆生命周期上的多条日志汇总成运营视图。
误区二:司机字段改一下就够了
不够。只有分配历史日志存在,责任迁移才可追溯。
误区三:保养日志只是给报表看的
也不是。它直接影响车辆的当前活动信号、里程链和后续管理节奏。
实战上怎么理解最稳
如果你要把 Fleet 用好,可以按这个思路落地:
- 车型尽量做标准模板,减少车辆主档手工录入
- 当前司机与未来司机解决“现在”和“接下来”
- 分配日志保留责任时间轴
- 每次服务都尽量带上费用、供应商与里程
- 用
service_activity和合同提醒做日常排查入口
最后总结
Odoo Fleet 最值得学的,不是它能登记多少车辆,而是它把 司机责任、里程变化、服务履历与待办提醒 全都压回到 fleet.vehicle 这个中心对象上。
这也是为什么车队模块看起来不复杂,却很适合做真正的资产运营管理。
DISCUSSION
评论区