refactor(fusion_accounting_ai): route accounts_receivable tools through FollowupAdapter
Task 13 Step 7 of phase-0 plan.
Routes the AR tools through the FollowupAdapter so they work identically on
fusion-native, Enterprise, and pure Community installs:
- get_ar_aging → FollowupAdapter.aged_receivables()
- get_overdue_invoices → FollowupAdapter.overdue_invoices()
- send_followup → FollowupAdapter.send_followup()
- get_followup_report → FollowupAdapter.followup_report_html()
FollowupAdapter extended:
- overdue_invoices() now includes partner_email, partner_phone and
amount_total so the tool wrapper can render its richer response.
- aged_receivables() and aged_payables() new shared-implementation method
_aged_buckets() produces the 5-bucket aging shape the AR/AP tools emit.
- followup_report_html() and send_followup() isolate the Enterprise
account.followup.report / partner.execute_followup calls; Community mode
returns a graceful error dict.
Pure-Community tools in accounts_receivable.py (get_partner_balance,
reconcile_payment_to_invoice, get_unmatched_payments) unchanged — they touch
account.move / account.move.line directly which is tri-mode safe.
3 new data-adapter tests added (total: 9; all passing on westin-v19).
Made-with: Cursor
This commit is contained in:
@@ -83,6 +83,38 @@ class TestFollowupAdapter(TransactionCase):
|
||||
rows = adapter.overdue_invoices(days_overdue=30)
|
||||
self.assertIsInstance(rows, list)
|
||||
|
||||
def test_overdue_invoices_row_has_contact_fields(self):
|
||||
"""The enriched shape must include email, phone, and amount_total so
|
||||
the accounts_receivable tool wrapper can render them."""
|
||||
adapter = get_adapter(self.env, 'followup')
|
||||
rows = adapter.overdue_invoices(days_overdue=30, limit=5)
|
||||
for row in rows:
|
||||
for key in (
|
||||
'id', 'name', 'partner_id', 'partner_name',
|
||||
'partner_email', 'partner_phone',
|
||||
'invoice_date_due', 'amount_total', 'amount_residual',
|
||||
'days_overdue',
|
||||
):
|
||||
self.assertIn(key, row, f"Missing key {key!r} in overdue row")
|
||||
|
||||
def test_aged_receivables_returns_bucket_shape(self):
|
||||
adapter = get_adapter(self.env, 'followup')
|
||||
result = adapter.aged_receivables(company_id=self.env.company.id)
|
||||
self.assertIn('total', result)
|
||||
self.assertIn('buckets', result)
|
||||
self.assertIn('line_count', result)
|
||||
for bucket in ('current', '1_30', '31_60', '61_90', '90_plus'):
|
||||
self.assertIn(bucket, result['buckets'])
|
||||
|
||||
def test_aged_payables_returns_bucket_shape(self):
|
||||
adapter = get_adapter(self.env, 'followup')
|
||||
result = adapter.aged_payables(company_id=self.env.company.id)
|
||||
self.assertIn('total', result)
|
||||
self.assertIn('buckets', result)
|
||||
self.assertIn('line_count', result)
|
||||
for bucket in ('current', '1_30', '31_60', '61_90', '90_plus'):
|
||||
self.assertIn(bucket, result['buckets'])
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestAssetsAdapter(TransactionCase):
|
||||
|
||||
Reference in New Issue
Block a user