1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from datetime import date, datetime
from pytz import utc, timezone
from odoo.addons.resource.models.utils import Intervals, sum_intervals
from odoo.fields import Date
from .common import TestContractCommon
class TestResource(TestContractCommon):
@classmethod
def setUpClass(cls):
super(TestResource, cls).setUpClass()
cls.calendar_richard = cls.env['resource.calendar'].create({'name': 'Calendar of Richard'})
cls.employee.resource_calendar_id = cls.calendar_richard
cls.calendar_35h = cls.env['resource.calendar'].create({
'name': '35h calendar',
'attendance_ids': [
(0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
(0, 0, {'name': 'Monday Lunch', 'dayofweek': '0', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
(0, 0, {'name': 'Monday Evening', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 16, 'day_period': 'afternoon'}),
(0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
(0, 0, {'name': 'Tuesday Lunch', 'dayofweek': '1', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
(0, 0, {'name': 'Tuesday Evening', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 16, 'day_period': 'afternoon'}),
(0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
(0, 0, {'name': 'Wednesday Lunch', 'dayofweek': '2', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
(0, 0, {'name': 'Wednesday Evening', 'dayofweek': '2', 'hour_from': 13, 'hour_to': 16, 'day_period': 'afternoon'}),
(0, 0, {'name': 'Thursday Morning', 'dayofweek': '3', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
(0, 0, {'name': 'Thursday Lunch', 'dayofweek': '3', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
(0, 0, {'name': 'Thursday Evening', 'dayofweek': '3', 'hour_from': 13, 'hour_to': 16, 'day_period': 'afternoon'}),
(0, 0, {'name': 'Friday Morning', 'dayofweek': '4', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
(0, 0, {'name': 'Friday Lunch', 'dayofweek': '4', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
(0, 0, {'name': 'Friday Evening', 'dayofweek': '4', 'hour_from': 13, 'hour_to': 16, 'day_period': 'afternoon'})
],
})
cls.contract_cdd = cls.env['hr.contract'].create({
'date_start': Date.to_date('2021-09-01'),
'date_end': Date.to_date('2021-10-31'),
'name': 'First CDD Contract for Richard',
'resource_calendar_id': cls.calendar_35h.id,
'wage': 5000.0,
'employee_id': cls.employee.id,
'state': 'open',
})
cls.contract_cdi = cls.env['hr.contract'].create({
'date_start': Date.to_date('2021-11-01'),
'name': 'CDI Contract for Richard',
'resource_calendar_id': cls.calendar_richard.id,
'wage': 5000.0,
'employee_id': cls.employee.id,
'state': 'draft',
'kanban_state': 'done',
})
def test_calendars_validity_within_period(self):
tz = timezone(self.employee.tz)
calendars = self.employee.resource_id._get_calendars_validity_within_period(
tz.localize(datetime(2021, 10, 1, 0, 0, 0)),
tz.localize(datetime(2021, 12, 1, 0, 0, 0)),
)
interval_35h = Intervals([(
tz.localize(datetime(2021, 10, 1, 0, 0, 0)),
tz.localize(datetime.combine(date(2021, 10, 31), datetime.max.time())),
self.env['resource.calendar.attendance']
)])
interval_40h = Intervals([(
tz.localize(datetime(2021, 11, 1, 0, 0, 0)),
tz.localize(datetime(2021, 12, 1, 0, 0, 0)),
self.env['resource.calendar.attendance']
)])
self.assertEqual(1, len(calendars), "The dict returned by calendars validity should only have 1 entry")
self.assertEqual(2, len(calendars[self.employee.resource_id.id]), "Jean should only have one calendar")
richard_entries = calendars[self.employee.resource_id.id]
for calendar in richard_entries:
self.assertTrue(calendar in (self.calendar_35h | self.calendar_richard), "Each calendar should be listed")
if calendar == self.calendar_35h:
self.assertFalse(richard_entries[calendar] - interval_35h, "Interval 35h should cover all calendar 35h validity")
self.assertFalse(interval_35h - richard_entries[calendar], "Calendar 35h validity should cover all interval 35h")
elif calendar == self.calendar_richard:
self.assertFalse(richard_entries[calendar] - interval_40h, "Interval 40h should cover all calendar 40h validity")
self.assertFalse(interval_40h - richard_entries[calendar], "Calendar 40h validity should cover all interval 40h")
def test_queries(self):
employees_test = self.env['hr.employee'].create([{
'name': 'Employee ' + str(i),
} for i in range(0, 50)])
for emp in employees_test:
new_contract = self.contract_cdd.copy()
new_contract.employee_id = emp
new_contract.state = 'open'
new_contract = self.contract_cdi.copy()
new_contract.employee_id = emp
new_contract.state = 'draft'
new_contract.kanban_state = 'done'
start = utc.localize(datetime(2021, 9, 1, 0, 0, 0))
end = utc.localize(datetime(2021, 11, 30, 23, 59, 59))
with self.assertQueryCount(15):
work_intervals, _ = (employees_test | self.employee).resource_id._get_valid_work_intervals(start, end)
self.assertEqual(len(work_intervals), 51)
def test_get_valid_work_intervals(self):
start = timezone(self.employee.tz).localize(datetime(2021, 10, 24, 2, 0, 0))
end = timezone(self.employee.tz).localize(datetime(2021, 11, 6, 23, 59, 59))
work_intervals, _ = self.employee.resource_id._get_valid_work_intervals(start, end)
sum_work_intervals = sum_intervals(work_intervals[self.employee.resource_id.id])
self.assertEqual(75, sum_work_intervals, "Sum of the work intervals for the employee should be 35h+40h = 75h")
def test_multi_contract_attendance(self):
""" Verify whether retrieving an employee's calendar attendances can
handle multiple contracts with different calendars.
"""
date_from = utc.localize(datetime(2021, 10, 1, 0, 0, 0))
date_to = utc.localize(datetime(2021, 11, 30, 0, 0, 0))
attendances = self.employee._get_calendar_attendances(date_from, date_to)
self.assertEqual(21 * 7, attendances['hours'],
"Attendances should only include running or finished contracts.")
self.contract_cdd.state = 'close'
self.contract_cdi.state = 'open'
attendances = self.employee._get_calendar_attendances(date_from, date_to)
self.assertEqual(21 * 7 + 21 * 8, attendances['hours'],
"Attendances should add up multiple contracts with varying work weeks.")
|