From d228dfe4983e159a909696b79c99379cec5bd102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 31 Aug 2018 16:56:03 +0200 Subject: [PATCH 01/12] [FIX] web: correctly find action-related form view ID in calendar When cliking on a calendar cell user is redirected to a form view to create a new record. However if the calendar action gives a specific form view ID it is not taken into account by calendar. Calendar code still handles views as not being a structure holding viewID and type but just an ordered list of items with (view ID, type). This commit fixes that code. One calendar JS test is updated to correctly match the current structure. This commit is linked to task ID 1876795 and PR #26571. --- addons/web/static/src/js/views/calendar/calendar_view.js | 4 ++-- addons/web/static/tests/views/calendar_tests.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/addons/web/static/src/js/views/calendar/calendar_view.js b/addons/web/static/src/js/views/calendar/calendar_view.js index c770c9eb642..20d358c517c 100644 --- a/addons/web/static/src/js/views/calendar/calendar_view.js +++ b/addons/web/static/src/js/views/calendar/calendar_view.js @@ -125,10 +125,10 @@ var CalendarView = AbstractView.extend({ attrs.form_view_id ? parseInt(attrs.form_view_id, 10) : false; if (!this.controllerParams.formViewId && params.action) { var formViewDescr = _.find(params.action.views, function (v) { - return v[1] === 'form'; + return v.type === 'form'; }); if (formViewDescr) { - this.controllerParams.formViewId = formViewDescr[0]; + this.controllerParams.formViewId = formViewDescr.viewID; } } diff --git a/addons/web/static/tests/views/calendar_tests.js b/addons/web/static/tests/views/calendar_tests.js index 9614350a9f8..54ecdbe07e7 100644 --- a/addons/web/static/tests/views/calendar_tests.js +++ b/addons/web/static/tests/views/calendar_tests.js @@ -2248,7 +2248,7 @@ QUnit.module('Views', { archs: archs, viewOptions: { initialDate: initialDate, - action: {views: [[1, 'kanban'], [43, 'form']]} + action: {views: [{viewID: 1, type: 'kanban'}, {viewID: 43, type: 'form'}]} }, mockRPC: function (route, args) { if (args.method === "create") { From 69b1ee65f462610a3e69642f338ee3223488adb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 3 Sep 2018 11:44:49 +0200 Subject: [PATCH 02/12] [IMP] hr: better synchronize user and its employee, especially timezone Currently user name is synchronized with employee name. However it is interesting to synchronize other fields like image, email and timezone. Changing an user linked to an employee through the UI already updates those fields. This commit ensure code handles synchronization like UI. When updating an user its related employees are updated. When changing the user linked to an employee through code all fields are also correctly synchronized. This commit is linked to task ID 1876795 and PR #26571. --- addons/hr/models/hr.py | 9 ++++++--- addons/hr/models/res_users.py | 14 ++++++-------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/addons/hr/models/hr.py b/addons/hr/models/hr.py index e36e6246ff3..06437298ed5 100644 --- a/addons/hr/models/hr.py +++ b/addons/hr/models/hr.py @@ -229,16 +229,17 @@ class Employee(models.Model): if self.user_id: self.update(self._sync_user(self.user_id)) - @api.onchange('user_id', 'resource_calendar_id') + @api.onchange('resource_calendar_id') def _onchange_timezone(self): - if self.user_id or self.resource_calendar_id: - self.tz = self.user_id.tz or self.resource_calendar_id.tz + if self.resource_calendar_id and not self.tz: + self.tz = self.resource_calendar_id.tz def _sync_user(self, user): return dict( name=user.name, image=user.image, work_email=user.email, + tz=user.tz, ) @api.model @@ -254,6 +255,8 @@ class Employee(models.Model): account_id = vals.get('bank_account_id') or self.bank_account_id.id if account_id: self.env['res.partner.bank'].browse(account_id).partner_id = vals['address_home_id'] + if vals.get('user_id'): + vals.update(self._sync_user(self.env['res.users'].browse(vals['user_id']))) tools.image_resize_images(vals) return super(Employee, self).write(vals) diff --git a/addons/hr/models/res_users.py b/addons/hr/models/res_users.py index b47d2160ba9..2e5acfe8ee7 100644 --- a/addons/hr/models/res_users.py +++ b/addons/hr/models/res_users.py @@ -2,11 +2,9 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from odoo import api, models, fields -from odoo import SUPERUSER_ID class User(models.Model): - _inherit = ['res.users'] employee_ids = fields.One2many('hr.employee', 'user_id', string='Related employees') @@ -19,11 +17,11 @@ class User(models.Model): @api.multi def write(self, vals): - """ When renaming admin user, we want its new name propagated to its related employees """ + """ Synchronize user and its related employee """ result = super(User, self).write(vals) - Employee = self.env['hr.employee'] - if vals.get('name'): - for user in self.filtered(lambda user: user.id == SUPERUSER_ID): - employees = Employee.search([('user_id', '=', user.id)]) - employees.write({'name': vals['name']}) + employee_values = {} + for fname in [f for f in ['name', 'email', 'image', 'tz'] if f in vals]: + employee_values[fname] = vals[fname] + if employee_values: + self.env['hr.employee'].sudo().search([('user_id', 'in', self.ids)]).write(employee_values) return result From 5013323b4fc79a21ab173ad39b31596afb4a6a21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 17 Aug 2018 08:42:04 +0200 Subject: [PATCH 03/12] [IMP] hr_holidays: improve Leave application menus It seems specifications of new menus implemented at 9af6e9070af1a949d3ec40a0767d2aa4ffc9719d were not totally correct and broke some Odoo conventions. New specification for leaves application menus are now the following : * Dashboard * My leaves (user sees this only) * New request (calendar view by default) * Leaves requests (only my, list view by default) * Allocation requests (only my, list view by default) * Summary (only my, summary list view by default) * Managers (HR officers or managers only) * To approve * Leaves (default filters: to approve, on my department) * Allocations (default filters: to approve, on my department) * All * Leaves * Allocations * Payroll * Leaves to report (default filters: grey kanban state) * Reporting (HR officers or managers only) * Leaves Analysis * Report by Department * Configuration * Leaves Types This commit is linked to task ID 1876795 and PR #26571. --- .../hr_holidays/report/hr_leave_reports.xml | 2 +- .../views/hr_leave_allocation_views.xml | 41 +++++++--- addons/hr_holidays/views/hr_leave_views.xml | 78 ++++++++++++++----- .../hr_holidays_summary_department_views.xml | 2 +- 4 files changed, 94 insertions(+), 29 deletions(-) diff --git a/addons/hr_holidays/report/hr_leave_reports.xml b/addons/hr_holidays/report/hr_leave_reports.xml index 51f339ca65b..da955bb2f12 100644 --- a/addons/hr_holidays/report/hr_leave_reports.xml +++ b/addons/hr_holidays/report/hr_leave_reports.xml @@ -153,7 +153,7 @@ diff --git a/addons/hr_holidays/views/hr_leave_allocation_views.xml b/addons/hr_holidays/views/hr_leave_allocation_views.xml index dc332b1a574..81c84624740 100644 --- a/addons/hr_holidays/views/hr_leave_allocation_views.xml +++ b/addons/hr_holidays/views/hr_leave_allocation_views.xml @@ -149,8 +149,23 @@ + + Allocations All + hr.leave.allocation + form + tree,kanban,form + +

+ Create a new leave allocation request +

+
+ {} + [] + +
+ - Allocation Request + Allocation Requests hr.leave.allocation form tree,kanban,form @@ -259,17 +274,25 @@ - - + sequence="6"/> + + + diff --git a/addons/hr_holidays/views/hr_leave_views.xml b/addons/hr_holidays/views/hr_leave_views.xml index dc134646c98..b7c955246b1 100644 --- a/addons/hr_holidays/views/hr_leave_views.xml +++ b/addons/hr_holidays/views/hr_leave_views.xml @@ -1,7 +1,6 @@ - hr.holidays.graph hr.leave @@ -65,8 +64,6 @@ - - Leave Request hr.leave @@ -217,6 +214,24 @@ parent="menu_hr_holidays_root" sequence="4" groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"/> + + + hr.leave form calendar,tree,form - + {} [('user_id', '=', uid)] @@ -267,8 +282,14 @@ + + - Leaves Request + Leaves Requests hr.leave form tree,calendar,form @@ -288,12 +309,6 @@ - - tree @@ -318,10 +333,10 @@ id="hr_leave_menu_my" parent="menu_hr_holidays_my_leaves" action="hr_leave_action_my_tree" - sequence="22"/> + sequence="4"/> - Leaves Overview + Leaves hr.leave form tree,kanban,form,calendar @@ -358,18 +373,45 @@ - + sequence="1"/> + + + Leaves Requests + hr.leave + form + tree,calendar,form + {'search_default_gray': True} + [] + +

+ Create a new leave request +

+ Once you have recorded your leave request, it will be sent + to a manager for validation. Be sure to set the right leave + type (recuperation, legal leaves, sickness) and the exact + number of open days related to your leave. +

