From 49ac63bc0b7f6ddffa9681eac0980e58d3a0a95a Mon Sep 17 00:00:00 2001 From: "robin.keunen" Date: Mon, 14 Feb 2022 18:27:55 +0100 Subject: [PATCH] [ADD] beesdoo_shift: next_shift_id on cooperative.status --- beesdoo_shift/data/cron.xml | 2 +- beesdoo_shift/models/cooperative_status.py | 69 +++++++++++++++++++++- beesdoo_shift/models/res_partner.py | 20 +++++++ beesdoo_shift/models/task.py | 2 - beesdoo_shift/tests/test_beesdoo_shift.py | 62 +++++++++++++++++++ beesdoo_shift/views/cooperative_status.xml | 7 +++ 6 files changed, 157 insertions(+), 5 deletions(-) diff --git a/beesdoo_shift/data/cron.xml b/beesdoo_shift/data/cron.xml index efcdccfc1..5b4485742 100644 --- a/beesdoo_shift/data/cron.xml +++ b/beesdoo_shift/data/cron.xml @@ -1,7 +1,7 @@ - Update Cooperatoor status base on the date + Update Cooperator status base on the date code model._set_today() diff --git a/beesdoo_shift/models/cooperative_status.py b/beesdoo_shift/models/cooperative_status.py index 4ce25955f..0c6df36ff 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", @@ -410,6 +429,52 @@ 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", + "today", + ) + def _compute_next_shift(self): + # try to use "today" field from status if possible + todays = self.mapped("today") + if len(todays) == 1: + today = todays.pop() + now = datetime(today.year, today.month, today.day, 0, 0, 0) + else: + now = datetime.now() + + # avoid searching for shift in loop + cooperator_ids = self.mapped("cooperator_id").ids + 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.id not in next_shift_by_worker: + next_shift_by_worker[shift.worker_id.id] = shift + + for rec in self: + rec.next_shift_id = next_shift_by_worker.get(rec.cooperator_id.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 f4c3f1571..8bf2286ca 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,24 @@ 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 e85269b64..1763f9585 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 7615ea942..56ef0dc51 100644 --- a/beesdoo_shift/views/cooperative_status.xml +++ b/beesdoo_shift/views/cooperative_status.xml @@ -149,6 +149,8 @@ + + +