feat(fusion_accounting_followup): tone_selector service

Made-with: Cursor
This commit is contained in:
gsinghpal
2026-04-19 20:39:17 -04:00
parent 397fb238c5
commit 63f3e0ec14
5 changed files with 46 additions and 1 deletions

View File

@@ -1,6 +1,6 @@
{
'name': 'Fusion Accounting Follow-up',
'version': '19.0.1.0.3',
'version': '19.0.1.0.4',
'category': 'Accounting/Accounting',
'summary': 'AI-augmented customer follow-ups (dunning) for unpaid invoices.',
'description': """

View File

@@ -1,3 +1,4 @@
from . import overdue_aging
from . import level_resolver
from . import risk_scorer
from . import tone_selector

View File

@@ -0,0 +1,18 @@
"""Tone selector: pick gentle/firm/legal based on follow-up level + risk score."""
TONE_BY_LEVEL = {
1: 'gentle',
2: 'firm',
3: 'legal',
4: 'legal',
}
def select_tone(*, level_sequence: int, risk_score: int = 0) -> str:
"""Default tone follows level sequence; high risk can escalate."""
base_tone = TONE_BY_LEVEL.get(level_sequence, 'gentle')
if risk_score >= 80 and base_tone == 'gentle':
return 'firm'
if risk_score >= 90 and base_tone == 'firm':
return 'legal'
return base_tone

View File

@@ -1,3 +1,4 @@
from . import test_overdue_aging
from . import test_level_resolver
from . import test_risk_scorer
from . import test_tone_selector

View File

@@ -0,0 +1,25 @@
from odoo.tests.common import TransactionCase
from odoo.tests import tagged
from odoo.addons.fusion_accounting_followup.services.tone_selector import select_tone
@tagged('post_install', '-at_install')
class TestToneSelector(TransactionCase):
def test_level_1_default_gentle(self):
self.assertEqual(select_tone(level_sequence=1), 'gentle')
def test_level_2_default_firm(self):
self.assertEqual(select_tone(level_sequence=2), 'firm')
def test_level_3_default_legal(self):
self.assertEqual(select_tone(level_sequence=3), 'legal')
def test_critical_risk_escalates_gentle_to_firm(self):
self.assertEqual(select_tone(level_sequence=1, risk_score=85), 'firm')
def test_extreme_risk_escalates_firm_to_legal(self):
self.assertEqual(select_tone(level_sequence=2, risk_score=95), 'legal')
def test_unknown_level_defaults_gentle(self):
self.assertEqual(select_tone(level_sequence=99), 'gentle')