-
-
Notifications
You must be signed in to change notification settings - Fork 110
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e0c301c
commit d5920e7
Showing
10 changed files
with
349 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import models |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# Copyright 2023 Camptocamp SA | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) | ||
|
||
{ | ||
"name": "HR Holidays validator list", | ||
"summary": "Allow to add several leave validators", | ||
"author": "Victor Vermot, Odoo Community Association (OCA)", | ||
"website": "https://github.com/OCA/hr-holidays", | ||
"category": "Human Resources", | ||
"version": "14.0.1.0.0", | ||
"license": "AGPL-3", | ||
"depends": ["hr_holidays"], | ||
"data": [ | ||
"views/hr_views.xml" | ||
], | ||
"installable": True, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from . import hr_employee |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Copyright 2023 Camptocamp SA | ||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html) | ||
|
||
from odoo import fields, models | ||
|
||
|
||
class HrEmployeeBase(models.AbstractModel): | ||
_inherit = "hr.employee.base" | ||
|
||
leave_manager_ids = fields.Many2many( | ||
'res.users', | ||
string='Time Off', | ||
compute='_compute_leave_manager', | ||
store=True, | ||
readonly=False, | ||
help='Select the users responsible for approving "Time Off" of this employee.\n' | ||
'If empty, the approval is done by an Administrator or Approver (determined in settings/users).', | ||
) | ||
|
||
def create(self, values): | ||
res = super().create(values) | ||
return res | ||
|
||
def write(self, values): | ||
re = super().write(values) | ||
return re | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# -*- coding: utf-8 -*- | ||
# Part of Odoo. See LICENSE file for full copyright and licensing details. | ||
|
||
# Copyright (c) 2005-2006 Axelor SARL. (http://www.axelor.com) | ||
|
||
|
||
from odoo import models | ||
|
||
|
||
class HolidaysAllocation(models.Model): | ||
""" Allocation Requests Access specifications: similar to leave requests """ | ||
_inherit = "hr.leave.allocation" | ||
|
||
def _get_responsible_for_approval(self): | ||
print("Need to override it") | ||
|
||
def _check_approval_update(self, state): | ||
print("Need to override it") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
* Victor Vermot-Petit-Outhenin <[email protected]> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
This module allows for an employee to have several leave validators. |
Empty file.
266 changes: 266 additions & 0 deletions
266
hr_holidays_validator_list/tests/test_hr_holidays_validator_list.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,266 @@ | ||
# Copyright 2016-2019 Onestein (<https://www.onestein.eu>) | ||
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl). | ||
|
||
from datetime import datetime, timedelta | ||
|
||
from odoo.exceptions import UserError, ValidationError | ||
from odoo.tests import common | ||
|
||
|
||
class TestHolidaysLeaveRepeated(common.TransactionCase): | ||
def setUp(self): | ||
super().setUp() | ||
|
||
self.date_start = datetime(2016, 12, 5, 8, 0, 0, 0) | ||
self.date_end = datetime(2016, 12, 5, 18, 0, 0, 0) | ||
|
||
self.calendar = self.env["resource.calendar"].create({"name": "Calendar 1"}) | ||
|
||
for i in range(0, 7): | ||
self.env["resource.calendar.attendance"].create( | ||
{ | ||
"name": "Day " + str(i), | ||
"dayofweek": str(i), | ||
"hour_from": 8.0, | ||
"hour_to": 16.0, | ||
"calendar_id": self.calendar.id, | ||
} | ||
) | ||
|
||
self.employee_1 = self.env["hr.employee"].create( | ||
{"name": "Employee 1", "resource_calendar_id": self.calendar.id} | ||
) | ||
self.employee_2 = self.env["hr.employee"].create( | ||
{"name": "Employee 2", "resource_calendar_id": self.calendar.id} | ||
) | ||
self.employee_3 = self.env["hr.employee"].create( | ||
{"name": "Employee 3", "resource_calendar_id": self.calendar.id} | ||
) | ||
self.employee_4 = self.env["hr.employee"].create( | ||
{"name": "Employee 4", "resource_calendar_id": self.calendar.id} | ||
) | ||
self.employee_5 = self.env["hr.employee"].create( | ||
{"name": "Failing Employee", "resource_calendar_id": self.calendar.id} | ||
) | ||
|
||
self.status_1 = self.env["hr.leave.type"].create( | ||
{"name": "Repeating Status", "repeat": True, "validity_start": False} | ||
) | ||
|
||
self.leave_1 = self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "workday", | ||
"repeat_mode": "times", | ||
"repeat_limit": 5, | ||
"date_from": self.date_start, | ||
"date_to": self.date_end, | ||
"employee_id": self.employee_1.id, | ||
} | ||
) | ||
self.leave_2 = self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "week", | ||
"repeat_mode": "times", | ||
"repeat_limit": 4, | ||
"date_from": self.date_start, | ||
"date_to": self.date_end, | ||
"employee_id": self.employee_2.id, | ||
} | ||
) | ||
self.leave_3 = self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "biweek", | ||
"repeat_mode": "times", | ||
"repeat_limit": 3, | ||
"date_from": self.date_start, | ||
"date_to": self.date_end, | ||
"employee_id": self.employee_3.id, | ||
} | ||
) | ||
self.leave_4 = self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "month", | ||
"repeat_mode": "times", | ||
"repeat_limit": 2, | ||
"date_from": self.date_start, | ||
"date_to": self.date_end, | ||
"employee_id": self.employee_4.id, | ||
} | ||
) | ||
|
||
def test_01_count_repetitions(self): | ||
|
||
leave_1_list = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_1.id), | ||
] | ||
) | ||
leave_2_list = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_2.id), | ||
] | ||
) | ||
leave_3_list = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_3.id), | ||
] | ||
) | ||
leave_4_list = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_4.id), | ||
] | ||
) | ||
|
||
self.assertEqual(len(leave_1_list), 5) | ||
self.assertEqual(len(leave_2_list), 4) | ||
self.assertEqual(len(leave_3_list), 3) | ||
self.assertEqual(len(leave_4_list), 2) | ||
|
||
def test_02_workdays(self): | ||
for i in range(0, 5): | ||
check_from = self.date_start + timedelta(days=i) | ||
check_to = self.date_end + timedelta(days=i) | ||
leaves = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_1.id), | ||
("date_from", "=", check_from), | ||
("date_to", "=", check_to), | ||
] | ||
) | ||
self.assertEqual(len(leaves), 1) | ||
|
||
def test_03_weeks(self): | ||
|
||
for i in range(0, 4): | ||
check_from = self.date_start + timedelta(days=i * 7) | ||
check_to = self.date_end + timedelta(days=i * 7) | ||
leaves = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_2.id), | ||
("date_from", "=", check_from), | ||
("date_to", "=", check_to), | ||
] | ||
) | ||
self.assertEqual(len(leaves), 1) | ||
|
||
def test_04_biweeks(self): | ||
for i in range(0, 3): | ||
check_from = self.date_start + timedelta(days=i * 14) | ||
check_to = self.date_end + timedelta(days=i * 14) | ||
leaves = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_3.id), | ||
("date_from", "=", check_from), | ||
("date_to", "=", check_to), | ||
] | ||
) | ||
self.assertEqual(len(leaves), 1) | ||
|
||
def test_05_months(self): | ||
for i in range(0, 2): | ||
check_from = self.date_start + timedelta(days=i * 28) | ||
check_to = self.date_end + timedelta(days=i * 28) | ||
leaves = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_4.id), | ||
("date_from", "=", check_from), | ||
("date_to", "=", check_to), | ||
] | ||
) | ||
self.assertEqual(len(leaves), 1) | ||
|
||
def test_06_check_dates(self): | ||
with self.assertRaises(ValidationError): | ||
self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "workday", | ||
"repeat_limit": -1, | ||
"date_from": self.date_start, | ||
"date_to": self.date_end, | ||
"employee_id": self.employee_5.id, | ||
} | ||
) | ||
|
||
def test_07_check_dates(self): | ||
date_start = datetime(2019, 2, 18, 8, 0, 0, 0) | ||
date_end = datetime(2019, 2, 20, 18, 0, 0, 0) | ||
with self.assertRaises(UserError): | ||
self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "workday", | ||
"repeat_mode": "times", | ||
"repeat_limit": 5, | ||
"date_from": date_start, | ||
"date_to": date_end, | ||
"employee_id": self.employee_5.id, | ||
} | ||
) | ||
|
||
def test_08_workdays_with_weekend(self): | ||
date_start = datetime(2019, 3, 1, 8, 0, 0, 0) | ||
date_end = datetime(2019, 3, 1, 18, 0, 0, 0) | ||
self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "workday", | ||
"repeat_mode": "times", | ||
"repeat_limit": 5, | ||
"date_from": date_start, | ||
"date_to": date_end, | ||
"employee_id": self.employee_1.id, | ||
} | ||
) | ||
for i in range(0, 7): | ||
datetime_from = date_start + timedelta(days=i) | ||
datetime_to = date_end + timedelta(days=i) | ||
leaves = self.env["hr.leave"].search( | ||
[ | ||
("holiday_status_id", "=", self.status_1.id), | ||
("employee_id", "=", self.employee_1.id), | ||
("date_from", "=", datetime_from), | ||
("date_to", "=", datetime_to), | ||
] | ||
) | ||
if datetime_from.weekday() < 5: # is a weekday | ||
self.assertEqual(len(leaves), 1) | ||
else: # is weekend | ||
self.assertEqual(len(leaves), 0) | ||
|
||
def test_09_check_repeat_end_date(self): | ||
old_date = datetime(2019, 3, 18, 8, 0, 0, 0) | ||
date_start = datetime(2019, 2, 18, 8, 0, 0, 0) | ||
date_end = datetime(2019, 2, 18, 18, 0, 0, 0) | ||
with self.assertRaises(ValidationError): | ||
self.env["hr.leave"].create( | ||
{ | ||
"holiday_status_id": self.status_1.id, | ||
"holiday_type": "employee", | ||
"repeat_every": "workday", | ||
"repeat_mode": "date", | ||
"repeat_end_date": old_date, | ||
"date_from": date_start, | ||
"date_to": date_end, | ||
"employee_id": self.employee_5.id, | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
<?xml version='1.0' encoding='UTF-8'?> | ||
<odoo> | ||
<!-- Hr employee inherit Legal Leaves --> | ||
<record id="view_employee_form_leave_inherit" model="ir.ui.view"> | ||
<field name="name">hr.employee.leave.form.inherit</field> | ||
<field name="model">hr.employee</field> | ||
<field name="inherit_id" ref="hr_holidays.view_employee_form_leave_inherit"/> | ||
<field name="arch" type="xml"> | ||
<xpath expr="//field[@name='leave_manager_id']" position="attributes"> | ||
<attribute name="invisible">1</attribute> | ||
</xpath> | ||
<xpath expr="//group[@name='managers']" position="inside"> | ||
<field name="leave_manager_ids" /> | ||
</xpath> | ||
</field> | ||
</record> | ||
</odoo> |