165 lines
6.3 KiB
Python
165 lines
6.3 KiB
Python
# -*- coding: utf-8 -*-
|
|
# Copyright 2024-2026 Nexa Systems Inc.
|
|
# License OPL-1 (Odoo Proprietary License v1.0)
|
|
|
|
import json
|
|
import logging
|
|
|
|
from odoo import api, models
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AIAgentFusionClaims(models.Model):
|
|
"""Extend ai.agent with Fusion Claims tool methods."""
|
|
_inherit = 'ai.agent'
|
|
|
|
def _fc_tool_search_clients(self, search_term=None, city_filter=None, condition_filter=None):
|
|
"""AI Tool: Search client profiles."""
|
|
Profile = self.env['fusion.client.profile'].sudo()
|
|
domain = []
|
|
if search_term:
|
|
domain = ['|', '|', '|',
|
|
('first_name', 'ilike', search_term),
|
|
('last_name', 'ilike', search_term),
|
|
('health_card_number', 'ilike', search_term),
|
|
('city', 'ilike', search_term),
|
|
]
|
|
if city_filter:
|
|
domain.append(('city', 'ilike', city_filter))
|
|
if condition_filter:
|
|
domain.append(('medical_condition', 'ilike', condition_filter))
|
|
|
|
profiles = Profile.search(domain, limit=20)
|
|
results = []
|
|
for p in profiles:
|
|
results.append({
|
|
'id': p.id,
|
|
'name': p.display_name,
|
|
'health_card': p.health_card_number or '',
|
|
'dob': str(p.date_of_birth) if p.date_of_birth else '',
|
|
'city': p.city or '',
|
|
'condition': (p.medical_condition or '')[:100],
|
|
'claims': p.claim_count,
|
|
'total_adp': float(p.total_adp_funded),
|
|
'total_client': float(p.total_client_portion),
|
|
})
|
|
return json.dumps({'count': len(results), 'profiles': results})
|
|
|
|
def _fc_tool_client_details(self, profile_id):
|
|
"""AI Tool: Get detailed client information."""
|
|
Profile = self.env['fusion.client.profile'].sudo()
|
|
profile = Profile.browse(int(profile_id))
|
|
if not profile.exists():
|
|
return json.dumps({'error': 'Profile not found'})
|
|
|
|
# Get orders
|
|
orders = []
|
|
if profile.partner_id:
|
|
for o in self.env['sale.order'].sudo().search([
|
|
('partner_id', '=', profile.partner_id.id),
|
|
('x_fc_sale_type', '!=', False),
|
|
], limit=20):
|
|
orders.append({
|
|
'name': o.name,
|
|
'sale_type': o.x_fc_sale_type,
|
|
'status': o.x_fc_adp_application_status or '',
|
|
'adp_total': float(o.x_fc_adp_portion_total),
|
|
'client_total': float(o.x_fc_client_portion_total),
|
|
'total': float(o.amount_total),
|
|
'date': str(o.date_order.date()) if o.date_order else '',
|
|
})
|
|
|
|
# Get applications
|
|
apps = []
|
|
for a in profile.application_data_ids[:10]:
|
|
apps.append({
|
|
'date': str(a.application_date) if a.application_date else '',
|
|
'device': a.base_device or '',
|
|
'category': a.device_category or '',
|
|
'reason': a.reason_for_application or '',
|
|
'condition': (a.medical_condition or '')[:100],
|
|
'authorizer': f'{a.authorizer_first_name or ""} {a.authorizer_last_name or ""}'.strip(),
|
|
})
|
|
|
|
return json.dumps({
|
|
'profile': {
|
|
'id': profile.id,
|
|
'name': profile.display_name,
|
|
'first_name': profile.first_name,
|
|
'last_name': profile.last_name,
|
|
'health_card': profile.health_card_number or '',
|
|
'dob': str(profile.date_of_birth) if profile.date_of_birth else '',
|
|
'city': profile.city or '',
|
|
'province': profile.province or '',
|
|
'postal_code': profile.postal_code or '',
|
|
'phone': profile.home_phone or '',
|
|
'condition': profile.medical_condition or '',
|
|
'mobility': profile.mobility_status or '',
|
|
'benefits': {
|
|
'social_assistance': profile.receives_social_assistance,
|
|
'type': profile.benefit_type or '',
|
|
'wsib': profile.wsib_eligible,
|
|
'vac': profile.vac_eligible,
|
|
},
|
|
'claims_count': profile.claim_count,
|
|
'total_adp': float(profile.total_adp_funded),
|
|
'total_client': float(profile.total_client_portion),
|
|
'total_amount': float(profile.total_amount),
|
|
'last_assessment': str(profile.last_assessment_date) if profile.last_assessment_date else '',
|
|
},
|
|
'orders': orders,
|
|
'applications': apps,
|
|
})
|
|
|
|
def _fc_tool_claims_stats(self):
|
|
"""AI Tool: Get aggregated claims statistics."""
|
|
SO = self.env['sale.order'].sudo()
|
|
Profile = self.env['fusion.client.profile'].sudo()
|
|
|
|
total_profiles = Profile.search_count([])
|
|
total_orders = SO.search_count([('x_fc_sale_type', '!=', False)])
|
|
|
|
# By sale type
|
|
type_data = SO.read_group(
|
|
[('x_fc_sale_type', '!=', False)],
|
|
['x_fc_sale_type', 'amount_total:sum'],
|
|
['x_fc_sale_type'],
|
|
)
|
|
by_type = {}
|
|
for r in type_data:
|
|
by_type[r['x_fc_sale_type']] = {
|
|
'count': r['x_fc_sale_type_count'],
|
|
'total': float(r['amount_total'] or 0),
|
|
}
|
|
|
|
# By status
|
|
status_data = SO.read_group(
|
|
[('x_fc_sale_type', '!=', False), ('x_fc_adp_application_status', '!=', False)],
|
|
['x_fc_adp_application_status'],
|
|
['x_fc_adp_application_status'],
|
|
)
|
|
by_status = {}
|
|
for r in status_data:
|
|
by_status[r['x_fc_adp_application_status']] = r['x_fc_adp_application_status_count']
|
|
|
|
# By city (top 10)
|
|
city_data = Profile.read_group(
|
|
[('city', '!=', False)],
|
|
['city'],
|
|
['city'],
|
|
limit=10,
|
|
orderby='city_count desc',
|
|
)
|
|
by_city = {}
|
|
for r in city_data:
|
|
by_city[r['city']] = r['city_count']
|
|
|
|
return json.dumps({
|
|
'total_profiles': total_profiles,
|
|
'total_orders': total_orders,
|
|
'by_sale_type': by_type,
|
|
'by_status': by_status,
|
|
'top_cities': by_city,
|
|
})
|