+
+
+ + diff --git a/addons/hr_holidays/wizard/hr_holidays_summary_department_views.xml b/addons/hr_holidays/wizard/hr_holidays_summary_department_views.xml index 9e22163fbf6..2d6aada20d5 100644 --- a/addons/hr_holidays/wizard/hr_holidays_summary_department_views.xml +++ b/addons/hr_holidays/wizard/hr_holidays_summary_department_views.xml @@ -29,7 +29,7 @@ From 3522fe1b89729e10eb3ce569c9f973181983a315 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 17 Aug 2018 15:19:10 +0200 Subject: [PATCH 04/12] [REF] hr_holidays: remove unused views and lint some bits of code Purpose is to clean a bit the code to prepare some incoming modifications. More specifically this commit focuses on removing unused views and actions to lessen future work in shaping them like requested. This commit contains : * small linting of leave fields; * remove some unused and unnecessary views and actions; * ensure default values for request_unit_all; * small linting of tests; This commit is linked to task ID 1876795 and PR #26571. --- addons/hr_holidays/models/hr_leave.py | 78 ++++---- .../hr_holidays/models/hr_leave_allocation.py | 54 +++--- addons/hr_holidays/models/hr_leave_type.py | 61 +++---- .../hr_holidays/report/hr_leave_reports.xml | 7 - addons/hr_holidays/tests/common.py | 19 +- .../hr_holidays/tests/test_hr_leave_type.py | 27 +-- .../views/hr_leave_allocation_views.xml | 129 ++----------- .../hr_holidays/views/hr_leave_type_views.xml | 34 +--- addons/hr_holidays/views/hr_leave_views.xml | 171 ++++-------------- addons/hr_holidays/views/hr_views.xml | 23 +-- 10 files changed, 172 insertions(+), 431 deletions(-) diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index 078c0d7f460..637e4770e06 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -10,12 +10,11 @@ from datetime import timedelta, datetime, time from pytz import timezone, UTC from odoo import api, fields, models +from odoo.addons.resource.models.resource import float_to_time from odoo.exceptions import AccessError, UserError, ValidationError from odoo.tools import float_compare from odoo.tools.translate import _ -from odoo.addons.resource.models.resource import float_to_time - _logger = logging.getLogger(__name__) @@ -87,25 +86,36 @@ class HolidaysRequest(models.Model): ('validate1', 'Second Approval'), ('validate', 'Approved') ], string='Status', readonly=True, track_visibility='onchange', copy=False, default='confirm', - help="The status is set to 'To Submit', when a leave request is created." + - "\nThe status is 'To Approve', when leave request is confirmed by user." + - "\nThe status is 'Refused', when leave request is refused by manager." + - "\nThe status is 'Approved', when leave request is approved by manager.") - payslip_status = fields.Boolean('Reported in last payslips', - help='Green this button when the leave has been taken into account in the payslip.') + help="The status is set to 'To Submit', when a leave request is created." + + "\nThe status is 'To Approve', when leave request is confirmed by user." + + "\nThe status is 'Refused', when leave request is refused by manager." + + "\nThe status is 'Approved', when leave request is approved by manager.") + payslip_status = fields.Boolean('Reported in last payslips', help='Green this button when the leave has been taken into account in the payslip.') report_note = fields.Text('HR Comments') user_id = fields.Many2one('res.users', string='User', related='employee_id.user_id', related_sudo=True, store=True, default=lambda self: self.env.uid, readonly=True) - date_from = fields.Datetime('Start Date', readonly=True, index=True, copy=False, required=True, + date_from = fields.Datetime( + 'Start Date', readonly=True, index=True, copy=False, required=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') - date_to = fields.Datetime('End Date', readonly=True, copy=False, required=True, + date_to = fields.Datetime( + 'End Date', readonly=True, copy=False, required=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') - holiday_status_id = fields.Many2one("hr.leave.type", string="Leave Type", required=True, readonly=True, + # leave type configuration + holiday_status_id = fields.Many2one( + "hr.leave.type", string="Leave Type", required=True, readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, domain=lambda self: self._default_domain_holiday_status()) - employee_id = fields.Many2one('hr.employee', string='Employee', index=True, readonly=True, + leave_type_request_unit = fields.Selection(related='holiday_status_id.request_unit', readonly=True) + validation_type = fields.Selection('Validation Type', related='holiday_status_id.validation_type') + # HR data + employee_id = fields.Many2one( + 'hr.employee', string='Employee', index=True, readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=_default_employee, track_visibility='onchange') manager_id = fields.Many2one('hr.employee', string='Manager', readonly=True) + department_id = fields.Many2one( + 'hr.department', string='Department', readonly=True, + states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + # details number_of_days_temp = fields.Float( 'Duration (Days)', copy=False, readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, @@ -115,45 +125,41 @@ class HolidaysRequest(models.Model): 'Duration (Hours)', copy=False, readonly=True, compute='_compute_number_of_hours', help='Number of hours of the leave request according to your working schedule.') meeting_id = fields.Many2one('calendar.event', string='Meeting') - parent_id = fields.Many2one('hr.leave', string='Parent', copy=False) linked_request_ids = fields.One2many('hr.leave', 'parent_id', string='Linked Requests') - department_id = fields.Many2one('hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) - category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True, + category_id = fields.Many2one( + 'hr.employee.category', string='Employee Tag', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee') holiday_type = fields.Selection([ ('employee', 'By Employee'), ('department', 'By Department'), - ('category', 'By Employee Tag') - ], string='Allocation Mode', readonly=True, required=True, default='employee', + ('category', 'By Employee Tag')], + string='Allocation Mode', readonly=True, required=True, default='employee', states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='By Employee: Allocation/Request for individual Employee, By Employee Tag: Allocation/Request for group of employees in category') - first_approver_id = fields.Many2one('hr.employee', string='First Approval', readonly=True, copy=False, + first_approver_id = fields.Many2one( + 'hr.employee', string='First Approval', readonly=True, copy=False, help='This area is automatically filled by the user who validate the leave', oldname='manager_id') - second_approver_id = fields.Many2one('hr.employee', string='Second Approval', readonly=True, copy=False, oldname='manager_id2', + second_approver_id = fields.Many2one( + 'hr.employee', string='Second Approval', readonly=True, copy=False, oldname='manager_id2', help='This area is automaticly filled by the user who validate the leave with second level (If Leave type need second validation)') - validation_type = fields.Selection('Validation Type', related='holiday_status_id.validation_type') can_reset = fields.Boolean('Can reset', compute='_compute_can_reset') can_approve = fields.Boolean('Can Approve', compute='_compute_can_approve') - - # Those fields are mostly for the interface only - - # Interface fields used when not using hour-based computation + # UX FIELDS + # used when not using hour-based computation request_date_from = fields.Date('Request Start Date') request_date_to = fields.Date('Request End Date') - - leave_type_request_unit = fields.Selection(related='holiday_status_id.request_unit', readonly=True) - - # These fields are only used only when the leave is taken in half days - request_date_from_period = fields.Selection([('am', 'Morning'), - ('pm', 'Afternoon')], string="Date Period Start", default='am') - request_date_to_period = fields.Selection([('am', 'Morning'), - ('pm', 'Afternoon')], string="Date Period End", default='pm') - + # used only when the leave is taken in half days + request_date_from_period = fields.Selection([ + ('am', 'Morning'), ('pm', 'Afternoon')], + string="Date Period Start", default='am') + request_date_to_period = fields.Selection([ + ('am', 'Morning'), ('pm', 'Afternoon')], + string="Date Period End", default='pm') + # request type + duplicate because we cannot hide some entries of a selection field request_unit_all = fields.Selection([('half', 'Half-day'), - ('day', '1 Day'), - ('period', 'Period')]) - # Duplicate field because we cannot hide some entries of a selection field + ('day', '1 Day'), + ('period', 'Period')], default='day') request_unit_day = fields.Selection([('day', '1 Day'), ('period', 'Period')], default='day') diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index e7ff67c498c..6c94c317813 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -5,17 +5,14 @@ import logging -import pytz - from datetime import datetime, time from dateutil.relativedelta import relativedelta from odoo import api, fields, models +from odoo.addons.resource.models.resource import HOURS_PER_DAY from odoo.exceptions import AccessError, UserError from odoo.tools.translate import _ -from odoo.addons.resource.models.resource import HOURS_PER_DAY - _logger = logging.getLogger(__name__) @@ -48,18 +45,22 @@ class HolidaysAllocation(models.Model): ('validate1', 'Second Approval'), ('validate', 'Approved') ], string='Status', readonly=True, track_visibility='onchange', copy=False, default='confirm', - help="The status is set to 'To Submit', when a leave request is created." + - "\nThe status is 'To Approve', when leave request is confirmed by user." + - "\nThe status is 'Refused', when leave request is refused by manager." + - "\nThe status is 'Approved', when leave request is approved by manager.") - date_from = fields.Datetime('Start Date', readonly=True, index=True, copy=False, + help="The status is set to 'To Submit', when a leave request is created." + + "\nThe status is 'To Approve', when leave request is confirmed by user." + + "\nThe status is 'Refused', when leave request is refused by manager." + + "\nThe status is 'Approved', when leave request is approved by manager.") + date_from = fields.Datetime( + 'Start Date', readonly=True, index=True, copy=False, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') - date_to = fields.Datetime('End Date', readonly=True, copy=False, + date_to = fields.Datetime( + 'End Date', readonly=True, copy=False, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') - holiday_status_id = fields.Many2one("hr.leave.type", string="Leave Type", required=True, readonly=True, + holiday_status_id = fields.Many2one( + "hr.leave.type", string="Leave Type", required=True, readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, domain=lambda self: self._default_domain_holiday_status_id(), default=_default_holiday_status_id) - employee_id = fields.Many2one('hr.employee', string='Employee', index=True, readonly=True, + employee_id = fields.Many2one( + 'hr.employee', string='Employee', index=True, readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=_default_employee, track_visibility='onchange') notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) number_of_days_temp = fields.Float( @@ -70,24 +71,29 @@ class HolidaysAllocation(models.Model): number_of_hours = fields.Float('Duration (hours)', help="Number of hours of the leave allocation according to your working schedule.") parent_id = fields.Many2one('hr.leave.allocation', string='Parent') linked_request_ids = fields.One2many('hr.leave.allocation', 'parent_id', string='Linked Requests') - department_id = fields.Many2one('hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) - category_id = fields.Many2one('hr.employee.category', string='Employee Tag', readonly=True, - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee') - holiday_type = fields.Selection([ - ('employee', 'By Employee'), - ('department', 'By Department'), - ('category', 'By Employee Tag') - ], string='Allocation Mode', readonly=True, required=True, default='employee', - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, - help='By Employee: Allocation for individual Employee, By Employee Tag: Allocation for group of employees in category') - first_approver_id = fields.Many2one('hr.employee', string='First Approval', readonly=True, copy=False, + first_approver_id = fields.Many2one( + 'hr.employee', string='First Approval', readonly=True, copy=False, help='This area is automatically filled by the user who validate the leave', oldname='manager_id') - second_approver_id = fields.Many2one('hr.employee', string='Second Approval', readonly=True, copy=False, oldname='manager_id2', + second_approver_id = fields.Many2one( + 'hr.employee', string='Second Approval', readonly=True, copy=False, oldname='manager_id2', help='This area is automaticly filled by the user who validate the leave with second level (If Leave type need second validation)') validation_type = fields.Selection('Validation Type', related='holiday_status_id.validation_type', readonly=True) can_reset = fields.Boolean('Can reset', compute='_compute_can_reset') can_approve = fields.Boolean('Can Approve', compute='_compute_can_approve') type_request_unit = fields.Selection(related='holiday_status_id.request_unit', readonly=True) + # mode + holiday_type = fields.Selection([ + ('employee', 'By Employee'), + ('department', 'By Department'), + ('category', 'By Employee Tag')], + string='Allocation Mode', readonly=True, required=True, default='employee', + states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, + help='By Employee: Allocation for individual Employee, By Employee Tag: Allocation for group of employees in category') + department_id = fields.Many2one('hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) + category_id = fields.Many2one( + 'hr.employee.category', string='Employee Tag', readonly=True, + states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Category of Employee') + # accrual configuration accrual = fields.Boolean("Accrual", related='holiday_status_id.accrual', store=True, readonly=True) number_per_interval = fields.Float("Number of unit per interval", readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=1) interval_number = fields.Integer("Number of unit between two intervals", readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=1) diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py index 216e1002de7..48936f1c9e7 100644 --- a/addons/hr_holidays/models/hr_leave_type.py +++ b/addons/hr_holidays/models/hr_leave_type.py @@ -21,7 +21,8 @@ class HolidaysType(models.Model): name = fields.Char('Leave Type', required=True, translate=True) sequence = fields.Integer(default=100, help='The type with the smallest sequence is the default value in leave request') - categ_id = fields.Many2one('calendar.event.type', string='Meeting Type', + categ_id = fields.Many2one( + 'calendar.event.type', string='Meeting Type', help='Once a leave is validated, Odoo will create a corresponding meeting of this type in the calendar.') color_name = fields.Selection([ ('red', 'Red'), @@ -41,56 +42,44 @@ class HolidaysType(models.Model): ('wheat', 'Wheat'), ('ivory', 'Ivory')], string='Color in Report', required=True, default='red', help='This color will be used in the leaves summary located in Reporting > Leaves by Department.') - limit = fields.Boolean('Exceed Allocation', - help="If you select this check box, the system will allow the employees to ask" - "for leaves without allocating some beforehand") + limit = fields.Boolean('Exceed Allocation', help="If you select this check box, the system will allow the employees to ask for leaves without allocating some beforehand") active = fields.Boolean('Active', default=True, - help="If the active field is set to false, it will allow you to hide the leave type without removing it.") - + help="If the active field is set to false, it will allow you to hide the leave type without removing it.") max_leaves = fields.Float(compute='_compute_leaves', string='Maximum Allowed', - help='This value is given by the sum of all leaves requests with a positive value.') - leaves_taken = fields.Float(compute='_compute_leaves', string='Leaves Already Taken', + help='This value is given by the sum of all leaves requests with a positive value.') + leaves_taken = fields.Float( + compute='_compute_leaves', string='Leaves Already Taken', help='This value is given by the sum of all leaves requests with a negative value.') - remaining_leaves = fields.Float(compute='_compute_leaves', string='Remaining Leaves', + remaining_leaves = fields.Float( + compute='_compute_leaves', string='Remaining Leaves', help='Maximum Leaves Allowed - Leaves Already Taken') - virtual_remaining_leaves = fields.Float(compute='_compute_leaves', string='Virtual Remaining Leaves', + virtual_remaining_leaves = fields.Float( + compute='_compute_leaves', string='Virtual Remaining Leaves', help='Maximum Leaves Allowed - Leaves Already Taken - Leaves Waiting Approval') - company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.user.company_id) - - validation_type = fields.Selection([('hr', 'Human Resource officer'), - ('manager', 'Employee Manager'), - ('both', 'Double Validation')], - default='hr', - string='Validation By') - - employee_applicability = fields.Selection([('both', 'Both'), - ('leave', 'Can be requested'), - ('allocation', 'Can be allocated')], - default=lambda self: 'leave' if self.limit else 'both', string='Mode', - help='This leave type will be available on Leave / Allocation request based on selected value') - + validation_type = fields.Selection([ + ('hr', 'Human Resource officer'), + ('manager', 'Employee Manager'), + ('both', 'Double Validation')], default='hr', string='Validation By') + employee_applicability = fields.Selection([ + ('both', 'Both'), + ('leave', 'Can be requested'), + ('allocation', 'Can be allocated')], + default=lambda self: 'leave' if self.limit else 'both', + string='Mode', help='This leave type will be available on Leave / Allocation request based on selected value') validity_start = fields.Date("Start Date", default=fields.Date.today, - help='Adding validity to types of leaves so that it cannot be selected outside' - 'this time period') + help='Adding validity to types of leaves so that it cannot be selected outside this time period') validity_stop = fields.Date("End Date") - valid = fields.Boolean(compute='_compute_valid', search='_search_valid', help='This indicates if it is still possible to use this type of leave') - - time_type = fields.Selection([('leave', 'Leave'), ('other', 'Other')], default='leave', string="Kind of Leave", help="Whether this should be computed as a holiday or as work time (eg: formation)") - request_unit = fields.Selection([('day', 'Day'), - ('half', 'Half-day'), - ('hour', 'Hours')], default='day', string='Take Leaves in', required=True) - + request_unit = fields.Selection([ + ('day', 'Day'), ('half', 'Half-day'), ('hour', 'Hours')], + default='day', string='Take Leaves in', required=True) accrual = fields.Boolean('Accrual', default=False, help='This option forces this type of leave to be allocated accrually') - unpaid = fields.Boolean('Is Unpaid', default=False) - negative = fields.Boolean('Allow Negative', help="This option allows to take more leaves than allocated") - balance_limit = fields.Float('Max Balance Limit', default=0, help="The maximum quantity of allocated days on this allocation, zero meaning infinite amount") _sql_constraints = [ diff --git a/addons/hr_holidays/report/hr_leave_reports.xml b/addons/hr_holidays/report/hr_leave_reports.xml index da955bb2f12..0420ead8ade 100644 --- a/addons/hr_holidays/report/hr_leave_reports.xml +++ b/addons/hr_holidays/report/hr_leave_reports.xml @@ -121,13 +121,6 @@ 'search_default_group_type': 1, 'search_default_year': 1 , 'search_default_my_leaves': 1, - 'needaction_menu_ref': - [ - 'hr_holidays.menu_open_ask_holidays_new', - 'hr_holidays.menu_open_allocation_holidays', - 'hr_holidays.menu_request_approve_allocation', - 'hr_holidays.menu_open_employee_leave', - ] }

