from odoo.exceptions import AccessError from odoo.tests.common import TransactionCase class TestFeeAccess(TransactionCase): @classmethod def setUpClass(cls): super().setUpClass() cls.program = cls.env["mc.program"].create({ "name": "TEST ACCESS Program", "code": "TEST-ACC-P1", "sequence_no": 1, "display_label": "Test Grade", }) cls.year = cls.env["mc.academic.year"].create({ "name": "TEST-ACCESS-2026-27", "date_start": "2026-06-01", "date_end": "2027-04-30", }) def make_user(login, groups): return cls.env["res.users"].create({ "name": login, "login": login, "email": f"{login}@example.com", "group_ids": [(6, 0, groups)], }) base_group = cls.env.ref("mc_education_base.group_school_staff").id cls.accountant = make_user("test_fees_accountant", [ cls.env.ref("mc_education_base.group_accountant").id, base_group, ]) cls.staff = make_user("test_fees_staff", [base_group]) cls.teacher = make_user("test_fees_teacher", [ cls.env.ref("mc_education_base.group_teacher").id, base_group, ]) def test_accountant_can_create_fee_structure(self): structure = self.env["mc.fee.structure"].with_user(self.accountant).create({ "program_id": self.program.id, "year_id": self.year.id, }) self.assertTrue(structure) def test_staff_cannot_create_fee_structure(self): with self.assertRaises(AccessError): self.env["mc.fee.structure"].with_user(self.staff).create({ "program_id": self.program.id, "year_id": self.year.id, }) def test_staff_can_read_fee_structure(self): structure = self.env["mc.fee.structure"].create({ "program_id": self.program.id, "year_id": self.year.id, }) # Should not raise: staff has read access. structure.with_user(self.staff).read(["program_id"]) def test_teacher_can_read_fee_structure(self): # Fee structure is per-program pricing, not per-student data - it # is not sensitive, and teacher inherits staff's read access to it # deliberately (group_teacher implies group_school_staff). structure = self.env["mc.fee.structure"].create({ "program_id": self.program.id, "year_id": self.year.id, }) # Should not raise. structure.with_user(self.teacher).read(["program_id"]) def test_teacher_cannot_read_concession(self): # Unlike fee structure, a concession reveals sensitive per-student # financial/personal information (e.g. a need-based hardship # discount and its reason). Neither staff nor teacher should be # able to read it, even though teacher implies staff elsewhere. student_partner = self.env["res.partner"].create({"name": "Access Test Student"}) student = self.env["mc.student"].create({ "partner_id": student_partner.id, "name": "Access Test Student", }) concession = self.env["mc.fee.concession"].create({ "student_id": student.id, "concession_type": "need_based", "computation": "percent", "value": 10, "reason": "x", "approver_id": self.env.uid, }) with self.assertRaises(AccessError): concession.with_user(self.teacher).read(["value"]) with self.assertRaises(AccessError): concession.with_user(self.staff).read(["value"]) def test_teacher_cannot_create_concession(self): student_partner = self.env["res.partner"].create({"name": "Access Test Student"}) student = self.env["mc.student"].create({ "partner_id": student_partner.id, "name": "Access Test Student", }) with self.assertRaises(AccessError): self.env["mc.fee.concession"].with_user(self.teacher).create({ "student_id": student.id, "concession_type": "merit", "computation": "percent", "value": 10, "reason": "x", "approver_id": self.teacher.id, })