feat(fusion_accounting_followup): fusion.followup.level definition model
Made-with: Cursor
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
'name': 'Fusion Accounting Follow-up',
|
||||
'version': '19.0.1.0.5',
|
||||
'version': '19.0.1.0.6',
|
||||
'category': 'Accounting/Accounting',
|
||||
'summary': 'AI-augmented customer follow-ups (dunning) for unpaid invoices.',
|
||||
'description': """
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
from . import fusion_followup_level
|
||||
|
||||
42
fusion_accounting_followup/models/fusion_followup_level.py
Normal file
42
fusion_accounting_followup/models/fusion_followup_level.py
Normal file
@@ -0,0 +1,42 @@
|
||||
"""Follow-up level definition (e.g. Reminder at 7 days, Warning at 30, Legal at 60)."""
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
|
||||
|
||||
TONE_SELECTION = [
|
||||
('gentle', 'Gentle'),
|
||||
('firm', 'Firm'),
|
||||
('legal', 'Legal'),
|
||||
]
|
||||
|
||||
|
||||
class FusionFollowupLevel(models.Model):
|
||||
_name = "fusion.followup.level"
|
||||
_description = "Fusion Follow-up Level"
|
||||
_order = "sequence, id"
|
||||
|
||||
name = fields.Char(required=True, translate=True)
|
||||
sequence = fields.Integer(required=True, default=10,
|
||||
help="Order in which levels escalate (1, 2, 3...).")
|
||||
delay_days = fields.Integer(required=True,
|
||||
help="Min days overdue to trigger this level.")
|
||||
tone = fields.Selection(TONE_SELECTION, required=True, default='gentle')
|
||||
description = fields.Text()
|
||||
company_id = fields.Many2one('res.company', default=lambda self: self.env.company)
|
||||
|
||||
mail_template_id = fields.Many2one('mail.template',
|
||||
domain=[('model', '=', 'res.partner')])
|
||||
|
||||
requires_manual_review = fields.Boolean(default=False,
|
||||
help="If True, follow-ups at this level need human approval before send.")
|
||||
|
||||
active = fields.Boolean(default=True)
|
||||
|
||||
_check_delay_positive = models.Constraint(
|
||||
'CHECK(delay_days >= 0)',
|
||||
'delay_days must be non-negative.',
|
||||
)
|
||||
_unique_sequence_per_company = models.Constraint(
|
||||
'UNIQUE(company_id, sequence)',
|
||||
'Sequence must be unique per company.',
|
||||
)
|
||||
@@ -1 +1,3 @@
|
||||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||
access_fusion_followup_level_user,fusion.followup.level.user,model_fusion_followup_level,base.group_user,1,0,0,0
|
||||
access_fusion_followup_level_admin,fusion.followup.level.admin,model_fusion_followup_level,fusion_accounting_core.group_fusion_accounting_admin,1,1,1,1
|
||||
|
||||
|
@@ -3,3 +3,4 @@ from . import test_level_resolver
|
||||
from . import test_risk_scorer
|
||||
from . import test_tone_selector
|
||||
from . import test_followup_text_generator
|
||||
from . import test_fusion_followup_level
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
from odoo.tests.common import TransactionCase
|
||||
from odoo.tests import tagged
|
||||
|
||||
|
||||
@tagged('post_install', '-at_install')
|
||||
class TestFusionFollowupLevel(TransactionCase):
|
||||
|
||||
def test_create_minimal(self):
|
||||
level = self.env['fusion.followup.level'].create({
|
||||
'name': 'Reminder', 'sequence': 1, 'delay_days': 7, 'tone': 'gentle',
|
||||
})
|
||||
self.assertEqual(level.name, 'Reminder')
|
||||
self.assertTrue(level.active)
|
||||
|
||||
def test_negative_delay_rejected(self):
|
||||
with self.assertRaises(Exception):
|
||||
self.env['fusion.followup.level'].create({
|
||||
'name': 'Bad', 'sequence': 1, 'delay_days': -5, 'tone': 'gentle',
|
||||
})
|
||||
|
||||
def test_duplicate_sequence_rejected(self):
|
||||
self.env['fusion.followup.level'].create({
|
||||
'name': 'A', 'sequence': 100, 'delay_days': 7, 'tone': 'gentle',
|
||||
})
|
||||
with self.assertRaises(Exception):
|
||||
self.env['fusion.followup.level'].create({
|
||||
'name': 'B', 'sequence': 100, 'delay_days': 30, 'tone': 'firm',
|
||||
})
|
||||
|
||||
def test_three_levels_escalate(self):
|
||||
for seq, name, days, tone in [(1, 'R', 7, 'gentle'),
|
||||
(2, 'W', 30, 'firm'),
|
||||
(3, 'L', 60, 'legal')]:
|
||||
self.env['fusion.followup.level'].create({
|
||||
'name': name, 'sequence': seq + 200,
|
||||
'delay_days': days, 'tone': tone,
|
||||
})
|
||||
levels = self.env['fusion.followup.level'].search([
|
||||
('sequence', '>', 200),
|
||||
], order='sequence')
|
||||
self.assertEqual(len(levels), 3)
|
||||
self.assertEqual(levels.mapped('tone'), ['gentle', 'firm', 'legal'])
|
||||
Reference in New Issue
Block a user