Skip to content

Commit 41e096d

Browse files
[IMP] account_invoice_overdue_reminder: add tests
1 parent 01a0171 commit 41e096d

File tree

7 files changed

+723
-0
lines changed

7 files changed

+723
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Copyright 2026 NICO SOLUTIONS - ENGINEERING & IT, Nils Coenen
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from . import test_account_invoice_overdue_reminder
4+
from . import test_account_move
5+
from . import test_overdue_reminder_action
6+
from . import test_overdue_reminder_start
7+
from . import test_overdue_reminder_step
8+
from . import test_overdue_reminder_mass_update
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
# Copyright 2026 NICO SOLUTIONS - ENGINEERING & IT, Nils Coenen
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from odoo import Command
4+
from odoo.exceptions import ValidationError
5+
from odoo.tests.common import TransactionCase
6+
7+
8+
class TestAccountInvoiceOverdueReminder(TransactionCase):
9+
@classmethod
10+
def setUpClass(cls):
11+
super().setUpClass()
12+
cls.partner = cls.env["res.partner"].create({"name": "Test Customer"})
13+
cls.invoice = cls.env["account.move"].create(
14+
{
15+
"move_type": "out_invoice",
16+
"partner_id": cls.partner.id,
17+
"invoice_line_ids": [
18+
Command.create(
19+
{
20+
"name": "Test line",
21+
"quantity": 1,
22+
"price_unit": 100,
23+
},
24+
)
25+
],
26+
}
27+
)
28+
cls.invalid_invoice = cls.env["account.move"].create(
29+
{
30+
"move_type": "in_invoice",
31+
"partner_id": cls.partner.id,
32+
"invoice_line_ids": [
33+
Command.create(
34+
{
35+
"name": "Vendor line",
36+
"quantity": 1,
37+
"price_unit": 100,
38+
},
39+
)
40+
],
41+
}
42+
)
43+
cls.reminder_action = cls.env["overdue.reminder.action"].create(
44+
{
45+
"commercial_partner_id": cls.partner.id,
46+
"partner_id": cls.partner.id,
47+
"date": "2024-01-01",
48+
"user_id": cls.env.ref("base.user_admin").id,
49+
"reminder_type": "mail",
50+
}
51+
)
52+
53+
def test_accept_out_invoice(self):
54+
rec = self.env["account.invoice.overdue.reminder"].create(
55+
{
56+
"invoice_id": self.invoice.id,
57+
"action_id": self.reminder_action.id,
58+
"counter": 1,
59+
}
60+
)
61+
self.assertTrue(rec.exists())
62+
self.assertEqual(rec.counter, 1)
63+
64+
def test_display_name_compute(self):
65+
rec = self.env["account.invoice.overdue.reminder"].create(
66+
{
67+
"invoice_id": self.invoice.id,
68+
"action_id": self.reminder_action.id,
69+
"counter": 3,
70+
}
71+
)
72+
expected = f"{self.invoice.name} Reminder n°3"
73+
self.assertEqual(rec.display_name, expected)
74+
75+
def test_reject_in_invoice(self):
76+
with self.assertRaises(ValidationError):
77+
self.env["account.invoice.overdue.reminder"].create(
78+
{
79+
"invoice_id": self.invalid_invoice.id,
80+
"action_id": self.reminder_action.id,
81+
"counter": 1,
82+
}
83+
)
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Copyright 2026 NICO SOLUTIONS - ENGINEERING & IT, Nils Coenen
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from odoo import Command, fields
4+
from odoo.tests.common import TransactionCase
5+
6+
7+
class TestAccountMove(TransactionCase):
8+
@classmethod
9+
def setUpClass(cls):
10+
super().setUpClass()
11+
cls.partner = cls.env["res.partner"].create({"name": "Test Customer"})
12+
cls.company = cls.env.company
13+
cls.overdue_invoice = cls.env["account.move"].create(
14+
{
15+
"move_type": "out_invoice",
16+
"partner_id": cls.partner.id,
17+
"invoice_date_due": fields.Date.subtract(fields.Date.today(), days=5),
18+
"invoice_line_ids": [
19+
Command.create(
20+
{
21+
"name": "Test line overdue",
22+
"quantity": 1,
23+
"price_unit": 100,
24+
},
25+
)
26+
],
27+
"company_id": cls.company.id,
28+
}
29+
)
30+
cls.overdue_invoice.action_post()
31+
cls.overdue_invoice.payment_state = "not_paid"
32+
cls.not_due_invoice = cls.env["account.move"].create(
33+
{
34+
"move_type": "out_invoice",
35+
"partner_id": cls.partner.id,
36+
"invoice_date_due": fields.Date.add(fields.Date.today(), days=5),
37+
"invoice_line_ids": [
38+
Command.create(
39+
{
40+
"name": "Test line not due",
41+
"quantity": 1,
42+
"price_unit": 100,
43+
},
44+
)
45+
],
46+
"company_id": cls.company.id,
47+
}
48+
)
49+
cls.not_due_invoice.action_post()
50+
cls.not_due_invoice.payment_state = "not_paid"
51+
52+
cls.reminder_action = cls.env["overdue.reminder.action"].create(
53+
{
54+
"commercial_partner_id": cls.partner.id,
55+
"partner_id": cls.partner.id,
56+
"date": fields.Date.today(),
57+
"user_id": cls.env.ref("base.user_admin").id,
58+
"reminder_type": "mail",
59+
}
60+
)
61+
62+
def test_overdue_computation(self):
63+
self.assertTrue(self.overdue_invoice.overdue, "Invoice should be overdue")
64+
self.assertFalse(self.not_due_invoice.overdue, "Invoice should not be overdue")
65+
66+
def test_overdue_reminder_counter_initial(self):
67+
self.assertEqual(self.overdue_invoice.overdue_reminder_counter, 0)
68+
self.assertFalse(self.overdue_invoice.overdue_reminder_last_date)
69+
70+
def test_overdue_remind_sent_logic(self):
71+
company = self.env.company
72+
company.overdue_reminder_min_interval_days = 3
73+
self.assertFalse(self.overdue_invoice.overdue_remind_sent)
74+
self.env["account.invoice.overdue.reminder"].create(
75+
{
76+
"invoice_id": self.overdue_invoice.id,
77+
"action_id": self.reminder_action.id,
78+
"counter": 1,
79+
"action_date": fields.Date.subtract(fields.Date.today(), days=1),
80+
}
81+
)
82+
self.overdue_invoice._compute_overdue_reminder_sent()
83+
self.assertTrue(self.overdue_invoice.overdue_remind_sent)
84+
85+
def test_compute_overdue_reminder_multiple(self):
86+
self.env["account.invoice.overdue.reminder"].create(
87+
{
88+
"invoice_id": self.overdue_invoice.id,
89+
"action_id": self.reminder_action.id,
90+
"counter": 1,
91+
"action_date": fields.Date.subtract(fields.Date.today(), days=5),
92+
}
93+
)
94+
self.env["account.invoice.overdue.reminder"].create(
95+
{
96+
"invoice_id": self.overdue_invoice.id,
97+
"action_id": self.reminder_action.id,
98+
"counter": 3,
99+
"action_date": fields.Date.subtract(fields.Date.today(), days=1),
100+
}
101+
)
102+
self.overdue_invoice._compute_overdue_reminder()
103+
reminder = self.env["account.invoice.overdue.reminder"].search(
104+
[("invoice_id", "=", self.overdue_invoice.id)],
105+
order="action_date desc, id desc",
106+
limit=1,
107+
)
108+
self.assertEqual(
109+
self.overdue_invoice.overdue_reminder_last_date, reminder.action_date
110+
)
111+
self.assertEqual(
112+
self.overdue_invoice.overdue_reminder_counter, reminder.counter
113+
)
114+
115+
def test_no_overdue_reminder_flag(self):
116+
self.overdue_invoice.no_overdue_reminder = True
117+
self.assertTrue(
118+
self.overdue_invoice.no_overdue_reminder,
119+
"Invoice should have no_overdue_reminder=True",
120+
)
121+
self.overdue_invoice._compute_overdue()
122+
self.assertTrue(
123+
self.overdue_invoice.overdue,
124+
"Overdue may still be True, we are only testing the flag here",
125+
)
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Copyright 2026 NICO SOLUTIONS - ENGINEERING & IT, Nils Coenen
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from odoo import Command, fields
4+
from odoo.tests.common import TransactionCase
5+
from odoo.tools.misc import format_date
6+
7+
8+
class TestOverdueReminderAction(TransactionCase):
9+
@classmethod
10+
def setUpClass(cls):
11+
super().setUpClass()
12+
cls.partner = cls.env["res.partner"].create({"name": "Test Partner"})
13+
cls.product = cls.env["product.product"].create({"name": "Test Product"})
14+
uom_unit = cls.env.ref("uom.product_uom_unit")
15+
cls.invoice_model = cls.env["account.move"].create(
16+
{
17+
"move_type": "out_invoice",
18+
"partner_id": cls.partner.id,
19+
"invoice_date": "2025-12-31",
20+
"line_ids": [
21+
Command.create(
22+
{
23+
"name": "Test line",
24+
"partner_id": cls.partner.id,
25+
"quantity": 1.0,
26+
"price_unit": 100.0,
27+
"product_id": cls.product.id,
28+
"product_uom_id": uom_unit.id,
29+
},
30+
)
31+
],
32+
}
33+
)
34+
cls.reminder_action = cls.env["overdue.reminder.action"].create(
35+
{
36+
"reminder_type": "mail",
37+
"partner_id": cls.partner.id,
38+
"commercial_partner_id": cls.partner.id,
39+
}
40+
)
41+
cls.reminder_model = cls.env["account.invoice.overdue.reminder"].create(
42+
{
43+
"invoice_id": cls.invoice_model.id,
44+
"action_id": cls.reminder_action.id,
45+
"counter": 0,
46+
}
47+
)
48+
49+
def test_default_values(self):
50+
self.assertEqual(self.reminder_action.user_id, self.env.user)
51+
self.assertEqual(self.reminder_action.reminder_type, "mail")
52+
self.assertEqual(
53+
self.reminder_action.date, fields.Date.context_today(self.reminder_action)
54+
)
55+
56+
def test_compute_invoice_count(self):
57+
self.reminder_action._compute_invoice_count()
58+
self.assertEqual(self.reminder_action.reminder_count, 1)
59+
60+
def test_compute_display_name(self):
61+
self.reminder_action._compute_display_name()
62+
self.assertIn("Test Partner", self.reminder_action.display_name)
63+
expected_date = format_date(self.env, self.reminder_action.date)
64+
self.assertIn(expected_date, self.reminder_action.display_name)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Copyright 2026 NICO SOLUTIONS - ENGINEERING & IT, Nils Coenen
2+
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
3+
from odoo import Command, fields
4+
from odoo.exceptions import UserError
5+
6+
from odoo.addons.base.tests.common import BaseCommon
7+
8+
9+
class TestOverdueRemindMassUpdate(BaseCommon):
10+
@classmethod
11+
def setUpClass(cls):
12+
super().setUpClass()
13+
cls.partner = cls.env["res.partner"].create(
14+
{
15+
"name": "Test Partner",
16+
"email": "test@example.com",
17+
}
18+
)
19+
cls.user_admin = cls.env.ref("base.user_admin")
20+
cls.invoice = cls.env["account.move"].create(
21+
{
22+
"move_type": "out_invoice",
23+
"partner_id": cls.partner.id,
24+
"invoice_date": fields.Date.today(),
25+
"invoice_date_due": fields.Date.today(),
26+
}
27+
)
28+
cls.step = cls.env["overdue.reminder.step"].create(
29+
{
30+
"partner_id": cls.partner.id,
31+
"commercial_partner_id": cls.partner.id,
32+
"user_id": cls.user_admin.id,
33+
"invoice_ids": [Command.set(cls.invoice.ids)],
34+
"reminder_type": "mail",
35+
}
36+
)
37+
38+
def _create_wizard(self, update_action, reminder_type=None):
39+
return self.env["overdue.reminder.mass.update"].create(
40+
{
41+
"update_action": update_action,
42+
"reminder_type": reminder_type,
43+
}
44+
)
45+
46+
def test_run_validate(self):
47+
wizard_rec = self._create_wizard("validate")
48+
wizard_rec.with_context(
49+
active_model="overdue.reminder.step", active_ids=[self.step.id]
50+
).run()
51+
self.assertEqual(self.step.state, "done")
52+
53+
def test_run_skip(self):
54+
wizard_rec = self._create_wizard("skip")
55+
wizard_rec.with_context(
56+
active_model="overdue.reminder.step", active_ids=[self.step.id]
57+
).run()
58+
self.assertEqual(self.step.state, "skipped")
59+
60+
def test_run_reminder_type_change(self):
61+
wizard = self.env["overdue.reminder.mass.update"].create(
62+
{
63+
"update_action": "reminder_type",
64+
"reminder_type": "phone",
65+
}
66+
)
67+
wizard.with_context(
68+
active_model="overdue.reminder.step", active_ids=[self.step.id]
69+
).run()
70+
self.assertEqual(self.step.reminder_type, "phone")
71+
72+
def test_run_reminder_type_missing(self):
73+
wizard = self._create_wizard("reminder_type")
74+
with self.assertRaises(UserError):
75+
wizard.with_context(
76+
active_model="overdue.reminder.step", active_ids=[self.step.id]
77+
).run()

0 commit comments

Comments
 (0)