diff --git a/addons/hr_holidays/tests/common.py b/addons/hr_holidays/tests/common.py index 467eff2037c..43c5df67181 100644 --- a/addons/hr_holidays/tests/common.py +++ b/addons/hr_holidays/tests/common.py @@ -9,38 +9,41 @@ class TestHrHolidaysBase(common.TransactionCase): def setUp(self): super(TestHrHolidaysBase, self).setUp() - Users = self.env['res.users'].with_context(no_reset_password=True) - - # Find Employee group - group_employee_id = self.ref('base.group_user') + self._quick_create_ctx = { + 'mail_create_nolog': True, + 'mail_create_nosubscribe': True, + 'mail_notrack': True, + } + self._quick_create_user_ctx = dict(self._quick_create_ctx, no_reset_password=True) # Test users to use through the various tests + Users = self.env['res.users'].with_context(self._quick_create_user_ctx) self.user_hruser = Users.create({ 'name': 'Armande HrUser', 'login': 'Armande', 'email': 'armande.hruser@example.com', - 'groups_id': [(6, 0, [group_employee_id, self.ref('hr_holidays.group_hr_holidays_user')])] + 'groups_id': [(6, 0, [self.ref('base.group_user'), self.ref('hr_holidays.group_hr_holidays_user')])] }) self.user_hruser_id = self.user_hruser.id self.user_hrmanager = Users.create({ 'name': 'Bastien HrManager', 'login': 'bastien', 'email': 'bastien.hrmanager@example.com', - 'groups_id': [(6, 0, [group_employee_id, self.ref('hr_holidays.group_hr_holidays_manager')])] + 'groups_id': [(6, 0, [self.ref('base.group_user'), self.ref('hr_holidays.group_hr_holidays_manager')])] }).id self.user_hrmanager_id = self.user_hrmanager self.user_employee = Users.create({ 'name': 'David Employee', 'login': 'david', 'email': 'david.employee@example.com', - 'groups_id': [(6, 0, [group_employee_id])] + 'groups_id': [(6, 0, [self.ref('base.group_user')])] }) self.user_employee_id = self.user_employee.id self.user_hrmanager_2_id = Users.create({ 'name': 'Florence HrManager', 'login': 'florence', 'email': 'florence.hrmanager@example.com', - 'groups_id': [(6, 0, [group_employee_id, self.ref('hr_holidays.group_hr_holidays_manager')])] + 'groups_id': [(6, 0, [self.ref('base.group_user'), self.ref('hr_holidays.group_hr_holidays_manager')])] }).id # Hr Data diff --git a/addons/hr_holidays/tests/test_hr_leave_type.py b/addons/hr_holidays/tests/test_hr_leave_type.py index ebd2851ff60..3232ddc39f0 100644 --- a/addons/hr_holidays/tests/test_hr_leave_type.py +++ b/addons/hr_holidays/tests/test_hr_leave_type.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- # Part of Odoo. See LICENSE file for full copyright and licensing details. + from datetime import datetime from dateutil.relativedelta import relativedelta @@ -7,35 +8,25 @@ from odoo.addons.hr_holidays.tests.common import TestHrHolidaysBase class TestHrLeaveType(TestHrHolidaysBase): - def setUp(self): - super(TestHrLeaveType, self).setUp() - LeaveType = self.env['hr.leave.type'] - - self.leave_leave = LeaveType.create({ + def test_time_type(self): + leave_type = self.env['hr.leave.type'].create({ 'name': 'Legal Leaves', 'limit': True, 'time_type': 'leave', }) - def test_time_type(self): - Leave = self.env['hr.leave'] - RLeave = self.env['resource.calendar.leaves'] - - leave_1 = Leave.create({ + leave_1 = self.env['hr.leave'].create({ 'name': 'Doctor Appointment', 'employee_id': self.employee_hruser_id, - 'holiday_status_id': self.leave_leave.id, + 'holiday_status_id': leave_type.id, 'date_from': (datetime.today() - relativedelta(days=1)), 'date_to': datetime.today(), 'number_of_days_temp': 1, }) - leave_1.action_approve() - self.assertEqual(RLeave.search([('holiday_id', '=', leave_1.id)]).time_type, 'leave') - - leave_1.action_refuse() - leave_1.action_draft() - - leave_1.unlink() + self.assertEqual( + self.env['resource.calendar.leaves'].search([('holiday_id', '=', leave_1.id)]).time_type, + 'leave' + ) diff --git a/addons/hr_holidays/views/hr_leave_allocation_views.xml b/addons/hr_holidays/views/hr_leave_allocation_views.xml index 81c84624740..2818b617d15 100644 --- a/addons/hr_holidays/views/hr_leave_allocation_views.xml +++ b/addons/hr_holidays/views/hr_leave_allocation_views.xml @@ -133,39 +133,8 @@ - - hr.holidays.my.allocation.tree - hr.leave.allocation - - - - - - - - - - - - - - Allocations All - hr.leave.allocation - form - tree,kanban,form - -

