feat(fusion_accounting_bank_rec): persisted AI suggestion model with state lifecycle
Made-with: Cursor
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from . import test_memo_tokenizer
|
||||
from . import test_exchange_diff
|
||||
from . import test_matching_strategies
|
||||
from . import test_ai_suggestion_lifecycle
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
from odoo.tests.common import TransactionCase, tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestSuggestionLifecycle(TransactionCase):
|
||||
"""The fusion.reconcile.suggestion state machine + computed band."""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
journal = self.env['account.journal'].create({
|
||||
'name': 'Test Bank Suggestion',
|
||||
'type': 'bank',
|
||||
'code': 'TBSG',
|
||||
})
|
||||
statement = self.env['account.bank.statement'].create({
|
||||
'name': 'Test Statement',
|
||||
'journal_id': journal.id,
|
||||
})
|
||||
self.line = self.env['account.bank.statement.line'].create({
|
||||
'statement_id': statement.id,
|
||||
'journal_id': journal.id,
|
||||
'date': '2026-04-19',
|
||||
'payment_ref': 'Test for suggestion',
|
||||
'amount': 100.00,
|
||||
})
|
||||
|
||||
def _make_suggestion(self, confidence=0.92, **vals):
|
||||
defaults = {
|
||||
'company_id': self.env.company.id,
|
||||
'statement_line_id': self.line.id,
|
||||
'confidence': confidence,
|
||||
'rank': 1,
|
||||
'reasoning': 'Test',
|
||||
}
|
||||
defaults.update(vals)
|
||||
return self.env['fusion.reconcile.suggestion'].create(defaults)
|
||||
|
||||
def test_compute_band_high(self):
|
||||
sug = self._make_suggestion(confidence=0.96)
|
||||
self.assertEqual(sug.confidence_band, 'high')
|
||||
|
||||
def test_compute_band_medium(self):
|
||||
sug = self._make_suggestion(confidence=0.75)
|
||||
self.assertEqual(sug.confidence_band, 'medium')
|
||||
|
||||
def test_compute_band_low(self):
|
||||
sug = self._make_suggestion(confidence=0.55)
|
||||
self.assertEqual(sug.confidence_band, 'low')
|
||||
|
||||
def test_compute_band_none(self):
|
||||
sug = self._make_suggestion(confidence=0.30)
|
||||
self.assertEqual(sug.confidence_band, 'none')
|
||||
|
||||
def test_default_state_is_pending(self):
|
||||
sug = self._make_suggestion()
|
||||
self.assertEqual(sug.state, 'pending')
|
||||
|
||||
def test_state_transition_to_accepted(self):
|
||||
sug = self._make_suggestion()
|
||||
sug.write({
|
||||
'state': 'accepted',
|
||||
'accepted_at': '2026-04-19 12:00:00',
|
||||
'accepted_by': self.env.user.id,
|
||||
})
|
||||
self.assertEqual(sug.state, 'accepted')
|
||||
self.assertTrue(sug.accepted_at)
|
||||
self.assertEqual(sug.accepted_by, self.env.user)
|
||||
|
||||
def test_state_transition_to_rejected_with_reason(self):
|
||||
sug = self._make_suggestion()
|
||||
sug.write({
|
||||
'state': 'rejected',
|
||||
'rejected_at': '2026-04-19 12:05:00',
|
||||
'rejected_reason': 'wrong_invoice',
|
||||
})
|
||||
self.assertEqual(sug.state, 'rejected')
|
||||
self.assertEqual(sug.rejected_reason, 'wrong_invoice')
|
||||
|
||||
def test_state_transition_to_superseded(self):
|
||||
sug = self._make_suggestion()
|
||||
sug.write({'state': 'superseded'})
|
||||
self.assertEqual(sug.state, 'superseded')
|
||||
|
||||
def test_currency_id_relates_to_line(self):
|
||||
sug = self._make_suggestion()
|
||||
self.assertEqual(sug.currency_id, self.line.currency_id)
|
||||
Reference in New Issue
Block a user