Skip to content
Open
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
36 changes: 36 additions & 0 deletions hr_shift/models/shift_planning.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,42 @@ def _constrain_template_id(self):
_("This employee is on leave so can't be assigned to this shift")
)

@api.constrains("start_time", "end_time", "employee_id", "state")
def _constrain_line_overlap(self):
lines = self.filtered(
lambda line: (
line.state == "assigned"
and line.start_time
and line.end_time
and line.employee_id
)
)
if not lines:
return
others = self.search(
[
("id", "not in", lines.ids),
("state", "=", "assigned"),
("employee_id", "in", lines.employee_id.ids),
("start_time", "<", max(lines.mapped("end_time"))),
("end_time", ">", min(lines.mapped("start_time"))),
]
)
for line in lines:
if others.filtered_domain(
[
("employee_id", "=", line.employee_id.id),
("start_time", "<", line.end_time),
("end_time", ">", line.start_time),
]
):
raise UserError(
_(
"%(employee)s already has an overlapping shift on this period.",
employee=line.employee_id.name,
)
)

@api.depends("template_id")
def _compute_state(self):
for shift in self:
Expand Down
34 changes: 34 additions & 0 deletions hr_shift/tests/test_hr_shift.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytz

from odoo import fields
from odoo.exceptions import UserError
from odoo.tests import Form
from odoo.tools import mute_logger

Expand Down Expand Up @@ -155,3 +156,36 @@ def test_hr_shift_planning_full(self):
shift_b_line_1 = shift_b.line_ids.filtered(lambda x: x.day_number == "1")
self.assertEqual(shift_b_line_1.state, "assigned")
self.assertEqual(shift_b_line_1.template_id, self.template_afternoon)

def test_hr_shift_planning_line_overlap_is_refused(self):
self.planning.generate_shifts()
shift = self.planning.shift_ids.filtered(
lambda s: s.employee_id == self.employee_a
)
line = shift.line_ids.filtered(lambda x: x.day_number == "0")
line.template_id = self.template_morning
with self.assertRaises(UserError):
self.env["hr.shift.planning.line"].create(
{
"shift_id": shift.id,
"day_number": "0",
"template_id": self.template_morning.id,
}
)

def test_hr_shift_planning_line_touch_to_touch_is_allowed(self):
self.planning.generate_shifts()
shift = self.planning.shift_ids.filtered(
lambda s: s.employee_id == self.employee_a
)
line = shift.line_ids.filtered(lambda x: x.day_number == "0")
line.template_id = self.template_morning
extra = self.env["hr.shift.planning.line"].create(
{
"shift_id": shift.id,
"day_number": "0",
"template_id": self.template_afternoon.id,
}
)
self.assertEqual(extra.state, "assigned")
self.assertEqual(line.end_time, extra.start_time)
Loading