- Create a new leave allocation request -

-
- {} - [] - -
- - - Allocation Requests + + My Allocations hr.leave.allocation form tree,kanban,form @@ -177,23 +146,24 @@ {} [('employee_id.user_id', '=', uid)] - - - Allocation Request + + All Allocations hr.leave.allocation form - { - 'search_default_approve':1, - } + tree,kanban,form + +

+ Create a new leave allocation request +

+
+ {} [] - -
- - Department Leaves Allocation + + Department Allocation to Approve hr.leave.allocation form tree,form,kanban @@ -204,80 +174,13 @@ Create a new leave allocation

- -
- - - Allocation Requests to Approve - hr.leave.allocation - form - tree,form - { - 'search_default_department_id': [active_id], - 'default_department_id': active_id, - 'search_default_approve':1} - - [] - - - - - - tree - - - - - - - form - - - - - - - tree - - - - - - - form - - - - - - Requests to Approve - hr.leave - form - { - 'search_default_approve':1, - } - - - - - - - tree - - - - - - - form - - - hr.leave.type.filter hr.leave.type @@ -60,19 +59,6 @@ - - hr.leave.type.tree - hr.leave.type - - - - - - - - - - hr.leave.type.kanban hr.leave.type @@ -98,38 +84,24 @@ hr.leave.type.normal.tree hr.leave.type - 35 - - - + + + - - hr.leave.type.search - hr.leave.type - - - - - - - - Leave Types ir.actions.act_window hr.leave.type form tree,kanban,form - - - hr.holidays.graph - hr.leave - + hr.holidays.graph + hr.leave + - + @@ -240,7 +240,7 @@ sequence="99" groups="hr_holidays.group_hr_holidays_manager,hr_holidays.group_hr_holidays_user"/> - + New Request hr.leave form @@ -261,42 +261,19 @@ - - - tree - - - - - - - form - - - - - - - calendar - - - - - + Leaves Requests hr.leave form tree,calendar,form - {} [('user_id', '=', uid)] -

Create a new leave request @@ -309,66 +286,53 @@ - - - tree - - - - - - - form - - - - - - - calendar - - - - + Leaves hr.leave form tree,kanban,form,calendar - + {} + []

Create a new leave request

- {} - [] -
- + Department Leaves hr.leave form tree,form,calendar,kanban - {'search_default_department':1, 'search_default_approve':1} + { + 'search_default_department':1, + 'search_default_approve':1} + []

Create a new leave request -

- Once you have recorded your leave request, it will be sent - to a manager for validation. Be sure to set the right leave - type (recuperation, legal leaves, sickness) and the exact - number of open days related to your leave.

- +
+ + + Leaves Analysis + hr.leave + form + graph,pivot + { + 'search_default_department_id': [active_id], + 'default_department_id': active_id} + + [('holiday_type','=','employee')] @@ -413,72 +377,6 @@ action="hr_leave_action_payroll" sequence="1"/> - - - hr.leave.allocation.tree.customize - hr.leave.allocation - - - - - - - - - - - - - - Leaves to be reported in Payslip - ir.actions.act_window - hr.leave - hr.employee - form - tree,form - {'search_default_employee_id': [active_id], 'search_default_validated': True, 'search_default_gray': True} - [('date_from','>=', context_today().strftime("%Y-%m-1")), ('date_from','<', ((context_today() + relativedelta(months=1)).strftime('%Y-%m-1')) )] - - - - - - Leave Request to Approve - hr.leave - form - tree,form - { - 'search_default_department_id': [active_id], - 'default_department_id': active_id, - 'search_default_approve':1} - - [] - - - - - - Leaves Analysis - hr.leave - form - graph,pivot - [('holiday_type','=','employee')] - - - - - Leaves Analysis - hr.leave - form - graph,pivot - [('holiday_type','=','employee')] - { - 'search_default_department_id': [active_id], - 'default_department_id': active_id} - - - - hr.holidays.report_pivot hr.leave @@ -514,13 +412,6 @@ - - - pivot - - - - graph diff --git a/addons/hr_holidays/views/hr_views.xml b/addons/hr_holidays/views/hr_views.xml index 3c7fef1f9e9..4093ea56d89 100644 --- a/addons/hr_holidays/views/hr_views.xml +++ b/addons/hr_holidays/views/hr_views.xml @@ -1,19 +1,6 @@ - - Leaves - ir.actions.act_window - hr.leave.report - hr.employee - form - tree,form - {'search_default_employee_id': [active_id], 'default_employee_id': active_id, 'search_default_group_type': 1, - 'search_default_year': 1} - [('holiday_type','=','employee'), ('holiday_status_id.limit', '=', False), ('state','!=', 'refuse')] - - - hr.employee.leave.tree hr.employee @@ -72,7 +59,7 @@
@@ -82,7 +69,7 @@
@@ -108,7 +95,7 @@
@@ -116,7 +103,7 @@
@@ -126,7 +113,7 @@
From af7901ca29e265ba032551a35ee6d5c3569f3751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Thu, 6 Sep 2018 14:52:44 +0200 Subject: [PATCH 05/12] [REM] hr_holidays: remove inverse on employee leaves fields Currently code somehow allows people to create allocation requests on the fly by writing on the computed remaining_leaves field. It work only under some conditions that are not likely to happen. Moreover creating and validating allocation requests should be done under the Leaves application while knowing it and not hidden in an inverse field. Let us remove that code and let people use the Leaves application to handle allocation requests. That code comes from old versions of Leave application. This commit is linked to task ID 1876795 and PR #26571. --- addons/hr_holidays/models/hr.py | 37 +------------------ .../hr_holidays/report/hr_leave_reports.xml | 7 +++- addons/hr_holidays/views/hr_views.xml | 27 -------------- 3 files changed, 7 insertions(+), 64 deletions(-) diff --git a/addons/hr_holidays/models/hr.py b/addons/hr_holidays/models/hr.py index 5c19745e412..e593b88b89a 100644 --- a/addons/hr_holidays/models/hr.py +++ b/addons/hr_holidays/models/hr.py @@ -61,10 +61,10 @@ class Department(models.Model): class Employee(models.Model): - _inherit = "hr.employee" - remaining_leaves = fields.Float(compute='_compute_remaining_leaves', string='Remaining Legal Leaves', inverse='_inverse_remaining_leaves', + remaining_leaves = fields.Float( + compute='_compute_remaining_leaves', string='Remaining Legal Leaves', help='Total number of legal leaves allocated to this employee, change this value to create allocation/leave request. ' 'Total based on all the leave types without overriding limit.') current_leave_state = fields.Selection(compute='_compute_leave_status', string="Current Leave Status", @@ -115,39 +115,6 @@ class Employee(models.Model): for employee in self: employee.remaining_leaves = float_round(remaining.get(employee.id, 0.0), precision_digits=2) - @api.multi - def _inverse_remaining_leaves(self): - status_list = self.env['hr.leave.type'].search([('limit', '=', False)]) - # Create leaves (adding remaining leaves) or raise (reducing remaining leaves) - actual_remaining = self._get_remaining_leaves() - for employee in self.filtered(lambda employee: employee.remaining_leaves): - # check the status list. This is done here and not before the loop to avoid raising - # exception on employee creation (since we are in a computed field). - if len(status_list) != 1: - raise UserError(_("The feature behind the field 'Remaining Legal Leaves' can only be used when there is only one " - "leave type with the option 'Allow to Override Limit' unchecked. (%s Found). " - "Otherwise, the update is ambiguous as we cannot decide on which leave type the update has to be done. " - "\n You may prefer to use the classic menus 'Leave Requests' and 'Allocation Requests' located in Leaves Application " - "to manage the leave days of the employees if the configuration does not allow to use this field.") % (len(status_list))) - status = status_list[0] if status_list else None - if not status: - continue - # if a status is found, then compute remaing leave for current employee - difference = float_round(employee.remaining_leaves - actual_remaining.get(employee.id, 0), precision_digits=2) - if difference > 0: - leave = self.env['hr.leave.allocation'].create({ - 'name': _('Allocation for %s') % employee.name, - 'employee_id': employee.id, - 'holiday_status_id': status.id, - 'holiday_type': 'employee', - 'number_of_days_temp': difference - }) - leave.action_approve() - if leave.validation_type == 'both': - leave.action_validate() - elif difference < 0: - raise UserError(_('You cannot reduce validated allocation requests.')) - @api.multi def _compute_leave_status(self): # Used SUPERUSER_ID to forcefully get status of other user's leave, to bypass record rule diff --git a/addons/hr_holidays/report/hr_leave_reports.xml b/addons/hr_holidays/report/hr_leave_reports.xml index 0420ead8ade..d4471fa8a72 100644 --- a/addons/hr_holidays/report/hr_leave_reports.xml +++ b/addons/hr_holidays/report/hr_leave_reports.xml @@ -138,9 +138,12 @@ hr.employee form tree,form - {'search_default_employee_id': [active_id], 'default_employee_id': active_id, 'search_default_group_type': 1, + { + 'search_default_employee_id': [active_id], + 'default_employee_id': active_id, + 'search_default_group_type': 1, 'search_default_year': 1} - [('holiday_type','=','employee'), ('holiday_status_id.limit', '=', False), ('state','!=', 'refuse')] + [('holiday_type','=','employee')] diff --git a/addons/hr_holidays/views/hr_views.xml b/addons/hr_holidays/views/hr_views.xml index 4093ea56d89..967ef412788 100644 --- a/addons/hr_holidays/views/hr_views.xml +++ b/addons/hr_holidays/views/hr_views.xml @@ -1,33 +1,6 @@ - - hr.employee.leave.tree - hr.employee - - - - - - - - - - - Allocate Leaves for Employees - ir.actions.act_window - hr.employee - form - tree,form - - -

