# pyrefly: ignore [missing-import] from odoo import api, fields, models class EducationStudent(models.Model): _inherit = 'education.student' ledger_line_ids = fields.One2many('education.student.ledger', 'student_id', string='Ledger Lines') payment_ids = fields.One2many('education.student.payment', 'student_id', string='Payments') currency_id = fields.Many2one('res.currency', string='Currency', related='company_id.currency_id', readonly=True, store=True) outstanding_amount = fields.Monetary(string='Outstanding Dues', compute='_compute_finance_metrics', currency_field='currency_id', store=True, index=True) total_fees = fields.Monetary(string='Total Fees', compute='_compute_finance_metrics', currency_field='currency_id', store=True, index=True) total_paid = fields.Monetary(string='Total Paid', compute='_compute_finance_metrics', currency_field='currency_id', store=True, index=True) last_payment_date = fields.Date(string='Last Payment Date', compute='_compute_finance_metrics', store=True, index=True) last_receipt_number = fields.Char(string='Last Receipt Number', compute='_compute_finance_metrics', store=True, index=True) payment_status = fields.Selection([ ('no_dues', 'No Dues'), ('partial', 'Partial'), ('overdue', 'Overdue'), ('fully_paid', 'Fully Paid') ], string='Payment Status', compute='_compute_finance_metrics', default='no_dues', store=True, index=True) @api.depends('ledger_line_ids.debit', 'ledger_line_ids.credit', 'ledger_line_ids.status', 'payment_ids.amount', 'payment_ids.status', 'payment_ids.payment_date', 'payment_ids.receipt_number') def _compute_finance_metrics(self): for rec in self: active_ledgers = rec.ledger_line_ids.filtered(lambda l: l.status in ('outstanding', 'paid')) total_debits = sum(line.debit for line in active_ledgers) total_credits = sum(line.credit for line in active_ledgers) rec.total_fees = total_debits confirmed_payments = rec.payment_ids.filtered(lambda p: p.status == 'confirmed').sorted(key=lambda p: (p.payment_date or fields.Date.today(), p.id), reverse=True) rec.total_paid = sum(p.amount for p in confirmed_payments) rec.outstanding_amount = total_debits - total_credits last_payment = confirmed_payments[0] if confirmed_payments else False rec.last_payment_date = last_payment.payment_date if last_payment else False rec.last_receipt_number = last_payment.receipt_number if last_payment else False if total_debits == 0: rec.payment_status = 'no_dues' elif rec.outstanding_amount <= 0: rec.payment_status = 'fully_paid' elif rec.total_paid > 0: rec.payment_status = 'partial' else: rec.payment_status = 'overdue'