# pyrefly: ignore [missing-import] from odoo import api, fields, models class EducationStudentLedger(models.Model): _name = 'education.student.ledger' _description = 'Student Financial Ledger' _order = 'date asc, id asc' student_id = fields.Many2one('education.student', string='Student', required=True, index=True, ondelete='cascade') academic_year_id = fields.Many2one('education.academic.year', string='Academic Year', index=True) semester_id = fields.Many2one('education.semester', string='Semester', index=True) category_id = fields.Many2one('education.fee.category', string='Fee Category', index=True) fee_type_id = fields.Many2one('education.fee.type', string='Fee Type', index=True) date = fields.Date(string='Date', required=True, default=fields.Date.context_today, index=True) ref = fields.Char(string='Reference', index=True) description = fields.Text(string='Description') currency_id = fields.Many2one( 'res.currency', string='Currency', required=True, default=lambda self: self.env.company.currency_id, ) debit = fields.Monetary(string='Debit (Charges)', default=0.0, currency_field='currency_id', index=True) credit = fields.Monetary(string='Credit (Payments/Credits)', default=0.0, currency_field='currency_id', index=True) balance = fields.Monetary(string='Balance', currency_field='currency_id', index=True) status = fields.Selection([ ('draft', 'Draft'), ('outstanding', 'Outstanding'), ('paid', 'Paid'), ('cancelled', 'Cancelled') ], string='Status', default='outstanding', required=True, index=True) active = fields.Boolean(default=True) company_id = fields.Many2one( 'res.company', string='Company', required=True, default=lambda self: self.env.company, index=True, ) def _recalculate_student_balances(self, student_ids): for student_id in student_ids: lines = self.search([ ('student_id', '=', student_id), ('status', 'in', ('outstanding', 'paid')) ], order='date asc, id asc') running = 0.0 for line in lines: running += line.debit - line.credit self.env.cr.execute( "UPDATE education_student_ledger SET balance = %s WHERE id = %s", (running, line.id) ) # Force metrics recalculation on the student record student = self.env['education.student'].browse(student_id) student.modified(['ledger_line_ids']) self.invalidate_model(['balance']) @api.model_create_multi def create(self, vals_list): records = super().create(vals_list) student_ids = records.mapped('student_id').ids self._recalculate_student_balances(student_ids) return records def write(self, vals): student_ids = self.mapped('student_id').ids res = super().write(vals) student_ids = list(set(student_ids + self.mapped('student_id').ids)) self._recalculate_student_balances(student_ids) return res def unlink(self): student_ids = self.mapped('student_id').ids res = super().unlink() self._recalculate_student_balances(student_ids) return res