Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[12.0][ADD] resource_multi_week_work_time_from_contracts #324

Merged
merged 11 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion company_today/tests/test_today.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class TestToday(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.company = cls.ref("base.main_company")
cls.company = cls.env.ref("base.main_company")

def test_today(self):
self.company.cron_update_today()
Expand Down
1 change: 1 addition & 0 deletions oca_dependencies.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# List the OCA project dependencies, one per line
# Add a repository url and branch if you need a forked version

hr https://github.com/coopiteasy/hr
partner-contact
timesheet
obeesdoo https://github.com/beescoop/Obeesdoo
5 changes: 5 additions & 0 deletions resource_multi_week_work_time_from_contracts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from . import models
21 changes: 21 additions & 0 deletions resource_multi_week_work_time_from_contracts/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

{
"name": "Multi-week calendars with work time from contracts",
"summary": """
A compatibility module.""",
"version": "12.0.1.0.0",
"category": "Hidden",
"website": "https://coopiteasy.be",
"author": "Coop IT Easy SC",
"maintainers": ["carmenbianca"],
"license": "AGPL-3",
"application": False,
"depends": [
"resource_multi_week_calendar",
"resource_work_time_from_contracts",
],
"auto_install": True,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from . import resource_calendar
from . import resource_mixin
15 changes: 15 additions & 0 deletions resource_multi_week_work_time_from_contracts/models/hr_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from odoo import fields, models


class HrContract(models.Model):
_inherit = "hr.contract"

# Add a domain.
resource_calendar_id = fields.Many2one(
"resource.calendar",
domain="[('parent_calendar_id', '=', False)]",
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

import datetime

from odoo import models


class ResourceCalendar(models.Model):
_inherit = "resource.calendar"

def _get_first_attendance(self, date_from):
if not self.is_multi_week:
return super()._get_first_attendance(date_from)
candidate = super(
ResourceCalendar, self._get_multi_week_calendar(date_from)
)._get_first_attendance(date_from)
# Week numbers not equal. This means we are AFTER any of the attendances
# in the target week. So get the first attendance of the succeeding
# week.
if candidate and candidate[0].isocalendar()[1] != date_from.isocalendar()[1]:
candidate = None
days_to_monday = (7 - date_from.weekday()) % 7 or 7
new_date_from = date_from
# Keep searching the Mondays of succeeding weeks until a match is
# found. Loop as many times as there are calendars.
for _ in self.multi_week_calendar_ids:
new_date_from = new_date_from + datetime.timedelta(days=days_to_monday)
candidate = super(
ResourceCalendar, self._get_multi_week_calendar(new_date_from)
)._get_first_attendance(new_date_from)
if candidate:
break
days_to_monday = 7
return candidate

def _get_last_attendance(self, date_to):
if not self.is_multi_week:
return super()._get_last_attendance(date_to)
candidate = super(
ResourceCalendar, self._get_multi_week_calendar(date_to)
)._get_last_attendance(date_to)
# Week numbers not equal. This means we are BEFORE any of the
# attendances in the target week. So get the last attendance of the
# preceding week.
if candidate and candidate[0].isocalendar()[1] != date_to.isocalendar()[1]:
candidate = None
days_since_sunday = date_to.weekday() + 1
new_date_to = date_to
# Keep searching the Sundays of preceding weeks until a match is
# found. Loop as many times as there are calendars.
for _ in self.multi_week_calendar_ids:
new_date_to = new_date_to - datetime.timedelta(days=days_since_sunday)
candidate = super(
ResourceCalendar, self._get_multi_week_calendar(new_date_to)
)._get_last_attendance(new_date_to)
if candidate:
break
days_since_sunday = 7
return candidate
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from odoo import models


class ResourceMixing(models.AbstractModel):
_inherit = "resource.mixin"

def get_calendar_for_date(self, date):
calendar = super().get_calendar_for_date(date)
return calendar._get_multi_week_calendar(day=date)
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
* `Coop IT Easy SC <https://coopiteasy.be>`_:

* Carmen Bianca BAKKER
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
A compatibility module.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from . import common
from . import test_calendar
from . import test_work_time
77 changes: 77 additions & 0 deletions resource_multi_week_work_time_from_contracts/tests/common.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

from odoo.tests.common import SavepointCase


class TestCalendarCommon(SavepointCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.Calendar = cls.env["resource.calendar"]
cls.parent_calendar = cls.Calendar.create(
{
"name": "Parent",
# This date is a Monday.
"multi_week_epoch_date": "2024-07-08",
}
)
cls.child_1 = cls.Calendar.create(
{
"name": "Child 1",
"parent_calendar_id": cls.parent_calendar.id,
"week_sequence": 10,
"attendance_ids": [
(
0,
False,
{
"name": "Wednesday morning",
"dayofweek": "2",
"hour_from": 8,
"hour_to": 12,
},
),
(
0,
False,
{
"name": "Thursday morning",
"dayofweek": "3",
"hour_from": 8,
"hour_to": 12,
},
),
],
}
)
cls.child_2 = cls.Calendar.create(
{
"name": "Child 2",
"parent_calendar_id": cls.parent_calendar.id,
"week_sequence": 20,
"attendance_ids": [
(
0,
False,
{
"name": "Monday morning",
"dayofweek": "0",
"hour_from": 8,
"hour_to": 12,
},
),
(
0,
False,
{
"name": "Friday morning",
"dayofweek": "4",
"hour_from": 8,
"hour_to": 12,
},
),
],
}
)
104 changes: 104 additions & 0 deletions resource_multi_week_work_time_from_contracts/tests/test_calendar.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# SPDX-FileCopyrightText: 2024 Coop IT Easy SC
#
# SPDX-License-Identifier: AGPL-3.0-or-later

import datetime

from .common import TestCalendarCommon


class TestCalendar(TestCalendarCommon):
def test_first_last_attendance_both_weeks(self):
result = self.parent_calendar.get_first_last_attendance(
datetime.date(2024, 7, 8),
datetime.date(2024, 7, 21),
)
# First date/attendance is the Wednesday.
self.assertEqual(result[0][0], datetime.date(2024, 7, 10))
self.assertEqual(result[0][1], self.child_1.attendance_ids[0])
# Last date/attendance is the Friday.
self.assertEqual(result[1][0], datetime.date(2024, 7, 19))
self.assertEqual(result[1][1], self.child_2.attendance_ids[-1])

def test_first_last_attendance_middle_to_middle(self):
result = self.parent_calendar.get_first_last_attendance(
datetime.date(2024, 7, 11),
datetime.date(2024, 7, 16),
)
# First date/attendance is the Thursday.
self.assertEqual(result[0][0], datetime.date(2024, 7, 11))
self.assertEqual(result[0][1], self.child_1.attendance_ids[1])
# Last date/attendance is the Monday.
self.assertEqual(result[1][0], datetime.date(2024, 7, 15))
self.assertEqual(result[1][1], self.child_2.attendance_ids[0])

def test_first_last_attendance_middle_to_before(self):
result = self.parent_calendar.get_first_last_attendance(
datetime.date(2024, 7, 16),
datetime.date(2024, 7, 22),
)
# First date/attendance is the Friday.
self.assertEqual(result[0][0], datetime.date(2024, 7, 19))
self.assertEqual(result[0][1], self.child_2.attendance_ids[1])
# Last date/attendance is the Friday of the week preceding the target date.
self.assertEqual(result[1][0], datetime.date(2024, 7, 19))
self.assertEqual(result[1][1], self.child_2.attendance_ids[1])

def test_first_last_attendance_middle_to_before_skip_a_week(self):
self.Calendar.create(
{
"name": "Empty child 3",
"parent_calendar_id": self.parent_calendar.id,
"week_sequence": 30, # After week 2.
"attendance_ids": [],
}
)
result = self.parent_calendar.get_first_last_attendance(
# Multi-week 2
datetime.date(2024, 7, 16),
# Multi-week 1
datetime.date(2024, 7, 30),
)
# First date/attendance is the Friday.
self.assertEqual(result[0][0], datetime.date(2024, 7, 19))
self.assertEqual(result[0][1], self.child_2.attendance_ids[1])
# Last date/attendance is the Friday of the second week preceding the
# target date.
self.assertEqual(result[1][0], datetime.date(2024, 7, 19))
self.assertEqual(result[1][1], self.child_2.attendance_ids[1])

def test_first_last_attendance_after_to_middle(self):
result = self.parent_calendar.get_first_last_attendance(
datetime.date(2024, 7, 12),
datetime.date(2024, 7, 17),
)
# First date/attendance is the Monday of the week succeeding the target date.
self.assertEqual(result[0][0], datetime.date(2024, 7, 15))
self.assertEqual(result[0][1], self.child_2.attendance_ids[0])
# Last date/attendance is the Monday.
self.assertEqual(result[1][0], datetime.date(2024, 7, 15))
self.assertEqual(result[1][1], self.child_2.attendance_ids[0])

def test_first_last_attendance_after_to_middle_skip_a_week(self):
self.Calendar.create(
{
"name": "Empty child 3",
"parent_calendar_id": self.parent_calendar.id,
# In between week 1 and 2, meaning child 2 is now week 3.
"week_sequence": 15,
"attendance_ids": [],
}
)
result = self.parent_calendar.get_first_last_attendance(
# Multi-week 1.
datetime.date(2024, 7, 12),
# Multi-week 3.
datetime.date(2024, 7, 24),
)
# First date/attendance is the Monday of the second week succeeding the
# target date.
self.assertEqual(result[0][0], datetime.date(2024, 7, 22))
self.assertEqual(result[0][1], self.child_2.attendance_ids[0])
# Last date/attendance is the Monday.
self.assertEqual(result[1][0], datetime.date(2024, 7, 22))
self.assertEqual(result[1][1], self.child_2.attendance_ids[0])
Loading
Loading