from odoo import models, fields, api from odoo.exceptions import ValidationError from datetime import datetime, timedelta import calendar import re class investmentCostings(models.Model): _name = 'investment.costings' _rec_name = 'investment_type_id' investment_type_id = fields.Many2one('it.investment.type') amount = fields.Integer() it_declaration_id = fields.Many2one('emp.it.declaration') employee_id = fields.Many2one( 'hr.employee', string="Employee", related='it_declaration_id.employee_id' ) period_id = fields.Many2one( 'payroll.period', string="Payroll Period", related='it_declaration_id.period_id' ) class pastEmpcostingType(models.Model): _name = 'past_employment.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_id = fields.Many2one('it.investment.type',related='investment_type_line_id.investment_type') investment_type_line_id = fields.Many2one('past_employment.investment.type') declaration_amount = fields.Integer(string='Declaration Amount',compute='_compute_declaration_amount',store=True,readonly=False) proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() @api.depends( 'it_declaration_id.past_employment_costings.declaration_amount', 'it_declaration_id.past_employment_costings_new.declaration_amount', 'investment_type_line_id.compute_method', 'investment_type_line_id.compute_code', 'it_declaration_id.tax_regime', 'declaration_amount' ) def _compute_declaration_amount(self): for rec in self: line = rec.investment_type_line_id if not line or not rec.it_declaration_id: rec.declaration_amount = 0 continue if line.compute_method and line.compute_code: siblings = ( rec.it_declaration_id.past_employment_costings if rec.it_declaration_id.tax_regime == 'old' else rec.it_declaration_id.past_employment_costings_new ) code_vars = {} for sibling in siblings: code = sibling.investment_type_line_id.investment_code if code: code_vars[code] = sibling.declaration_amount or 0 try: # Extract variable names from compute_code var_names = set(re.findall(r'\b[A-Z]+\b', line.compute_code)) for var in var_names: code_vars.setdefault(var, 0) # Ensure missing variables default to 0 rec.declaration_amount = int(eval(line.compute_code, {"__builtins__": {}}, code_vars)) except Exception as e: raise ValidationError(f"Error in compute_code for {line.name}: {e}") else: # Allow manual entry pass @api.onchange('investment_type_line_id', 'declaration_amount') def _onchange_declaration_amount_live(self): for rec in self: line = rec.investment_type_line_id if not line or not rec.it_declaration_id: return siblings = rec.it_declaration_id.past_employment_costings | rec.it_declaration_id.past_employment_costings_new code_vars = {} for sibling in siblings: code = sibling.investment_type_line_id.investment_code if code: code_vars[code] = sibling.declaration_amount or 0 if line.compute_method and line.compute_code: try: rec.declaration_amount = int(eval(line.compute_code, {"__builtins__": {}}, code_vars)) except Exception as e: rec.declaration_amount = 0 # fallback class us80cCostingType(models.Model): _name = 'us80c.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('us80c.investment.type') investment_type_id = fields.Many2one('it.investment.type',related='investment_type_line_id.investment_type') declaration_amount = fields.Integer(string='Declaration Amount') action_id = fields.Many2one('ir.actions.act_window', related='investment_type_line_id.action_id') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() def open_action_wizard(self): self.ensure_one() model = self.env[self.action_id.res_model] action_model = model.sudo().search([('it_declaration_id','=',self.it_declaration_id.id),('us80c_id','=',self.id)],order='id desc',limit=1) # it_declaration_id if not action_model: # Explicitly create record so children get added in create() action_model = model.sudo().create({ 'it_declaration_id': self.it_declaration_id.id, 'us80c_id': self.id, }) return { 'type': 'ir.actions.act_window', 'name': self.action_id.name, 'res_model': self.action_id.res_model, 'res_id': action_model.id, 'view_mode': self.action_id.view_mode, 'target': 'new', } class us80dCostingType(models.Model): _name = 'us80d.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('us80d.investment.type') investment_type_id = fields.Many2one('it.investment.type',related='investment_type_line_id.investment_type') declaration_amount = fields.Integer(string='Declaration Amount') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() class us10CostingType(models.Model): _name = 'us10.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('us10.investment.type') investment_type_id = fields.Many2one('it.investment.type',related='investment_type_line_id.investment_type') declaration_amount = fields.Integer(string='Declaration Amount') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() class us80gCostingType(models.Model): _name = 'us80g.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('us80g.investment.type') investment_type_id = fields.Many2one('it.investment.type',related='investment_type_line_id.investment_type') declaration_amount = fields.Integer(string='Declaration Amount') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() class chapterViaCostingType(models.Model): _name = 'chapter.via.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('chapter.via.investment.type') investment_type_id = fields.Many2one('it.investment.type',related='investment_type_line_id.investment_type') declaration_amount = fields.Integer(string='Declaration Amount') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() class us17CostingType(models.Model): _name = 'us17.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('us17.investment.type') declaration_amount = fields.Integer(string='Declaration Amount') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() class OtherILCostingType(models.Model): _name = 'other.il.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('other.il.investment.type') declaration_amount = fields.Integer(string='Declaration Amount') action_id = fields.Many2one('ir.actions.act_window', related='investment_type_line_id.action_id') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() def open_action_wizard(self): self.ensure_one() model = self.env[self.action_id.res_model] action_model = model.sudo().search([('it_declaration_id','=',self.it_declaration_id.id),('other_il_id','=',self.id)],order='id desc',limit=1) # it_declaration_id if not action_model: # Explicitly create record so children get added in create() action_model = model.sudo().create({ 'it_declaration_id': self.it_declaration_id.id, 'other_il_id': self.id, }) return { 'type': 'ir.actions.act_window', 'name': self.action_id.name, 'res_model': self.action_id.res_model, 'res_id': action_model.id, 'view_mode': self.action_id.view_mode, 'target': 'new', } class OtherDeclarationCostingType(models.Model): _name = 'other.declaration.costing.type' _rec_name = 'investment_type_line_id' costing_type = fields.Many2one('investment.costings') it_declaration_id = fields.Many2one('emp.it.declaration') investment_type_line_id = fields.Many2one('other.declaration.investment.type') declaration_amount = fields.Integer(string='Declaration Amount') proof_amount = fields.Integer(string="Proof Amount") remarks = fields.Text(string="Remarks") proof = fields.Binary(string="PROOF") proof_name = fields.Char() limit = fields.Integer() class HouseRentDeclaration(models.Model): _name = 'house.rent.declaration' _description = 'House Rent Declaration' it_declaration_id = fields.Many2one('emp.it.declaration') costing_type = fields.Many2one('investment.costings') hra_exemption_type = fields.Selection([ ('u_s_10', 'U/S 10 - HRA Exemption'), ('u_s_80gg', 'U/S 80GG - HRA Exemption') ], string="HRA Exemption Type", required=True, default='u_s_10') rent_amount = fields.Float(string="Total Rent for the Period", required=True) from_date = fields.Date(string="From Date", required=True) to_date = fields.Date(string="To Date", required=True) remarks = fields.Text(string="Remarks") landlord_pan_no = fields.Char(string="Landlord PAN No") landlord_name_address = fields.Text(string="Landlord Name & Address") landlord_pan_status = fields.Selection([ ('has_pan', 'Landlord has PAN CARD'), ('declaration', 'Declaration By Landlord') ], string="Landlord PAN Status", required=True, default='has_pan') attachment = fields.Binary(string="Proof Attachment") attachment_filename = fields.Char(string="Attachment Filename") @api.model def create(self, vals): # Auto-link applicant_id if context is passed correctly if self.env.context.get('default_it_declaration_id'): import pdb pdb.set_trace() costing_id = self.env['investment.costings'].sudo().search([('id','=',self.env.context.get('it_declaration_id')),('investment_type_id.investment_type','=','house_rent')],limit=1) vals['costing_type'] = costing_id.id return super().create(vals)