from odoo import fields, models, api, _ from odoo.exceptions import ValidationError class IncomeTaxSlabMaster(models.Model): _name = 'it.slab.master' _description = 'Income Tax Slab Master' _rec_name = 'name' _sql_constraints = [ ( 'unique_slab', 'unique(regime, age_category, residence_type)', 'Slab must be unique for the same Regime, Age Category, and Residence Type!' ) ] name = fields.Char(string="Slab Name", required=True) regime = fields.Selection([ ('old', 'Old Tax Regime'), ('new', 'New Tax Regime') ], required=True) age_category = fields.Selection([ ('below_60', 'Below 60 Years'), ('60_to_80', '60-80 Years'), ('above_80', 'Above 80 Years') ], required=True) residence_type = fields.Selection([ ('resident', 'Resident'), ('non_resident', 'Non Resident'), ('both', 'Both') ], required=True) standard_deduction = fields.Float(string="Standard Deduction") active = fields.Boolean(default=True) rules = fields.One2many('it.slab.master.rules','slab_id', string="Slab Rules") class IncomeTaxSlabMasterRules(models.Model): _name = 'it.slab.master.rules' _description = 'Income Tax slab rules' _rec_name = 'slab_id' _sql_constraints = [ ( 'check_min_max_income', 'CHECK (max_income IS NULL OR max_income > min_income)', 'Max Income must be greater than Min Income!' ) ] min_income = fields.Float(string="Min Income (₹)", required=True) max_income = fields.Float(string="Max Income (₹)") tax_rate = fields.Float(string="Tax Rate (%)", required=True) fixed_amount = fields.Float(string="Fixed Amount (₹)") excess_threshold = fields.Float(string="Excess Threshold (₹)") surcharge_rate = fields.Float(string="Surcharge Rate (%)") cess_rate = fields.Float(string="Health & Education (%)", default=4.0) slab_id = fields.Many2one('it.slab.master') @api.constrains('min_income', 'max_income', 'slab_id') def _check_overlap(self): """Ensure no overlapping or duplicate ranges within the same slab""" for rule in self: domain = [ ('slab_id', '=', rule.slab_id.id), ('id', '!=', rule.id) ] others = self.search(domain) for other in others: if not (rule.max_income and other.min_income >= rule.max_income) and \ not (other.max_income and rule.min_income >= other.max_income): raise ValidationError( f"Income ranges overlap with another slab rule: {other.min_income} - {other.max_income}" )