1+ # SPDX-FileCopyrightText: 2026 Coop IT Easy SC
2+ #
3+ # SPDX-License-Identifier: AGPL-3.0-or-later
4+
15from datetime import date , datetime , timedelta
26
7+ from psycopg2 .errors import IntegrityError
8+
39from odoo .exceptions import AccessError , ValidationError
410from odoo .tests .common import TransactionCase
11+ from odoo .tools import mute_logger
512
613
714class TestShiftChange (TransactionCase ):
@@ -29,8 +36,8 @@ def setUp(self):
2936 {
3037 "name" : "shift_1" ,
3138 "task_template_id" : self .task_template_1 .id ,
32- "start_time" : self .now ,
33- "end_time" : self .now ,
39+ "start_time" : self .now + timedelta ( days = 2 ) ,
40+ "end_time" : self .now + timedelta ( days = 2 ) ,
3441 "is_regular" : True ,
3542 "worker_id" : self .worker_regular_1 .id ,
3643 }
@@ -39,8 +46,8 @@ def setUp(self):
3946 {
4047 "name" : "shift_2" ,
4148 "task_template_id" : self .task_template_2 .id ,
42- "start_time" : self .now ,
43- "end_time" : self .now ,
49+ "start_time" : self .now + timedelta ( days = 2 ) ,
50+ "end_time" : self .now + timedelta ( days = 2 ) ,
4451 "is_regular" : True ,
4552 "worker_id" : self .worker_regular_2 .id ,
4653 }
@@ -49,16 +56,16 @@ def setUp(self):
4956 {
5057 "name" : "shift_3" ,
5158 "task_template_id" : self .task_template_2 .id ,
52- "start_time" : self .now + timedelta (days = 2 ),
53- "end_time" : self .now + timedelta (days = 2 ),
59+ "start_time" : self .now + timedelta (days = 4 ),
60+ "end_time" : self .now + timedelta (days = 4 ),
5461 "worker_id" : False ,
5562 }
5663 )
5764 self .shift_4 = self .shift_model .create (
5865 {
5966 "name" : "shift_4" ,
6067 "task_template_id" : self .task_template_2 .id ,
61- "start_time" : self .now - timedelta (days = 2 ),
68+ "start_time" : self .now - timedelta (days = 4 ),
6269 "end_time" : self .now ,
6370 "worker_id" : False ,
6471 }
@@ -67,7 +74,7 @@ def setUp(self):
6774 {
6875 "name" : "shift_5" ,
6976 "task_template_id" : self .task_template_2 .id ,
70- "start_time" : self .now + timedelta (days = 2 ),
77+ "start_time" : self .now + timedelta (days = 4 ),
7178 "end_time" : self .now ,
7279 "worker_id" : False ,
7380 }
@@ -85,6 +92,11 @@ def setUp(self):
8592 # Set context to avoid shift generation in the past
8693 self .env .context = dict (self .env .context , visualize_date = date .today ())
8794
95+ # Set maximum change shift for testing
96+ self .env ["ir.config_parameter" ].set_param (
97+ "shift_change.same_shift_change_max" , 1
98+ )
99+
88100 def test_shift_change (self ):
89101 """Test change a shift"""
90102 self .assertEqual (self .shift_1 .worker_id , self .worker_regular_1 )
@@ -99,6 +111,29 @@ def test_shift_change(self):
99111 self .assertFalse (self .shift_1 .worker_id )
100112 self .assertEqual (self .shift_3 .worker_id , self .worker_regular_1 )
101113
114+ def test_shift_change_max (self ):
115+ """Test change a shift several times"""
116+ self .assertEqual (self .shift_1 .worker_id , self .worker_regular_1 )
117+ self .assertFalse (self .shift_3 .worker_id )
118+ self .assertFalse (self .shift_5 .worker_id )
119+ self .shift_change_model .create (
120+ {
121+ "worker_id" : self .worker_regular_1 .id ,
122+ "old_shift_id" : self .shift_1 .id ,
123+ "new_shift_id" : self .shift_3 .id ,
124+ }
125+ )
126+ self .assertFalse (self .shift_1 .worker_id )
127+ self .assertEqual (self .shift_3 .worker_id , self .worker_regular_1 )
128+ with self .assertRaises (ValidationError ):
129+ self .shift_change_model .create (
130+ {
131+ "worker_id" : self .worker_regular_1 .id ,
132+ "old_shift_id" : self .shift_3 .id ,
133+ "new_shift_id" : self .shift_5 .id ,
134+ }
135+ )
136+
102137 def test_shift_change_not_empty (self ):
103138 """Test changing a shift to a non empty shift"""
104139 self .assertEqual (self .shift_1 .worker_id , self .worker_regular_1 )
@@ -142,12 +177,13 @@ def test_shift_change_wrong_worker(self):
142177
143178 def test_shift_change_missing_required_fields (self ):
144179 """Test creating a shift with missing fields"""
145- with self .assertRaises (ValidationError ):
146- self .shift_change_model .create (
147- {
148- "worker_id" : self .worker_regular_1 .id ,
149- }
150- )
180+ with self .assertRaises (IntegrityError ):
181+ with mute_logger ("odoo.sql_db" ):
182+ self .shift_change_model .create (
183+ {
184+ "worker_id" : self .worker_regular_1 .id ,
185+ }
186+ )
151187
152188 def test_shift_change_writing (self ):
153189 """Test that writing to a shift fails"""
0 commit comments