[IMP] hr_holidays_timeoff_analysis : apply changes proposed by pre-commit
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
|
.ruff_cache/
|
||||||
*.*~
|
*.*~
|
||||||
*.pyc
|
*.pyc
|
||||||
|
|||||||
@@ -49,12 +49,9 @@ repos:
|
|||||||
$(git rev-parse --show-toplevel))"'
|
$(git rev-parse --show-toplevel))"'
|
||||||
- id: oca-gen-addon-readme
|
- id: oca-gen-addon-readme
|
||||||
entry:
|
entry:
|
||||||
bash -c 'oca-gen-addon-readme
|
bash -c 'oca-gen-addon-readme --addons-dir=. --branch=$(git symbolic-ref
|
||||||
--addons-dir=.
|
|
||||||
--branch=$(git symbolic-ref
|
|
||||||
refs/remotes/origin/HEAD | sed "s@^refs/remotes/origin/@@")
|
refs/remotes/origin/HEAD | sed "s@^refs/remotes/origin/@@")
|
||||||
--repo-name=$(basename $(git rev-parse --show-toplevel))
|
--repo-name=$(basename $(git rev-parse --show-toplevel)) --org-name="Elabore"
|
||||||
--org-name="Elabore"
|
|
||||||
--if-source-changed --keep-source-digest'
|
--if-source-changed --keep-source-digest'
|
||||||
|
|
||||||
- repo: https://github.com/OCA/odoo-pre-commit-hooks
|
- repo: https://github.com/OCA/odoo-pre-commit-hooks
|
||||||
|
|||||||
2
hr_holidays_timeoff_analysis/.gitignore
vendored
2
hr_holidays_timeoff_analysis/.gitignore
vendored
@@ -1,2 +1,2 @@
|
|||||||
*.*~
|
*.*~
|
||||||
*pyc
|
*pyc
|
||||||
|
|||||||
@@ -1,4 +1 @@
|
|||||||
from . import models
|
from . import models
|
||||||
from . import tests
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,16 @@
|
|||||||
"name": "hr_holidays_timeoff_analysis",
|
"name": "hr_holidays_timeoff_analysis",
|
||||||
"version": "18.0.1.0.0",
|
"version": "18.0.1.0.0",
|
||||||
"author": "Elabore",
|
"author": "Elabore",
|
||||||
"website": "https://elabore.coop",
|
"website": "https://git.elabore.coop/elabore/hr-tools",
|
||||||
"maintainer": "Elabore",
|
"maintainer": "Elabore",
|
||||||
"license": "AGPL-3",
|
"license": "AGPL-3",
|
||||||
"category": "HR",
|
"category": "HR",
|
||||||
"summary": "indicate day by day if a date is timeoff or not and generate an analyses pivot by employee",
|
"summary": "indicate day by day if a date is timeoff or not and "
|
||||||
|
"generate an analyses pivot by employee",
|
||||||
# any module necessary for this one to work correctly
|
# any module necessary for this one to work correctly
|
||||||
"depends": [
|
"depends": [
|
||||||
"base","hr_holidays",
|
"base",
|
||||||
|
"hr_holidays",
|
||||||
],
|
],
|
||||||
"qweb": [],
|
"qweb": [],
|
||||||
"external_dependencies": {
|
"external_dependencies": {
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
<odoo>
|
<odoo noupdate="1">
|
||||||
<data noupdate="1">
|
<record id="ir_cron_create_timeoff_day" model="ir.cron">
|
||||||
<record id="ir_cron_create_timeoff_day" model="ir.cron">
|
<field name="name">Create and update Timeoff Days</field>
|
||||||
<field name="name">Create and update Timeoff Days</field>
|
<field name="model_id" ref="model_hr_leave_timeoff_day" />
|
||||||
<field name="model_id" ref="model_hr_leave_timeoff_day" />
|
<field name="state">code</field>
|
||||||
<field name="state">code</field>
|
<field name="code">model.cron_manage_timeoff_days()</field>
|
||||||
<field name="code">model.cron_manage_timeoff_days()</field>
|
<field name="interval_number">1</field>
|
||||||
<field name="interval_number">1</field>
|
<field name="interval_type">days</field>
|
||||||
<field name="interval_type">days</field>
|
<field name="numbercall">-1</field>
|
||||||
<field name="numbercall">-1</field>
|
<field name="active">True</field>
|
||||||
<field name="active">True</field>
|
</record>
|
||||||
</record>
|
</odoo>
|
||||||
</data>
|
|
||||||
</odoo>
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
from . import hr_leave_timeoff_day
|
from . import hr_leave_timeoff_day
|
||||||
|
|||||||
@@ -1,20 +1,25 @@
|
|||||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
from odoo import fields, models, api
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
from odoo import api, fields, models
|
||||||
|
|
||||||
|
|
||||||
class TimeOffDay(models.Model):
|
class TimeOffDay(models.Model):
|
||||||
_name = 'hr.leave.timeoff.day'
|
_name = "hr.leave.timeoff.day"
|
||||||
_description = 'Timeoff Day'
|
_description = "Timeoff Day"
|
||||||
_order = 'date desc'
|
_order = "date desc"
|
||||||
|
|
||||||
date = fields.Date()
|
date = fields.Date()
|
||||||
employee_id = fields.Many2one('hr.employee')
|
employee_id = fields.Many2one("hr.employee")
|
||||||
hr_leave_id = fields.Many2one('hr.leave')
|
hr_leave_id = fields.Many2one("hr.leave")
|
||||||
hr_leave_type = fields.Many2one(related='hr_leave_id.holiday_status_id', store=True)
|
hr_leave_type = fields.Many2one(related="hr_leave_id.holiday_status_id", store=True)
|
||||||
leave_duration_by_day = fields.Float()
|
leave_duration_by_day = fields.Float()
|
||||||
|
|
||||||
def employee_is_scheduled_to_work_this_day(self, date, employee):
|
def employee_is_scheduled_to_work_this_day(self, date, employee):
|
||||||
""" Check if the employee is scheduled to work on this day according to his calendar """
|
"""
|
||||||
|
Check if the employee is scheduled to work on this day according to his
|
||||||
|
calendar.
|
||||||
|
"""
|
||||||
calendar = employee.resource_calendar_id
|
calendar = employee.resource_calendar_id
|
||||||
if not calendar or not calendar.attendance_ids:
|
if not calendar or not calendar.attendance_ids:
|
||||||
return False
|
return False
|
||||||
@@ -23,21 +28,28 @@ class TimeOffDay(models.Model):
|
|||||||
lambda att: att.dayofweek == day_of_week
|
lambda att: att.dayofweek == day_of_week
|
||||||
)
|
)
|
||||||
return bool(attendances)
|
return bool(attendances)
|
||||||
|
|
||||||
def is_a_public_holiday(self, date, employee):
|
def is_a_public_holiday(self, date, employee):
|
||||||
""" Check if the day is a public holiday """
|
"""
|
||||||
# public holidays start the day before in database (ex: date_from : 7mai 22:00 and date_to : 8mai 23:59 for 8mai public holiday) )
|
Check if the day is a public holiday.
|
||||||
public_holidays = self.env['resource.calendar.leaves'].search([
|
"""
|
||||||
('date_from', '<=', date-timedelta(days=1)),
|
# public holidays start the day before in database
|
||||||
('date_to', '>=', date),
|
# (ex: date_from : 7mai 22:00 and date_to : 8mai 23:59 for 8mai public holiday))
|
||||||
('resource_id', '=', False) # resource_id is null for public holiday
|
public_holidays = self.env["resource.calendar.leaves"].search(
|
||||||
])
|
[
|
||||||
|
("date_from", "<=", date - timedelta(days=1)),
|
||||||
|
("date_to", ">=", date),
|
||||||
|
("resource_id", "=", False), # resource_id is null for public holiday
|
||||||
|
]
|
||||||
|
)
|
||||||
if public_holidays:
|
if public_holidays:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def compute_leave_duration_by_day(self, leave):
|
def compute_leave_duration_by_day(self, leave):
|
||||||
""" Compute the leave duration by day based on the leave type """
|
"""
|
||||||
|
Compute the leave duration by day based on the leave type.
|
||||||
|
"""
|
||||||
leave_duration_by_day = 0.0
|
leave_duration_by_day = 0.0
|
||||||
# Full day case
|
# Full day case
|
||||||
if leave.request_unit_half:
|
if leave.request_unit_half:
|
||||||
@@ -55,46 +67,64 @@ class TimeOffDay(models.Model):
|
|||||||
|
|
||||||
def cron_create_timeoff_days(self):
|
def cron_create_timeoff_days(self):
|
||||||
# Browse all validated leaves
|
# Browse all validated leaves
|
||||||
leaves = self.env['hr.leave'].search([
|
leaves = self.env["hr.leave"].search(
|
||||||
('state', '=', 'validate'),
|
[
|
||||||
('request_date_from', '!=', False),
|
("state", "=", "validate"),
|
||||||
('request_date_to', '!=', False),
|
("request_date_from", "!=", False),
|
||||||
('employee_id', '!=', False),
|
("request_date_to", "!=", False),
|
||||||
])
|
("employee_id", "!=", False),
|
||||||
|
]
|
||||||
|
)
|
||||||
for leave in leaves:
|
for leave in leaves:
|
||||||
current_date = leave.request_date_from
|
current_date = leave.request_date_from
|
||||||
employee = leave.employee_id
|
employee = leave.employee_id
|
||||||
while current_date <= leave.request_date_to:
|
while current_date <= leave.request_date_to:
|
||||||
if self.employee_is_scheduled_to_work_this_day(current_date, employee) and not self.is_a_public_holiday(current_date, employee):
|
if self.employee_is_scheduled_to_work_this_day(
|
||||||
# The employee is scheluded to work this day according his calendar and it's not a public holiday,
|
current_date, employee
|
||||||
|
) and not self.is_a_public_holiday(current_date, employee):
|
||||||
|
# The employee is scheluded to work this day according his calendar
|
||||||
|
# and it's not a public holiday,
|
||||||
# so create a timeoff day record if it does not already exist
|
# so create a timeoff day record if it does not already exist
|
||||||
if not self.search([
|
if not self.search(
|
||||||
('date', '=', current_date),
|
[
|
||||||
('employee_id', '=', employee.id),
|
("date", "=", current_date),
|
||||||
('hr_leave_id', '=', leave.id),
|
("employee_id", "=", employee.id),
|
||||||
], limit=1):
|
("hr_leave_id", "=", leave.id),
|
||||||
self.create({
|
],
|
||||||
'date': current_date,
|
limit=1,
|
||||||
'employee_id': employee.id,
|
):
|
||||||
'hr_leave_id': leave.id,
|
self.create(
|
||||||
'leave_duration_by_day': self.compute_leave_duration_by_day(leave),
|
{
|
||||||
})
|
"date": current_date,
|
||||||
|
"employee_id": employee.id,
|
||||||
|
"hr_leave_id": leave.id,
|
||||||
|
"leave_duration_by_day": self.compute_leave_duration_by_day( # noqa: E501
|
||||||
|
leave
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
current_date += timedelta(days=1)
|
current_date += timedelta(days=1)
|
||||||
|
|
||||||
def cron_delete_timeoff_days(self):
|
def cron_delete_timeoff_days(self):
|
||||||
# Browse all unvalidated leaves
|
# Browse all unvalidated leaves
|
||||||
leaves = self.env['hr.leave'].search([
|
leaves = self.env["hr.leave"].search(
|
||||||
('state', '!=', 'validate'),
|
[
|
||||||
('request_date_from', '!=', False),
|
("state", "!=", "validate"),
|
||||||
('request_date_to', '!=', False),
|
("request_date_from", "!=", False),
|
||||||
('employee_id', '!=', False),
|
("request_date_to", "!=", False),
|
||||||
])
|
("employee_id", "!=", False),
|
||||||
|
]
|
||||||
|
)
|
||||||
# Delete timeoff days for leaves that are no longer validated
|
# Delete timeoff days for leaves that are no longer validated
|
||||||
for leave in leaves:
|
for leave in leaves:
|
||||||
self.search([
|
self.search(
|
||||||
('hr_leave_id', '=', leave.id),
|
[
|
||||||
]).unlink()
|
("hr_leave_id", "=", leave.id),
|
||||||
|
]
|
||||||
|
).unlink()
|
||||||
# Delete timeoff days that are not linked to any leave
|
# Delete timeoff days that are not linked to any leave
|
||||||
self.search([
|
self.search(
|
||||||
('hr_leave_id', '=', False),
|
[
|
||||||
]).unlink()
|
("hr_leave_id", "=", False),
|
||||||
|
]
|
||||||
|
).unlink()
|
||||||
|
|||||||
@@ -1,3 +1 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
from . import test_hr_leave_timeoff_day
|
from . import test_hr_leave_timeoff_day
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
from odoo.fields import Date
|
from odoo.fields import Date
|
||||||
from odoo.tests import tagged
|
from odoo.tests import tagged
|
||||||
from odoo.tests.common import TransactionCase
|
from odoo.tests.common import TransactionCase
|
||||||
@@ -96,21 +95,123 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_leave_duration_by_day_hour_compare_to_employee_calendar(self):
|
def test_leave_duration_by_day_hour_compare_to_employee_calendar(self):
|
||||||
employee_calendar = self.env['resource.calendar'].create({
|
employee_calendar = self.env["resource.calendar"].create(
|
||||||
'name': 'Employee Calendar',
|
{
|
||||||
'attendance_ids': [
|
"name": "Employee Calendar",
|
||||||
(0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
"attendance_ids": [
|
||||||
(0, 0, {'name': 'Monday Afternoon', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
(
|
||||||
(0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
0,
|
||||||
(0, 0, {'name': 'Tuesday Afternoon', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
0,
|
||||||
(0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
{
|
||||||
(0, 0, {'name': 'Wednesday Afternoon', 'dayofweek': '2', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
"name": "Monday Morning",
|
||||||
(0, 0, {'name': 'Thursday Morning', 'dayofweek': '3', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
"dayofweek": "0",
|
||||||
(0, 0, {'name': 'Thursday Afternoon', 'dayofweek': '3', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
"hour_from": 8,
|
||||||
(0, 0, {'name': 'Friday Morning', 'dayofweek': '4', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
"hour_to": 12,
|
||||||
(0, 0, {'name': 'Friday Afternoon', 'dayofweek': '4', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
"day_period": "morning",
|
||||||
],
|
},
|
||||||
})
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Monday Afternoon",
|
||||||
|
"dayofweek": "0",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Tuesday Morning",
|
||||||
|
"dayofweek": "1",
|
||||||
|
"hour_from": 8,
|
||||||
|
"hour_to": 12,
|
||||||
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Tuesday Afternoon",
|
||||||
|
"dayofweek": "1",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Wednesday Morning",
|
||||||
|
"dayofweek": "2",
|
||||||
|
"hour_from": 8,
|
||||||
|
"hour_to": 12,
|
||||||
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Wednesday Afternoon",
|
||||||
|
"dayofweek": "2",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Thursday Morning",
|
||||||
|
"dayofweek": "3",
|
||||||
|
"hour_from": 8,
|
||||||
|
"hour_to": 12,
|
||||||
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Thursday Afternoon",
|
||||||
|
"dayofweek": "3",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Friday Morning",
|
||||||
|
"dayofweek": "4",
|
||||||
|
"hour_from": 8,
|
||||||
|
"hour_to": 12,
|
||||||
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Friday Afternoon",
|
||||||
|
"dayofweek": "4",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
self.employee.resource_calendar_id = employee_calendar
|
self.employee.resource_calendar_id = employee_calendar
|
||||||
|
|
||||||
leave = self.env["hr.leave"].create(
|
leave = self.env["hr.leave"].create(
|
||||||
@@ -119,7 +220,7 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
"request_date_from": Date.to_date("2025-07-03"),
|
"request_date_from": Date.to_date("2025-07-03"),
|
||||||
"request_date_to": Date.to_date("2025-07-03"),
|
"request_date_to": Date.to_date("2025-07-03"),
|
||||||
"request_unit_hours": True,
|
"request_unit_hours": True,
|
||||||
"request_hour_from":"8",
|
"request_hour_from": "8",
|
||||||
"request_hour_to": "12",
|
"request_hour_to": "12",
|
||||||
"holiday_status_id": self.time_off_hour_type.id,
|
"holiday_status_id": self.time_off_hour_type.id,
|
||||||
}
|
}
|
||||||
@@ -129,8 +230,6 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
leave._compute_number_of_days_display()
|
leave._compute_number_of_days_display()
|
||||||
leave.state = "validate" # Simulate the leave being validated
|
leave.state = "validate" # Simulate the leave being validated
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.env["hr.leave.timeoff.day"].cron_manage_timeoff_days()
|
self.env["hr.leave.timeoff.day"].cron_manage_timeoff_days()
|
||||||
timeoff_days = self.env["hr.leave.timeoff.day"].search(
|
timeoff_days = self.env["hr.leave.timeoff.day"].search(
|
||||||
[
|
[
|
||||||
@@ -150,19 +249,101 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_leave_duration_by_day_compare_to_time_part_employee_calendar(self):
|
def test_leave_duration_by_day_compare_to_time_part_employee_calendar(self):
|
||||||
employee_calendar = self.env['resource.calendar'].create({
|
employee_calendar = self.env["resource.calendar"].create(
|
||||||
'name': 'Employee Calendar',
|
{
|
||||||
'attendance_ids': [
|
"name": "Employee Calendar",
|
||||||
(0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
"attendance_ids": [
|
||||||
(0, 0, {'name': 'Monday Afternoon', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
(
|
||||||
(0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
0,
|
||||||
(0, 0, {'name': 'Tuesday Afternoon', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
0,
|
||||||
(0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
{
|
||||||
(0, 0, {'name': 'Wednesday Afternoon', 'dayofweek': '2', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
"name": "Monday Morning",
|
||||||
(0, 0, {'name': 'Thursday Morning', 'dayofweek': '3', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
"dayofweek": "0",
|
||||||
(0, 0, {'name': 'Thursday Afternoon', 'dayofweek': '3', 'hour_from': 13, 'hour_to': 17, 'day_period': 'afternoon'}),
|
"hour_from": 8,
|
||||||
],
|
"hour_to": 12,
|
||||||
})
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Monday Afternoon",
|
||||||
|
"dayofweek": "0",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Tuesday Morning",
|
||||||
|
"dayofweek": "1",
|
||||||
|
"hour_from": 8,
|
||||||
|
"hour_to": 12,
|
||||||
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Tuesday Afternoon",
|
||||||
|
"dayofweek": "1",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Wednesday Morning",
|
||||||
|
"dayofweek": "2",
|
||||||
|
"hour_from": 8,
|
||||||
|
"hour_to": 12,
|
||||||
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Wednesday Afternoon",
|
||||||
|
"dayofweek": "2",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Thursday Morning",
|
||||||
|
"dayofweek": "3",
|
||||||
|
"hour_from": 8,
|
||||||
|
"hour_to": 12,
|
||||||
|
"day_period": "morning",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
{
|
||||||
|
"name": "Thursday Afternoon",
|
||||||
|
"dayofweek": "3",
|
||||||
|
"hour_from": 13,
|
||||||
|
"hour_to": 17,
|
||||||
|
"day_period": "afternoon",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
)
|
||||||
self.employee.resource_calendar_id = employee_calendar
|
self.employee.resource_calendar_id = employee_calendar
|
||||||
|
|
||||||
leave = self.env["hr.leave"].create(
|
leave = self.env["hr.leave"].create(
|
||||||
@@ -194,7 +375,8 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_public_holidays_between_a_leave(self):
|
def test_public_holidays_between_a_leave(self):
|
||||||
# Leaves the code below commented because default database already has a public holiday on 8th May 2025
|
# Leaves the code below commented because
|
||||||
|
# the default database already has a public holiday on 8th May 2025
|
||||||
# self.env["resource.calendar.leaves"].create(
|
# self.env["resource.calendar.leaves"].create(
|
||||||
# {
|
# {
|
||||||
# "name": "8 mai 2025",
|
# "name": "8 mai 2025",
|
||||||
@@ -206,7 +388,9 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
{
|
{
|
||||||
"employee_id": self.employee.id,
|
"employee_id": self.employee.id,
|
||||||
"request_date_from": Date.to_date("2025-05-05"),
|
"request_date_from": Date.to_date("2025-05-05"),
|
||||||
"request_date_to": Date.to_date("2025-05-11"), #a public holiday is in between (8 may)
|
"request_date_to": Date.to_date(
|
||||||
|
"2025-05-11"
|
||||||
|
), # a public holiday is in between (8 may)
|
||||||
"holiday_status_id": self.time_off_type.id,
|
"holiday_status_id": self.time_off_type.id,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -267,7 +451,7 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(timeoff_days), 0, "There should be no timeoff days for this leave"
|
len(timeoff_days), 0, "There should be no timeoff days for this leave"
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_deleted_leave(self):
|
def test_deleted_leave(self):
|
||||||
leave = self.env["hr.leave"].create(
|
leave = self.env["hr.leave"].create(
|
||||||
{
|
{
|
||||||
@@ -305,4 +489,3 @@ class TestHrLeaveTimeoffDay(TransactionCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
len(timeoff_days), 0, "There should be no timeoff days for this leave"
|
len(timeoff_days), 0, "There should be no timeoff days for this leave"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
<?xml version='1.0' encoding='UTF-8'?>
|
<?xml version='1.0' encoding='UTF-8' ?>
|
||||||
<odoo>
|
<odoo>
|
||||||
<record id="hr_leave_timeoff_day_view_list" model="ir.ui.view">
|
<record id="hr_leave_timeoff_day_view_list" model="ir.ui.view">
|
||||||
<field name="model">hr.leave.timeoff.day</field>
|
<field name="model">hr.leave.timeoff.day</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<tree editable="bottom">
|
<tree editable="bottom">
|
||||||
<field name="date" />
|
<field name="date" />
|
||||||
<field name="employee_id" groups="base.group_user"/>
|
<field name="employee_id" groups="base.group_user" />
|
||||||
<field name="hr_leave_id"/>
|
<field name="hr_leave_id" />
|
||||||
<field name="hr_leave_type"/>
|
<field name="hr_leave_type" />
|
||||||
<field name="leave_duration_by_day"/>
|
<field name="leave_duration_by_day" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
<field name="model">hr.leave.timeoff.day</field>
|
<field name="model">hr.leave.timeoff.day</field>
|
||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<pivot string="Timeoff Days Analysis">
|
<pivot string="Timeoff Days Analysis">
|
||||||
<field name="date" type="col" interval="month"/>
|
<field name="date" type="col" interval="month" />
|
||||||
<field name="employee_id" type="row"/>
|
<field name="employee_id" type="row" />
|
||||||
<field name="hr_leave_type" type="row"/>
|
<field name="hr_leave_type" type="row" />
|
||||||
<field name="leave_duration_by_day" type="measure" />
|
<field name="leave_duration_by_day" type="measure" />
|
||||||
</pivot>
|
</pivot>
|
||||||
</field>
|
</field>
|
||||||
@@ -30,10 +30,14 @@
|
|||||||
<field name="arch" type="xml">
|
<field name="arch" type="xml">
|
||||||
<search string="Timeoff Days">
|
<search string="Timeoff Days">
|
||||||
<field name="date" />
|
<field name="date" />
|
||||||
<field name="employee_id" groups="base.group_user"/>
|
<field name="employee_id" groups="base.group_user" />
|
||||||
<separator />
|
<separator />
|
||||||
<filter name="filter_date" date="date" default_period="this_year"
|
<filter
|
||||||
string="Period" />
|
name="filter_date"
|
||||||
|
date="date"
|
||||||
|
default_period="this_year"
|
||||||
|
string="Period"
|
||||||
|
/>
|
||||||
</search>
|
</search>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
@@ -42,7 +46,7 @@
|
|||||||
<field name="name">Timeoff Days</field>
|
<field name="name">Timeoff Days</field>
|
||||||
<field name="res_model">hr.leave.timeoff.day</field>
|
<field name="res_model">hr.leave.timeoff.day</field>
|
||||||
<field name="view_mode">tree,form,pivot</field>
|
<field name="view_mode">tree,form,pivot</field>
|
||||||
<field name="search_view_id" ref="hr_leave_timeoff_day_view_search"/>
|
<field name="search_view_id" ref="hr_leave_timeoff_day_view_search" />
|
||||||
<field name="context">{'search_default_filter_date': True}</field>
|
<field name="context">{'search_default_filter_date': True}</field>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
@@ -52,6 +56,7 @@
|
|||||||
parent="hr_holidays.menu_hr_holidays_configuration"
|
parent="hr_holidays.menu_hr_holidays_configuration"
|
||||||
action="hr_leave_timeoff_day_action"
|
action="hr_leave_timeoff_day_action"
|
||||||
groups="hr_holidays.group_hr_holidays_manager"
|
groups="hr_holidays.group_hr_holidays_manager"
|
||||||
sequence="6"/>
|
sequence="6"
|
||||||
|
/>
|
||||||
|
|
||||||
</odoo>
|
</odoo>
|
||||||
|
|||||||
Reference in New Issue
Block a user