feat(fusion_helpdesk): embedded ticket inbox UI + unread badge
Dialog gains New/My Tickets tabs, ticket list (with admin Mine/All toggle + unread dots), thread view with inline reply, confirmed reply-email field, and an Open-full-ticket magic link. Systray shows an unread-reply badge (polled). Controller returns portal_url + per-message attachment counts. Assets compile clean (light+dark). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -442,7 +442,8 @@ class FusionHelpdeskController(http.Controller):
|
||||
[[('model', '=', 'helpdesk.ticket'),
|
||||
('res_id', '=', ticket_id),
|
||||
('message_type', 'in', ['comment', 'email'])]],
|
||||
{'fields': ['id', 'date', 'body', 'author_id', 'subtype_id'],
|
||||
{'fields': ['id', 'date', 'body', 'author_id', 'subtype_id',
|
||||
'attachment_ids'],
|
||||
'order': 'id asc'},
|
||||
)
|
||||
internal = self._internal_subtype_map(
|
||||
@@ -456,6 +457,7 @@ class FusionHelpdeskController(http.Controller):
|
||||
'body': m['body'] or '',
|
||||
'author': (m['author_id'][1] if m['author_id'] else ''),
|
||||
'author_id': (m['author_id'][0] if m['author_id'] else False),
|
||||
'attachment_count': len(m.get('attachment_ids') or []),
|
||||
'subtype_is_internal': internal.get(st[0], False) if st else False,
|
||||
}
|
||||
if is_public_message(msg):
|
||||
@@ -549,7 +551,8 @@ class FusionHelpdeskController(http.Controller):
|
||||
) + [('id', '=', ticket_id)]
|
||||
try:
|
||||
found = self._rpc(cfg, 'helpdesk.ticket', 'search_read', [domain],
|
||||
{'fields': ['id', 'name', 'stage_id'], 'limit': 1})
|
||||
{'fields': ['id', 'name', 'stage_id',
|
||||
'access_token'], 'limit': 1})
|
||||
if not found:
|
||||
return {'ok': False, 'error': 'not_found',
|
||||
'message': _('Ticket not found or not accessible.')}
|
||||
@@ -560,9 +563,16 @@ class FusionHelpdeskController(http.Controller):
|
||||
request.env['fusion.helpdesk.ticket.seen']._mark_seen(
|
||||
ticket_id, max(m['id'] for m in messages))
|
||||
t = found[0]
|
||||
# Magic link: the customer's own access-token URL on central, so they
|
||||
# can open the full ticket (incl. attachments) in the portal if needed.
|
||||
portal_url = ''
|
||||
if t.get('access_token'):
|
||||
portal_url = '%s/my/ticket/%s/%s' % (
|
||||
cfg['url'].rstrip('/'), t['id'], t['access_token'])
|
||||
return {'ok': True, 'ticket': {
|
||||
'id': t['id'], 'subject': t['name'],
|
||||
'stage': t['stage_id'][1] if t['stage_id'] else '',
|
||||
'portal_url': portal_url,
|
||||
'messages': messages}}
|
||||
|
||||
@http.route('/fusion_helpdesk/ticket/<int:ticket_id>/reply',
|
||||
|
||||
Reference in New Issue
Block a user