diff --git a/fusion_accounting_ai/services/data_adapters/bank_rec.py b/fusion_accounting_ai/services/data_adapters/bank_rec.py index 727e9c3e..2f48be80 100644 --- a/fusion_accounting_ai/services/data_adapters/bank_rec.py +++ b/fusion_accounting_ai/services/data_adapters/bank_rec.py @@ -14,28 +14,60 @@ class BankRecAdapter(DataAdapter): FUSION_MODEL = 'fusion.bank.rec.widget' ENTERPRISE_MODULE = 'account_accountant' - def list_unreconciled(self, journal_id, limit=100): - """Return unreconciled bank statement lines for a journal.""" - return self._dispatch('list_unreconciled', journal_id=journal_id, limit=limit) + def list_unreconciled(self, journal_id=None, limit=100, date_from=None, + date_to=None, min_amount=None, company_id=None): + """Return unreconciled bank statement lines. - def list_unreconciled_via_fusion(self, journal_id, limit=100): + All filter params are optional; pass company_id to restrict results to + a single company (the AI tools always do this). + """ + return self._dispatch( + 'list_unreconciled', + journal_id=journal_id, limit=limit, + date_from=date_from, date_to=date_to, + min_amount=min_amount, company_id=company_id, + ) + + def list_unreconciled_via_fusion(self, journal_id=None, limit=100, + date_from=None, date_to=None, + min_amount=None, company_id=None): # Phase 1 will add fusion.bank.rec.widget; this method becomes the primary path. # For now: even when the model exists, delegate to community read shape. - return self.list_unreconciled_via_community(journal_id=journal_id, limit=limit) + return self.list_unreconciled_via_community( + journal_id=journal_id, limit=limit, + date_from=date_from, date_to=date_to, + min_amount=min_amount, company_id=company_id, + ) - def list_unreconciled_via_enterprise(self, journal_id, limit=100): + def list_unreconciled_via_enterprise(self, journal_id=None, limit=100, + date_from=None, date_to=None, + min_amount=None, company_id=None): # Enterprise's bank rec uses a JS-side service; from Python the cleanest # backend access is the same Community search (the data lives in # account.bank.statement.line either way). This adapter's purpose is # to expose a stable shape to AI tools regardless of which UI the user has. - return self.list_unreconciled_via_community(journal_id=journal_id, limit=limit) + return self.list_unreconciled_via_community( + journal_id=journal_id, limit=limit, + date_from=date_from, date_to=date_to, + min_amount=min_amount, company_id=company_id, + ) - def list_unreconciled_via_community(self, journal_id, limit=100): + def list_unreconciled_via_community(self, journal_id=None, limit=100, + date_from=None, date_to=None, + min_amount=None, company_id=None): Line = self.env['account.bank.statement.line'].sudo() - records = Line.search([ - ('journal_id', '=', journal_id), - ('is_reconciled', '=', False), - ], limit=limit, order='date desc, id desc') + domain = [('is_reconciled', '=', False)] + if journal_id is not None: + domain.append(('journal_id', '=', journal_id)) + if company_id is not None: + domain.append(('company_id', '=', company_id)) + if date_from: + domain.append(('date', '>=', date_from)) + if date_to: + domain.append(('date', '<=', date_to)) + if min_amount is not None: + domain.append(('amount', '>=', min_amount)) + records = Line.search(domain, limit=limit, order='date desc, id desc') return [ { 'id': r.id, @@ -43,8 +75,10 @@ class BankRecAdapter(DataAdapter): 'payment_ref': r.payment_ref, 'amount': r.amount, 'partner_id': r.partner_id.id if r.partner_id else None, - 'partner_name': r.partner_id.name if r.partner_id else None, + 'partner_name': r.partner_name or (r.partner_id.name if r.partner_id else None), 'currency_id': r.currency_id.id if r.currency_id else None, + 'journal_id': r.journal_id.id, + 'journal_name': r.journal_id.name, } for r in records ] diff --git a/fusion_accounting_ai/services/tools/bank_reconciliation.py b/fusion_accounting_ai/services/tools/bank_reconciliation.py index 82cc2e8d..7c1b0a5b 100644 --- a/fusion_accounting_ai/services/tools/bank_reconciliation.py +++ b/fusion_accounting_ai/services/tools/bank_reconciliation.py @@ -6,28 +6,32 @@ _logger = logging.getLogger(__name__) def get_unreconciled_bank_lines(env, params): - domain = [('is_reconciled', '=', False), ('company_id', '=', env.company.id)] - if params.get('journal_id'): - domain.append(('journal_id', '=', int(params['journal_id']))) - if params.get('date_from'): - domain.append(('date', '>=', params['date_from'])) - if params.get('date_to'): - domain.append(('date', '<=', params['date_to'])) - if params.get('min_amount'): - domain.append(('amount', '>=', float(params['min_amount']))) - limit = int(params.get('limit', 50)) - lines = env['account.bank.statement.line'].search(domain, limit=limit, order='date desc') + """Return unreconciled bank lines for a journal/company. + + Routed through the bank_rec data adapter so the result shape is identical + whether the install profile is fusion-native, Enterprise, or pure Community. + """ + from ..data_adapters import get_adapter + adapter = get_adapter(env, 'bank_rec') + rows = adapter.list_unreconciled( + journal_id=int(params['journal_id']) if params.get('journal_id') else None, + limit=int(params.get('limit', 50)), + date_from=params.get('date_from'), + date_to=params.get('date_to'), + min_amount=float(params['min_amount']) if params.get('min_amount') else None, + company_id=env.company.id, + ) return { - 'count': len(lines), - 'total_amount': sum(abs(l.amount) for l in lines), + 'count': len(rows), + 'total_amount': sum(abs(r['amount']) for r in rows), 'lines': [{ - 'id': l.id, - 'date': str(l.date), - 'payment_ref': l.payment_ref or '', - 'partner_name': l.partner_name or (l.partner_id.name if l.partner_id else ''), - 'amount': l.amount, - 'journal': l.journal_id.name, - } for l in lines], + 'id': r['id'], + 'date': str(r['date']) if r['date'] else '', + 'payment_ref': r['payment_ref'] or '', + 'partner_name': r['partner_name'] or '', + 'amount': r['amount'], + 'journal': r['journal_name'], + } for r in rows], }