From ee1776dc5f12fa5055ab0ff0998edbc08da3c8c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lucas=20Lef=C3=A8vre?= Date: Fri, 7 Jun 2019 08:54:27 +0000 Subject: [PATCH] [IMP] hr_attendance: Display checked in hours today Purpose ====== When an empoyee wants to check out, he does not know the number of hours he worked today. Specification ========== In the check out view, display how many hours the employee was checked in today. closes odoo/odoo#33974 Signed-off-by: Yannick Tivisse (yti) --- addons/hr_attendance/models/hr_employee.py | 24 +++++++++++++++++ .../src/js/employee_kanban_view_handler.js | 1 + .../static/src/js/kiosk_confirm.js | 2 ++ .../static/src/js/my_attendances.js | 6 ++++- .../static/src/xml/attendance.xml | 2 ++ .../static/tests/hr_attendance_tests.js | 1 + .../tests/test_hr_attendance_process.py | 27 +++++++++++++++++++ .../hr_attendance/views/hr_employee_view.xml | 1 + 8 files changed, 63 insertions(+), 1 deletion(-) diff --git a/addons/hr_attendance/models/hr_employee.py b/addons/hr_attendance/models/hr_employee.py index def4f72c2d4..c526230dc93 100644 --- a/addons/hr_attendance/models/hr_employee.py +++ b/addons/hr_attendance/models/hr_employee.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. +import pytz from datetime import datetime from dateutil.relativedelta import relativedelta @@ -14,6 +15,7 @@ class HrEmployeeBase(models.AbstractModel): last_attendance_id = fields.Many2one('hr.attendance', compute='_compute_last_attendance_id', store=True) attendance_state = fields.Selection(string="Attendance Status", compute='_compute_attendance_state', selection=[('checked_out', "Checked out"), ('checked_in', "Checked in")]) hours_last_month = fields.Float(compute='_compute_hours_last_month') + hours_today = fields.Float(compute='_compute_hours_today') def _compute_hours_last_month(self): for employee in self: @@ -27,6 +29,28 @@ class HrEmployeeBase(models.AbstractModel): ]) employee.hours_last_month = sum(attendances.mapped('worked_hours')) + def _compute_hours_today(self): + now = fields.Datetime.now() + now_utc = pytz.utc.localize(now) + for employee in self: + # start of day in the employee's timezone might be the previous day in utc + tz = pytz.timezone(employee.tz) + now_tz = now_utc.astimezone(tz) + start_tz = now_tz + relativedelta(hour=0, minute=0) # day start in the employee's timezone + start_naive = start_tz.astimezone(pytz.utc).replace(tzinfo=None) + + attendances = self.env['hr.attendance'].search([ + ('employee_id', '=', employee.id), + ('check_in', '<=', now), + '|', ('check_out', '>=', start_naive), ('check_out', '=', False), + ]) + + worked_hours = 0 + for attendance in attendances: + delta = (attendance.check_out or now) - max(attendance.check_in, start_naive) + worked_hours += delta.total_seconds() / 3600.0 + employee.hours_today = worked_hours + @api.depends('attendance_ids') def _compute_last_attendance_id(self): for employee in self: diff --git a/addons/hr_attendance/static/src/js/employee_kanban_view_handler.js b/addons/hr_attendance/static/src/js/employee_kanban_view_handler.js index 9949b9d8db2..eb9133e5d21 100644 --- a/addons/hr_attendance/static/src/js/employee_kanban_view_handler.js +++ b/addons/hr_attendance/static/src/js/employee_kanban_view_handler.js @@ -23,6 +23,7 @@ KanbanRecord.include({ employee_id: this.record.id.raw_value, employee_name: this.record.name.raw_value, employee_state: this.record.attendance_state.raw_value, + employee_hours_today: this.record.hours_today.raw_value, }; this.do_action(action); } else { diff --git a/addons/hr_attendance/static/src/js/kiosk_confirm.js b/addons/hr_attendance/static/src/js/kiosk_confirm.js index c7640527297..8262b24c8f8 100644 --- a/addons/hr_attendance/static/src/js/kiosk_confirm.js +++ b/addons/hr_attendance/static/src/js/kiosk_confirm.js @@ -3,6 +3,7 @@ odoo.define('hr_attendance.kiosk_confirm', function (require) { var AbstractAction = require('web.AbstractAction'); var core = require('web.core'); +var field_utils = require('web.field_utils'); var QWeb = core.qweb; @@ -61,6 +62,7 @@ var KioskConfirm = AbstractAction.extend({ this.employee_id = action.employee_id; this.employee_name = action.employee_name; this.employee_state = action.employee_state; + this.employee_hours_today = field_utils.format.float_time(action.employee_hours_today); }, start: function () { diff --git a/addons/hr_attendance/static/src/js/my_attendances.js b/addons/hr_attendance/static/src/js/my_attendances.js index 5bf9884875d..91acb7f1599 100644 --- a/addons/hr_attendance/static/src/js/my_attendances.js +++ b/addons/hr_attendance/static/src/js/my_attendances.js @@ -3,6 +3,7 @@ odoo.define('hr_attendance.my_attendances', function (require) { var AbstractAction = require('web.AbstractAction'); var core = require('web.core'); +var field_utils = require('web.field_utils'); var MyAttendances = AbstractAction.extend({ @@ -19,10 +20,13 @@ var MyAttendances = AbstractAction.extend({ var def = this._rpc({ model: 'hr.employee', method: 'search_read', - args: [[['user_id', '=', this.getSession().uid]], ['attendance_state', 'name']], + args: [[['user_id', '=', this.getSession().uid]], ['attendance_state', 'name', 'hours_today']], }) .then(function (res) { self.employee = res.length && res[0]; + if (res.length) { + self.hours_today = field_utils.format.float_time(self.employee.hours_today); + } }); return Promise.all([def, this._super.apply(this, arguments)]); diff --git a/addons/hr_attendance/static/src/xml/attendance.xml b/addons/hr_attendance/static/src/xml/attendance.xml index 3becfa5cccd..f38dd7cfa7c 100644 --- a/addons/hr_attendance/static/src/xml/attendance.xml +++ b/addons/hr_attendance/static/src/xml/attendance.xml @@ -42,6 +42,7 @@

Welcome!Want to check out?

+

Today's work hours: