先说结论
Odoo 的 Homeworking 不是一个“员工默认在家办公”开关。
在 /home/ubuntu/odoo-temp/addons/hr_homeworking/models/ 下,官方实际拆成了三层:
- 周规则层:周一到周日各自的默认工作地点
- 例外层:某个具体日期的特殊地点
- 展示层:今天在员工目录和图标里应该呈现什么
所以它关心的不是“这个人是不是 remote”,而是:
这个员工今天应当出现在什么工作地点语义下。
第一层:每周地点不是偏好,而是稳定规则
hr_employee.py 里直接给员工加了 7 个字段:
monday_location_idtuesday_location_id- ...
sunday_location_id
这已经说明一个很关键的建模判断:
官方认为混合办公首先是一个按星期循环的稳定制度,而不是一个自由备注。
也就是说,Odoo 不是在问:
- 员工喜欢在哪里办公?
而是在问:
- 周二默认去哪儿?
- 周四默认去哪儿?
- 周末是否也定义地点?
这对排班、目录可见性、跨团队协作都更有价值。
第二层:例外日期是独立模型,不去污染周规则
hr_homeworking.py 里定义了 hr.employee.location:
employee_idwork_location_iddate
而且还有唯一约束:
同一个员工同一天只能有一条例外地点记录。
这说明官方很清楚“临时变更”不应该直接覆盖周规则。
比如:
- 平时周三在家
- 这周三临时去客户现场
这件事不该通过修改 wednesday_location_id 完成,因为那会把长期规则弄脏。
正确做法是:
- 周规则继续保留
- 某一天单独挂一个 exception
这样才有“今天例外,但明天恢复默认”的能力。
第三层:当天地点的优先级是“例外覆盖周规则”
_compute_exceptional_location_id() 会先去找今天有没有 hr.employee.location。
然后 _compute_presence_icon()、_compute_work_location_name()、_compute_work_location_type() 都遵循同一个优先级:
- 今天有例外地点,就用例外地点
- 没有,再读当天星期对应的周规则字段
这个优先级非常合理,因为它明确表达了:
周规则是默认值,例外才是最终事实。
如果你反过来设计,让例外去回写周字段,系统就会很快失去“临时变更”的语义。
第四层:为什么官方还要单独算 icon display
很多人看到 hr_icon_display 时会觉得只是界面小细节。
其实不是。
源码会把当天地点类型转成:
presence_homepresence_officepresence_other
这意味着在员工目录里,地点不仅是文字,还会被压缩成一个可快速识别的协作信号。
这件事对混合办公团队特别重要,因为目录页最需要回答的问题通常不是:
- 这位同事完整地点名称是什么?
而是:
- 他今天在办公室、在家,还是在别处?
图标层就是为这个高频问题服务的。
第五层:为什么搜索视图里要动态替换字段
get_views() 里有一段很值得注意的 Hack:
- 搜索视图中的
today_location_name - 会在加载时被替换成当天对应的星期字段
这说明 Odoo 不是为了炫技,而是在解决一个真实问题:
- 员工一周有 7 个地点字段
- 但用户想筛选的是“今天在哪”
- 而不是“周三字段叫什么”
所以官方用一个占位字段,把“今天地点”这个业务概念映射成实际星期字段。
这也是为什么 Homeworking 看起来像单一字段,底层却是“7 个周期字段 + 1 个例外模型”的组合。
第六层:Homeworking 管的是地点语义,不是工时事实
需要特别注意的是,Homeworking 并不自动等于:
- 已签到
- 在岗
- 已产生产出
- 自动生成工资规则
它更像一个工作地点事实层。
后续如果要联动:
- Attendance
- Presence
- Calendar
- 工位管理
- 差旅/现场服务
都是建立在“今天地点是什么”这个事实之上,而不是由 Homeworking 自己完成全链路。
实施时最容易踩的 4 个坑
1. 用改周规则来处理临时变更
这样很快就会把长期制度和短期例外混在一起。
2. 把地点当自由文本
源码明显更偏向结构化地点对象,而不是备注。
3. 以为 Homeworking 能代替考勤
地点和出勤是两回事。
4. 忽略“今天地点”在目录里的协作价值
如果只在员工表单里维护,不把它暴露成当天可读信号,业务价值会大打折扣。
最后一句话
Odoo 的混合办公设计,本质上是在回答‘今天该按哪个工作地点理解这名员工’,所以它必须同时有周规则、例外日期和当天展示三层。
DISCUSSION
评论区