feat(fusion_accounting_followup): tone_selector service
Made-with: Cursor
This commit is contained in:
@@ -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': """
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
from . import overdue_aging
|
||||
from . import level_resolver
|
||||
from . import risk_scorer
|
||||
from . import tone_selector
|
||||
|
||||
18
fusion_accounting_followup/services/tone_selector.py
Normal file
18
fusion_accounting_followup/services/tone_selector.py
Normal 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
|
||||
@@ -1,3 +1,4 @@
|
||||
from . import test_overdue_aging
|
||||
from . import test_level_resolver
|
||||
from . import test_risk_scorer
|
||||
from . import test_tone_selector
|
||||
|
||||
25
fusion_accounting_followup/tests/test_tone_selector.py
Normal file
25
fusion_accounting_followup/tests/test_tone_selector.py
Normal 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')
|
||||
Reference in New Issue
Block a user