"""Fusion-engine-routed AI tools for customer follow-ups. These tools are exposed through TOOL_DISPATCH and let the assistant query the customer follow-up engine via natural language. All tools degrade gracefully when fusion_accounting_followup is not installed. """ import logging _logger = logging.getLogger(__name__) def fusion_list_overdue(env, params): """List partners with overdue invoices, sorted by risk.""" if 'fusion.followup.engine' not in env.registry: return {'error': 'fusion_accounting_followup not installed'} from ..data_adapters import get_adapter adapter = get_adapter(env, 'followup') return adapter.list_overdue( status=params.get('status'), limit=int(params.get('limit', 50)), company_id=int(params['company_id']) if params.get('company_id') else env.company.id, ) def fusion_get_partner_followup_detail(env, params): """Detailed follow-up state for a single partner: aging, risk, history.""" if 'fusion.followup.engine' not in env.registry: return {'error': 'fusion_accounting_followup not installed'} Partner = env['res.partner'] partner = Partner.browse(int(params['partner_id'])) if not partner.exists(): return {'error': 'Partner not found'} engine = env['fusion.followup.engine'] overdue = engine.get_overdue_for_partner(partner) history = engine.snapshot_followup_history(partner, limit=10) return { 'partner_id': partner.id, 'partner_name': partner.name, 'overdue': overdue, 'history': history, } def fusion_generate_followup_text(env, params): """Generate (or fall back to template) follow-up subject + body.""" if 'fusion.followup.engine' not in env.registry: return {'error': 'fusion_accounting_followup not installed'} from odoo.addons.fusion_accounting_followup.services.followup_text_generator import ( generate_followup_text, ) return generate_followup_text( env, partner_name=params.get('partner_name', ''), total_overdue=float(params.get('total_overdue', 0)), currency_code=params.get('currency_code', 'USD'), longest_overdue_days=int(params.get('longest_overdue_days', 0)), tone=params.get('tone', 'gentle'), invoice_count=int(params.get('invoice_count', 0)), ) def fusion_send_followup(env, params): """Send a follow-up email via the engine (creates a fusion.followup.run).""" if 'fusion.followup.engine' not in env.registry: return {'error': 'fusion_accounting_followup not installed'} from ..data_adapters import get_adapter adapter = get_adapter(env, 'followup') return adapter.send_followup( partner_id=int(params['partner_id']), level_id=int(params['level_id']) if params.get('level_id') else None, force=bool(params.get('force', False)), ) def fusion_get_partner_risk_score(env, params): """Compute and return the payment-risk score + drivers for a partner.""" if 'fusion.followup.engine' not in env.registry: return {'error': 'fusion_accounting_followup not installed'} partner = env['res.partner'].browse(int(params['partner_id'])) if not partner.exists(): return {'error': 'Partner not found'} overdue = env['fusion.followup.engine'].get_overdue_for_partner(partner) return { 'partner_id': partner.id, 'partner_name': partner.name, 'risk': overdue['risk'], } TOOLS = { 'fusion_list_overdue': fusion_list_overdue, 'fusion_get_partner_followup_detail': fusion_get_partner_followup_detail, 'fusion_generate_followup_text': fusion_generate_followup_text, 'fusion_send_followup': fusion_send_followup, 'fusion_get_partner_risk_score': fusion_get_partner_risk_score, }