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"/>
+
+
+
+
+
- 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
-
-