Files
Odoo-Modules/fusion_claims/models/dashboard.py
2026-02-22 01:22:18 -05:00

163 lines
6.6 KiB
Python

# -*- coding: utf-8 -*-
# Copyright 2024-2026 Nexa Systems Inc.
# License OPL-1 (Odoo Proprietary License v1.0)
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'
_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')
# 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()
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>'
)
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 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, []),
}