86 lines
3.4 KiB
Python
86 lines
3.4 KiB
Python
# pyrefly: ignore [missing-import]
|
|
from odoo import api, fields, models
|
|
# pyrefly: ignore [missing-import]
|
|
from odoo.exceptions import ValidationError
|
|
|
|
|
|
class EducationStudentDiscount(models.Model):
|
|
_name = 'education.student.discount'
|
|
_description = 'Student Fee Discount'
|
|
_order = 'id desc'
|
|
|
|
student_id = fields.Many2one('education.student', string='Student', required=True, index=True)
|
|
type = fields.Selection([
|
|
('percentage', 'Percentage'),
|
|
('fixed', 'Fixed Amount')
|
|
], string='Discount Type', required=True, default='fixed')
|
|
|
|
currency_id = fields.Many2one(
|
|
'res.currency',
|
|
string='Currency',
|
|
required=True,
|
|
default=lambda self: self.env.company.currency_id,
|
|
)
|
|
amount = fields.Monetary(string='Discount Value', required=True, currency_field='currency_id', default=0.0)
|
|
reason = fields.Text(string='Reason for Discount', required=True)
|
|
approved_by = fields.Many2one('res.users', string='Approved By', default=lambda self: self.env.user, required=True)
|
|
validity = fields.Date(string='Validity Date')
|
|
state = fields.Selection([
|
|
('draft', 'Draft'),
|
|
('confirmed', 'Confirmed'),
|
|
('cancelled', 'Cancelled')
|
|
], string='Status', default='draft', 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,
|
|
)
|
|
|
|
@api.constrains('amount')
|
|
def _check_amount(self):
|
|
for rec in self:
|
|
if rec.amount <= 0:
|
|
raise ValidationError('Discount value must be greater than zero.')
|
|
if rec.type == 'percentage' and rec.amount > 100:
|
|
raise ValidationError('Discount percentage cannot exceed 100%.')
|
|
|
|
def action_confirm(self):
|
|
for rec in self:
|
|
if rec.state == 'confirmed':
|
|
continue
|
|
|
|
discount_amount = rec.amount
|
|
if rec.type == 'percentage':
|
|
outstanding = rec.student_id.outstanding_amount
|
|
discount_amount = outstanding * (rec.amount / 100.0)
|
|
|
|
if discount_amount <= 0:
|
|
raise ValidationError('Calculated discount amount must be greater than zero.')
|
|
if discount_amount > rec.student_id.outstanding_amount:
|
|
raise ValidationError(f'Cannot apply a discount of {discount_amount} because it exceeds the student outstanding dues of {rec.student_id.outstanding_amount}.')
|
|
|
|
self.env['education.student.ledger'].create({
|
|
'student_id': rec.student_id.id,
|
|
'date': fields.Date.today(),
|
|
'ref': f"DISC/{rec.id}",
|
|
'description': f"Discount Applied - {rec.reason} (Approved by: {rec.approved_by.name})",
|
|
'debit': 0.0,
|
|
'credit': discount_amount,
|
|
'status': 'paid',
|
|
'company_id': rec.company_id.id,
|
|
})
|
|
rec.state = 'confirmed'
|
|
|
|
def action_cancel(self):
|
|
for rec in self:
|
|
if rec.state == 'confirmed':
|
|
ledger_entries = self.env['education.student.ledger'].search([
|
|
('student_id', '=', rec.student_id.id),
|
|
('ref', '=', f"DISC/{rec.id}"),
|
|
])
|
|
ledger_entries.unlink()
|
|
rec.state = 'cancelled'
|