Skip to content

Commit 2f9ff31

Browse files
authored
Merge pull request #1781 from frappe/mergify/bp/version-14-hotfix/pr-1765
fix: validation of overlapping shift dates (backport #1765)
2 parents f6abbc4 + d3ad5a6 commit 2f9ff31

File tree

3 files changed

+19
-101
lines changed

3 files changed

+19
-101
lines changed

hrms/hr/doctype/shift_assignment/shift_assignment.py

+2-23
Original file line numberDiff line numberDiff line change
@@ -80,33 +80,12 @@ def get_overlapping_dates(self):
8080
& (shift.docstatus == 1)
8181
& (shift.name != self.name)
8282
& (shift.status == "Active")
83+
& ((shift.end_date >= self.start_date) | (shift.end_date.isnull()))
8384
)
8485
)
8586

8687
if self.end_date:
87-
query = query.where(
88-
Criterion.any(
89-
[
90-
Criterion.any(
91-
[
92-
shift.end_date.isnull(),
93-
((self.start_date >= shift.start_date) & (self.start_date <= shift.end_date)),
94-
]
95-
),
96-
Criterion.any(
97-
[
98-
((self.end_date >= shift.start_date) & (self.end_date <= shift.end_date)),
99-
shift.start_date.between(self.start_date, self.end_date),
100-
]
101-
),
102-
]
103-
)
104-
)
105-
else:
106-
query = query.where(
107-
shift.end_date.isnull()
108-
| ((self.start_date >= shift.start_date) & (self.start_date <= shift.end_date))
109-
)
88+
query = query.where(shift.start_date <= self.end_date)
11089

11190
return query.run(as_dict=True)
11291

hrms/hr/doctype/shift_assignment/test_shift_assignment.py

+10-54
Original file line numberDiff line numberDiff line change
@@ -23,39 +23,18 @@ def setUp(self):
2323
frappe.db.delete("Shift Assignment")
2424
frappe.db.delete("Shift Type")
2525

26-
def test_make_shift_assignment(self):
27-
setup_shift_type(shift_type="Day Shift")
28-
shift_assignment = frappe.get_doc(
29-
{
30-
"doctype": "Shift Assignment",
31-
"shift_type": "Day Shift",
32-
"company": "_Test Company",
33-
"employee": "_T-Employee-00001",
34-
"start_date": nowdate(),
35-
}
36-
).insert()
37-
shift_assignment.submit()
38-
39-
self.assertEqual(shift_assignment.docstatus, 1)
40-
4126
def test_overlapping_for_ongoing_shift(self):
4227
# shift should be Ongoing if Only start_date is present and status = Active
4328
setup_shift_type(shift_type="Day Shift")
44-
shift_assignment_1 = frappe.get_doc(
45-
{
46-
"doctype": "Shift Assignment",
47-
"shift_type": "Day Shift",
48-
"company": "_Test Company",
49-
"employee": "_T-Employee-00001",
50-
"start_date": nowdate(),
51-
"status": "Active",
52-
}
53-
).insert()
54-
shift_assignment_1.submit()
29+
make_shift_assignment("Day Shift", "_T-Employee-00001", nowdate())
5530

56-
self.assertEqual(shift_assignment_1.docstatus, 1)
31+
# shift ends before ongoing shift starts
32+
non_overlapping_shift = make_shift_assignment(
33+
"Day Shift", "_T-Employee-00001", add_days(nowdate(), -1), add_days(nowdate(), -1)
34+
)
35+
self.assertEqual(non_overlapping_shift.docstatus, 1)
5736

58-
shift_assignment = frappe.get_doc(
37+
overlapping_shift = frappe.get_doc(
5938
{
6039
"doctype": "Shift Assignment",
6140
"shift_type": "Day Shift",
@@ -64,23 +43,11 @@ def test_overlapping_for_ongoing_shift(self):
6443
"start_date": add_days(nowdate(), 2),
6544
}
6645
)
67-
68-
self.assertRaises(OverlappingShiftError, shift_assignment.save)
46+
self.assertRaises(OverlappingShiftError, overlapping_shift.save)
6947

7048
def test_multiple_shift_assignments_for_same_date(self):
7149
setup_shift_type(shift_type="Day Shift")
72-
shift_assignment_1 = frappe.get_doc(
73-
{
74-
"doctype": "Shift Assignment",
75-
"shift_type": "Day Shift",
76-
"company": "_Test Company",
77-
"employee": "_T-Employee-00001",
78-
"start_date": nowdate(),
79-
"end_date": add_days(nowdate(), 30),
80-
"status": "Active",
81-
}
82-
).insert()
83-
shift_assignment_1.submit()
50+
make_shift_assignment("Day Shift", "_T-Employee-00001", nowdate(), add_days(nowdate(), 30))
8451

8552
setup_shift_type(shift_type="Night Shift", start_time="19:00:00", end_time="23:00:00")
8653
shift_assignment_2 = frappe.get_doc(
@@ -103,18 +70,7 @@ def test_multiple_shift_assignments_for_same_date(self):
10370
def test_overlapping_for_fixed_period_shift(self):
10471
# shift should is for Fixed period if Only start_date and end_date both are present and status = Active
10572
setup_shift_type(shift_type="Day Shift")
106-
shift_assignment_1 = frappe.get_doc(
107-
{
108-
"doctype": "Shift Assignment",
109-
"shift_type": "Day Shift",
110-
"company": "_Test Company",
111-
"employee": "_T-Employee-00001",
112-
"start_date": nowdate(),
113-
"end_date": add_days(nowdate(), 30),
114-
"status": "Active",
115-
}
116-
).insert()
117-
shift_assignment_1.submit()
73+
make_shift_assignment("Day Shift", "_T-Employee-00001", nowdate(), add_days(nowdate(), 30))
11874

11975
# it should not allowed within period of any shift.
12076
shift_assignment_3 = frappe.get_doc(

hrms/hr/doctype/shift_request/shift_request.py

+7-24
Original file line numberDiff line numberDiff line change
@@ -97,33 +97,16 @@ def get_overlapping_dates(self):
9797
query = (
9898
frappe.qb.from_(shift)
9999
.select(shift.name, shift.shift_type)
100-
.where((shift.employee == self.employee) & (shift.docstatus < 2) & (shift.name != self.name))
100+
.where(
101+
(shift.employee == self.employee)
102+
& (shift.docstatus < 2)
103+
& (shift.name != self.name)
104+
& ((shift.to_date >= self.from_date) | (shift.to_date.isnull()))
105+
)
101106
)
102107

103108
if self.to_date:
104-
query = query.where(
105-
Criterion.any(
106-
[
107-
Criterion.any(
108-
[
109-
shift.to_date.isnull(),
110-
((self.from_date >= shift.from_date) & (self.from_date <= shift.to_date)),
111-
]
112-
),
113-
Criterion.any(
114-
[
115-
((self.to_date >= shift.from_date) & (self.to_date <= shift.to_date)),
116-
shift.from_date.between(self.from_date, self.to_date),
117-
]
118-
),
119-
]
120-
)
121-
)
122-
else:
123-
query = query.where(
124-
shift.to_date.isnull()
125-
| ((self.from_date >= shift.from_date) & (self.from_date <= shift.to_date))
126-
)
109+
query = query.where(shift.from_date <= self.to_date)
127110

128111
return query.run(as_dict=True)
129112

0 commit comments

Comments
 (0)