diff --git a/fusion_claims/models/dashboard.py b/fusion_claims/models/dashboard.py index 3b6fcfc5..29386954 100644 --- a/fusion_claims/models/dashboard.py +++ b/fusion_claims/models/dashboard.py @@ -300,3 +300,198 @@ class FusionClaimsDashboard(models.TransientModel): rec.mod_pod_submitted_count = SO.search_count(base + [ ('x_fc_mod_status', '=', 'pod_submitted'), ]) + + # ========================================================================= + # Open-list action methods + # ========================================================================= + def _so_list_action(self, name, domain): + return { + 'type': 'ir.actions.act_window', + 'name': name, + 'res_model': 'sale.order', + 'view_mode': 'list,form', + 'domain': self._role_filter_domain() + domain, + 'target': 'current', + } + + # ----- ADP Pre-Approval ----- + def action_open_adp_waiting_app(self): + return self._so_list_action('ADP — Waiting for Application', [ + ('x_fc_adp_application_status', 'in', + ['waiting_for_application', 'assessment_completed']), + ]) + + def action_open_adp_app_received(self): + return self._so_list_action('ADP — Application Received', [ + ('x_fc_adp_application_status', '=', 'application_received'), + ]) + + def action_open_adp_ready_submit(self): + return self._so_list_action('ADP — Ready for Submission', [ + ('x_fc_adp_application_status', '=', 'ready_submission'), + ]) + + def action_open_adp_needs_correction(self): + return self._so_list_action('ADP — Needs Correction', [ + ('x_fc_adp_application_status', '=', 'needs_correction'), + ]) + + # ----- ADP Post-Approval ----- + def action_open_adp_approved(self): + return self._so_list_action('ADP — Approved', [ + ('x_fc_adp_application_status', 'in', ['approved', 'approved_deduction']), + ]) + + def action_open_adp_ready_delivery(self): + return self._so_list_action('ADP — Ready for Delivery', [ + ('x_fc_adp_application_status', '=', 'ready_delivery'), + ]) + + def action_open_adp_ready_bill(self): + return self._so_list_action('ADP — Ready to Bill', [ + ('x_fc_adp_application_status', '=', 'ready_bill'), + ]) + + def action_open_adp_on_hold(self): + return self._so_list_action('ADP — On Hold', [ + ('x_fc_adp_application_status', '=', 'on_hold'), + ]) + + # ----- MOD ----- + def action_open_mod_awaiting_funding(self): + return self._so_list_action('MOD — Awaiting Funding', [ + ('x_fc_mod_status', '=', 'awaiting_funding'), + ]) + + def action_open_mod_funding_approved(self): + return self._so_list_action('MOD — Funding Approved', [ + ('x_fc_mod_status', '=', 'funding_approved'), + ]) + + def action_open_mod_pca_received(self): + return self._so_list_action('MOD — PCA Received', [ + ('x_fc_mod_status', '=', 'contract_received'), + ]) + + def action_open_mod_project_complete(self): + return self._so_list_action('MOD — Project Complete', [ + ('x_fc_mod_status', '=', 'project_complete'), + ]) + + def action_open_mod_pod_submitted(self): + return self._so_list_action('MOD — POD Submitted', [ + ('x_fc_mod_status', '=', 'pod_submitted'), + ]) + + # ----- Other funders ----- + def action_open_odsp_cases(self): + return self._so_list_action('ODSP Cases', [ + ('state', '!=', 'cancel'), + ('x_fc_sale_type', 'in', ['odsp', 'adp_odsp']), + ]) + + def action_open_wsib_cases(self): + return self._so_list_action('WSIB Cases', [ + ('state', '!=', 'cancel'), + ('x_fc_sale_type', '=', 'wsib'), + ]) + + def action_open_insurance_cases(self): + return self._so_list_action('Insurance Cases', [ + ('state', '!=', 'cancel'), + ('x_fc_sale_type', '=', 'insurance'), + ]) + + def action_open_mdc_cases(self): + return self._so_list_action('Muscular Dystrophy Cases', [ + ('state', '!=', 'cancel'), + ('x_fc_sale_type', '=', 'muscular_dystrophy'), + ]) + + def action_open_hardship_cases(self): + return self._so_list_action('Hardship Cases', [ + ('state', '!=', 'cancel'), + ('x_fc_sale_type', '=', 'hardship'), + ]) + + def action_open_acsd_cases(self): + return self._so_list_action('ACSD Cases', [ + ('state', '!=', 'cancel'), + ('x_fc_client_type', '=', 'ACS'), + ]) + + # ----- Bottlenecks ----- + def action_open_bottleneck_no_pod(self): + return self._so_list_action('Bottleneck — Approved without POD', [ + ('x_fc_adp_application_status', 'in', ['approved', 'approved_deduction']), + ('x_fc_proof_of_delivery', '=', False), + ]) + + def action_open_bottleneck_no_response(self): + from datetime import date, timedelta + cutoff = date.today() - timedelta(days=14) + return self._so_list_action('Bottleneck — Submitted, no response', [ + ('x_fc_adp_application_status', 'in', ['submitted', 'resubmitted']), + ('x_fc_claim_submission_date', '<', cutoff), + ]) + + # ----- Activities ----- + def action_open_my_activities(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'My Activities', + 'res_model': 'mail.activity', + 'view_mode': 'list,form', + 'domain': [ + ('user_id', '=', self.env.user.id), + ('res_model', 'in', ['sale.order', 'account.move', + 'fusion.technician.task']), + ], + 'target': 'current', + } + + # ----- KPI drill-downs ----- + def action_open_kpi_ready(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'Ready to Claim (ADP)', + 'res_model': 'account.move', + 'view_mode': 'list,form', + 'domain': self._invoice_role_filter() + [ + ('move_type', '=', 'out_invoice'), + ('state', '=', 'posted'), + ('x_fc_adp_billing_status', '=', 'waiting'), + ('adp_exported', '=', False), + ], + 'target': 'current', + } + + def action_open_kpi_claimed(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'Claimed This Period', + 'res_model': 'account.move', + 'view_mode': 'list,form', + 'domain': self._invoice_role_filter() + [ + ('move_type', '=', 'out_invoice'), + ('state', '=', 'posted'), + ('x_fc_adp_billing_status', 'in', ['submitted', 'resubmitted']), + ('adp_export_date', '>=', self.posting_period_start), + ], + 'target': 'current', + } + + def action_open_kpi_ar(self): + return { + 'type': 'ir.actions.act_window', + 'name': 'Total AR (ADP)', + 'res_model': 'account.move', + 'view_mode': 'list,form', + 'domain': self._invoice_role_filter() + [ + ('move_type', '=', 'out_invoice'), + ('state', '=', 'posted'), + ('x_fc_invoice_type', '=', 'adp'), + ('payment_state', 'in', ['not_paid', 'partial']), + ], + 'target': 'current', + } diff --git a/fusion_claims/tests/test_dashboard.py b/fusion_claims/tests/test_dashboard.py index 08faf6f0..d87f4c94 100644 --- a/fusion_claims/tests/test_dashboard.py +++ b/fusion_claims/tests/test_dashboard.py @@ -299,3 +299,31 @@ class TestFusionClaimsDashboard(TransactionCase): self.assertEqual(dashboard.mod_pca_received_count, 1) self.assertEqual(dashboard.mod_project_complete_count, 1) self.assertEqual(dashboard.mod_pod_submitted_count, 1) + + # ------------------------------------------------------------------------- + # Task 7 — Open-list action methods + # ------------------------------------------------------------------------- + def test_action_open_adp_waiting_app_returns_correct_domain(self): + dashboard = self.Dashboard.with_user(self.manager).create({}) + action = dashboard.action_open_adp_waiting_app() + self.assertEqual(action['res_model'], 'sale.order') + self.assertIn(('x_fc_adp_application_status', 'in', + ['waiting_for_application', 'assessment_completed']), + action['domain']) + + def test_action_open_bottleneck_no_pod_returns_correct_domain(self): + dashboard = self.Dashboard.with_user(self.manager).create({}) + action = dashboard.action_open_bottleneck_no_pod() + self.assertEqual(action['res_model'], 'sale.order') + self.assertIn(('x_fc_proof_of_delivery', '=', False), action['domain']) + + def test_action_open_mod_awaiting_funding_returns_correct_domain(self): + dashboard = self.Dashboard.with_user(self.manager).create({}) + action = dashboard.action_open_mod_awaiting_funding() + self.assertEqual(action['res_model'], 'sale.order') + self.assertIn(('x_fc_mod_status', '=', 'awaiting_funding'), action['domain']) + + def test_action_open_my_activities_returns_activity_model(self): + dashboard = self.Dashboard.with_user(self.manager).create({}) + action = dashboard.action_open_my_activities() + self.assertEqual(action['res_model'], 'mail.activity')