File: test_resource.py

package info (click to toggle)
odoo 18.0.0%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 878,716 kB
  • sloc: javascript: 927,937; python: 685,670; xml: 388,524; sh: 1,033; sql: 415; makefile: 26
file content (132 lines) | stat: -rw-r--r-- 7,483 bytes parent folder | download
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.")