diff --git a/fusion_helpdesk_central/__manifest__.py b/fusion_helpdesk_central/__manifest__.py index f116394a..004e39f8 100644 --- a/fusion_helpdesk_central/__manifest__.py +++ b/fusion_helpdesk_central/__manifest__.py @@ -3,7 +3,7 @@ # License OPL-1 { 'name': 'Fusion Helpdesk Central — Client API Keys', - 'version': '19.0.2.3.3', + 'version': '19.0.2.3.4', 'category': 'Productivity', 'summary': 'Admin UI on the central Odoo for issuing per-client API ' 'keys used by fusion_helpdesk client deployments.', diff --git a/fusion_helpdesk_central/models/engagement_wizard.py b/fusion_helpdesk_central/models/engagement_wizard.py index c4e3f6af..1ae5e438 100644 --- a/fusion_helpdesk_central/models/engagement_wizard.py +++ b/fusion_helpdesk_central/models/engagement_wizard.py @@ -331,12 +331,16 @@ class FusionHelpdeskEngagementWizard(models.TransientModel): # ------------------------------------------------------------------ def action_generate_summary(self): """Single mode: fire OpenAI with the current findings, drop the - result into ai_summary. Returns True (no navigation) so the - wizard stays open and the form view re-renders with the new - summary populated. DO NOT return an `act_window` with - `res_id=self.id` here — that puts the WIZARD's id into the new - action's `active_id`, which then collides with default_get's - ticket lookup and raises "Ticket no longer exists". + result into ai_summary. Returns an act_window dict that re-opens + the SAME wizard record — the only Odoo-19 idiom that reliably + keeps a target='new' wizard dialog open after a button click. + Returning True/None auto-closes the modal (Odoo's "wizard done" + convention). + + The previous self-id collision bug (where active_id of the + re-opened action was the wizard's own id, which default_get + mis-read as a ticket id) is now prevented by default_get's + active_model=='helpdesk.ticket' guard. """ self.ensure_one() if self.mode != 'single' or not self.ticket_id: @@ -349,15 +353,12 @@ class FusionHelpdeskEngagementWizard(models.TransientModel): ) self.ai_summary = summary self.ai_unavailable = not bool(summary) - return True + return self._reopen_action() def action_generate_all_summaries(self): """Bulk mode: fire OpenAI per-ticket in parallel using each line's - own findings. Lines that already have a non-empty ai_summary get - regenerated too (the user clicked the button — they meant it). - - Returns True for the same reason as action_generate_summary: - keep the dialog open; don't re-navigate. + own findings. Returns an act_window dict to keep the dialog open + (see action_generate_summary for why we can't just return True). """ self.ensure_one() if self.mode != 'bulk' or not self.line_ids: @@ -373,7 +374,28 @@ class FusionHelpdeskEngagementWizard(models.TransientModel): line.ai_summary = results.get(line.ticket_id.id, '') any_ok = any(results.values()) self.ai_unavailable = not any_ok - return True + return self._reopen_action() + + def _reopen_action(self): + """Return the act_window dict that re-opens the same wizard record. + + Passes an EXPLICITLY EMPTY context override so the parent ticket + form's active_id / active_model don't leak in and confuse any + future default_get call. The wizard record is loaded directly by + res_id; default_get won't be called for a load (Odoo 19 only + invokes it when creating new records), but the empty context is + belt-and-suspenders against future regressions. + """ + self.ensure_one() + return { + 'type': 'ir.actions.act_window', + 'name': _('Request Owner Approval'), + 'res_model': self._name, + 'res_id': self.id, + 'view_mode': 'form', + 'target': 'new', + 'context': {}, + } # ------------------------------------------------------------------ # Send: write engagement state + queue mail