Skip to content

Commit 40f73c9

Browse files
committed
[ADD] shift_change_portal
1 parent 2f164f6 commit 40f73c9

30 files changed

Lines changed: 1317 additions & 62 deletions
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../../shift_change_portal

setup/shift_change_portal/setup.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import setuptools
2+
3+
setuptools.setup(
4+
setup_requires=['setuptools-odoo'],
5+
odoo_addon=True,
6+
)

shift_change/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
15
from . import models

shift_change/__manifest__.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
# Copyright 2022 Coop IT Easy SC
2-
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
1+
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
34

45
{
56
"name": "Shift Change",
Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8" ?>
2+
<!--
3+
SPDX-FileCopyrightText: 2026 Coop IT Easy SC
4+
5+
SPDX-License-Identifier: AGPL-3.0-or-later
6+
-->
17
<odoo noupdate="1">
2-
<record id="enable_shift_changes" model="ir.config_parameter" forcecreate="False">
3-
<field name="key">shift_change.enable_shift_changes</field>
4-
<field name="value">True</field>
5-
</record>
6-
<record id="hour_limit_change" model="ir.config_parameter" forcecreate="False">
8+
<record id="hour_limit_change" model="ir.config_parameter">
79
<field name="key">shift_change.hour_limit_change</field>
810
<field name="value">24</field>
911
</record>
10-
<record id="enable_solidarity" model="ir.config_parameter" forcecreate="False">
11-
<field name="key">beesdoo_shift.enable_solidarity</field>
12-
<field name="value">True</field>
12+
<record id="same_shift_change_max" model="ir.config_parameter">
13+
<field name="key">shift_change.same_shift_change_max</field>
14+
<field name="value">3</field>
1315
</record>
1416
</odoo>

shift_change/demo/demo.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
<?xml version="1.0" encoding="utf-8" ?>
2+
<!--
3+
SPDX-FileCopyrightText: 2026 Coop IT Easy SC
4+
5+
SPDX-License-Identifier: AGPL-3.0-or-later
6+
-->
27
<odoo>
38

49
<!-- Worker -->

shift_change/models/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
1+
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
15
from . import shift_change
26
from . import res_config_settings
Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1+
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
15
from odoo import fields, models
26

37

48
class ResConfigSettings(models.TransientModel):
59
_inherit = "res.config.settings"
610

7-
# enable_exchanges
8-
enable_shift_changes = fields.Boolean(
9-
string="Activate shift changes",
10-
config_parameter="shift_change.enable_shift_changes",
11-
)
12-
# day_limit_swap
1311
hour_limit_change = fields.Integer(
1412
string="Number of hours above which a cooperator cannot change his shift",
1513
config_parameter="shift_change.hour_limit_change",
1614
)
15+
same_shift_change_max = fields.Integer(
16+
string="Number of time the same shift can be changed",
17+
config_parameter="shift_change.same_shift_change_max",
18+
)

shift_change/models/shift_change.py

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
15
from datetime import datetime, timedelta
26

37
from odoo import _, api, fields, models
@@ -32,50 +36,112 @@ def create(self, vals_list):
3236
to the old shift and subscribe him/her to the new one
3337
"""
3438
res = super().create(vals_list)
35-
res._unsubscribe_old_shift()
3639
res._subscribe_new_shift()
40+
res._unsubscribe_old_shift()
3741
return res
3842

3943
def _unsubscribe_old_shift(self):
4044
"""
4145
Unsubscribe self.worker_id from old_shift
42-
Return True is unsubscription is successful.
43-
:return: Boolean
46+
Raise error if not possible.
4447
"""
45-
if (
46-
self.old_shift_id.worker_id
47-
and self.old_shift_id.worker_id == self.worker_id
48-
):
49-
self.old_shift_id.worker_id = False
50-
else:
51-
raise ValidationError(_("You can't change shift that your are not worker."))
48+
self._check_old_shift(self.old_shift_id, self.worker_id)
49+
self.old_shift_id.write(
50+
{
51+
"worker_id": False,
52+
"is_regular": False,
53+
"is_compensation": False,
54+
}
55+
)
5256

5357
def _subscribe_new_shift(self):
5458
"""
5559
Subscribe self.worker_id to the new shift
56-
Return True is subscription is successful.
57-
:return: Boolean
60+
Raise error if not possible.
5861
"""
62+
self._check_new_shift(self.new_shift_id)
63+
self.new_shift_id.write(
64+
{
65+
"worker_id": self.worker_id.id,
66+
"is_regular": self.old_shift_id.is_regular,
67+
"is_compensation": self.old_shift_id.is_compensation,
68+
}
69+
)
70+
71+
@api.model
72+
def _check_old_shift(self, old_shift_id, worker_id):
73+
"""Check if old shift can be changed"""
74+
try:
75+
hour_limit_change = int(
76+
self.env["ir.config_parameter"].get_param(
77+
"shift_change.hour_limit_change"
78+
)
79+
)
80+
except ValueError:
81+
# fall back to a default value
82+
hour_limit_change = 0
83+
if not old_shift_id.worker_id or old_shift_id.worker_id != worker_id:
84+
raise ValidationError(_("You can't change shift that your are not worker."))
85+
if old_shift_id.start_time <= datetime.now():
86+
raise ValidationError(_("You can't change shift that is in the past."))
87+
if old_shift_id.start_time <= datetime.now() + timedelta(
88+
hours=hour_limit_change
89+
):
90+
raise ValidationError(_("You can't change a shift so close in the futur."))
91+
try:
92+
same_shift_change_max = int(
93+
self.env["ir.config_parameter"].get_param(
94+
"shift_change.same_shift_change_max"
95+
)
96+
)
97+
except ValueError:
98+
# fall back to a default value
99+
same_shift_change_max = 0
100+
if same_shift_change_max:
101+
same_shift_change_nb = 0
102+
tmp_old_shift_id = old_shift_id
103+
while tmp_old_shift_id:
104+
change = self.search(
105+
[
106+
("new_shift_id", "=", tmp_old_shift_id.id),
107+
("worker_id", "=", worker_id.id),
108+
],
109+
limit=1,
110+
)
111+
if change:
112+
same_shift_change_nb += 1
113+
tmp_old_shift_id = change.old_shift_id
114+
else:
115+
tmp_old_shift_id = None
116+
if same_shift_change_nb >= same_shift_change_max:
117+
raise ValidationError(
118+
_(
119+
"You can't change the same shift more than"
120+
f"{same_shift_change_max} times."
121+
)
122+
)
123+
124+
@api.model
125+
def _check_new_shift(self, new_shift_id):
126+
"""Check if shift can be changed or not"""
59127
try:
60128
hour_limit_change = int(
61129
self.env["ir.config_parameter"].get_param(
62130
"shift_change.hour_limit_change"
63131
)
64132
)
65133
except ValueError:
66-
# Fall back to a default value
134+
# fall back to a default value
67135
hour_limit_change = 0
68-
if self.new_shift_id.worker_id:
136+
if new_shift_id.worker_id:
69137
raise ValidationError(
70138
_("You can't subscribe to a shift assigned to someone else.")
71139
)
72-
elif self.new_shift_id.start_time <= datetime.now():
140+
if new_shift_id.start_time <= datetime.now():
73141
raise ValidationError(_("You can't subscribe to a shift in the past."))
74-
elif self.new_shift_id.start_time <= datetime.now() + timedelta(
142+
if new_shift_id.start_time <= datetime.now() + timedelta(
75143
hours=hour_limit_change
76144
):
77145
raise ValidationError(
78146
_("You can't subscribe to a shift so close in the futur.")
79147
)
80-
else:
81-
self.new_shift_id.worker_id = self.worker_id

shift_change/tests/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
1+
# SPDX-FileCopyrightText: 2026 Coop IT Easy SC
2+
#
3+
# SPDX-License-Identifier: AGPL-3.0-or-later
4+
15
from . import test_shift_change

0 commit comments

Comments
 (0)