From d5e954d45c0902db1178cb5991b1dcf4d2d5da50 Mon Sep 17 00:00:00 2001 From: gsinghpal Date: Wed, 6 May 2026 23:08:04 -0400 Subject: [PATCH] feat(fusion_planning): auto-publish new shifts + bulk-assign to many employees MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two manager-side time savers on the Add Shift dialog: 1. Auto-publish on create Override planning.slot.create() to default state='published' for every new shift (was: 'draft', requiring a separate Publish step per slot — painful with recurrence which can generate dozens at a time). Recurrency-generated copies inherit the parent slot's state, so a single recurring shift now publishes the whole series in one save. Manager can still pass state='draft' explicitly to opt out. 2. Apply Also To (multi-resource bulk create) New x_fc_additional_resource_ids m2m on planning.slot. When set, create() splits the vals into one slot per additional resource (deduped against the primary). Combined with recurrence, picking N employees and a date range now creates the full N x M shift matrix in a single Save instead of N manual repeats. Field appears in the Add Shift dialog under Role, hidden once the slot is saved (it's a create-time helper, not ongoing data), and gated to planning.group_planning_manager. Co-Authored-By: Claude Opus 4.7 (1M context) --- fusion_planning/__init__.py | 1 + fusion_planning/__manifest__.py | 3 +- fusion_planning/models/__init__.py | 2 + fusion_planning/models/planning_slot.py | 65 +++++++++++++++++++ fusion_planning/views/planning_slot_views.xml | 22 +++++++ 5 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 fusion_planning/models/__init__.py create mode 100644 fusion_planning/models/planning_slot.py create mode 100644 fusion_planning/views/planning_slot_views.xml diff --git a/fusion_planning/__init__.py b/fusion_planning/__init__.py index 153a9e31..9e5827f9 100644 --- a/fusion_planning/__init__.py +++ b/fusion_planning/__init__.py @@ -1,2 +1,3 @@ # -*- coding: utf-8 -*- from . import controllers +from . import models diff --git a/fusion_planning/__manifest__.py b/fusion_planning/__manifest__.py index 20c04519..1cc9e100 100644 --- a/fusion_planning/__manifest__.py +++ b/fusion_planning/__manifest__.py @@ -5,7 +5,7 @@ { 'name': 'Fusion Planning', - 'version': '19.0.1.0.2', + 'version': '19.0.1.1.0', 'category': 'Human Resources/Planning', 'summary': 'Fusion Clock bridge to Odoo Planning - employee schedule on the portal', 'description': """ @@ -26,6 +26,7 @@ Adds Odoo Planning to the Fusion Clock product family: 'fusion_clock', ], 'data': [ + 'views/planning_slot_views.xml', 'views/portal_schedule_templates.xml', 'views/portal_nav_inherit.xml', ], diff --git a/fusion_planning/models/__init__.py b/fusion_planning/models/__init__.py new file mode 100644 index 00000000..3d3d7a1f --- /dev/null +++ b/fusion_planning/models/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- +from . import planning_slot diff --git a/fusion_planning/models/planning_slot.py b/fusion_planning/models/planning_slot.py new file mode 100644 index 00000000..8ef49295 --- /dev/null +++ b/fusion_planning/models/planning_slot.py @@ -0,0 +1,65 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 Nexa Systems Inc. +# License OPL-1 (Odoo Proprietary License v1.0) + +from odoo import api, fields, models + + +class PlanningSlot(models.Model): + _inherit = 'planning.slot' + + # Bulk-create helper: when set on a NEW slot, the system also creates + # one identical copy of the shift for each of these resources. + # Combined with the recurrence config, this lets a manager schedule + # the same shift across many employees in a single Save. + x_fc_additional_resource_ids = fields.Many2many( + 'resource.resource', + 'fc_planning_slot_extra_resource_rel', + 'slot_id', + 'resource_id', + string='Apply Also To', + help="Also create this same shift for each of these employees. " + "Useful when scheduling the same shift across many people in one go.", + ) + + @api.model_create_multi + def create(self, vals_list): + # 1. Auto-publish: every new shift is born published so employees + # see it immediately. Manager keeps full control via the existing + # Publish/Unpublish buttons after the fact. + # 2. Multi-resource expansion: if a manager fills the Apply Also To + # field, build one extra vals dict per additional resource. + expanded_vals_list = [] + for vals in vals_list: + vals.setdefault('state', 'published') + + extra_ids = self._fc_pop_additional_resource_ids(vals) + primary_rid = vals.get('resource_id') + + expanded_vals_list.append(vals) + + for rid in extra_ids: + if rid == primary_rid: + continue + copy_vals = dict(vals) + copy_vals['resource_id'] = rid + copy_vals.pop('x_fc_additional_resource_ids', None) + expanded_vals_list.append(copy_vals) + + return super().create(expanded_vals_list) + + @api.model + def _fc_pop_additional_resource_ids(self, vals): + """Pop and flatten the m2m vals into a plain list of resource ids.""" + cmds = vals.pop('x_fc_additional_resource_ids', None) or [] + ids = [] + for cmd in cmds: + # Odoo m2m commands: (6, 0, ids) replace, (4, id) link, (1, id, vals) update + if isinstance(cmd, (list, tuple)): + if cmd[0] == 6 and len(cmd) >= 3: + ids.extend(cmd[2]) + elif cmd[0] == 4 and len(cmd) >= 2: + ids.append(cmd[1]) + elif isinstance(cmd, int): + ids.append(cmd) + return ids diff --git a/fusion_planning/views/planning_slot_views.xml b/fusion_planning/views/planning_slot_views.xml new file mode 100644 index 00000000..818b3572 --- /dev/null +++ b/fusion_planning/views/planning_slot_views.xml @@ -0,0 +1,22 @@ + + + + + + planning.slot.form.inherit.fusion_planning + planning.slot + + + + + + + + +