diff --git a/beesdoo_shift/models/cooperative_status.py b/beesdoo_shift/models/cooperative_status.py index 5bb085fa2..dfc96645c 100644 --- a/beesdoo_shift/models/cooperative_status.py +++ b/beesdoo_shift/models/cooperative_status.py @@ -1,11 +1,13 @@ import logging -from datetime import timedelta +from datetime import datetime, timedelta from odoo import _, api, fields, models from odoo.exceptions import UserError, ValidationError _logger = logging.getLogger(__name__) +# todo rename mentions to cooperatives + def add_days_delta(date_from, days_delta): if not date_from: @@ -65,7 +67,7 @@ def _get_status(self): "are based on the current date", default=fields.Date.today, ) - cooperator_id = fields.Many2one("res.partner") + cooperator_id = fields.Many2one("res.partner") # todo rename to worker_id active = fields.Boolean( related="cooperator_id.active", store=True, index=True ) @@ -119,6 +121,23 @@ def _get_status(self): ) # TODO unsubscribe when reach -2 future_alert_date = fields.Date(compute="_compute_future_alert_date") next_countdown_date = fields.Date(compute="_compute_next_countdown_date") + next_shift_id = fields.Many2one( + comodel_name="beesdoo.shift.shift", + string="Next Shift", + compute="_compute_next_shift", + store=True, + help="Next shift the worker is subscribed to.", + ) + next_shift_date = fields.Datetime( + related="next_shift_id.start_time", + string="Next Shift Date", + store=True, + ) + is_subscribed_to_shift = fields.Boolean( + string="Subscribed before Alert Date", + compute="_compute_next_shift", + store=True, + ) temporary_exempt_reason_id = fields.Many2one( comodel_name="cooperative.exempt.reason", @@ -403,6 +422,44 @@ def _compute_next_countdown_date(self): for rec in self: rec.next_countdown_date = False + @api.multi + @api.depends( + "cooperator_id.shift_shift_ids", + "cooperator_id.shift_shift_ids.start_time", + "future_alert_date", + ) + def _compute_next_shift(self): + now = fields.Datetime.now() + cooperator_ids = self.mapped("cooperator_id").ids + # avoid searching for shift in loop + next_shifts = self.env["beesdoo.shift.shift"].search( + [("start_time", ">=", now), ("worker_id", "in", cooperator_ids)], + order="worker_id, start_time", + ) + + next_shift_by_worker = {} + for shift in next_shifts: + # take fist shift for each worker + if shift.worker_id not in next_shift_by_worker: + next_shift_by_worker[shift.worker_id] = shift + + for rec in self: + rec.next_shift_id = next_shift_by_worker[rec.cooperator_id] + if rec.next_shift_id: + if rec.future_alert_date: + future_alert_date_time = datetime( + rec.future_alert_date.year, + rec.future_alert_date.month, + rec.future_alert_date.day, + ) + rec.is_subscribed_to_shift = ( + rec.next_shift_id.start_time < future_alert_date_time + ) + else: + rec.is_subscribed_to_shift = True + else: + rec.is_subscribed_to_shift = False + def _can_shop_status(self): """ return the list of status that give access diff --git a/beesdoo_shift/models/res_partner.py b/beesdoo_shift/models/res_partner.py index 02b7b2435..6157c3096 100644 --- a/beesdoo_shift/models/res_partner.py +++ b/beesdoo_shift/models/res_partner.py @@ -20,6 +20,8 @@ class ResPartner(models.Model): compute="_compute_can_shop", store=True, ) + # todo implement as delegated inheritance ? + # resolve as part of migration to OCA cooperative_status_ids = fields.One2many( string="Cooperative Statuses", comodel_name="cooperative.status", @@ -66,6 +68,21 @@ class ResPartner(models.Model): subscribed_shift_ids = fields.Many2many( comodel_name="beesdoo.shift.template", readonly=True ) + shift_shift_ids = fields.One2many( + comodel_name="beesdoo.shift.shift", + inverse_name="worker_id", + string="Shifts", + help="All the shifts the worker is subscribed to.", + ) + next_shift_id = fields.Many2one( + related="cooperative_status_ids.next_shift_id", store=True, + ) + is_subscribed_to_shift = fields.Boolean( + related="cooperative_status_ids.is_subscribed_to_shift", store=True, + ) + next_shift_date = fields.Datetime( + related="cooperative_status_ids.next_shift_date", store=True, + ) @api.depends("cooperative_status_ids") def _compute_can_shop(self): diff --git a/beesdoo_shift/models/task.py b/beesdoo_shift/models/task.py index 97f4141ee..a3950b138 100644 --- a/beesdoo_shift/models/task.py +++ b/beesdoo_shift/models/task.py @@ -9,9 +9,7 @@ class Task(models.Model): _name = "beesdoo.shift.shift" - _inherit = ["mail.thread"] - _order = "start_time asc" ################################## diff --git a/beesdoo_shift/tests/test_beesdoo_shift.py b/beesdoo_shift/tests/test_beesdoo_shift.py index e8a202e35..f7be949da 100644 --- a/beesdoo_shift/tests/test_beesdoo_shift.py +++ b/beesdoo_shift/tests/test_beesdoo_shift.py @@ -22,6 +22,9 @@ def setUp(self): self.worker_regular_1 = self.env.ref( "beesdoo_shift.res_partner_worker_1_demo" ) + self.worker_irregular_2 = self.env.ref( + "beesdoo_shift.res_partner_worker_2_demo" + ) self.worker_regular_3 = self.env.ref( "beesdoo_shift.res_partner_worker_3_demo" ) @@ -473,3 +476,62 @@ def test_change_worker_temporary_exemption_2(self): ) exemption_wiz.exempt() self.assertEqual(self._count_number_of_shift(self.worker_regular_1), 4) + + def test_irregular_worker_subscribed_to_shift_before_alert(self): + self._generate_shifts(days=1, nb=2) + self.assertFalse( + self.worker_irregular_2.cooperative_status_ids.next_shift_id + ) + + some_empty_shift = self.shift_model.search( + [("start_time", ">=", datetime.now()), ("worker_id", "=", False)], + limit=1, + ) + + some_empty_shift.worker_id = self.worker_irregular_2 + self.assertEqual( + self.worker_irregular_2.cooperative_status_ids.next_shift_id, + some_empty_shift, + ) + + some_empty_shift.worker_id = False + self.assertFalse( + self.worker_irregular_2.cooperative_status_ids.next_shift_id + ) + + def test_unsubscribe_worker_from_task_template_computes_next_shift(self): + self._generate_shifts(days=1, nb=2) + now = datetime.now() + # Check that initialisation works well + next_shift = self.shift_model.search( + [ + ("start_time", ">=", now), + ("worker_id", "=", self.worker_regular_1.id), + ("task_template_id", "=", self.task_template_1.id), + ] + ) + self.assertEqual( + self.worker_regular_1.cooperative_status_ids.next_shift_id, + next_shift, + ) + + # Unsubscribe a worker from the task template + self.task_template_1.worker_ids -= self.worker_regular_1 + + self.assertFalse( + self.worker_regular_1.cooperative_status_ids.next_shift_id + ) + + # Subscribe a worker from the task template + self.task_template_1.worker_ids += self.worker_regular_1 + next_shift = self.shift_model.search( + [ + ("start_time", ">=", now), + ("worker_id", "=", self.worker_regular_1.id), + ("task_template_id", "=", self.task_template_1.id), + ] + ) + self.assertEqual( + self.worker_regular_1.cooperative_status_ids.next_shift_id, + next_shift, + ) diff --git a/beesdoo_shift/views/cooperative_status.xml b/beesdoo_shift/views/cooperative_status.xml index 83f4301e2..0dd64654b 100644 --- a/beesdoo_shift/views/cooperative_status.xml +++ b/beesdoo_shift/views/cooperative_status.xml @@ -149,6 +149,8 @@ + + +