From 0cb64fd99c7359bf6e576eda69ec0f9d60602aba Mon Sep 17 00:00:00 2001 From: Arnaud Joset Date: Mon, 17 Aug 2020 09:06:19 +0000 Subject: [PATCH] [IMP] resource: improve clarity of two weeks explanations Before this commit, when two week calendar were used, the tooltip was wrongfully assuming which week were odd and even. Even with correct information, it was not easy to fill and could easily lead to wrong information on the payroll. closes odoo/odoo#56055 Taskid: 2308804 Signed-off-by: Yannick Tivisse (yti) --- addons/hr_holidays/models/hr_leave.py | 5 +-- addons/resource/models/resource.py | 39 ++++++++++++++----- .../static/src/js/section_fields_backend.js | 4 +- addons/resource/views/resource_views.xml | 3 +- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index fed3140b8a8..77b7526493b 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -333,7 +333,7 @@ class HolidaysRequest(models.Model): if resource_calendar_id.two_weeks_calendar: # find week type of start_date - start_week_type = int(math.floor((holiday.request_date_from.toordinal() - 1) / 7) % 2) + start_week_type = self.env['resource.calendar.attendance'].get_week_type(holiday.request_date_from) attendance_actual_week = [att for att in attendances if att.week_type is False or int(att.week_type) == start_week_type] attendance_actual_next_week = [att for att in attendances if att.week_type is False or int(att.week_type) != start_week_type] # First, add days of actual week coming after date_from @@ -342,8 +342,7 @@ class HolidaysRequest(models.Model): attendance_filtred += list(attendance_actual_next_week) # Third, add days of actual week (to consider days that we have remove first because they coming before date_from) attendance_filtred += list(attendance_actual_week) - - end_week_type = int(math.floor((holiday.request_date_to.toordinal() - 1) / 7) % 2) + end_week_type = self.env['resource.calendar.attendance'].get_week_type(holiday.request_date_to) attendance_actual_week = [att for att in attendances if att.week_type is False or int(att.week_type) == end_week_type] attendance_actual_next_week = [att for att in attendances if att.week_type is False or int(att.week_type) != end_week_type] attendance_filtred_reversed = list(reversed([att for att in attendance_actual_week if int(att.dayofweek) <= holiday.request_date_to.weekday()])) diff --git a/addons/resource/models/resource.py b/addons/resource/models/resource.py index 4f75a2e1edf..e8b6f6e56bc 100644 --- a/addons/resource/models/resource.py +++ b/addons/resource/models/resource.py @@ -217,10 +217,12 @@ class ResourceCalendar(models.Model): @api.depends('two_weeks_calendar') def _compute_two_weeks_explanation(self): today = fields.Date.today() - week_type = _("odd") if int(math.floor((today.toordinal() - 1) / 7) % 2) else _("even") + week_type = self.env['resource.calendar.attendance'].get_week_type(today) + week_type_str = _("second") if week_type else _("first") first_day = date_utils.start_of(today, 'week') last_day = date_utils.end_of(today, 'week') - self.two_weeks_explanation = "This week (from %s to %s) is an %s week." % (first_day, last_day, week_type) + self.two_weeks_explanation = _("The current week (from %s to %s) correspond to the %s one.", first_day, + last_day, week_type_str) def _get_global_attendances(self): return self.attendance_ids.filtered(lambda attendance: @@ -253,7 +255,7 @@ class ResourceCalendar(models.Model): self.attendance_ids.unlink() self.attendance_ids = [ (0, 0, { - 'name': 'Even week', + 'name': 'First week', 'dayofweek': '0', 'sequence': '0', 'hour_from': 0, @@ -263,12 +265,11 @@ class ResourceCalendar(models.Model): 'display_type': 'line_section'}), (0, 0, { - 'name': 'Odd week', + 'name': 'Second week', 'dayofweek': '0', 'sequence': '25', 'hour_from': 0, - 'day_period': - 'morning', + 'day_period': 'morning', 'week_type': '1', 'hour_to': 0, 'display_type': 'line_section'}), @@ -388,7 +389,7 @@ class ResourceCalendar(models.Model): if attendance.date_to: until = min(until, attendance.date_to) if attendance.week_type: - start_week_type = int(math.floor((start.toordinal()-1)/7) % 2) + start_week_type = self.env['resource.calendar.attendance'].get_week_type(start) if start_week_type != int(attendance.week_type): # start must be the week of the attendance # if it's not the case, we must remove one week @@ -769,9 +770,9 @@ class ResourceCalendarAttendance(models.Model): day_period = fields.Selection([('morning', 'Morning'), ('afternoon', 'Afternoon')], required=True, default='morning') resource_id = fields.Many2one('resource.resource', 'Resource') week_type = fields.Selection([ - ('1', 'Odd week'), - ('0', 'Even week') - ], 'Week Even/Odd', default=False) + ('1', 'Second'), + ('0', 'First') + ], 'Week Number', default=False) two_weeks_calendar = fields.Boolean("Calendar in 2 weeks mode", related='calendar_id.two_weeks_calendar') display_type = fields.Selection([ ('line_section', "Section")], default=False, help="Technical field for UX purpose.") @@ -789,6 +790,24 @@ class ResourceCalendarAttendance(models.Model): # avoid wrong order self.hour_to = max(self.hour_to, self.hour_from) + @api.model + def get_week_type(self, date): + # week_type is defined by + # * counting the number of days from January 1 of year 1 + # (extrapolated to dates prior to the first adoption of the Gregorian calendar) + # * converted to week numbers and then the parity of this number is asserted. + # It ensures that an even week number always follows an odd week number. With classical week number, + # some years have 53 weeks. Therefore, two consecutive odd week number follow each other (53 --> 1). + return int(math.floor((date.toordinal() - 1) / 7) % 2) + + def _compute_display_name(self): + super()._compute_display_name() + this_week_type = str(self.get_week_type(fields.Date.context_today(self))) + section_names = {'0': _('First week'), '1': _('Second week')} + section_info = {True: _('this week'), False: _('other week')} + for record in self.filtered(lambda l: l.display_type == 'line_section'): + section_name = "%s (%s)" % (section_names[record.week_type], section_info[this_week_type == record.week_type]) + record.display_name = section_name class ResourceResource(models.Model): _name = "resource.resource" diff --git a/addons/resource/static/src/js/section_fields_backend.js b/addons/resource/static/src/js/section_fields_backend.js index e96757c586c..a2dc72ad7c7 100644 --- a/addons/resource/static/src/js/section_fields_backend.js +++ b/addons/resource/static/src/js/section_fields_backend.js @@ -23,7 +23,7 @@ var SectionListRenderer = ListRenderer.extend({ if (isSection) { if (node.attrs.widget === "handle") { return $cell; - } else if (node.attrs.name === "name") { + } else if (node.attrs.name === "display_name") { var nbrColumns = this._getNumberOfCols(); if (this.handleField) { nbrColumns--; @@ -63,6 +63,8 @@ var SectionListRenderer = ListRenderer.extend({ var self = this; return this._super.apply(this, arguments).then(function () { self.$('.o_list_table').addClass('o_section_list_view'); + // Discard the possibility to remove the sections + self.$('.o_is_line_section .o_list_record_remove').remove() }); }, }); diff --git a/addons/resource/views/resource_views.xml b/addons/resource/views/resource_views.xml index 3da77c37383..5086ded41ad 100644 --- a/addons/resource/views/resource_views.xml +++ b/addons/resource/views/resource_views.xml @@ -197,7 +197,8 @@ - + +