from odoo.exceptions import ValidationError from odoo.tests.common import TransactionCase # Names are deliberately distinct from demo data (see ../demo/) - these # tests must pass whether or not demo data is loaded. class TestFeeStructure(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() cls.year = cls.env["mc.academic.year"].create({ "name": "TEST-FEES-2026-27", "date_start": "2026-06-01", "date_end": "2027-04-30", }) cls.term1 = cls.env["mc.academic.term"].create({ "name": "TEST Term 1", "year_id": cls.year.id, "date_start": "2026-06-01", "date_end": "2026-09-30", }) cls.term2 = cls.env["mc.academic.term"].create({ "name": "TEST Term 2", "year_id": cls.year.id, "date_start": "2026-10-01", "date_end": "2026-12-31", }) cls.program = cls.env["mc.program"].create({ "name": "TEST Program", "code": "TEST-FEES-P1", "sequence_no": 1, "display_label": "Test Grade", }) cls.category_tuition = cls.env["mc.fee.category"].create({"name": "TEST Tuition"}) cls.category_lab = cls.env["mc.fee.category"].create({"name": "TEST Lab"}) def test_total_amount_computed_from_lines(self): structure = self.env["mc.fee.structure"].create({ "program_id": self.program.id, "year_id": self.year.id, "line_ids": [ (0, 0, {"category_id": self.category_tuition.id, "amount": 40000}), (0, 0, {"category_id": self.category_lab.id, "amount": 5000}), ], }) self.assertEqual(structure.total_amount, 45000) def test_duplicate_structure_for_same_program_year_rejected(self): self.env["mc.fee.structure"].create({ "program_id": self.program.id, "year_id": self.year.id, }) with self.assertRaises(Exception): with self.cr.savepoint(): self.env["mc.fee.structure"].create({ "program_id": self.program.id, "year_id": self.year.id, }) def test_schedule_can_be_built_up_incrementally(self): # Adding one term at a time is the normal workflow, and the total # is under 100% after every step but the last - must not raise. structure = self.env["mc.fee.structure"].create({ "program_id": self.program.id, "year_id": self.year.id, }) schedule = self.env["mc.fee.schedule"].create({"structure_id": structure.id}) self.env["mc.fee.schedule.line"].create({ "schedule_id": schedule.id, "term_id": self.term1.id, "due_date": "2026-06-15", "percentage": 40, }) self.assertEqual(schedule.total_percentage, 40) self.env["mc.fee.schedule.line"].create({ "schedule_id": schedule.id, "term_id": self.term2.id, "due_date": "2026-10-15", "percentage": 60, }) self.assertEqual(schedule.total_percentage, 100) def test_schedule_over_100_percent_rejected(self): structure = self.env["mc.fee.structure"].create({ "program_id": self.program.id, "year_id": self.year.id, }) schedule = self.env["mc.fee.schedule"].create({"structure_id": structure.id}) self.env["mc.fee.schedule.line"].create({ "schedule_id": schedule.id, "term_id": self.term1.id, "due_date": "2026-06-15", "percentage": 70, }) with self.assertRaises(ValidationError): self.env["mc.fee.schedule.line"].create({ "schedule_id": schedule.id, "term_id": self.term2.id, "due_date": "2026-10-15", "percentage": 40, })