From bbfab85bf80023d0921cc5e0e5aa9e698f5a83b4 Mon Sep 17 00:00:00 2001 From: Thor Date: Thu, 26 Dec 2019 16:30:11 +0100 Subject: [PATCH] [ADD] hr_attendance_resume_of: New menu "Imputations resume R". --- hr_attendance_resume_of/README.rst | 29 +++ hr_attendance_resume_of/__init__.py | 3 + hr_attendance_resume_of/__manifest__.py | 18 ++ hr_attendance_resume_of/_common.py | 46 ++++ hr_attendance_resume_of/i18n/es.po | 103 ++++++++ .../i18n/hr_attendance_resume_of.pot | 103 ++++++++ hr_attendance_resume_of/models/__init__.py | 5 + .../models/hr_attendance.py | 238 ++++++++++++++++++ hr_attendance_resume_of/models/hr_employee.py | 53 ++++ .../models/resource_calendar_attendance.py | 18 ++ .../views/hr_attendance_resume_view.xml | 85 +++++++ 11 files changed, 701 insertions(+) create mode 100644 hr_attendance_resume_of/README.rst create mode 100644 hr_attendance_resume_of/__init__.py create mode 100644 hr_attendance_resume_of/__manifest__.py create mode 100644 hr_attendance_resume_of/_common.py create mode 100644 hr_attendance_resume_of/i18n/es.po create mode 100644 hr_attendance_resume_of/i18n/hr_attendance_resume_of.pot create mode 100644 hr_attendance_resume_of/models/__init__.py create mode 100644 hr_attendance_resume_of/models/hr_attendance.py create mode 100644 hr_attendance_resume_of/models/hr_employee.py create mode 100644 hr_attendance_resume_of/models/resource_calendar_attendance.py create mode 100644 hr_attendance_resume_of/views/hr_attendance_resume_view.xml diff --git a/hr_attendance_resume_of/README.rst b/hr_attendance_resume_of/README.rst new file mode 100644 index 00000000..4b1358a5 --- /dev/null +++ b/hr_attendance_resume_of/README.rst @@ -0,0 +1,29 @@ +.. image:: https://img.shields.io/badge/licence-AGPL--3-blue.svg + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 + +======================= +Hr attendance resume of +======================= + +* New menu "Imputations resume R". The new menu option for this object is + found in Attendances - Manage attendances - Imputations resume R. To see this + new menu option, the user must be in the group "Attendance-User". + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues +`_. In case of trouble, please +check there if your issue has already been reported. If you spotted it first, +help us smash it by providing detailed and welcomed feedback. + +Credits +======= + +Contributors +------------ +* Ana Juaristi +* Alfredo de la Fuente + +Do not contact contributors directly about support or help with technical issues. diff --git a/hr_attendance_resume_of/__init__.py b/hr_attendance_resume_of/__init__.py new file mode 100644 index 00000000..1fd704ff --- /dev/null +++ b/hr_attendance_resume_of/__init__.py @@ -0,0 +1,3 @@ +# Copyright 2019 Alfredo de la Fuente - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from . import models diff --git a/hr_attendance_resume_of/__manifest__.py b/hr_attendance_resume_of/__manifest__.py new file mode 100644 index 00000000..d4de4008 --- /dev/null +++ b/hr_attendance_resume_of/__manifest__.py @@ -0,0 +1,18 @@ +# Copyright 2019 Alfredo de la Fuente - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +{ + "name": "Hr Attendance Resume OF", + "version": "12.0.1.0.0", + "license": "AGPL-3", + "depends": [ + "hr_attendance_resume_anomaly", + "resource_gesalaga", + ], + "author": "AvanzOSC", + "website": "http://www.avanzosc.es", + "category": "Human Resources", + "data": [ + "views/hr_attendance_resume_view.xml", + ], + "installable": True, +} diff --git a/hr_attendance_resume_of/_common.py b/hr_attendance_resume_of/_common.py new file mode 100644 index 00000000..860b4db4 --- /dev/null +++ b/hr_attendance_resume_of/_common.py @@ -0,0 +1,46 @@ +# Copyright 2019 Alfredo de la Fuente - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from datetime import date as datetype +from dateutil.relativedelta import relativedelta +from pytz import timezone, utc +from odoo import fields + +str2datetime = fields.Datetime.from_string +date2str = fields.Date.to_string + + +def _convert_to_local_date(date, tz=u'UTC'): + if not date: + return False + if not tz: + tz = u'UTC' + new_date = str2datetime(date) if isinstance(date, str) else date + new_date = new_date.replace(tzinfo=utc) + local_date = new_date.astimezone(timezone(tz)).replace(tzinfo=None) + return local_date + + +def _convert_time_to_float(date, tz=u'UTC'): + if not date: + return False + if not tz: + tz = u'UTC' + local_time = _convert_to_local_date(date, tz=tz) + hour = float(local_time.hour) + minutes = float(local_time.minute) / 60 + seconds = float(local_time.second) / 360 + return (hour + minutes + seconds) + + +def _convert_to_utc_date(date, time=0.0, tz=u'UTC'): + if not date: + return False + if not tz: + tz = u'UTC' + date = date2str(date) if isinstance(date, datetype) else date + date = str2datetime(date) if isinstance(date, str) else date + date += relativedelta(hours=float(time)) + local = timezone(tz) + local_date = local.localize(date, is_dst=None) + utc_date = local_date.astimezone(utc).replace(tzinfo=None) + return utc_date diff --git a/hr_attendance_resume_of/i18n/es.po b/hr_attendance_resume_of/i18n/es.po new file mode 100644 index 00000000..32b2feab --- /dev/null +++ b/hr_attendance_resume_of/i18n/es.po @@ -0,0 +1,103 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_attendance_resume_of +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-03-03 13:40+0000\n" +"PO-Revision-Date: 2020-03-03 13:40+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_hr_attendance +msgid "Attendance" +msgstr "Asistencia" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__difference_hours_of +msgid "Difference hours" +msgstr "Diferencia horas" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__difference_minutes_of +msgid "Difference minutes" +msgstr "Diferencia minutos" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_hr_employee +msgid "Employee" +msgstr "Empleado" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_hr_attendance_resume +msgid "Hours imputations resume" +msgstr "Resumen horas imputaciones" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__imputable_time_of +msgid "Imputable time of" +msgstr "Tiempo imputable" + +#. module: hr_attendance_resume_of +#: model:ir.actions.act_window,name:hr_attendance_resume_of.action_hr_attendance_resume_of +#: model:ir.ui.menu,name:hr_attendance_resume_of.hr_attendance_resume_of_group_view +msgid "Imputations resume R" +msgstr "Resumen imputaciones R" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__markings_of +msgid "Markings of (E=Entrance, O=Output)" +msgstr "Fichajes (E=Entrada, S=Salida)" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__presence_time_of +msgid "Presence time of" +msgstr "Tiempo presencia" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__theoretical_time_final_of +msgid "Theoretical time" +msgstr "Tiempo teorico" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance__theoretical_time_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__theoretical_time_of +msgid "Theoretical time of" +msgstr "Tiempo teorico" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_resource_calendar_attendance +msgid "Work Detail" +msgstr "Detalle del trabajo" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__work_time_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_resource_calendar_attendance__work_time_of +msgid "Work time of" +msgstr "Tiempo trabajo" + +#. module: hr_attendance_resume_of +#: code:addons/hr_attendance_resume_of/models/hr_attendance.py:230 +#, python-format +msgid "{}/{}:{}E{}:{}O" +msgstr "" + +#. module: hr_attendance_resume_of +#: code:addons/hr_attendance_resume_of/models/hr_attendance.py:218 +#, python-format +msgid "{}:{}E{}:{}O" +msgstr "" + +#. module: hr_attendance_resume_of +#: code:addons/hr_attendance_resume_of/models/hr_attendance.py:224 +#, python-format +msgid "{}{}:{}E{}:{}O" +msgstr "" + diff --git a/hr_attendance_resume_of/i18n/hr_attendance_resume_of.pot b/hr_attendance_resume_of/i18n/hr_attendance_resume_of.pot new file mode 100644 index 00000000..b2ea08ff --- /dev/null +++ b/hr_attendance_resume_of/i18n/hr_attendance_resume_of.pot @@ -0,0 +1,103 @@ +# Translation of Odoo Server. +# This file contains the translation of the following modules: +# * hr_attendance_resume_of +# +msgid "" +msgstr "" +"Project-Id-Version: Odoo Server 12.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-03-03 13:39+0000\n" +"PO-Revision-Date: 2020-03-03 13:39+0000\n" +"Last-Translator: <>\n" +"Language-Team: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: \n" +"Plural-Forms: \n" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_hr_attendance +msgid "Attendance" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__difference_hours_of +msgid "Difference hours" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__difference_minutes_of +msgid "Difference minutes" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_hr_employee +msgid "Employee" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_hr_attendance_resume +msgid "Hours imputations resume" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__imputable_time_of +msgid "Imputable time of" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.actions.act_window,name:hr_attendance_resume_of.action_hr_attendance_resume_of +#: model:ir.ui.menu,name:hr_attendance_resume_of.hr_attendance_resume_of_group_view +msgid "Imputations resume R" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__markings_of +msgid "Markings of (E=Entrance, O=Output)" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__presence_time_of +msgid "Presence time of" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__theoretical_time_final_of +msgid "Theoretical time" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance__theoretical_time_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__theoretical_time_of +msgid "Theoretical time of" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model,name:hr_attendance_resume_of.model_resource_calendar_attendance +msgid "Work Detail" +msgstr "" + +#. module: hr_attendance_resume_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_hr_attendance_resume__work_time_of +#: model:ir.model.fields,field_description:hr_attendance_resume_of.field_resource_calendar_attendance__work_time_of +msgid "Work time of" +msgstr "" + +#. module: hr_attendance_resume_of +#: code:addons/hr_attendance_resume_of/models/hr_attendance.py:230 +#, python-format +msgid "{}/{}:{}E{}:{}O" +msgstr "" + +#. module: hr_attendance_resume_of +#: code:addons/hr_attendance_resume_of/models/hr_attendance.py:218 +#, python-format +msgid "{}:{}E{}:{}O" +msgstr "" + +#. module: hr_attendance_resume_of +#: code:addons/hr_attendance_resume_of/models/hr_attendance.py:224 +#, python-format +msgid "{}{}:{}E{}:{}O" +msgstr "" + diff --git a/hr_attendance_resume_of/models/__init__.py b/hr_attendance_resume_of/models/__init__.py new file mode 100644 index 00000000..fe19fdcc --- /dev/null +++ b/hr_attendance_resume_of/models/__init__.py @@ -0,0 +1,5 @@ +# Copyright 2019 Alfredo de la Fuente - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from . import hr_attendance +from . import resource_calendar_attendance +from . import hr_employee diff --git a/hr_attendance_resume_of/models/hr_attendance.py b/hr_attendance_resume_of/models/hr_attendance.py new file mode 100644 index 00000000..512addfb --- /dev/null +++ b/hr_attendance_resume_of/models/hr_attendance.py @@ -0,0 +1,238 @@ +# Copyright 2019 Alfredo de la fuente - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from odoo import models, fields, api, _ +from dateutil.relativedelta import relativedelta +from .._common import _convert_to_local_date, _convert_to_utc_date + + +class HrAttendance(models.Model): + _inherit = 'hr.attendance' + + theoretical_time_of = fields.Float( + string='Theoretical time of', compute='_compute_imputation_date_hour', + store=True) + + @api.depends( + 'check_in', 'check_out', 'employee_id', + 'employee_id.resource_calendar_id', + 'employee_id.resource_calendar_id.attendance_ids', + 'employee_id.resource_calendar_id.attendance_ids.delay_hour_from', + 'employee_id.resource_calendar_id.attendance_ids.delay_hour_to', + 'employee_id.resource_calendar_id.attendance_ids.rest_time', + 'employee_id.resource_calendar_id.attendance_ids.night_shift', + 'employee_id.resource_calendar_id.attendance_ids.work_time_of', + 'employee_id.calendar_ids', 'employee_id.calendar_ids.date_start', + 'employee_id.calendar_ids.date_end', + 'employee_id.calendar_ids.calendar_id', + 'employee_id.resource_calendar_id.tz') + def _compute_imputation_date_hour(self): + result = super(HrAttendance, self)._compute_imputation_date_hour() + for record in self.filtered( + lambda c: c.employee_id.resource_calendar_id and c.check_out): + date = _convert_to_local_date( + record.check_in, record.employee_id.resource_calendar_id.tz) + calendar = record.employee_id._get_employee_calendar( + date=date.date()) + days = calendar.mapped('attendance_ids').filtered( + lambda x: x.dayofweek == str(date.date().weekday())) + imputation_date = date.date() + if not days: + imputation_date = (date.date() + relativedelta(days=-1)) + calendar2 = record.employee_id._get_employee_calendar( + date=imputation_date) + days = calendar2.mapped('attendance_ids').filtered( + lambda x: x.dayofweek == str(imputation_date.weekday())) + for day in days: + fec_des = _convert_to_utc_date( + imputation_date, time=day.delay_hour_from, tz=u'UTC') + hours = day.delay_hour_to + my_date = fec_des.date() + if hours > 24.0: + hours -= 24 + my_date = (fec_des.date() + relativedelta(days=+1)) + fec_has = _convert_to_utc_date( + my_date, time=hours, tz=u'UTC') + if (date >= fec_des and date <= fec_has and not + day.night_shift): + record.theoretical_time_of = sum( + days.mapped('work_time_of')) + break + if date >= fec_des and date <= fec_has and day.night_shift: + calendar2 = False + days2 = False + if day.hour_from == 0.0 and day.rest_time == 0.0: + date2 = imputation_date + relativedelta(days=-1) + calendar2 = record.employee_id._get_employee_calendar( + date=date2) + if (day.hour_from == 0.0 and day.rest_time == 0.0 and + calendar2): + days2 = calendar2.mapped('attendance_ids').filtered( + lambda x: x.hour_to == 23.9833333333333 and + x.dayofweek == str(date2.weekday())) + if (day.hour_from == 0.0 and day.rest_time == 0.0 and + calendar2 and days2): + record.theoretical_time_of = ( + day.work_time_of + days2.work_time_of) + if day.hour_to == 23.9833333333333: + date2 = imputation_date + relativedelta(days=+1) + calendar2 = record.employee_id._get_employee_calendar( + date=date2) + if day.hour_to == 23.9833333333333 and calendar2: + days2 = calendar2.mapped('attendance_ids').filtered( + lambda x: x.hour_from == 0 and + x.dayofweek == str(date2.weekday())) + if (day.hour_to == 23.9833333333333 and calendar2 and + days2): + record.theoretical_time_of = ( + day.work_time_of + days2.work_time_of) + break + return result + + def _catch_values_for_create_resume(self): + vals = super(HrAttendance, self)._catch_values_for_create_resume() + min_fec = min(self, key=lambda x: x.check_in) + vals['theoretical_time_of'] = min_fec.theoretical_time_of + return vals + + def _catch_values_for_anomaly(self, employee, min_date, work_time, + anomaly, calendar): + vals = super( + HrAttendance, self)._catch_values_for_anomaly( + employee, min_date, work_time, anomaly, calendar) + work_time_of, real_hour_from, real_hour_to = employee._get_day_info_of( + calendar, min_date) + vals['theoretical_time_of'] = work_time_of + return vals + + +class HrAttendanceResume(models.Model): + _inherit = 'hr.attendance.resume' + + presence_time_of = fields.Float( + string='Presence time of', compute='_compute_of_times', store=True) + work_time_of = fields.Float( + string='Work time of', compute='_compute_of_times', store=True) + imputable_time_of = fields.Float( + string='Imputable time of', compute='_compute_of_times', store=True) + theoretical_time_of = fields.Float( + string='Theoretical time of') + markings_of = fields.Char( + string='Markings of (E=Entrance, O=Output)', store=True, + compute='_compute_markings_of') + theoretical_time_final_of = fields.Float( + string='Theoretical time', compute='_compute_theoretical_time_final', + store=True) + difference_hours_of = fields.Float( + string='Difference hours', store=True, + compute='_compute_imputable_diference_of') + difference_minutes_of = fields.Integer( + string='Difference minutes', store=True, + compute='_compute_imputable_diference_of') + + @api.depends('theoretical_time', 'theoretical_time_of', 'leave_id', + 'attendance_anomaly_ids') + def _compute_theoretical_time_final(self): + result = super( + HrAttendanceResume, self)._compute_theoretical_time_final() + for record in self: + record.theoretical_time_final_of = record.theoretical_time_of + return result + + @api.depends('presence_time', 'work_time', 'imputable_time', + 'bonus_hours', 'theoretical_time', 'theoretical_time_of') + def _compute_of_times(self): + for record in self: + emp = record.employee_id + calendar = emp._get_employee_calendar(date=record.date) + if calendar: + # alfredo 2 + work_time_of = record.theoretical_time_of + work_time = record.theoretical_time + dif = work_time - work_time_of + record.presence_time_of = ( + 0.0 if not record.presence_time else + record.presence_time - dif) + record.work_time_of = ( + 0.0 if not record.work_time else record.work_time - dif) + record.imputable_time_of = ( + 0.0 if not record.imputable_time else + record.imputable_time + record.bonus_hours - dif) + + @api.depends('imputable_time_of', 'theoretical_time_final_of') + def _compute_imputable_diference_of(self): + for record in self: + difference_hours = ( + record.imputable_time_of - record.theoretical_time_final_of) + if difference_hours != 0: + record.difference_hours_of = difference_hours + record.difference_minutes_of = round(difference_hours * 60) + + @api.depends('markings', 'hr_attendance_ids') + def _compute_markings_of(self): + for record in self: + record.markings_of = record._calculate_markings_of() + + def _calculate_markings_of(self): + employee = self.employee_id + calendar = employee._get_employee_calendar(date=self.date) + if not calendar: + return self.markings + # alfredo 2 + work_time_of = self.theoretical_time_of + if work_time_of == 0.0: + return self.markings + work_time = self.theoretical_time + if work_time_of == work_time: + return self.markings + dif = work_time - work_time_of + hours = {} + dates = sorted(set(self.hr_attendance_ids.mapped('check_in'))) + count = 0 + for my_date in dates: + imputation = self.hr_attendance_ids.filtered( + lambda x: x.check_in == my_date) + count += 1 + key = str(count) + if key not in hours: + check_in = imputation.check_in + if count == 1: + check_in += relativedelta(hours=float(dif / 2)) + check_out = imputation.check_out + if count == len(dates): + check_out -= relativedelta(hours=float(dif / 2)) + vals = {'check_in': check_in, + 'check_out': check_out} + hours[key] = vals + markings = '' + count = 0 + for key in hours.keys(): + check_in = ( + _convert_to_local_date( + hours.get(key).get('check_in'), calendar.tz)) + check_out = ( + _convert_to_local_date( + hours.get(key).get('check_out'), calendar.tz)) + count += 1 + if count == 1: + if not markings: + markings = _(u'{}:{}E{}:{}O').format( + str(check_in.hour).zfill(2), + str(check_in.minute).zfill(2), + str(check_out.hour).zfill(2), + str(check_out.minute).zfill(2)) + else: + markings = _(u'{}{}:{}E{}:{}O').format( + markings, str(check_in.hour).zfill(2), + str(check_in.minute).zfill(2), + str(check_out.hour).zfill(2), + str(check_out.minute).zfill(2)) + else: + markings = _(u'{}/{}:{}E{}:{}O').format( + markings, str(check_in.hour).zfill(2), + str(check_in.minute).zfill(2), + str(check_out.hour).zfill(2), + str(check_out.minute).zfill(2)) + if count == 2: + markings += '\n' + count = 0 + return markings diff --git a/hr_attendance_resume_of/models/hr_employee.py b/hr_attendance_resume_of/models/hr_employee.py new file mode 100644 index 00000000..e2e9d997 --- /dev/null +++ b/hr_attendance_resume_of/models/hr_employee.py @@ -0,0 +1,53 @@ +# Copyright 2019 Alfredo de la fuente - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from odoo import models +from dateutil.relativedelta import relativedelta + + +class HrEmployee(models.Model): + _inherit = 'hr.employee' + + def _get_day_info_of(self, calendar, date): + days = calendar.mapped('attendance_ids').filtered( + lambda x: x.dayofweek == str(date.weekday())) + if not days: + return 0.0, 0.0, 0.0 + if len(days) == 1: + if days.hour_from != 0.0 and days.hour_to != 23.9833333333333: + return days.work_time_of, days.real_hour_from, days.real_hour_to + my_date = date + if days.hour_from == 0.0: + my_date += relativedelta(days=-1) + days2 = calendar.mapped('attendance_ids').filtered( + lambda x: x.dayofweek == str(my_date.weekday())) + if (days2 and days2.filtered( + lambda x: x.hour_to == 23.9833333333333)): + return 0.0, 0.0, 0.0 + else: + work_time = days2.work_time_of + days.work_time_of + return work_time, days2.real_hour_from, days.real_hour_to + if days.hour_to == 23.9833333333333: + return self._get_night_time_info_of( + days.work_time_of, days.real_hour_from, days.real_hour_to, + date, calendar) + if not any(p.hour_to == 23.9833333333333 for p in days): + min_hour = min(days, key=lambda x: x.hour_from) + max_hour = max(days, key=lambda x: x.hour_to) + hours = sum(days.mapped('work_time_of')) + return hours, min_hour.real_hour_from, max_hour.real_hour_to + day = days.filtered(lambda x: x.hour_to == 23.9833333333333) + return self._get_night_time_info_of( + day.work_time_of, day.real_hour_from, day.real_hour_to, date, + calendar) + + def _get_night_time_info_of(self, work_time_of, real_hour_from, + real_hour_to, my_date, calendar): + my_date += relativedelta(days=+1) + days2 = calendar.mapped('attendance_ids').filtered( + lambda x: x.dayofweek == str(my_date.weekday())) + if days2: + day2 = min(days2, key=lambda x: x.hour_from) + if day2.hour_from == 0.0: + work_time_of += day2.work_time_of + return work_time_of, real_hour_from, day2.real_hour_to + return work_time_of, real_hour_from, real_hour_to diff --git a/hr_attendance_resume_of/models/resource_calendar_attendance.py b/hr_attendance_resume_of/models/resource_calendar_attendance.py new file mode 100644 index 00000000..71325854 --- /dev/null +++ b/hr_attendance_resume_of/models/resource_calendar_attendance.py @@ -0,0 +1,18 @@ +# Copyright 2019 Alfredo de la fuente - AvanzOSC +# License AGPL-3 - See http://www.gnu.org/licenses/agpl-3.0.html +from odoo import models, fields, api + + +class ResourceCalendarAttendance(models.Model): + _inherit = 'resource.calendar.attendance' + + work_time_of = fields.Float( + string='Work time of', compute='_compute_work_time_of', store=True) + + @api.depends('real_hour_from', 'real_hour_to') + def _compute_work_time_of(self): + for record in self: + hours = record.real_hour_to - record.real_hour_from + if record.real_hour_to == 23.9833333333333: + hours += 0.0166666666666667 + record.work_time_of = hours diff --git a/hr_attendance_resume_of/views/hr_attendance_resume_view.xml b/hr_attendance_resume_of/views/hr_attendance_resume_view.xml new file mode 100644 index 00000000..6acea6e2 --- /dev/null +++ b/hr_attendance_resume_of/views/hr_attendance_resume_view.xml @@ -0,0 +1,85 @@ + + + + hr.attendance.resume + + + + + + + + + + + + + + + + + + + + + + + hr.attendance.resume + +
+ +
+
+ + + + + + + + + + + + + + + + + + + + +
+
+
+
+ + Imputations resume R + hr.attendance.resume + form + form,tree + + + + + tree + + + + + + + form + + + + +