feat(fusion_claims): scaffold dashboard model with role filter

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-05-21 03:46:17 -04:00
parent 53fd6114e7
commit 1a8a96d94e

View File

@@ -4,159 +4,40 @@
from odoo import api, fields, models
CASE_TYPE_SELECTION = [
('adp', 'ADP'),
('odsp', 'ODSP'),
('march_of_dimes', 'March of Dimes'),
('hardship', 'Hardship Funding'),
('acsd', 'ACSD'),
('muscular_dystrophy', 'Muscular Dystrophy'),
('insurance', 'Insurance'),
('wsib', 'WSIB'),
]
TYPE_DOMAINS = {
'adp': [('x_fc_sale_type', 'in', ['adp', 'adp_odsp'])],
'odsp': [('x_fc_sale_type', 'in', ['odsp', 'adp_odsp'])],
'march_of_dimes': [('x_fc_sale_type', '=', 'march_of_dimes')],
'hardship': [('x_fc_sale_type', '=', 'hardship')],
'acsd': [('x_fc_client_type', '=', 'ACS')],
'muscular_dystrophy': [('x_fc_sale_type', '=', 'muscular_dystrophy')],
'insurance': [('x_fc_sale_type', '=', 'insurance')],
'wsib': [('x_fc_sale_type', '=', 'wsib')],
}
TYPE_LABELS = dict(CASE_TYPE_SELECTION)
class FusionClaimsDashboard(models.TransientModel):
_name = 'fusion.claims.dashboard'
_inherit = 'fusion_claims.adp.posting.schedule.mixin'
_description = 'Fusion Claims Dashboard'
_rec_name = 'name'
name = fields.Char(default='Dashboard', readonly=True)
# Case counts by funding type
adp_count = fields.Integer(compute='_compute_stats')
odsp_count = fields.Integer(compute='_compute_stats')
march_of_dimes_count = fields.Integer(compute='_compute_stats')
hardship_count = fields.Integer(compute='_compute_stats')
acsd_count = fields.Integer(compute='_compute_stats')
muscular_dystrophy_count = fields.Integer(compute='_compute_stats')
insurance_count = fields.Integer(compute='_compute_stats')
wsib_count = fields.Integer(compute='_compute_stats')
total_profiles = fields.Integer(compute='_compute_stats')
# =========================================================================
# Role-aware filter
# =========================================================================
is_manager = fields.Boolean(compute='_compute_is_manager')
# Panel selectors (4 panels)
panel1_type = fields.Selection(CASE_TYPE_SELECTION, string='Window 1', default='adp')
panel2_type = fields.Selection(CASE_TYPE_SELECTION, string='Window 2', default='odsp')
panel3_type = fields.Selection(CASE_TYPE_SELECTION, string='Window 3', default='march_of_dimes')
panel4_type = fields.Selection(CASE_TYPE_SELECTION, string='Window 4', default='hardship')
# Panel HTML
panel1_html = fields.Html(compute='_compute_panels', sanitize=False)
panel2_html = fields.Html(compute='_compute_panels', sanitize=False)
panel3_html = fields.Html(compute='_compute_panels', sanitize=False)
panel4_html = fields.Html(compute='_compute_panels', sanitize=False)
panel1_title = fields.Char(compute='_compute_panels')
panel2_title = fields.Char(compute='_compute_panels')
panel3_title = fields.Char(compute='_compute_panels')
panel4_title = fields.Char(compute='_compute_panels')
def _compute_stats(self):
SO = self.env['sale.order'].sudo()
Profile = self.env['fusion.client.profile'].sudo()
def _compute_is_manager(self):
manager_group = self.env.ref('fusion_claims.group_fusion_claims_manager',
raise_if_not_found=False)
sale_mgr_group = self.env.ref('sales_team.group_sale_manager',
raise_if_not_found=False)
for rec in self:
rec.adp_count = SO.search_count(TYPE_DOMAINS['adp'])
rec.odsp_count = SO.search_count(TYPE_DOMAINS['odsp'])
rec.march_of_dimes_count = SO.search_count(TYPE_DOMAINS['march_of_dimes'])
rec.hardship_count = SO.search_count(TYPE_DOMAINS['hardship'])
rec.acsd_count = SO.search_count(TYPE_DOMAINS['acsd'])
rec.muscular_dystrophy_count = SO.search_count(TYPE_DOMAINS['muscular_dystrophy'])
rec.insurance_count = SO.search_count(TYPE_DOMAINS['insurance'])
rec.wsib_count = SO.search_count(TYPE_DOMAINS['wsib'])
rec.total_profiles = Profile.search_count([])
@api.depends('panel1_type', 'panel2_type', 'panel3_type', 'panel4_type')
def _compute_panels(self):
SO = self.env['sale.order'].sudo()
for rec in self:
for i in range(1, 5):
ptype = getattr(rec, f'panel{i}_type') or 'adp'
domain = TYPE_DOMAINS.get(ptype, [])
orders = SO.search(domain, order='create_date desc', limit=50)
count = SO.search_count(domain)
title = f'Window {i} - {TYPE_LABELS.get(ptype, ptype)} ({count} cases)'
html = rec._build_top_list(orders)
setattr(rec, f'panel{i}_title', title)
setattr(rec, f'panel{i}_html', html)
def _build_top_list(self, orders):
if not orders:
return '<p class="text-muted text-center py-4">No cases found</p>'
rows = []
for o in orders:
status = o.x_fc_adp_application_status or ''
status_label = dict(o._fields['x_fc_adp_application_status'].selection).get(status, status)
rows.append(
f'<tr>'
f'<td><a href="/odoo/sales/{o.id}">{o.name}</a></td>'
f'<td>{o.partner_id.name or ""}</td>'
f'<td>{status_label}</td>'
f'<td class="text-end">${o.amount_total:,.2f}</td>'
f'</tr>'
user = rec.env.user
rec.is_manager = bool(
(manager_group and user.has_group('fusion_claims.group_fusion_claims_manager'))
or (sale_mgr_group and user.has_group('sales_team.group_sale_manager'))
)
return (
'<table class="table table-sm table-hover mb-0">'
'<thead><tr><th>Order</th><th>Client</th><th>Status</th><th class="text-end">Total</th></tr></thead>'
'<tbody>' + ''.join(rows) + '</tbody></table>'
)
def action_open_order(self, order_id):
"""Open a specific sale order with breadcrumbs."""
return {
'type': 'ir.actions.act_window',
'name': 'Sale Order',
'res_model': 'sale.order',
'view_mode': 'form',
'res_id': order_id,
'target': 'current',
}
def _role_filter_domain(self):
"""Common domain prefix for SO-based counts.
def action_open_adp(self):
return self._open_type_action('adp')
def action_open_odsp(self):
return self._open_type_action('odsp')
def action_open_march(self):
return self._open_type_action('march_of_dimes')
def action_open_hardship(self):
return self._open_type_action('hardship')
def action_open_acsd(self):
return self._open_type_action('acsd')
def action_open_muscular(self):
return self._open_type_action('muscular_dystrophy')
def action_open_insurance(self):
return self._open_type_action('insurance')
def action_open_wsib(self):
return self._open_type_action('wsib')
def action_open_profiles(self):
return {
'type': 'ir.actions.act_window', 'name': 'Client Profiles',
'res_model': 'fusion.client.profile', 'view_mode': 'list,form',
}
def _open_type_action(self, type_key):
return {
'type': 'ir.actions.act_window',
'name': f'{TYPE_LABELS.get(type_key, type_key)} Cases',
'res_model': 'sale.order', 'view_mode': 'list,form',
'domain': TYPE_DOMAINS.get(type_key, []),
}
Managers (fusion_claims.group_fusion_claims_manager or
sales_team.group_sale_manager) see everything.
Other users see only SOs where they are the salesperson.
"""
self.ensure_one()
if self.is_manager:
return []
return [('user_id', '=', self.env.user.id)]