如何在Odoo的attendance module中采集签到、签退的Geo-location
Odoo考勤模块采集签到/签退地理位置实现方案
本方案适配Odoo 13及以上社区版、企业版,无需依赖第三方付费插件,通过自定义扩展即可实现需求。
1. 扩展考勤模型新增地理位置存储字段
首先创建自定义模块,继承原生hr.attendance考勤模型,新增字段分别存储签到、签退节点的经纬度和地址信息,参考代码:
from odoo import models, fields class HrAttendance(models.Model): _inherit = 'hr.attendance' # 签到节点地理位置字段 check_in_latitude = fields.Float(string="签到纬度", digits=(10, 7)) check_in_longitude = fields.Float(string="签到经度", digits=(10, 7)) check_in_address = fields.Char(string="签到详细地址") # 签退节点地理位置字段 check_out_latitude = fields.Float(string="签退纬度", digits=(10, 7)) check_out_longitude = fields.Float(string="签退经度", digits=(10, 7)) check_out_address = fields.Char(string="签退详细地址")
2. 扩展前端考勤组件,触发定位采集
重写原生考勤签到/签退按钮的点击逻辑,在用户提交操作前先调用浏览器/移动端的定位接口获取当前位置,将位置参数随签到/签退请求一起传给后端,核心逻辑参考:
// 扩展考勤按钮组件 odoo.define('your_module_name.attendance_geo', function (require) { "use strict"; const AttendanceKioskComponent = require('hr_attendance.kiosk_mode').AttendanceKioskComponent; AttendanceKioskComponent.include({ async onSignInOut() { // 先获取定位 const geoInfo = await new Promise((resolve, reject) => { if (!navigator.geolocation) { reject(new Error('当前设备不支持定位')); } navigator.geolocation.getCurrentPosition( (position) => resolve({ latitude: position.coords.latitude, longitude: position.coords.longitude }), (err) => reject(err) ); }); // 将定位信息传入请求上下文 this.env.services.rpc({ model: 'hr.attendance', method: 'check_in_or_out', args: [this.employeeId], kwargs: { context: Object.assign({}, this.env.user.context, {attendance_geo_info: geoInfo}) } }).then(res => { // 执行原生签到/签退逻辑 this._super.apply(this, arguments); }); } }); });
注意:生产环境部署必须使用HTTPS协议,否则浏览器会禁止调用定位接口,本地调试可使用HTTP localhost环境
3. 适配后端接口存储定位信息
修改考勤模型的签到、签退方法,接收前端传入的定位参数并存储到对应字段,可同时增加考勤范围校验逻辑,参考代码:
from odoo import models, api, ValidationError class HrAttendance(models.Model): _inherit = 'hr.attendance' @api.model def create(self, vals): # 签到时写入签到定位信息 geo_info = self.env.context.get('attendance_geo_info') if geo_info: # 如需校验考勤范围,可在这里比对定位与预设考勤点的距离,超出范围抛出异常 # if calculate_distance(geo_info['latitude'], geo_info['longitude'], preset_lat, preset_lng) > 1000: # raise ValidationError("当前位置超出考勤允许范围") vals.update({ 'check_in_latitude': geo_info.get('latitude'), 'check_in_longitude': geo_info.get('longitude'), 'check_in_address': geo_info.get('address', '') }) return super().create(vals) def action_check_out(self): res = super().action_check_out() # 签退时写入签退定位信息 geo_info = self.env.context.get('attendance_geo_info') if geo_info: self.write({ 'check_out_latitude': geo_info.get('latitude'), 'check_out_longitude': geo_info.get('longitude'), 'check_out_address': geo_info.get('address', '') }) return res
如果需要显示详细地址,可以接入逆地理编码服务,把经纬度转换成文字地址写入对应的check_in_address/check_out_address字段即可。
4. 调整视图展示定位信息
修改考勤模块的列表视图、表单视图,把新增的6个定位字段添加到视图中,管理员和员工即可查看每次签到、签退对应的地理位置信息。
内容的提问来源于stack exchange,提问作者Nik
相关产品推荐
相关产品推荐