- You can assign remaining Legal Leaves for each employee, Odoo - will automatically create and validate allocation requests. -

-
-
- Absent Employees hr.employee From 2e3b392a6f60b678858e544bf42e7d0875f69f81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 24 Aug 2018 17:12:57 +0200 Subject: [PATCH 06/12] [REF] hr_holidays: differentiate personal and manager leave / allocation views Purpose of this commit is to clean allocation and request views and prepare future modifications. We would like to separate personal views (making a request for myself) from manager views (giving more options). Specifications * views under "My" menu should be simplified * in a general way there should be no action buttons under my. Hide approve/refuse buttons in personal mode; * show only leave type, description and duration when asking for an allocation; hide details about group allocation and accrual; hide action buttons; * show only leave type, description and from/to choice as well as duration when asking for a leave; hide details about group allocation; hide action buttons; * in list view hide employee and buttons my menu; * views under "Manager" menu should be complete * display complete form view; * add buttons to approve / refuse directly from the list view in manager menus; This commit is linked to task ID 1876795 and PR #26571. --- .../views/hr_leave_allocation_views.xml | 135 ++++++++++++----- addons/hr_holidays/views/hr_leave_views.xml | 136 ++++++++++++++---- 2 files changed, 211 insertions(+), 60 deletions(-) diff --git a/addons/hr_holidays/views/hr_leave_allocation_views.xml b/addons/hr_holidays/views/hr_leave_allocation_views.xml index 2818b617d15..33a9eccad9c 100644 --- a/addons/hr_holidays/views/hr_leave_allocation_views.xml +++ b/addons/hr_holidays/views/hr_leave_allocation_views.xml @@ -47,9 +47,10 @@
- - Allocation Request + + hr.leave.allocation.view.form hr.leave.allocation + 32
@@ -57,18 +58,11 @@
-

+

