feat(fusion_helpdesk): group My Tickets into Critical/New/Solved sections

The flat write_date-sorted list was hard to scan with 50+ tickets — solved
ones were intermixed with active ones, and there was no signal for
priority. Bucket each ticket server-side into 'critical' (open + priority
High/Urgent), 'solved' (stage marked fold=True on central) or 'open'
(everything else), and render three labelled sections in the dialog with
sticky headers, count badges, and per-group accent colours. Backend keeps
its write_date desc order so latest is always at top within each bucket.

Bucketing uses helpdesk.stage.fold (not the stage name) so renaming
"Solved" to "Done" on the central won't quietly mis-categorise rows.
Adds bucket_ticket() in utils.py with unit tests covering the
folded-wins-over-priority precedence and the missing-priority fallback.

Also surfaces a small Urgent (triangle) / High (arrow) icon on each row
so a critical ticket reads at a glance even after a user scrolls past
the section header.

Bumps fusion_helpdesk to 19.0.1.6.0.
This commit is contained in:
gsinghpal
2026-05-27 11:04:31 -04:00
parent aabfc1afe7
commit 3e5ced1655
7 changed files with 172 additions and 10 deletions

View File

@@ -12,6 +12,7 @@ from odoo.tests import TransactionCase, tagged
from odoo.addons.fusion_helpdesk.utils import (
build_ticket_vals,
build_scope_domain,
bucket_ticket,
is_public_message,
compute_unread_count,
_norm_email,
@@ -129,3 +130,32 @@ class TestNormEmail(TransactionCase):
# every inbox endpoint. Guard that the name is resolvable there.
from odoo.addons.fusion_helpdesk.controllers import main
self.assertTrue(hasattr(main, '_norm_email'))
@tagged('post_install', '-at_install', 'fusion_helpdesk')
class TestBucketTicket(TransactionCase):
"""Bucketing pins how the My Tickets inbox sections work — getting this
wrong used to scatter Solved tickets in with New ones, defeating the
whole point of the grouped view."""
def test_folded_stage_goes_to_solved(self):
# Folded wins even if priority is high — closed tickets aren't
# actionable so they belong in Solved regardless.
self.assertEqual(bucket_ticket(True, '0'), 'solved')
self.assertEqual(bucket_ticket(True, '3'), 'solved')
def test_open_high_or_urgent_promotes_to_critical(self):
self.assertEqual(bucket_ticket(False, '2'), 'critical')
self.assertEqual(bucket_ticket(False, '3'), 'critical')
def test_open_low_or_normal_is_just_open(self):
self.assertEqual(bucket_ticket(False, '0'), 'open')
self.assertEqual(bucket_ticket(False, '1'), 'open')
self.assertEqual(bucket_ticket(False, None), 'open') # missing -> normal
self.assertEqual(bucket_ticket(False, ''), 'open')
def test_controller_namespace_resolves_bucket_ticket(self):
# Regression: the inbox controller imports bucket_ticket — if the
# name disappears from utils.py, every list call would 500.
from odoo.addons.fusion_helpdesk.controllers import main
self.assertTrue(hasattr(main, 'bucket_ticket'))