@@ -77,35 +71,23 @@ diff --git a/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py b/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py index a7e484f18d4..a17deae822e 100644 --- a/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py +++ b/addons/project_timesheet_holidays/tests/test_timesheet_holidays.py @@ -16,7 +16,7 @@ class TestTimesheetHolidaysCreate(common.TransactionCase): """Ensure that when a status is created, it fullfills the project and task constrains""" status = self.env['hr.leave.type'].create({ 'name': 'A nice Leave Type', - 'limit': True + 'allocation_type': 'no' }) company = self.env.user.company_id @@ -42,14 +42,14 @@ class TestTimesheetHolidays(TestTimesheet): self.hr_leave_type_with_ts = self.env['hr.leave.type'].create({ 'name': 'Leave Type with timesheet generation', - 'limit': True, + 'allocation_type': 'no', 'timesheet_generate': True, 'timesheet_project_id': self.internal_project.id, 'timesheet_task_id': self.internal_task_leaves.id, }) self.hr_leave_type_no_ts = self.env['hr.leave.type'].create({ 'name': 'Leave Type without timesheet generation', - 'limit': True, + 'allocation_type': 'no', 'timesheet_generate': False, 'timesheet_project_id': False, 'timesheet_task_id': False, diff --git a/addons/project_timesheet_holidays/views/hr_holidays_views.xml b/addons/project_timesheet_holidays/views/hr_holidays_views.xml index 1e010067a57..a74b6aca55a 100644 --- a/addons/project_timesheet_holidays/views/hr_holidays_views.xml +++ b/addons/project_timesheet_holidays/views/hr_holidays_views.xml @@ -6,12 +6,10 @@ hr.leave.type - - - - - - + + + +
From 14491e8f9b23525f6d9017cfbc91366849a63389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 3 Sep 2018 12:57:53 +0200 Subject: [PATCH 08/12] [REF] hr_holidays: clean fields used to store and display duration Purpose of this commit is to simplify fields used in leave and allocation used to store the duration of the requests. We want notably to get rid of "number of days temp" that, contrary to its name, is not temporary at all as it stores the real number of days. We also want to clarify the hours or days encoding that is different on leave and allocation models. Specifications * number_of_days on leave and allocation is the master field holding the leave or allocation duration in days; * two fields are used for interface that are suffixed by _display in order to indicate they are UX only: number_of_hours_display and number_of_days_ display. They are interface fields used for the user and correct number of days is computed and stored in number_of_days; * more specifically for leave model * display fields are readonly as it is computed based on dates given by the user, directly (from / to) or indirectly (half-day leaves for example); * duration field is computed through an onchange. It could be directly set by hand by managers if some confusion in the number of days appear; * more specifically for allocation model * display fields trigger an inverse as they are the real duration given by HR officers or managers; * duration field is computed through the inverse of display fields; Various reports, data and use of leave / allocation models are updated to use the correct field. This commit is linked to task ID 1876795 and PR #26571. --- addons/hr_holidays/data/hr_holidays_demo.xml | 13 ++-- addons/hr_holidays/models/hr.py | 2 +- addons/hr_holidays/models/hr_leave.py | 69 +++++++++-------- .../hr_holidays/models/hr_leave_allocation.py | 77 ++++++++++--------- addons/hr_holidays/models/hr_leave_type.py | 16 ++-- .../report/holidays_summary_report.py | 2 +- addons/hr_holidays/report/hr_leave_report.py | 2 +- .../hr_holidays/tests/test_access_rights.py | 20 ++--- .../tests/test_accrual_allocations.py | 22 +++--- .../hr_holidays/tests/test_holidays_flow.py | 28 +++---- .../hr_holidays/tests/test_hr_leave_type.py | 2 +- .../views/hr_leave_allocation_views.xml | 18 ++--- addons/hr_holidays/views/hr_leave_views.xml | 9 ++- .../tests/test_timesheet_holidays.py | 8 +- 14 files changed, 149 insertions(+), 139 deletions(-) diff --git a/addons/hr_holidays/data/hr_holidays_demo.xml b/addons/hr_holidays/data/hr_holidays_demo.xml index 29f5ebf723f..c28ed7bc6fe 100644 --- a/addons/hr_holidays/data/hr_holidays_demo.xml +++ b/addons/hr_holidays/data/hr_holidays_demo.xml @@ -29,7 +29,7 @@ Legal Leaves for Peter Parker - 20 + 20 confirm @@ -37,7 +37,7 @@ International Tour - 7 + 7 confirm @@ -45,15 +45,14 @@ Overtime Compensation - 160 - 20 + 20 Summer Vacation - 7 + 7 @@ -82,7 +81,7 @@ - 3 + 3
@@ -91,7 +90,7 @@ - 3 + 3 confirm diff --git a/addons/hr_holidays/models/hr.py b/addons/hr_holidays/models/hr.py index 908dc25eadd..f879a0c0ef4 100644 --- a/addons/hr_holidays/models/hr.py +++ b/addons/hr_holidays/models/hr.py @@ -97,7 +97,7 @@ class Employee(models.Model): state, employee_id FROM hr_leave_allocation UNION - SELECT holiday_status_id, number_of_days, + SELECT holiday_status_id, (number_of_days * -1) as number_of_days, state, employee_id FROM hr_leave ) h diff --git a/addons/hr_holidays/models/hr_leave.py b/addons/hr_holidays/models/hr_leave.py index e343e5c9406..a51ab643a18 100644 --- a/addons/hr_holidays/models/hr_leave.py +++ b/addons/hr_holidays/models/hr_leave.py @@ -88,12 +88,6 @@ class HolidaysRequest(models.Model): payslip_status = fields.Boolean('Reported in last payslips', help='Green this button when the leave has been taken into account in the payslip.') report_note = fields.Text('HR Comments') user_id = fields.Many2one('res.users', string='User', related='employee_id.user_id', related_sudo=True, store=True, default=lambda self: self.env.uid, readonly=True) - date_from = fields.Datetime( - 'Start Date', readonly=True, index=True, copy=False, required=True, - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') - date_to = fields.Datetime( - 'End Date', readonly=True, copy=False, required=True, - states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') # leave type configuration holiday_status_id = fields.Many2one( "hr.leave.type", string="Leave Type", required=True, readonly=True, @@ -110,15 +104,24 @@ class HolidaysRequest(models.Model): 'hr.department', string='Department', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) - # details - number_of_days_temp = fields.Float( - 'Duration (Days)', copy=False, readonly=True, + # duration + date_from = fields.Datetime( + 'Start Date', readonly=True, index=True, copy=False, required=True, + states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') + date_to = fields.Datetime( + 'End Date', readonly=True, copy=False, required=True, + states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, track_visibility='onchange') + number_of_days = fields.Float( + 'Duration (Days)', copy=False, readonly=True, track_visibility='onchange', states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, help='Number of days of the leave request according to your working schedule.') - number_of_days = fields.Float('Number of Days', compute='_compute_number_of_days', store=True, track_visibility='onchange') - number_of_hours = fields.Float( - 'Duration (Hours)', copy=False, readonly=True, compute='_compute_number_of_hours', - help='Number of hours of the leave request according to your working schedule.') + number_of_days_display = fields.Float( + 'Duration in days', compute='_compute_number_of_days_display', copy=False, readonly=True, + help='Number of days of the leave request. Used for interface.') + number_of_hours_display = fields.Float( + 'Duration in hours', compute='_compute_number_of_hours_display', copy=False, readonly=True, + help='Number of hours of the leave request according to your working schedule. Used for interface.') + # details meeting_id = fields.Many2one('calendar.event', string='Meeting') parent_id = fields.Many2one('hr.leave', string='Parent', copy=False) linked_request_ids = fields.One2many('hr.leave', 'parent_id', string='Linked Requests') @@ -158,7 +161,7 @@ class HolidaysRequest(models.Model): ('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL) or (holiday_type='department' AND department_id IS NOT NULL) )", "The employee, department or employee category of this request is missing. Please make sure that your user login is linked to an employee."), ('date_check2', "CHECK ((date_from <= date_to))", "The start date must be anterior to the end date."), - ('date_check', "CHECK ( number_of_days_temp >= 0 )", "If you want to change the number of days you should use the 'period' mode"), + ('duration_check', "CHECK ( number_of_days >= 0 )", "If you want to change the number of days you should use the 'period' mode"), ] @api.onchange('request_unit', 'request_date_from_period', 'request_date_to_period', @@ -187,7 +190,7 @@ class HolidaysRequest(models.Model): self.date_from = date_from if date_to: self.date_to = date_to - self.number_of_days_temp = 0 + self.number_of_days = 0 return domain = [('calendar_id', '=', self.employee_id.resource_calendar_id.id)] @@ -213,8 +216,8 @@ class HolidaysRequest(models.Model): date_to = fields.Datetime.from_string(date_to) else: tz = self.env.user.tz or 'UTC' - date_from = timezone(tz).localize(datetime.combine(first_day, hour_from)).astimezone(UTC) - date_to = timezone(tz).localize(datetime.combine(last_day, hour_to)).astimezone(UTC) + date_from = timezone(tz).localize(datetime.combine(first_day, hour_from)).astimezone(UTC).replace(tzinfo=None) + date_to = timezone(tz).localize(datetime.combine(last_day, hour_to)).astimezone(UTC).replace(tzinfo=None) self.date_from = date_from self.date_to = date_to @@ -223,7 +226,7 @@ class HolidaysRequest(models.Model): date_from = date_from date_to = date_to - self.number_of_days_temp = self._get_number_of_days(date_from, date_to, self.employee_id.id) + self.number_of_days = self._get_number_of_days(date_from, date_to, self.employee_id.id) @api.onchange('holiday_type') def _onchange_type(self): @@ -259,9 +262,9 @@ class HolidaysRequest(models.Model): # Compute and update the number of days if (date_to and date_from) and (date_from <= date_to): - self.number_of_days_temp = self._get_number_of_days(date_from, date_to, self.employee_id.id) + self.number_of_days = self._get_number_of_days(date_from, date_to, self.employee_id.id) else: - self.number_of_days_temp = 0 + self.number_of_days = 0 @api.onchange('date_to') def _onchange_date_to(self): @@ -277,9 +280,9 @@ class HolidaysRequest(models.Model): # Compute and update the number of days if (date_to and date_from) and (date_from <= date_to): - self.number_of_days_temp = self._get_number_of_days(date_from, date_to, self.employee_id.id) + self.number_of_days = self._get_number_of_days(date_from, date_to, self.employee_id.id) else: - self.number_of_days_temp = 0 + self.number_of_days = 0 @api.onchange('employee_id') def _onchange_employee_id(self): @@ -287,16 +290,16 @@ class HolidaysRequest(models.Model): self.department_id = self.employee_id.department_id @api.multi - @api.depends('number_of_days_temp') - def _compute_number_of_days(self): + @api.depends('number_of_days') + def _compute_number_of_days_display(self): for holiday in self: - holiday.number_of_days = -holiday.number_of_days_temp + holiday.number_of_days_display = holiday.number_of_days @api.multi - @api.depends('number_of_days_temp') - def _compute_number_of_hours(self): + @api.depends('number_of_days') + def _compute_number_of_hours_display(self): for holiday in self: - holiday.number_of_hours = holiday.number_of_days_temp * self.employee_id.resource_calendar_id.hours_per_day + holiday.number_of_hours_display = holiday.number_of_days * self.employee_id.resource_calendar_id.hours_per_day @api.multi @api.depends('state', 'employee_id', 'department_id') @@ -336,7 +339,7 @@ class HolidaysRequest(models.Model): if nholidays: raise ValidationError(_('You can not have 2 leaves that overlaps on the same day.')) - @api.constrains('state', 'number_of_days_temp', 'holiday_status_id') + @api.constrains('state', 'number_of_days', 'holiday_status_id') def _check_holidays(self): for holiday in self: if holiday.holiday_type != 'employee' or not holiday.employee_id or holiday.holiday_status_id.allocation_type == 'no': @@ -365,9 +368,9 @@ class HolidaysRequest(models.Model): res = [] for leave in self: if self.env.context.get('short_name'): - res.append((leave.id, _("%s : %.2f day(s)") % (leave.name or leave.holiday_status_id.name, leave.number_of_days_temp))) + res.append((leave.id, _("%s : %.2f day(s)") % (leave.name or leave.holiday_status_id.name, leave.number_of_days))) else: - res.append((leave.id, _("%s on %s : %.2f day(s)") % (leave.employee_id.name or leave.category_id.name, leave.holiday_status_id.name, leave.number_of_days_temp))) + res.append((leave.id, _("%s on %s : %.2f day(s)") % (leave.employee_id.name or leave.category_id.name, leave.holiday_status_id.name, leave.number_of_days))) return res @api.multi @@ -486,7 +489,7 @@ class HolidaysRequest(models.Model): 'name': self.display_name, 'categ_ids': [(6, 0, [ self.holiday_status_id.categ_id.id])] if self.holiday_status_id.categ_id else [], - 'duration': self.number_of_days_temp * self.employee_id.resource_calendar_id.hours_per_day, + 'duration': self.number_of_days * self.employee_id.resource_calendar_id.hours_per_day, 'description': self.notes, 'user_id': self.user_id.id, 'start': self.date_from, @@ -511,7 +514,7 @@ class HolidaysRequest(models.Model): 'date_from': self.date_from, 'date_to': self.date_to, 'notes': self.notes, - 'number_of_days_temp': self.number_of_days_temp, + 'number_of_days': self.number_of_days, 'parent_id': self.id, 'employee_id': employee.id } diff --git a/addons/hr_holidays/models/hr_leave_allocation.py b/addons/hr_holidays/models/hr_leave_allocation.py index e288aaf68e0..16c35241dc2 100644 --- a/addons/hr_holidays/models/hr_leave_allocation.py +++ b/addons/hr_holidays/models/hr_leave_allocation.py @@ -57,12 +57,18 @@ class HolidaysAllocation(models.Model): 'hr.employee', string='Employee', index=True, readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, default=_default_employee, track_visibility='onchange') notes = fields.Text('Reasons', readonly=True, states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}) - number_of_days_temp = fields.Float( - 'Duration (days)', copy=False, readonly=True, + # duration + number_of_days = fields.Float( + 'Number of Days', track_visibility='onchange', + help='Duration in days. Reference field to use when necessary.') + number_of_days_display = fields.Float( + 'Duration (days)', compute='_compute_number_of_days_display', inverse='_inverse_number_of_days_display', states={'draft': [('readonly', False)], 'confirm': [('readonly', False)]}, - help='Number of days of the leave request according to your working schedule.') - number_of_days = fields.Float('Number of Days', compute='_compute_number_of_days', store=True, track_visibility='onchange') - number_of_hours = fields.Float('Duration (hours)', help="Number of hours of the leave allocation according to your working schedule.") + help="UX field allowing to see and modify the allocation duration, computed in days.") + number_of_hours_display = fields.Float( + 'Duration (hours)', compute='_compute_number_of_hours_display', inverse='_inverse_number_of_hours_display', + help="UX field allowing to see and modify the allocation duration, computed in hours.") + # details parent_id = fields.Many2one('hr.leave.allocation', string='Parent') linked_request_ids = fields.One2many('hr.leave.allocation', 'parent_id', string='Linked Requests') first_approver_id = fields.Many2one( @@ -108,7 +114,7 @@ class HolidaysAllocation(models.Model): _sql_constraints = [ ('type_value', "CHECK( (holiday_type='employee' AND employee_id IS NOT NULL) or (holiday_type='category' AND category_id IS NOT NULL) or (holiday_type='department' AND department_id IS NOT NULL) )", "The employee, department or employee category of this request is missing. Please make sure that your user login is linked to an employee."), - ('date_check', "CHECK ( number_of_days_temp >= 0 )", "The number of days must be greater than 0."), + ('duration_check', "CHECK ( number_of_days >= 0 )", "The number of days must be greater than 0."), ('number_per_interval_check', "CHECK(number_per_interval > 0)", "The number per interval should be greater than 0"), ('interval_number_check', "CHECK(interval_number > 0)", "The interval number should be greater than 0"), ] @@ -164,29 +170,35 @@ class HolidaysAllocation(models.Model): # As we encode everything in days in the database we need to convert # the number of hours into days for this we use the # mean number of hours set on the employee's calendar - days_to_give = days_to_give / holiday.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY - - values['number_of_days_temp'] = holiday.number_of_days_temp + days_to_give * prorata + days_to_give = days_to_give / (holiday.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY) + values['number_of_days'] = holiday.number_of_days + days_to_give * prorata if holiday.accrual_limit > 0: - values['number_of_days_temp'] = min(values['number_of_days_temp'], holiday.accrual_limit) - - values['number_of_hours'] = values['number_of_days_temp'] * holiday.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY + values['number_of_days'] = min(values['number_of_days'], holiday.accrual_limit) holiday.write(values) @api.multi - @api.depends('number_of_days_temp', 'type_request_unit', 'number_of_hours', 'holiday_status_id', 'employee_id') - def _compute_number_of_days(self): - for holiday in self: - number_of_days = holiday.number_of_days_temp - if holiday.type_request_unit == 'hour': - # In this case we need the number of days to reflect the number of hours taken - number_of_days = holiday.number_of_hours / holiday.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY - if holiday.accrual_limit > 0: - number_of_days = min(number_of_days, holiday.accrual_limit) + @api.depends('number_of_days') + def _compute_number_of_days_display(self): + for allocation in self: + allocation.number_of_days_display = allocation.number_of_days - holiday.number_of_days = number_of_days + @api.multi + def _inverse_number_of_days_display(self): + for allocation in self: + allocation.number_of_days = allocation.number_of_days_display + + @api.multi + @api.depends('number_of_days', 'employee_id') + def _compute_number_of_hours_display(self): + for allocation in self: + allocation.number_of_hours_display = allocation.number_of_days * (allocation.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY) + + @api.multi + def _inverse_number_of_hours_display(self): + for allocation in self: + allocation.number_of_days = allocation.number_of_hours_display / (allocation.employee_id.resource_calendar_id.hours_per_day or HOURS_PER_DAY) @api.multi @api.depends('state', 'employee_id', 'department_id') @@ -230,20 +242,15 @@ class HolidaysAllocation(models.Model): if self.holiday_type == 'employee': self.department_id = self.employee_id.department_id - @api.onchange('number_of_days_temp') - def _onchange_number_of_days_temp(self): - self.number_of_hours = self.number_of_days_temp * self.employee_id.resource_calendar_id.hours_per_day - - @api.onchange('number_of_hours') - def _onchange_number_of_hours(self): - self.number_of_days_temp = self.number_of_hours / self.employee_id.resource_calendar_id.hours_per_day - @api.onchange('holiday_status_id') def _onchange_holiday_status_id(self): - self.date_to = datetime.combine(self.holiday_status_id.validity_stop, time.max) + if self.holiday_status_id.validity_stop and self.date_to: + new_date_to = datetime.combine(self.holiday_status_id.validity_stop, time.max) + if new_date_to < self.date_to: + self.date_to = new_date_to if self.accrual: - self.number_of_days_temp = 0 + self.number_of_days = 0 if self.holiday_status_id.request_unit == 'hour': self.unit_per_interval = 'hours' @@ -264,9 +271,9 @@ class HolidaysAllocation(models.Model): res = [] for leave in self: if leave.type_request_unit == 'hour': - res.append((leave.id, _("Allocation of %s : %.2f hour(s) To %s") % (leave.holiday_status_id.name, leave.number_of_hours, leave.employee_id.name))) + res.append((leave.id, _("Allocation of %s : %.2f hour(s) To %s") % (leave.holiday_status_id.name, leave.number_of_hours_display, leave.employee_id.name))) else: - res.append((leave.id, _("Allocation of %s : %.2f day(s) To %s") % (leave.holiday_status_id.name, leave.number_of_days_temp, leave.employee_id.name))) + res.append((leave.id, _("Allocation of %s : %.2f day(s) To %s") % (leave.holiday_status_id.name, leave.number_of_days, leave.employee_id.name))) return res @api.multi @@ -332,7 +339,7 @@ class HolidaysAllocation(models.Model): 'holiday_type': 'employee', 'holiday_status_id': self.holiday_status_id.id, 'notes': self.notes, - 'number_of_days_temp': self.number_of_days_temp, + 'number_of_days': self.number_of_days, 'parent_id': self.id, 'employee_id': employee.id } diff --git a/addons/hr_holidays/models/hr_leave_type.py b/addons/hr_holidays/models/hr_leave_type.py index 83d81af70c6..a5101ace28c 100644 --- a/addons/hr_holidays/models/hr_leave_type.py +++ b/addons/hr_holidays/models/hr_leave_type.py @@ -133,10 +133,10 @@ class HolidaysType(models.Model): for request in requests: status_dict = result[request.holiday_status_id.id] - status_dict['virtual_remaining_leaves'] -= request.number_of_days_temp + status_dict['virtual_remaining_leaves'] -= request.number_of_days if request.state == 'validate': - status_dict['leaves_taken'] += request.number_of_days_temp - status_dict['remaining_leaves'] -= request.number_of_days_temp + status_dict['leaves_taken'] += request.number_of_days + status_dict['remaining_leaves'] -= request.number_of_days for allocation in allocations: status_dict = result[allocation.holiday_status_id.id] @@ -144,9 +144,9 @@ class HolidaysType(models.Model): # note: add only validated allocation even for the virtual # count; otherwise pending then refused allocation allow # the employee to create more leaves than possible - status_dict['virtual_remaining_leaves'] += allocation.number_of_days_temp - status_dict['max_leaves'] += allocation.number_of_days_temp - status_dict['remaining_leaves'] += allocation.number_of_days_temp + status_dict['virtual_remaining_leaves'] += allocation.number_of_days + status_dict['max_leaves'] += allocation.number_of_days + status_dict['remaining_leaves'] += allocation.number_of_days return result @@ -173,10 +173,10 @@ class HolidaysType(models.Model): grouped_res = self.env['hr.leave.allocation'].read_group( [('holiday_status_id', 'in', self.ids), ('holiday_type', '!=', 'employee'), ('state', '=', 'validate'), ('date_from', '>=', fields.Datetime.to_string(datetime.datetime.now().replace(month=1, day=1, hour=0, minute=0, second=0, microsecond=0)))], - ['holiday_status_id', 'number_of_days_temp'], + ['holiday_status_id', 'number_of_days'], ['holiday_status_id'], ) - grouped_dict = dict((data['holiday_status_id'][0], data['number_of_days_temp']) for data in grouped_res) + grouped_dict = dict((data['holiday_status_id'][0], data['number_of_days']) for data in grouped_res) for allocation in self: allocation.group_days_allocation = grouped_dict.get(allocation.id, 0) diff --git a/addons/hr_holidays/report/holidays_summary_report.py b/addons/hr_holidays/report/holidays_summary_report.py index 1f75ea51fae..3337acc7af9 100644 --- a/addons/hr_holidays/report/holidays_summary_report.py +++ b/addons/hr_holidays/report/holidays_summary_report.py @@ -74,7 +74,7 @@ class HrHolidaySummaryReport(models.AbstractModel): if date_from >= start_date and date_from <= end_date: res[(date_from-start_date).days]['color'] = holiday.holiday_status_id.color_name date_from += timedelta(1) - count += abs(holiday.number_of_days) + count += holiday.number_of_days self.sum = count return res diff --git a/addons/hr_holidays/report/hr_leave_report.py b/addons/hr_holidays/report/hr_leave_report.py index 50f4c1a69ca..cbef7ec4b20 100644 --- a/addons/hr_holidays/report/hr_leave_report.py +++ b/addons/hr_holidays/report/hr_leave_report.py @@ -65,7 +65,7 @@ class LeaveReport(models.Model): union all select request.employee_id as employee_id, request.name as name, - request.number_of_days as number_of_days, + (request.number_of_days * -1) as number_of_days, request.category_id as category_id, request.department_id as department_id, request.holiday_status_id as holiday_status_id, diff --git a/addons/hr_holidays/tests/test_access_rights.py b/addons/hr_holidays/tests/test_access_rights.py index 997bbf5bbcc..cf4e8f76ad8 100644 --- a/addons/hr_holidays/tests/test_access_rights.py +++ b/addons/hr_holidays/tests/test_access_rights.py @@ -30,7 +30,7 @@ class TestLeavesRights(TestHrHolidaysBase): 'employee_id': self.employee_emp.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') @@ -60,9 +60,9 @@ class TestLeavesRights(TestHrHolidaysBase): 'employee_id': self.employee_hruser.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) - res = other_leave.sudo(self.user_employee_id).read(['number_of_days_temp', 'state', 'name']) + res = other_leave.sudo(self.user_employee_id).read(['number_of_days', 'state', 'name']) self.assertEqual( res[0]['name'], '*****', 'Private information should have been stripped, received %s instead' % res[0]['name'] @@ -78,7 +78,7 @@ class TestLeavesRights(TestHrHolidaysBase): 'employee_id': self.employee_hruser.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) self.assertEqual( other_leave.sudo(self.user_employee_id).name, '*****', @@ -88,7 +88,7 @@ class TestLeavesRights(TestHrHolidaysBase): @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') def test_leave_read_by_user_own(self): """ Users should be able to read name field of own requests """ - res = self.employee_leave.read(['name', 'number_of_days_temp', 'state']) + res = self.employee_leave.read(['name', 'number_of_days', 'state']) self.assertEqual(res[0]['name'], 'Test') @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') @@ -112,7 +112,7 @@ class TestLeavesRights(TestHrHolidaysBase): 'employee_id': self.employee_hruser.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) with self.assertRaises(AccessError): other_leave.sudo(self.user_employee_id).write({'name': 'Crocodile Dundee is my man'}) @@ -131,7 +131,7 @@ class TestLeavesRights(TestHrHolidaysBase): 'employee_id': self.employee_hrmanager.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) manager_leave.sudo(self.user_hrmanager).action_draft() @@ -150,7 +150,7 @@ class TestLeavesRights(TestHrHolidaysBase): 'employee_id': self.employee_hruser.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) officer_leave.sudo(self.user_hruser).action_draft() @@ -175,7 +175,7 @@ class TestLeavesRights(TestHrHolidaysBase): 'employee_id': self.employee_hruser.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) with self.assertRaises(UserError): other_leave.sudo(self.user_employee_id).action_draft() @@ -330,7 +330,7 @@ class TestMultiCompany(TestHrHolidaysBase): 'employee_id': self.employee_emp.id, 'date_from': datetime.now(), 'date_to': datetime.now() + relativedelta(days=1), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) @mute_logger('odoo.models.unlink', 'odoo.addons.mail.models.mail_mail') diff --git a/addons/hr_holidays/tests/test_accrual_allocations.py b/addons/hr_holidays/tests/test_accrual_allocations.py index 06ce87d49be..c877643cc2e 100644 --- a/addons/hr_holidays/tests/test_accrual_allocations.py +++ b/addons/hr_holidays/tests/test_accrual_allocations.py @@ -50,7 +50,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 1, 'interval_number': 1, 'unit_per_interval': 'days', @@ -68,7 +68,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_hruser_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 1, 'interval_number': 1, 'unit_per_interval': 'days', @@ -87,7 +87,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'holiday_status_id': self.unpaid_type.id, 'date_from': datetime.combine(df, time(0, 0, 0)), 'date_to': datetime.combine(df + relativedelta(days=1), time(0, 0, 0)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) leave.action_approve() @@ -107,7 +107,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 1, 'interval_number': 2, 'unit_per_interval': 'days', @@ -119,7 +119,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 4, 'interval_number': 1, 'unit_per_interval': 'hours', @@ -131,7 +131,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 2, 'interval_number': 1, 'unit_per_interval': 'days', @@ -143,7 +143,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 20, 'interval_number': 1, 'unit_per_interval': 'days', @@ -173,7 +173,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 1, 'interval_number': 1, 'unit_per_interval': 'days', @@ -193,7 +193,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, 'accrual': True, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 1, 'interval_number': 2, 'unit_per_interval': 'days', @@ -215,7 +215,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'name': '20 days per year', 'employee_id': self.employee_emp_id, 'holiday_status_id': self.accrual_type.id, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 20, 'interval_number': 1, 'unit_per_interval': 'days', @@ -237,7 +237,7 @@ class TestAccrualAllocations(TestHrHolidaysBase): 'holiday_status_id': self.accrual_type.id, 'accrual': True, 'accrual_limit': 5, - 'number_of_days_temp': 0, + 'number_of_days': 0, 'number_per_interval': 6, 'interval_number': 1, 'unit_per_interval': 'days', diff --git a/addons/hr_holidays/tests/test_holidays_flow.py b/addons/hr_holidays/tests/test_holidays_flow.py index 03cf5b2b7a0..51bcafe049c 100644 --- a/addons/hr_holidays/tests/test_holidays_flow.py +++ b/addons/hr_holidays/tests/test_holidays_flow.py @@ -81,7 +81,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_1.id, 'date_from': (datetime.today() - relativedelta(days=1)), 'date_to': datetime.today(), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) hol1_user_group = hol1_employee_group.sudo(self.user_hruser_id) hol1_manager_group = hol1_employee_group.sudo(self.user_hrmanager_id) @@ -101,7 +101,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_3.id, 'date_from': (datetime.today() + relativedelta(days=12)), 'date_to': (datetime.today() + relativedelta(days=13)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) hol12_user_group = hol12_employee_group.sudo(self.user_hruser_id) hol12_manager_group = hol12_employee_group.sudo(self.user_hrmanager_id) @@ -126,7 +126,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_1.id, 'date_from': (datetime.today() - relativedelta(days=1)).strftime('%Y-%m-%d %H:%M'), 'date_to': datetime.today(), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) # Employee creates a leave request in a limited category -> crash, not enough days left @@ -137,7 +137,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_2.id, 'date_from': (datetime.today() + relativedelta(days=1)).strftime('%Y-%m-%d %H:%M'), 'date_to': (datetime.today() + relativedelta(days=2)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) # Clean transaction @@ -148,7 +148,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'name': 'Days for limited category', 'employee_id': self.employee_emp_id, 'holiday_status_id': self.holidays_status_2.id, - 'number_of_days_temp': 2, + 'number_of_days': 2, }) # HrUser validates the first step aloc1_user_group.action_approve() @@ -166,7 +166,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_2.id, 'date_from': (datetime.today() + relativedelta(days=2)).strftime('%Y-%m-%d %H:%M'), 'date_to': (datetime.today() + relativedelta(days=3)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) hol2_user_group = hol2.sudo(self.user_hruser_id) # Check left days: - 1 virtual remaining day @@ -205,7 +205,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): hol2_manager_group.write({ 'date_from': (datetime.today() + relativedelta(days=4)).strftime('%Y-%m-%d %H:%M'), 'date_to': (datetime.today() + relativedelta(days=7)), - 'number_of_days_temp': 4, + 'number_of_days': 4, }) with self.assertRaises(ValidationError): hol2_manager_group.action_confirm() @@ -220,7 +220,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'date_from': datetime.today().strftime('%Y-%m-10 10:00:00'), 'date_to': datetime.today().strftime('%Y-%m-11 19:00:00'), 'employee_id': employee_id, - 'number_of_days_temp': 1, + 'number_of_days': 1, }) # I find a small mistake on my leave request to I click on "Refuse" button to correct a mistake. hol3.action_refuse() @@ -242,7 +242,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'date_from': fields.Datetime.from_string('2017-03-03 06:00:00'), 'date_to': fields.Datetime.from_string('2017-03-11 19:00:00'), 'employee_id': employee_id, - 'number_of_days_temp': 1, + 'number_of_days': 1, }).unlink() with self.assertRaises(ValidationError): @@ -252,7 +252,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'date_from': fields.Datetime.from_string('2017-07-03 06:00:00'), 'date_to': fields.Datetime.from_string('2017-07-11 19:00:00'), 'employee_id': employee_id, - 'number_of_days_temp': 1, + 'number_of_days': 1, }) hol41 = HolidaysEmployeeGroup.create({ @@ -261,7 +261,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_1.id, 'date_from': (datetime.today() + relativedelta(days=9)).strftime('%Y-%m-%d %H:%M'), 'date_to': (datetime.today() + relativedelta(days=10)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) # A simple user should be able to reset it's own leave @@ -274,7 +274,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_1.id, 'date_from': (datetime.today() + relativedelta(days=9)).strftime('%Y-%m-%d %H:%M'), 'date_to': (datetime.today() + relativedelta(days=10)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) # A manager should be able to reset someone else's leave @@ -288,7 +288,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_1.id, 'date_from': (datetime.today() + relativedelta(days=15)).strftime('%Y-%m-%d %H:%M'), 'date_to': (datetime.today() + relativedelta(days=16)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) hol51.action_approve() @@ -300,7 +300,7 @@ class TestHolidaysFlow(TestHrHolidaysBase): 'holiday_status_id': self.holidays_status_1.id, 'date_from': (datetime.today() + relativedelta(days=15)).strftime('%Y-%m-%d %H:%M'), 'date_to': (datetime.today() + relativedelta(days=16)), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) hol52.action_approve() diff --git a/addons/hr_holidays/tests/test_hr_leave_type.py b/addons/hr_holidays/tests/test_hr_leave_type.py index 72fbaa4aee6..495d1aa2e4b 100644 --- a/addons/hr_holidays/tests/test_hr_leave_type.py +++ b/addons/hr_holidays/tests/test_hr_leave_type.py @@ -22,7 +22,7 @@ class TestHrLeaveType(TestHrHolidaysBase): 'holiday_status_id': leave_type.id, 'date_from': (datetime.today() - relativedelta(days=1)), 'date_to': datetime.today(), - 'number_of_days_temp': 1, + 'number_of_days': 1, }) leave_1.action_approve() diff --git a/addons/hr_holidays/views/hr_leave_allocation_views.xml b/addons/hr_holidays/views/hr_leave_allocation_views.xml index dd167e073c7..1922cb0b8d7 100644 --- a/addons/hr_holidays/views/hr_leave_allocation_views.xml +++ b/addons/hr_holidays/views/hr_leave_allocation_views.xml @@ -70,17 +70,17 @@ -