employee it declartion module
This commit is contained in:
parent
4061ba226f
commit
33fbe0ebe2
|
|
@ -0,0 +1,2 @@
|
||||||
|
from . import models
|
||||||
|
from . import wizards
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
{
|
||||||
|
'name': "Payroll Tax Management",
|
||||||
|
|
||||||
|
'summary': "Manage Income Tax Declarations for Employees in Payroll",
|
||||||
|
'description': """
|
||||||
|
Payroll IT Declarations
|
||||||
|
========================
|
||||||
|
|
||||||
|
This module allows HR and payroll departments to manage and track Income Tax (IT) declarations submitted by employees.
|
||||||
|
|
||||||
|
Features:
|
||||||
|
---------
|
||||||
|
- Employee-wise tax declaration submission
|
||||||
|
- HR approval workflow for declarations
|
||||||
|
- Category-wise declaration limits (e.g. 80C, HRA, LTA, etc.)
|
||||||
|
- Auto-calculation of eligible deductions
|
||||||
|
- Integration with Odoo Payroll for accurate tax computation
|
||||||
|
- Attach supporting documents (PDFs, images)
|
||||||
|
- Employee self-service through portal
|
||||||
|
|
||||||
|
Built with usability and compliance in mind, this module streamlines the IT declaration process and ensures transparency and efficiency across the organization.
|
||||||
|
|
||||||
|
Developed by: Pranay
|
||||||
|
""",
|
||||||
|
|
||||||
|
'author': "Pranay",
|
||||||
|
'website': "https://www.ftprotech.com",
|
||||||
|
|
||||||
|
# Categories can be used to filter modules in modules listing
|
||||||
|
# Check https://github.com/odoo/odoo/blob/15.0/odoo/addons/base/data/ir_module_category_data.xml
|
||||||
|
# for the full list
|
||||||
|
'category': 'Human Resources',
|
||||||
|
'version': '0.1',
|
||||||
|
|
||||||
|
# any module necessary for this one to work correctly
|
||||||
|
'depends': ['base','hr','hr_payroll','hr_employee_extended'],
|
||||||
|
|
||||||
|
# always loaded
|
||||||
|
'data': [
|
||||||
|
'security/ir.model.access.csv',
|
||||||
|
'views/payroll_periods.xml',
|
||||||
|
'views/investment_types.xml',
|
||||||
|
# 'views/payroll_periods.xml',
|
||||||
|
'views/slab_master.xml',
|
||||||
|
'views/emp_it_declaration.xml',
|
||||||
|
'views/report_it_tax_statement.xml',
|
||||||
|
'report/report_action.xml',
|
||||||
|
'report/it_tax_template.xml',
|
||||||
|
'views/it_tax_menu_and_wizard_view.xml',
|
||||||
|
'wizards/children_education_costing.xml',
|
||||||
|
'wizards/employee_life_insurance.xml',
|
||||||
|
'wizards/nsc_declaration.xml',
|
||||||
|
'wizards/self_occupied_property.xml',
|
||||||
|
'wizards/letout_house_property.xml',
|
||||||
|
'wizards/nsc_income_loss.xml',
|
||||||
|
# 'views/it_investment_type.xml',
|
||||||
|
# 'views/it_investment_costing.xml'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
from . import payroll_periods
|
||||||
|
from . import investment_types
|
||||||
|
from . import investment_costings
|
||||||
|
from . import emp_it_declaration
|
||||||
|
from . import slab_master
|
||||||
|
from . import it_tax_statement
|
||||||
|
from . import it_tax_statement_wiz
|
||||||
|
|
@ -0,0 +1,274 @@
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import calendar
|
||||||
|
|
||||||
|
|
||||||
|
class EmpITDeclaration(models.Model):
|
||||||
|
_name = 'emp.it.declaration'
|
||||||
|
_rec_name = 'employee_id'
|
||||||
|
_description = "IT Declaration"
|
||||||
|
|
||||||
|
# @api.depends('period_id', 'employee_id')
|
||||||
|
# def _compute_name(self):
|
||||||
|
# for sheet in self:
|
||||||
|
# # sheet.name = _('%(period_id)s, %(emp_name)s', period_id=sheet.period_id.name, emp_name=sheet.employee_id.name)
|
||||||
|
# sheet.name='hello world'
|
||||||
|
|
||||||
|
employee_id = fields.Many2one(
|
||||||
|
'hr.employee',
|
||||||
|
string="Employee",
|
||||||
|
default=lambda self: self.env.user.employee_id,
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
period_id = fields.Many2one(
|
||||||
|
'payroll.period',
|
||||||
|
string="Payroll Period",
|
||||||
|
required=True
|
||||||
|
)
|
||||||
|
|
||||||
|
display_period_label = fields.Char(string="Period Label", compute='_compute_display_period_label')
|
||||||
|
|
||||||
|
@api.depends('period_id.name')
|
||||||
|
def _compute_display_period_label(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.period_id:
|
||||||
|
rec.display_period_label = f"Financial Year {rec.period_id.name}"
|
||||||
|
else:
|
||||||
|
rec.display_period_label = ""
|
||||||
|
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime')
|
||||||
|
], string="Tax Regime", required=True, default='new')
|
||||||
|
|
||||||
|
total_investment = fields.Float(string='Total Investment')
|
||||||
|
|
||||||
|
costing_details_generated = fields.Boolean(default=False)
|
||||||
|
|
||||||
|
investment_costing_ids = fields.One2many('investment.costings','it_declaration_id')
|
||||||
|
house_rent_costing_id = fields.Many2one('investment.costings', compute="_compute_investment_costing")
|
||||||
|
is_section_open = fields.Boolean()
|
||||||
|
@api.depends('costing_details_generated','investment_costing_ids')
|
||||||
|
def _compute_investment_costing(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.investment_costing_ids and rec.costing_details_generated:
|
||||||
|
rec.house_rent_costing_id = rec.investment_costing_ids.filtered(
|
||||||
|
lambda e: e.investment_type_id.investment_type == 'house_rent'
|
||||||
|
)[:1]
|
||||||
|
else:
|
||||||
|
rec.house_rent_costing_id = False
|
||||||
|
past_employment_costings = fields.One2many('past_employment.costing.type','it_declaration_id',domain=[('investment_type_line_id.tax_regime', 'in', ['old', 'both'])])
|
||||||
|
past_employment_costings_new = fields.One2many('past_employment.costing.type','it_declaration_id',domain=[('investment_type_line_id.tax_regime', 'in', ['new', 'both'])])
|
||||||
|
us80c_costings = fields.One2many('us80c.costing.type','it_declaration_id')
|
||||||
|
us80d_selection_type = fields.Selection([('self_family','Self-family'),('self_family_parent','Self-family and parent'),('self_family_senior_parent','Self-family and senior parent')], default='self_family',required=True)
|
||||||
|
us80d_health_checkup = fields.Boolean(string='Preventive Health Checkup')
|
||||||
|
us80d_costings = fields.One2many('us80d.costing.type','it_declaration_id',domain=[('investment_type_line_id.for_family','=',True),('investment_type_line_id.for_parents','=',False),('investment_type_line_id.for_senior_parent','=',False)])
|
||||||
|
us80d_costings_parents = fields.One2many('us80d.costing.type','it_declaration_id',domain=['|',('investment_type_line_id.for_family','=',True),('investment_type_line_id.for_parents','=',True),('investment_type_line_id.for_senior_parent','=',False)])
|
||||||
|
us80d_costings_senior_parents = fields.One2many('us80d.costing.type','it_declaration_id',domain=['|','|',('investment_type_line_id.for_family','=',True),('investment_type_line_id.for_parents','=',True),('investment_type_line_id.for_senior_parent','=',True)])
|
||||||
|
|
||||||
|
us10_costings = fields.One2many('us10.costing.type','it_declaration_id')
|
||||||
|
us80g_costings = fields.One2many('us80g.costing.type','it_declaration_id')
|
||||||
|
chapter_via_costings = fields.One2many('chapter.via.costing.type','it_declaration_id',domain=[('investment_type_line_id.tax_regime', 'in', ['old', 'both'])])
|
||||||
|
chapter_via_costings_new = fields.One2many('chapter.via.costing.type','it_declaration_id',domain=[('investment_type_line_id.tax_regime', 'in', ['new', 'both'])])
|
||||||
|
us17_costings = fields.One2many('us17.costing.type','it_declaration_id')
|
||||||
|
|
||||||
|
house_rent_costings = fields.One2many('house.rent.declaration','it_declaration_id')
|
||||||
|
|
||||||
|
other_il_costings = fields.One2many('other.il.costing.type','it_declaration_id',domain=[('investment_type_line_id.tax_regime', 'in', ['old', 'both'])])
|
||||||
|
other_il_costings_new = fields.One2many('other.il.costing.type','it_declaration_id',domain=[('investment_type_line_id.tax_regime', 'in', ['new', 'both'])])
|
||||||
|
other_declaration_costings = fields.One2many('other.declaration.costing.type','it_declaration_id')
|
||||||
|
|
||||||
|
|
||||||
|
def toggle_section_visibility(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.is_section_open = not rec.is_section_open
|
||||||
|
if rec.is_section_open:
|
||||||
|
for investment_type in rec.investment_costing_ids:
|
||||||
|
if investment_type.investment_type_id.investment_type == 'past_employment':
|
||||||
|
if rec.tax_regime == 'old':
|
||||||
|
investment_type.amount = sum(
|
||||||
|
cost.declaration_amount
|
||||||
|
for cost in rec.past_employment_costings
|
||||||
|
if not cost.investment_type_line_id.compute_method
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
investment_type.amount = sum(
|
||||||
|
cost.declaration_amount
|
||||||
|
for cost in rec.past_employment_costings_new
|
||||||
|
if not cost.investment_type_line_id.compute_method
|
||||||
|
)
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'us_80c':
|
||||||
|
investment_type.amount = sum(
|
||||||
|
cost.declaration_amount
|
||||||
|
for cost in rec.us80c_costings
|
||||||
|
if not cost.investment_type_line_id.compute_method
|
||||||
|
) if rec.tax_regime == 'old' else 0
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'us_80d':
|
||||||
|
if rec.us80d_selection_type == 'self_family':
|
||||||
|
investment_type.amount = sum(rec.us80d_costings.mapped('declaration_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
if rec.us80d_selection_type == 'self_family_parent':
|
||||||
|
investment_type.amount = sum(rec.us80d_costings_parents.mapped('declaration_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
if rec.us80d_selection_type == 'self_family_senior_parent':
|
||||||
|
investment_type.amount = sum(rec.us80d_costings_senior_parents.mapped('declaration_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'us_10':
|
||||||
|
investment_type.amount = sum(rec.us10_costings.mapped('declaration_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'us_80g':
|
||||||
|
investment_type.amount = sum(rec.us80g_costings.mapped('declaration_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'chapter_via':
|
||||||
|
if rec.tax_regime == 'old':
|
||||||
|
investment_type.amount = sum(rec.chapter_via_costings.mapped('declaration_amount') or [0])
|
||||||
|
else:
|
||||||
|
investment_type.amount = sum(rec.chapter_via_costings_new.mapped('declaration_amount') or [0])
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'us_17':
|
||||||
|
investment_type.amount = sum(rec.us17_costings.mapped('declaration_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'house_rent':
|
||||||
|
investment_type.amount = sum(rec.house_rent_costings.mapped('rent_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'other_i_or_l':
|
||||||
|
if rec.tax_regime == 'old':
|
||||||
|
investment_type.amount = sum(rec.other_il_costings.mapped('declaration_amount') or [0])
|
||||||
|
else:
|
||||||
|
investment_type.amount = sum(rec.other_il_costings_new.mapped('declaration_amount') or [0])
|
||||||
|
elif investment_type.investment_type_id.investment_type == 'other_declaration':
|
||||||
|
investment_type.amount = sum(rec.other_declaration_costings.mapped('declaration_amount') or [0]) if rec.tax_regime == 'old' else 0
|
||||||
|
|
||||||
|
@api.onchange('tax_regime')
|
||||||
|
def _onchange_tax_regime(self):
|
||||||
|
if self.tax_regime:
|
||||||
|
# res = super(empITDeclaration, self).fields_get(allfields, attributes)
|
||||||
|
# self.fields_get()
|
||||||
|
if self.tax_regime == 'new':
|
||||||
|
domain = [('investment_type_line_id.tax_regime', 'in', ['new', 'both'])]
|
||||||
|
elif self.tax_regime == 'old':
|
||||||
|
domain = [('investment_type_line_id.tax_regime', 'in', ['old', 'both'])]
|
||||||
|
else:
|
||||||
|
domain = [] # Default case, although 'tax_regime' is required
|
||||||
|
return {'domain': {'past_employment_costings': domain}}
|
||||||
|
else:
|
||||||
|
return {'domain': {'past_employment_costings': []}} # Handle potential empty state
|
||||||
|
|
||||||
|
# def fields_get(self, allfields=None, attributes=None):
|
||||||
|
# import pdb
|
||||||
|
# pdb.set_trace()
|
||||||
|
# res = super(empITDeclaration, self).fields_get(allfields, attributes)
|
||||||
|
# print(res)
|
||||||
|
#
|
||||||
|
# # Example: Modify domain of field_1 based on field_2
|
||||||
|
# if 'tax_regime' in res:
|
||||||
|
# if self.tax_regime == '':
|
||||||
|
# res['field_1']['domain'] = [('some_field', '=', 123)]
|
||||||
|
# else:
|
||||||
|
# res['field_1']['domain'] = [('some_field', '=', 456)]
|
||||||
|
#
|
||||||
|
# return res
|
||||||
|
# import pdb
|
||||||
|
# pdb.set_trace()
|
||||||
|
# if rec.tax_regime:
|
||||||
|
# return {'domain': {'past_employment_costings': [('investment_type_line_id.tax_regime', 'in', ['new','both'])]}}
|
||||||
|
# return {
|
||||||
|
# 'domain': {
|
||||||
|
# 'past_employment_costings': [('investment_type_line_id.tax_regime', 'in', ['new','both'])]
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
|
||||||
|
def generate_declarations(self):
|
||||||
|
for rec in self:
|
||||||
|
investment_types = self.env['it.investment.type'].sudo().search([])
|
||||||
|
for inv_type in investment_types:
|
||||||
|
investment_costing = self.env['investment.costings'].sudo().create({
|
||||||
|
'investment_type_id': inv_type.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
})
|
||||||
|
|
||||||
|
if inv_type.investment_type == 'past_employment':
|
||||||
|
past_emp_costing_ids = [
|
||||||
|
self.env['past_employment.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.past_employment_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'us_80c':
|
||||||
|
|
||||||
|
us80c_costing_ids = [
|
||||||
|
self.env['us80c.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.us80c_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'us_80d':
|
||||||
|
us80d_costing_ids = [
|
||||||
|
self.env['us80d.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.us80d_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'us_10':
|
||||||
|
us10_costing_ids = [
|
||||||
|
self.env['us10.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.us10_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'us_80g':
|
||||||
|
us80g_costing_ids = [
|
||||||
|
self.env['us80g.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.us80g_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'chapter_via':
|
||||||
|
chapter_via_ids = [
|
||||||
|
self.env['chapter.via.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.chapter_via_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'us_17':
|
||||||
|
us17_costing_ids = [
|
||||||
|
self.env['us17.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.us17_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'other_i_or_l':
|
||||||
|
other_il_costing_ids = [
|
||||||
|
self.env['other.il.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.other_il_ids
|
||||||
|
]
|
||||||
|
if inv_type.investment_type == 'other_declaration':
|
||||||
|
other_declaration_costing_ids = [
|
||||||
|
self.env['other.declaration.costing.type'].sudo().create({
|
||||||
|
'costing_type': investment_costing.id,
|
||||||
|
'it_declaration_id': rec.id,
|
||||||
|
'investment_type_line_id': investment_line.id,
|
||||||
|
'limit': investment_line.limit
|
||||||
|
}).id
|
||||||
|
for investment_line in inv_type.other_declaration_ids
|
||||||
|
]
|
||||||
|
rec.costing_details_generated = True
|
||||||
|
|
@ -0,0 +1,309 @@
|
||||||
|
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)
|
||||||
|
|
@ -0,0 +1,220 @@
|
||||||
|
from odoo import models, fields
|
||||||
|
|
||||||
|
|
||||||
|
class ItInvestmentType(models.Model):
|
||||||
|
_name = 'it.investment.type'
|
||||||
|
_rec_name = 'investment_type'
|
||||||
|
|
||||||
|
sequence = fields.Integer()
|
||||||
|
investment_type = fields.Selection(
|
||||||
|
[('past_employment', 'PAST EMPLOYMENT'), ('us_80c', 'US 80C'), ('us_80d', 'US 80D'), ('us_10', 'US 10'),
|
||||||
|
('us_80g', 'US 80G'), ('chapter_via', 'CHAPTER VIA'), ('us_17', 'US 17'), ('house_rent', 'HOUSE RENT'),
|
||||||
|
('other_i_or_l', 'OTHER INCOME/LOSS'), ('other_declaration', 'OTHER DECLARATION')], string="Investment Type",
|
||||||
|
required=True)
|
||||||
|
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
past_employment_ids = fields.One2many('past_employment.investment.type','investment_type')
|
||||||
|
us80c_ids = fields.One2many('us80c.investment.type', 'investment_type')
|
||||||
|
us80d_ids = fields.One2many('us80d.investment.type', 'investment_type')
|
||||||
|
us10_ids = fields.One2many('us10.investment.type', 'investment_type')
|
||||||
|
us80g_ids = fields.One2many('us80g.investment.type', 'investment_type')
|
||||||
|
chapter_via_ids = fields.One2many('chapter.via.investment.type', 'investment_type')
|
||||||
|
us17_ids = fields.One2many('us17.investment.type', 'investment_type')
|
||||||
|
other_il_ids = fields.One2many('other.il.investment.type', 'investment_type')
|
||||||
|
other_declaration_ids = fields.One2many('other.declaration.investment.type', 'investment_type')
|
||||||
|
|
||||||
|
class pastEmpInvestmentType(models.Model):
|
||||||
|
_name = 'past_employment.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
_sql_constraints = [
|
||||||
|
('investment_code_unique', 'unique(investment_code)', 'Code must be unique'),
|
||||||
|
]
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
investment_code = fields.Char()
|
||||||
|
compute_method = fields.Boolean()
|
||||||
|
compute_code = fields.Text('Python Code')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class us80cInvestmentType(models.Model):
|
||||||
|
_name = 'us80c.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
investment_code = fields.Char()
|
||||||
|
compute_method = fields.Boolean()
|
||||||
|
compute_code = fields.Text('Python Code')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
require_action = fields.Boolean()
|
||||||
|
action_id = fields.Many2one('ir.actions.act_window')
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class us80dInvestmentType(models.Model):
|
||||||
|
_name = 'us80d.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
for_family = fields.Boolean()
|
||||||
|
for_parents = fields.Boolean()
|
||||||
|
for_senior_parent = fields.Boolean()
|
||||||
|
sequence = fields.Integer()
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class us10InvestmentType(models.Model):
|
||||||
|
_name = 'us10.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class us80gInvestmentType(models.Model):
|
||||||
|
_name = 'us80g.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", required=True)
|
||||||
|
|
||||||
|
|
||||||
|
class chapterViaInvestmentType(models.Model):
|
||||||
|
_name = 'chapter.via.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class us17InvestmentType(models.Model):
|
||||||
|
_name = 'us17.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
class OtherILInvestmentType(models.Model):
|
||||||
|
_name = 'other.il.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
require_action = fields.Boolean()
|
||||||
|
action_id = fields.Many2one('ir.actions.act_window')
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class OtherDeclarationInvestmentType(models.Model):
|
||||||
|
_name = 'other.declaration.investment.type'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
name = fields.Char(string='GENERAL', required=True)
|
||||||
|
investment_type = fields.Many2one('it.investment.type')
|
||||||
|
limit = fields.Integer(string='LIMIT')
|
||||||
|
sequence = fields.Integer()
|
||||||
|
active = fields.Boolean(default=True)
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime'),
|
||||||
|
('both', 'Both')
|
||||||
|
], string="Tax Regime", store=True, required=True)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# class ItInvestmentTypeLine(models.Model):
|
||||||
|
# _name = 'it.investment.type.line'
|
||||||
|
# _description = 'IT Investment Type Line'
|
||||||
|
# _rec_name = 'name'
|
||||||
|
#
|
||||||
|
# investment_type_id = fields.Many2one(
|
||||||
|
# 'it.investment.type',
|
||||||
|
# string="Investment Type",
|
||||||
|
# required=True,
|
||||||
|
# ondelete='cascade'
|
||||||
|
# )
|
||||||
|
# investment_type = fields.Selection(
|
||||||
|
# [('past_employment', 'PAST EMPLOYMENT'), ('us_80c', 'US 80C'), ('us_80d', 'US 80D'), ('us_10', 'US 10'),
|
||||||
|
# ('us_80g', 'US 80G'), ('chapter_via', 'CHAPTER VIA'), ('us_17', 'US 17'), ('house_rent', 'HOUSE RENT'),
|
||||||
|
# ('other_i_or_l', 'OTHER INCOME/LOSS'), ('other_declaration', 'OTHER DECLARATION')], string="Investment Type",
|
||||||
|
# related='investment_type_id.name')
|
||||||
|
# name = fields.Char(string="Line Name", required=True)
|
||||||
|
# need_action = fields.Boolean(string="Needs Action")
|
||||||
|
# action_id = fields.Many2one(
|
||||||
|
# 'ir.actions.actions',
|
||||||
|
# string="Action",
|
||||||
|
# help="Linked Odoo action if needed"
|
||||||
|
# )
|
||||||
|
# tax_regime = fields.Selection([
|
||||||
|
# ('new', 'New Regime'),
|
||||||
|
# ('old', 'Old Regime')
|
||||||
|
# ], string="Tax Regime", required=True)
|
||||||
|
# sequence = fields.Integer()
|
||||||
|
# active = fields.Boolean(default=True)
|
||||||
|
# limit = fields.Integer()
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
class ITTaxStatement(models.Model):
|
||||||
|
_name = 'it.tax.statement'
|
||||||
|
_description = 'IT Tax Statement'
|
||||||
|
_rec_name = 'employee_id'
|
||||||
|
|
||||||
|
employee_id = fields.Many2one('hr.employee', required=True)
|
||||||
|
declaration_id = fields.Many2one('emp.it.declaration', required=True)
|
||||||
|
period_id = fields.Many2one('payroll.period', related='declaration_id.period_id', store=True)
|
||||||
|
period_line = fields.Many2one('payroll.period.line')
|
||||||
|
total_declared_amount = fields.Float(compute='_compute_totals')
|
||||||
|
tax_regime = fields.Selection(related='declaration_id.tax_regime')
|
||||||
|
pdf_generated = fields.Boolean(default=False)
|
||||||
|
|
||||||
|
@api.depends('declaration_id')
|
||||||
|
def _compute_totals(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.total_declared_amount = sum(rec.declaration_id.investment_costing_ids.mapped('amount'))
|
||||||
|
|
@ -0,0 +1,594 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
from odoo import api, fields, models, _
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from datetime import date, timedelta
|
||||||
|
from dateutil.relativedelta import relativedelta
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
class ITTaxStatementWizard(models.TransientModel):
|
||||||
|
_name = 'it.tax.statement.wizard'
|
||||||
|
_rec_name = 'employee_id'
|
||||||
|
_description = 'Generate IT Tax Statement (Old vs New)'
|
||||||
|
|
||||||
|
# Inputs
|
||||||
|
employee_id = fields.Many2one('hr.employee', required=True, default=lambda self: self.env.user.employee_id.id)
|
||||||
|
emp_doj = fields.Date(related='employee_id.doj', store=True)
|
||||||
|
contract_id = fields.Many2one('hr.contract', related='employee_id.contract_id', required=True)
|
||||||
|
|
||||||
|
period_id = fields.Many2one('payroll.period', required=True)
|
||||||
|
period_line = fields.Many2one('payroll.period.line')
|
||||||
|
|
||||||
|
# Taxpayer profile
|
||||||
|
taxpayer_name = fields.Char(related='employee_id.name')
|
||||||
|
taxpayer_age = fields.Integer(required=True, default=False)
|
||||||
|
residential_status = fields.Selection([
|
||||||
|
('RESIDENT', 'Resident'),
|
||||||
|
('NON-RESIDENT', 'Non-Resident')
|
||||||
|
], default='RESIDENT', required=True)
|
||||||
|
parent_age = fields.Integer(default=65)
|
||||||
|
|
||||||
|
# Tax regime selection
|
||||||
|
tax_regime = fields.Selection([
|
||||||
|
('new', 'New Regime'),
|
||||||
|
('old', 'Old Regime')
|
||||||
|
], string="Tax Regime", required=True, default='new')
|
||||||
|
lock_regime = fields.Selection([
|
||||||
|
('UNLOCKED', 'Unlocked'),
|
||||||
|
('LOCKED', 'Locked')
|
||||||
|
], default='UNLOCKED', string="Lock Regime")
|
||||||
|
|
||||||
|
# Computed fields for salary breakdown
|
||||||
|
basic_salary = fields.Float(compute='_compute_salary_components', store=False)
|
||||||
|
hra_salary = fields.Float(compute='_compute_salary_components', store=False)
|
||||||
|
lta_salary = fields.Float(compute='_compute_salary_components', store=False)
|
||||||
|
special_allowance = fields.Float(compute='_compute_salary_components', store=False)
|
||||||
|
gross_salary = fields.Float(compute='_compute_salary_components', store=False)
|
||||||
|
|
||||||
|
# Deductions
|
||||||
|
professional_tax = fields.Float(compute='_compute_deductions', store=False)
|
||||||
|
standard_deduction = fields.Float(compute='_compute_deductions', store=False)
|
||||||
|
nps_employer_contribution = fields.Float(compute='_compute_deductions', store=False)
|
||||||
|
|
||||||
|
# Other income
|
||||||
|
other_income = fields.Float(string="Other Income", default=0.0)
|
||||||
|
|
||||||
|
# Additional fields for tax calculation
|
||||||
|
hra_exemption = fields.Float(string="HRA Exemption", default=0.0)
|
||||||
|
interest_home_loan_self = fields.Float(string="Interest on Home Loan (Self Occupied)", default=0.0)
|
||||||
|
interest_home_loan_letout = fields.Float(string="Interest on Home Loan (Let Out)", default=0.0)
|
||||||
|
rental_income = fields.Float(string="Rental Income", default=0.0)
|
||||||
|
|
||||||
|
# Deductions under Chapter VI-A
|
||||||
|
ded_80C = fields.Float(string="Deduction under 80C", default=0.0)
|
||||||
|
ded_80CCD1B = fields.Float(string="Deduction under 80CCD(1B)", default=0.0)
|
||||||
|
ded_80D_self = fields.Float(string="Deduction under 80D (Self)", default=0.0)
|
||||||
|
ded_80D_parents = fields.Float(string="Deduction under 80D (Parents)", default=0.0)
|
||||||
|
ded_80G = fields.Float(string="Deduction under 80G", default=0.0)
|
||||||
|
ded_other = fields.Float(string="Other Deductions", default=0.0)
|
||||||
|
|
||||||
|
def _get_applicable_slab(self, regime, age, residence_type):
|
||||||
|
"""Get the applicable tax slab based on regime, age, and residence type"""
|
||||||
|
# Determine age category
|
||||||
|
if age < 60:
|
||||||
|
age_category = 'below_60'
|
||||||
|
elif age < 80:
|
||||||
|
age_category = '60_to_80'
|
||||||
|
else:
|
||||||
|
age_category = 'above_80'
|
||||||
|
|
||||||
|
# Search for slab master
|
||||||
|
slab_master = self.env['it.slab.master'].search([
|
||||||
|
('regime', '=', regime),
|
||||||
|
('age_category', '=', age_category),
|
||||||
|
'|',
|
||||||
|
('residence_type', '=', residence_type.lower()),
|
||||||
|
('residence_type', '=', 'both')
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
if not slab_master:
|
||||||
|
raise ValidationError(_(
|
||||||
|
"No tax slab found for %s Regime with Age Category: %s and Residence Type: %s"
|
||||||
|
) % (regime.capitalize(), age_category.replace('_', ' ').title(), residence_type))
|
||||||
|
|
||||||
|
return slab_master
|
||||||
|
|
||||||
|
def _compute_tax_using_slab(self, taxable, slab_master):
|
||||||
|
"""Compute tax using slab master rules"""
|
||||||
|
tax = 0.0
|
||||||
|
|
||||||
|
# Get rules sorted by min_income
|
||||||
|
rules = slab_master.rules.sorted('min_income')
|
||||||
|
|
||||||
|
for rule in rules:
|
||||||
|
if taxable <= rule.min_income:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Calculate amount in this bracket
|
||||||
|
bracket_max = rule.max_income if rule.max_income else float('inf')
|
||||||
|
amount_in_bracket = min(taxable, bracket_max) - rule.min_income
|
||||||
|
|
||||||
|
# Apply tax calculation based on rule structure
|
||||||
|
if rule.fixed_amount and rule.excess_threshold:
|
||||||
|
# Rule with fixed amount and excess threshold
|
||||||
|
excess_amount = max(0, taxable - rule.excess_threshold)
|
||||||
|
tax_for_bracket = rule.fixed_amount + (excess_amount * rule.tax_rate / 100)
|
||||||
|
else:
|
||||||
|
# Standard bracket calculation
|
||||||
|
tax_for_bracket = amount_in_bracket * rule.tax_rate / 100
|
||||||
|
|
||||||
|
tax += tax_for_bracket
|
||||||
|
|
||||||
|
return tax
|
||||||
|
|
||||||
|
@api.depends('employee_id', 'contract_id', 'period_id')
|
||||||
|
def _compute_salary_components(self):
|
||||||
|
"""Compute salary components from payroll data"""
|
||||||
|
for rec in self:
|
||||||
|
if not rec.employee_id or not rec.contract_id:
|
||||||
|
continue
|
||||||
|
# Get payslip for the period
|
||||||
|
payslip = self.env['hr.payslip'].search([
|
||||||
|
('employee_id', '=', rec.employee_id.id),
|
||||||
|
('date_from', '>=', rec.period_line.from_date),
|
||||||
|
('date_to', '<=', rec.period_line.to_date),
|
||||||
|
('state', 'in', ['verify','done','paid'])
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
if payslip:
|
||||||
|
# Extract salary components from payslip lines
|
||||||
|
rec.basic_salary = self._get_salary_rule_amount(payslip, 'BASIC')
|
||||||
|
rec.hra_salary = self._get_salary_rule_amount(payslip, 'HRA')
|
||||||
|
rec.lta_salary = self._get_salary_rule_amount(payslip, 'LTA')
|
||||||
|
rec.special_allowance = self._get_salary_rule_amount(payslip, 'SPA')
|
||||||
|
rec.gross_salary = self._get_salary_rule_amount(payslip, 'GROSS')
|
||||||
|
else:
|
||||||
|
# Fallback to contract values
|
||||||
|
rec.basic_salary = rec.contract_id.wage * 0.4 # Assuming 40% basic
|
||||||
|
rec.hra_salary = rec.contract_id.wage * 0.2 # Assuming 20% HRA
|
||||||
|
rec.lta_salary = rec.contract_id.wage * 0.1 # Assuming 10% LTA
|
||||||
|
rec.special_allowance = rec.contract_id.wage * 0.3 # Remaining as special allowance
|
||||||
|
rec.gross_salary = rec.contract_id.wage
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_salary_components(self):
|
||||||
|
"""fetch salary components from payroll data"""
|
||||||
|
for rec in self:
|
||||||
|
if not rec.employee_id or not rec.contract_id:
|
||||||
|
continue
|
||||||
|
data = {
|
||||||
|
'basic_salary' : {'actual':[],'projected':[]},
|
||||||
|
'hra_salary': {'actual': [], 'projected': []},
|
||||||
|
'lta_salary': {'actual': [], 'projected': []},
|
||||||
|
'special_allowance' : {'actual':[],'projected':[]},
|
||||||
|
'gross_salary' : {'actual':[],'projected':[]}
|
||||||
|
}
|
||||||
|
period_lines = rec.period_id.period_line_ids
|
||||||
|
|
||||||
|
for line in period_lines:
|
||||||
|
basic_salary = float()
|
||||||
|
hra_salary = float()
|
||||||
|
lta_salary = float()
|
||||||
|
special_allowance = float()
|
||||||
|
gross_salary = float()
|
||||||
|
payslip = self.env['hr.payslip'].search([
|
||||||
|
('employee_id', '=', rec.employee_id.id),
|
||||||
|
('date_from', '>=', line.from_date),
|
||||||
|
('date_to', '<=', line.to_date),
|
||||||
|
('state', 'in', ['verify', 'done', 'paid'])
|
||||||
|
], limit=1)
|
||||||
|
if payslip:
|
||||||
|
# Extract salary components from payslip lines
|
||||||
|
basic_salary = self._get_salary_rule_amount(payslip, 'BASIC')
|
||||||
|
hra_salary = self._get_salary_rule_amount(payslip, 'HRA')
|
||||||
|
lta_salary = self._get_salary_rule_amount(payslip, 'LTA')
|
||||||
|
special_allowance = self._get_salary_rule_amount(payslip, 'SPA')
|
||||||
|
gross_salary = self._get_salary_rule_amount(payslip, 'GROSS')
|
||||||
|
else:
|
||||||
|
payslip = self.env['hr.payslip'].sudo().create({
|
||||||
|
'name': 'Test Payslip',
|
||||||
|
'employee_id': rec.employee_id.id,
|
||||||
|
'date_from': line.from_date,
|
||||||
|
'date_to': line.to_date
|
||||||
|
})
|
||||||
|
payslip.sudo().compute_sheet()
|
||||||
|
|
||||||
|
# Extract salary components from payslip lines
|
||||||
|
basic_salary = self._get_salary_rule_amount(payslip, 'BASIC')
|
||||||
|
hra_salary = self._get_salary_rule_amount(payslip, 'HRA')
|
||||||
|
lta_salary = self._get_salary_rule_amount(payslip, 'LTA')
|
||||||
|
special_allowance = self._get_salary_rule_amount(payslip, 'SPA')
|
||||||
|
gross_salary = self._get_salary_rule_amount(payslip, 'GROSS')
|
||||||
|
|
||||||
|
payslip.sudo().action_payslip_cancel()
|
||||||
|
payslip.sudo().unlink()
|
||||||
|
|
||||||
|
if line.from_date <= rec.period_line.from_date:
|
||||||
|
data['basic_salary']['actual'].append(basic_salary)
|
||||||
|
data['hra_salary']['actual'].append(hra_salary)
|
||||||
|
data['lta_salary']['actual'].append(lta_salary)
|
||||||
|
data['special_allowance']['actual'].append(special_allowance)
|
||||||
|
data['gross_salary']['actual'].append(gross_salary)
|
||||||
|
else:
|
||||||
|
data['basic_salary']['projected'].append(basic_salary)
|
||||||
|
data['hra_salary']['projected'].append(hra_salary)
|
||||||
|
data['lta_salary']['projected'].append(lta_salary)
|
||||||
|
data['special_allowance']['projected'].append(special_allowance)
|
||||||
|
data['gross_salary']['projected'].append(gross_salary)
|
||||||
|
return data
|
||||||
|
|
||||||
|
def _get_salary_rule_amount(self, payslip, rule_code):
|
||||||
|
"""Get amount for a specific salary rule from payslip"""
|
||||||
|
line = payslip.line_ids.filtered(lambda l: l.salary_rule_id.code == rule_code)
|
||||||
|
return line.total if line else 0.0
|
||||||
|
|
||||||
|
@api.depends('employee_id', 'contract_id', 'period_id', 'tax_regime')
|
||||||
|
def _compute_deductions(self):
|
||||||
|
"""Compute deductions from payroll data"""
|
||||||
|
for rec in self:
|
||||||
|
if not rec.employee_id or not rec.contract_id:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Get payslip for the period
|
||||||
|
payslip = self.env['hr.payslip'].search([
|
||||||
|
('employee_id', '=', rec.employee_id.id),
|
||||||
|
('date_from', '>=', rec.period_id.from_date),
|
||||||
|
('date_to', '<=', rec.period_id.to_date),
|
||||||
|
('state', 'in', ['verify', 'done', 'paid'])
|
||||||
|
], limit=1)
|
||||||
|
|
||||||
|
fy_start = self.period_id.from_date
|
||||||
|
fy_end = self.period_id.to_date
|
||||||
|
total_months = ((fy_end.year - fy_start.year) * 12 +
|
||||||
|
(fy_end.month - fy_start.month) + 1)
|
||||||
|
|
||||||
|
line_start = self.period_line.from_date
|
||||||
|
current_month_index = ((line_start.year - fy_start.year) * 12 +
|
||||||
|
(line_start.month - fy_start.month) + 1)
|
||||||
|
if payslip:
|
||||||
|
rec.professional_tax = (self._get_salary_rule_amount(payslip, 'PT'))*current_month_index
|
||||||
|
rec.nps_employer_contribution = self._get_salary_rule_amount(payslip, 'PFE')
|
||||||
|
else:
|
||||||
|
rec.professional_tax = 0.0
|
||||||
|
rec.nps_employer_contribution = 0.0
|
||||||
|
|
||||||
|
# Get standard deduction from slab master
|
||||||
|
if rec.tax_regime == 'new':
|
||||||
|
slab_master = self._get_applicable_slab('new', rec.taxpayer_age, rec.residential_status)
|
||||||
|
else:
|
||||||
|
slab_master = self._get_applicable_slab('old', rec.taxpayer_age, rec.residential_status)
|
||||||
|
|
||||||
|
rec.standard_deduction = slab_master.standard_deduction if slab_master else (
|
||||||
|
75000 if rec.tax_regime == 'new' else 50000
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@api.onchange('employee_id')
|
||||||
|
def onchange_employee_id(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.employee_id and rec.employee_id.birthday:
|
||||||
|
age = relativedelta(date.today(), rec.employee_id.birthday).years
|
||||||
|
rec.taxpayer_age = age
|
||||||
|
else:
|
||||||
|
rec.taxpayer_age = rec.taxpayer_age or 0
|
||||||
|
|
||||||
|
@api.onchange('basic_salary', 'hra_salary')
|
||||||
|
def onchange_hra_exemption(self):
|
||||||
|
"""Calculate HRA exemption based on salary components"""
|
||||||
|
for rec in self:
|
||||||
|
if rec.basic_salary and rec.hra_salary:
|
||||||
|
# Basic formula for HRA exemption
|
||||||
|
# Minimum of:
|
||||||
|
# 1. Actual HRA received
|
||||||
|
# 2. 50% of basic salary (for metro cities) or 40% (non-metro)
|
||||||
|
# 3. Rent paid minus 10% of basic salary
|
||||||
|
|
||||||
|
# Assuming metro city for calculation
|
||||||
|
exemption_option1 = rec.hra_salary
|
||||||
|
exemption_option2 = 0.5 * rec.basic_salary
|
||||||
|
# Rent paid would need to be input by user
|
||||||
|
rent_paid = rec.hra_exemption or 0
|
||||||
|
exemption_option3 = max(0, rent_paid - 0.1 * rec.basic_salary)
|
||||||
|
|
||||||
|
rec.hra_exemption = min(exemption_option1, exemption_option2, exemption_option3)
|
||||||
|
|
||||||
|
# --- Tax Calculation Methods ---
|
||||||
|
def _old_basic_exemption(self, age):
|
||||||
|
if age < 60:
|
||||||
|
return 250000.0
|
||||||
|
elif age < 80:
|
||||||
|
return 300000.0
|
||||||
|
return 500000.0
|
||||||
|
|
||||||
|
def _rebate_old(self, taxable, slab_tax):
|
||||||
|
if self.residential_status != 'RESIDENT':
|
||||||
|
return 0.0
|
||||||
|
if taxable <= 500000.0:
|
||||||
|
return min(12500.0, slab_tax)
|
||||||
|
return 0.0
|
||||||
|
|
||||||
|
def _rebate_new(self, taxable, slab_tax):
|
||||||
|
if self.residential_status != 'RESIDENT':
|
||||||
|
return 0.0
|
||||||
|
if taxable >= 1200000.0:
|
||||||
|
needed = taxable - 1200000.0
|
||||||
|
if slab_tax >= needed:
|
||||||
|
return max(0.0, slab_tax - needed)
|
||||||
|
return 0.0
|
||||||
|
else:
|
||||||
|
return min(60000.0, slab_tax)
|
||||||
|
|
||||||
|
def _apply_surcharge_with_mr(self, slab_master, taxable, tax_after_rebate, regime):
|
||||||
|
rules = slab_master.rules.sorted('min_income')
|
||||||
|
table = [(rule.min_income, rule.surcharge_rate) for rule in rules if rule.surcharge_rate > 0]
|
||||||
|
|
||||||
|
threshold = None
|
||||||
|
rate = 0.0
|
||||||
|
for th, rt in table:
|
||||||
|
if taxable > th:
|
||||||
|
threshold, rate = th, rt
|
||||||
|
|
||||||
|
if not threshold:
|
||||||
|
return 0.0, 0.0, tax_after_rebate
|
||||||
|
|
||||||
|
surcharge = tax_after_rebate * rate
|
||||||
|
total_before_mr = tax_after_rebate + surcharge
|
||||||
|
|
||||||
|
mr = max(0.0, total_before_mr)
|
||||||
|
tax_with_surcharge = total_before_mr - mr
|
||||||
|
return surcharge, mr, tax_with_surcharge
|
||||||
|
|
||||||
|
def _compute_tax_old_regime(self, taxable):
|
||||||
|
# Get applicable slab
|
||||||
|
slab_master = self._get_applicable_slab('old', self.taxpayer_age, self.residential_status)
|
||||||
|
|
||||||
|
# Compute slab tax
|
||||||
|
slab_tax = self._compute_tax_using_slab(taxable, slab_master)
|
||||||
|
|
||||||
|
# Apply rebate
|
||||||
|
rebate = self._rebate_old(taxable, slab_tax)
|
||||||
|
tax_after_rebate = max(0.0, slab_tax - rebate)
|
||||||
|
|
||||||
|
# Apply surcharge and marginal relief
|
||||||
|
surcharge, marginal_relief, tax_with_surcharge = self._apply_surcharge_with_mr(
|
||||||
|
slab_master, taxable, tax_after_rebate, regime='old'
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply cess
|
||||||
|
rules = slab_master.rules.sorted('min_income')
|
||||||
|
|
||||||
|
cess_rate = [rule.cess_rate for rule in rules if rule.min_income<=taxable and rule.max_income >= taxable]
|
||||||
|
cess = tax_with_surcharge * cess_rate[0]/100
|
||||||
|
|
||||||
|
total_tax = tax_with_surcharge + cess
|
||||||
|
|
||||||
|
return {
|
||||||
|
'taxable_income': taxable,
|
||||||
|
'slab_tax': slab_tax,
|
||||||
|
'rebate_87a': rebate,
|
||||||
|
'tax_after_rebate': tax_after_rebate,
|
||||||
|
'surcharge': surcharge,
|
||||||
|
'marginal_relief': marginal_relief,
|
||||||
|
'tax_with_surcharge': tax_with_surcharge,
|
||||||
|
'cess_4pct': cess,
|
||||||
|
'total_tax': total_tax
|
||||||
|
}
|
||||||
|
|
||||||
|
def _compute_tax_new_regime(self, taxable):
|
||||||
|
# Get applicable slab (new regime doesn't depend on age)
|
||||||
|
slab_master = self._get_applicable_slab('new', self.taxpayer_age, self.residential_status)
|
||||||
|
|
||||||
|
# Compute slab tax
|
||||||
|
slab_tax = self._compute_tax_using_slab(taxable, slab_master)
|
||||||
|
|
||||||
|
# Apply rebate
|
||||||
|
rebate = self._rebate_new(taxable, slab_tax)
|
||||||
|
tax_after_rebate = max(0.0, slab_tax - rebate)
|
||||||
|
|
||||||
|
# Apply surcharge and marginal relief
|
||||||
|
surcharge, marginal_relief, tax_with_surcharge = self._apply_surcharge_with_mr(
|
||||||
|
slab_master, taxable, tax_after_rebate, regime='new'
|
||||||
|
)
|
||||||
|
|
||||||
|
rules = slab_master.rules.sorted('min_income')
|
||||||
|
cess_rate = [rule.cess_rate for rule in rules if rule.min_income<=taxable and rule.max_income >= taxable]
|
||||||
|
# Apply cess
|
||||||
|
cess = tax_with_surcharge * cess_rate[0]/100
|
||||||
|
total_tax = tax_with_surcharge + cess
|
||||||
|
|
||||||
|
return {
|
||||||
|
'taxable_income': taxable,
|
||||||
|
'slab_tax': slab_tax,
|
||||||
|
'rebate_87a': rebate,
|
||||||
|
'tax_after_rebate': tax_after_rebate,
|
||||||
|
'surcharge': surcharge,
|
||||||
|
'marginal_relief': marginal_relief,
|
||||||
|
'tax_with_surcharge': tax_with_surcharge,
|
||||||
|
'cess_4pct': cess,
|
||||||
|
'total_tax': total_tax
|
||||||
|
}
|
||||||
|
|
||||||
|
def _compute_house_property_income(self):
|
||||||
|
"""Returns net house property income"""
|
||||||
|
rent = float(self.rental_income or 0.0)
|
||||||
|
if rent > 0.0:
|
||||||
|
nav = rent
|
||||||
|
std_ded = 0.30 * nav
|
||||||
|
interest_allowed = float(self.interest_home_loan_letout or 0.0)
|
||||||
|
hp_income = nav - std_ded - interest_allowed
|
||||||
|
else:
|
||||||
|
interest_allowed = min(float(self.interest_home_loan_self or 0.0), 200000.0)
|
||||||
|
hp_income = -interest_allowed
|
||||||
|
return hp_income
|
||||||
|
|
||||||
|
def _prepare_income_tax_data(self):
|
||||||
|
"""Prepare data for the tax statement report"""
|
||||||
|
today = date.today()
|
||||||
|
fy_start = self.period_id.from_date
|
||||||
|
fy_end = self.period_id.to_date
|
||||||
|
total_months = ((fy_end.year - fy_start.year) * 12 +
|
||||||
|
(fy_end.month - fy_start.month) + 1)
|
||||||
|
|
||||||
|
line_start = self.period_line.from_date
|
||||||
|
current_month_index = ((line_start.year - fy_start.year) * 12 +
|
||||||
|
(line_start.month - fy_start.month) + 1)
|
||||||
|
if today.month >= 4:
|
||||||
|
fy_start = date(today.year, 4, 1)
|
||||||
|
fy_end = date(today.year + 1, 3, 31)
|
||||||
|
else:
|
||||||
|
fy_start = date(today.year - 1, 4, 1)
|
||||||
|
fy_end = date(today.year, 3, 31)
|
||||||
|
|
||||||
|
# Calculate taxable income for both regimes
|
||||||
|
# Old regime
|
||||||
|
old_deductions = (
|
||||||
|
self.standard_deduction +
|
||||||
|
self.hra_exemption +
|
||||||
|
self.professional_tax +
|
||||||
|
self.ded_80C +
|
||||||
|
self.ded_80CCD1B +
|
||||||
|
self.ded_80D_self +
|
||||||
|
self.ded_80D_parents +
|
||||||
|
self.ded_80G +
|
||||||
|
self.ded_other +
|
||||||
|
self.nps_employer_contribution
|
||||||
|
)
|
||||||
|
|
||||||
|
# House property income
|
||||||
|
hp_income = self._compute_house_property_income()
|
||||||
|
|
||||||
|
# Taxable income for old regime
|
||||||
|
taxable_old = max(0.0, (self.gross_salary * total_months) + self.other_income + hp_income - self.standard_deduction)
|
||||||
|
|
||||||
|
# New regime - fewer deductions
|
||||||
|
new_deductions = (
|
||||||
|
self.standard_deduction +
|
||||||
|
self.professional_tax +
|
||||||
|
self.nps_employer_contribution
|
||||||
|
)
|
||||||
|
|
||||||
|
# Taxable income for new regime
|
||||||
|
|
||||||
|
taxable_new = max(0.0, (self.gross_salary * total_months) + self.other_income + hp_income - self.standard_deduction)
|
||||||
|
|
||||||
|
# Compute tax for both regimes
|
||||||
|
tax_result_old = self._compute_tax_old_regime(taxable_old)
|
||||||
|
tax_result_new = self._compute_tax_new_regime(taxable_new)
|
||||||
|
|
||||||
|
# Determine which regime to use
|
||||||
|
if self.tax_regime == 'old':
|
||||||
|
tax_result = tax_result_old
|
||||||
|
taxable_income = taxable_old
|
||||||
|
chosen = 'old'
|
||||||
|
else:
|
||||||
|
tax_result = tax_result_new
|
||||||
|
taxable_income = taxable_new
|
||||||
|
chosen = 'new'
|
||||||
|
|
||||||
|
# Calculate tax savings
|
||||||
|
tax_savings = abs(tax_result_old['total_tax'] - tax_result_new['total_tax'])
|
||||||
|
beneficial_regime = 'old' if tax_result_old['total_tax'] < tax_result_new['total_tax'] else 'new'
|
||||||
|
|
||||||
|
# Prepare data structure matching screenshot format
|
||||||
|
# Financial year (period_id)
|
||||||
|
fy_start = self.period_id.from_date
|
||||||
|
fy_end = self.period_id.to_date
|
||||||
|
total_months = ((fy_end.year - fy_start.year) * 12 +
|
||||||
|
(fy_end.month - fy_start.month) + 1)
|
||||||
|
|
||||||
|
# Current month (period_line)
|
||||||
|
line_start = self.period_line.from_date
|
||||||
|
current_month_index = ((line_start.year - fy_start.year) * 12 +
|
||||||
|
(line_start.month - fy_start.month) + 1)
|
||||||
|
tax_result['roundoff_taxable_income'] = float(round(tax_result["taxable_income"] / 10) * 10)
|
||||||
|
birthday = self.employee_id.birthday
|
||||||
|
if birthday:
|
||||||
|
diff = relativedelta(date.today(), birthday)
|
||||||
|
years_months = f"{diff.years} years {diff.months} months"
|
||||||
|
else:
|
||||||
|
years_months = "N/A"
|
||||||
|
month_age = str(self.period_line.name)+ " / " + str(years_months)
|
||||||
|
salary_components_data = self.fetch_salary_components()
|
||||||
|
data = {
|
||||||
|
'financial_year': f"{fy_start.year}-{fy_end.year}",
|
||||||
|
'assessment_year': fy_end.year + 1,
|
||||||
|
'report_time': today.strftime('%d-%m-%Y %H:%M'),
|
||||||
|
'user': 'ESS',
|
||||||
|
'emp_code': self.employee_id.employee_id,
|
||||||
|
'company_name': self.employee_id.company_id.name,
|
||||||
|
'profile': {
|
||||||
|
'name': self.taxpayer_name or (self.employee_id.name if self.employee_id else ''),
|
||||||
|
'age': self.taxpayer_age,
|
||||||
|
'residential_status': self.residential_status,
|
||||||
|
'parent_age': self.parent_age,
|
||||||
|
'doj': self.employee_id.doj,
|
||||||
|
'pan': self.employee_id.pan_no if hasattr(self.employee_id, 'pan_no') else '',
|
||||||
|
'gender': self.employee_id.gender,
|
||||||
|
'month_age': month_age
|
||||||
|
},
|
||||||
|
|
||||||
|
'regime_info': {
|
||||||
|
'lock_regime': self.lock_regime,
|
||||||
|
'tax_regime': 'NEW REGIME' if self.tax_regime == 'new' else 'OLD REGIME',
|
||||||
|
},
|
||||||
|
|
||||||
|
'salary_components': {
|
||||||
|
'basic': {'actual': sum(salary_components_data['basic_salary']['actual']), 'projected': sum(salary_components_data['basic_salary']['projected']), 'total':sum(salary_components_data['basic_salary']['actual']) + sum(salary_components_data['basic_salary']['projected'])},
|
||||||
|
'house_rent': {'actual': sum(salary_components_data['hra_salary']['actual']), 'projected': sum(salary_components_data['hra_salary']['projected']), 'total':sum(salary_components_data['hra_salary']['actual']) + sum(salary_components_data['hra_salary']['projected'])},
|
||||||
|
'lta': {'actual': sum(salary_components_data['lta_salary']['actual']), 'projected': sum(salary_components_data['lta_salary']['projected']), 'total':sum(salary_components_data['lta_salary']['actual']) + sum(salary_components_data['lta_salary']['projected'])},
|
||||||
|
'special_allowance':{'actual': sum(salary_components_data['special_allowance']['actual']), 'projected': sum(salary_components_data['special_allowance']['projected']), 'total':sum(salary_components_data['special_allowance']['actual']) + sum(salary_components_data['special_allowance']['projected'])},
|
||||||
|
'perquisites': {'actual': 0 * current_month_index, 'projected': 0 * (total_months - current_month_index), 'total': 0 * total_months},
|
||||||
|
'reimbursement': {'actual': 0 * current_month_index, 'projected': 0 * (total_months - current_month_index), 'total': 0 * total_months},
|
||||||
|
'gross_salary': {'actual': sum(salary_components_data['gross_salary']['actual']), 'projected': sum(salary_components_data['gross_salary']['projected']), 'total':sum(salary_components_data['gross_salary']['actual']) + sum(salary_components_data['gross_salary']['projected'])},
|
||||||
|
'net_salary': {'actual': self.gross_salary * current_month_index, 'projected': self.gross_salary * (total_months - current_month_index),
|
||||||
|
'total': self.gross_salary * total_months}
|
||||||
|
},
|
||||||
|
|
||||||
|
'deductions': {
|
||||||
|
'professional_tax': self.professional_tax,
|
||||||
|
'standard_deduction': self.standard_deduction,
|
||||||
|
'nps_employer': self.nps_employer_contribution,
|
||||||
|
'hra_exemption': self.hra_exemption,
|
||||||
|
'interest_home_loan': self.interest_home_loan_self + self.interest_home_loan_letout,
|
||||||
|
'ded_80C': self.ded_80C,
|
||||||
|
'ded_80CCD1B': self.ded_80CCD1B,
|
||||||
|
'ded_80D_self': self.ded_80D_self,
|
||||||
|
'ded_80D_parents': self.ded_80D_parents,
|
||||||
|
'ded_80G': self.ded_80G,
|
||||||
|
'ded_other': self.ded_other,
|
||||||
|
'total_deductions': old_deductions if self.tax_regime == 'old' else new_deductions,
|
||||||
|
},
|
||||||
|
|
||||||
|
'income_details': {
|
||||||
|
'gross_salary': self.gross_salary,
|
||||||
|
'other_income': self.other_income,
|
||||||
|
'house_property_income': hp_income,
|
||||||
|
'gross_total_income': (self.gross_salary * total_months) + self.other_income + hp_income - self.standard_deduction,
|
||||||
|
},
|
||||||
|
|
||||||
|
'taxable_income': {
|
||||||
|
'old_regime': taxable_old,
|
||||||
|
'new_regime': taxable_new,
|
||||||
|
'current_regime': taxable_income,
|
||||||
|
},
|
||||||
|
|
||||||
|
'tax_computation': tax_result,
|
||||||
|
'regime_used': chosen,
|
||||||
|
|
||||||
|
'comparison': {
|
||||||
|
'old_regime_tax': tax_result_old['total_tax'],
|
||||||
|
'new_regime_tax': tax_result_new['total_tax'],
|
||||||
|
'tax_savings': tax_savings,
|
||||||
|
'beneficial_regime': beneficial_regime,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {'data': data}
|
||||||
|
|
||||||
|
def action_generate_report(self):
|
||||||
|
report_data = self._prepare_income_tax_data()
|
||||||
|
|
||||||
|
return self.env.ref('employee_it_declaration.income_tax_statement_action_report').report_action(
|
||||||
|
self,
|
||||||
|
data={'report_data': report_data},
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
from odoo.exceptions import ValidationError
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
import calendar
|
||||||
|
|
||||||
|
|
||||||
|
class PayrollPeriod(models.Model):
|
||||||
|
_name = 'payroll.period'
|
||||||
|
_description = 'Payroll Period'
|
||||||
|
_rec_name = 'name'
|
||||||
|
_sql_constraints = [
|
||||||
|
('unique_name', 'unique(name)', 'The name must be unique.')
|
||||||
|
]
|
||||||
|
|
||||||
|
from_date = fields.Date(string="From Date", required=True)
|
||||||
|
to_date = fields.Date(string="To Date", required=True)
|
||||||
|
name = fields.Char(string="Name", required=True)
|
||||||
|
period_line_ids = fields.One2many('payroll.period.line', 'period_id', string="Monthly Periods")
|
||||||
|
|
||||||
|
@api.onchange('from_date', 'to_date')
|
||||||
|
def onchange_from_to_date(self):
|
||||||
|
for rec in self:
|
||||||
|
if rec.from_date and rec.to_date:
|
||||||
|
rec.name = f"{rec.from_date.year}-{rec.to_date.year}"
|
||||||
|
|
||||||
|
|
||||||
|
def action_generate_month_lines(self):
|
||||||
|
self.ensure_one()
|
||||||
|
if not (self.from_date and self.to_date):
|
||||||
|
raise ValidationError("Please set both From Date and To Date.")
|
||||||
|
|
||||||
|
lines = []
|
||||||
|
current = self.from_date.replace(day=1)
|
||||||
|
while current <= self.to_date:
|
||||||
|
end_of_month = current.replace(day=calendar.monthrange(current.year, current.month)[1])
|
||||||
|
if end_of_month > self.to_date:
|
||||||
|
end_of_month = self.to_date
|
||||||
|
|
||||||
|
lines.append((0, 0, {
|
||||||
|
'from_date': current,
|
||||||
|
'to_date': end_of_month,
|
||||||
|
'name': f"{current.strftime('%b')} - {str(current.year)[-2:]}"
|
||||||
|
}))
|
||||||
|
|
||||||
|
if current.month == 12:
|
||||||
|
current = current.replace(year=current.year + 1, month=1)
|
||||||
|
else:
|
||||||
|
current = current.replace(month=current.month + 1)
|
||||||
|
|
||||||
|
self.period_line_ids = lines
|
||||||
|
|
||||||
|
|
||||||
|
class PayrollPeriodLine(models.Model):
|
||||||
|
_name = 'payroll.period.line'
|
||||||
|
_description = 'Payroll Period Line'
|
||||||
|
_rec_name = 'name'
|
||||||
|
|
||||||
|
period_id = fields.Many2one('payroll.period', string="Payroll Period", required=True, ondelete='cascade')
|
||||||
|
from_date = fields.Date(string="From Date")
|
||||||
|
to_date = fields.Date(string="To Date")
|
||||||
|
name = fields.Char(string="Name")
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
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}"
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,726 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
<template id="generate_income_tax_statement_rpt">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<div class="page">
|
||||||
|
<t t-set="data" t-value="report_data['data']"/>
|
||||||
|
<t t-set="profile" t-value="data.get('profile')"/>
|
||||||
|
<t t-set="company_name" t-value="data.get('company_name')"/>
|
||||||
|
<t t-set="regime_info" t-value="data.get('regime_info')"/>
|
||||||
|
<t t-set="salary_components" t-value="data.get('salary_components')"/>
|
||||||
|
<t t-set="deductions" t-value="data.get('deductions')"/>
|
||||||
|
<t t-set="income_details" t-value="data.get('income_details')"/>
|
||||||
|
<t t-set="taxable_income" t-value="data.get('taxable_income')"/>
|
||||||
|
<t t-set="tax_computation" t-value="data.get('tax_computation')"/>
|
||||||
|
<t t-set="regime_used" t-value="data.get('regime_used')"/>
|
||||||
|
<t t-set="comparison" t-value="data.get('comparison')"/>
|
||||||
|
<!-- Set Dynamic Variables -->
|
||||||
|
<t t-set="emp_code" t-value="data.get('emp_code')"/>
|
||||||
|
<t t-set="name" t-value="profile.get('name', '')"/>
|
||||||
|
<t t-set="pan" t-value="profile.get('pan', '')"/>
|
||||||
|
<t t-set="month_age" t-value="profile.get('month_age', '')"/>
|
||||||
|
<t t-set="gender" t-value="(profile.get('gender', '') or '').upper()"/>
|
||||||
|
<t t-set="joining_date" t-value="profile.get('doj', '')"/>
|
||||||
|
<t t-set="leaving_date" t-value=""/>
|
||||||
|
<t t-set="status" t-value="Active"/>
|
||||||
|
<t t-set="lock_regime" t-value="regime_info.get('lock_regime', '')"/>
|
||||||
|
<t t-set="net_salary"
|
||||||
|
t-value="'{:,.0f}'.format(salary_components.get('net_salary', {}).get('total', 0))"/>
|
||||||
|
<t t-set="tax_employment" t-value="'{:,.0f}'.format(deductions.get('professional_tax', 0))"/>
|
||||||
|
<t t-set="standard_deduction" t-value="'{:,.0f}'.format(deductions.get('standard_deduction', 0))"/>
|
||||||
|
<t t-set="other_income" t-value="'{:,.0f}'.format(income_details.get('other_income', 0))"/>
|
||||||
|
<t t-set="gross_total_income" t-value="'{:,.0f}'.format(income_details.get('gross_total_income', 0))"/>
|
||||||
|
<t t-set="taxable_income" t-value="'{:,.0f}'.format(tax_computation.get('taxable_income', 0))"/>
|
||||||
|
<t t-set="roundoff_taxable_income" t-value="'{:,.0f}'.format(tax_computation.get('roundoff_taxable_income', 0))"/>
|
||||||
|
<t t-set="tax_payable" t-value="'{:,.0f}'.format(tax_computation.get('slab_tax', 0))"/>
|
||||||
|
<t t-set="rebate_87a" t-value="'{:,.0f}'.format(tax_computation.get('rebate_87a', 0))"/>
|
||||||
|
<t t-set="cess" t-value="'{:,.0f}'.format(tax_computation.get('cess_4pct', 0))"/>
|
||||||
|
<t t-set="total_tax" t-value="'{:,.0f}'.format(tax_computation.get('total_tax', 0))"/>
|
||||||
|
<t t-set="report_time" t-value="data.get('report_time', '')"/>
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div style="text-align: center; margin-bottom: 20px;">
|
||||||
|
<h2 style="font-weight: bold; margin-bottom: 5px;"><t t-esc="company_name"/></h2>
|
||||||
|
<h3 style="font-weight: bold; margin-top: 0;">INCOME TAX COMPUTATION STATEMENT</h3>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Employee Info -->
|
||||||
|
<table class="table table-sm" style="width: 100%; margin-bottom: 25px;">
|
||||||
|
<tr>
|
||||||
|
<td style="width: 33%;">
|
||||||
|
<strong>Emp Code:</strong>
|
||||||
|
<t t-esc="emp_code"/>
|
||||||
|
</td>
|
||||||
|
<td style="width: 33%;">
|
||||||
|
<strong>Name:</strong>
|
||||||
|
<t t-esc="name"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<table class="table table-sm" style="width: 100%; margin-bottom: 25px;">
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Assessment Year:</strong>
|
||||||
|
<t t-esc="data.get('assessment_year', '')"/>-
|
||||||
|
<t t-esc="(data.get('assessment_year', 0) or 0) + 1"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Month / Age:</strong>
|
||||||
|
<t t-esc="month_age"/>
|
||||||
|
</td>
|
||||||
|
<td style="width: 34%;">
|
||||||
|
<strong>PAN:</strong>
|
||||||
|
<t t-esc="pan"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Date of Joining:</strong>
|
||||||
|
<t t-esc="joining_date"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Leaving Date:</strong>
|
||||||
|
<t t-esc="leaving_date"/>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<strong>Gender:</strong>
|
||||||
|
<t t-esc="gender"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Head of Income -->
|
||||||
|
<h4 style="font-weight: bold; border-bottom: 2px solid #ddd; padding-bottom: 5px; margin-bottom: 15px;">
|
||||||
|
Head of Income
|
||||||
|
</h4>
|
||||||
|
<table class="table table-bordered table-sm" style="width: 100%; margin-bottom: 20px;">
|
||||||
|
<thead>
|
||||||
|
<tr style="background-color: #f8f9fa;">
|
||||||
|
<th style="font-weight: bold; text-align: left;">Description</th>
|
||||||
|
<th style="font-weight: bold; text-align: right;">Actual</th>
|
||||||
|
<th style="font-weight: bold; text-align: right;">Projected</th>
|
||||||
|
<th style="font-weight: bold; text-align: right;">Total</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Basic</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('basic', {}).get('actual', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('basic', {}).get('projected', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('basic', {}).get('total', 0))"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>House Rent</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('house_rent', {}).get('actual', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('house_rent', {}).get('projected', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('house_rent', {}).get('total', 0))"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>LTA</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('lta', {}).get('actual', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('lta', {}).get('projected', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('lta', {}).get('total', 0))"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Special Allowance</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('special_allowance', {}).get('actual', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('special_allowance', {}).get('projected', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('special_allowance', {}).get('total', 0))"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Reimbursement</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('reimbursement', {}).get('actual', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('reimbursement', {}).get('projected', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('reimbursement', {}).get('total', 0))"/>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid #ddd; font-weight: bold;">
|
||||||
|
<td>Gross Salary</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('gross_salary', {}).get('actual', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('gross_salary', {}).get('projected', 0))"/>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="'{:,.0f}'.format(salary_components.get('gross_salary', {}).get('total', 0))"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Less: Exemption under section 10</td>
|
||||||
|
<td colspan="3"></td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid #ddd; font-weight: bold; margin-bottom: 8px; margin-top: 10px;">
|
||||||
|
<td>Net Salary</td>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="net_salary"/>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid #ddd; margin-bottom: 8px; margin-top: 10px;">
|
||||||
|
<td><strong>Less:</strong> Deduction under section 16</td>
|
||||||
|
<td colspan="3"></td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid #ddd; margin-bottom: 8px; margin-top: 10px;">
|
||||||
|
<td style="padding-left: 30px;">Tax on Employment: Sec 16 - Prof. Tax</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="tax_employment"/>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid #ddd; margin-bottom: 8px; margin-top: 10px;">
|
||||||
|
<td style="padding-left: 30px;">Less: Standard Deduction for Salaried Employees</td>
|
||||||
|
<td colspan="2"></td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="standard_deduction"/>
|
||||||
|
</tr>
|
||||||
|
<tr style="border-top: 2px solid #ddd; margin-bottom: 8px; margin-top: 10px;">
|
||||||
|
<td style="padding-left: 30px;">Total</td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="tax_employment"/>
|
||||||
|
<td colspan="1"></td>
|
||||||
|
<td style="text-align: right;"
|
||||||
|
t-esc="standard_deduction"/>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr style="border-top: 2px solid #ddd; font-weight: bold; margin-bottom: 8px; margin-top: 10px;">
|
||||||
|
<td>Other Income</td>
|
||||||
|
<td colspan="3"></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- <div style="margin-bottom: 8px;">-->
|
||||||
|
<!-- <strong>Net Salary:</strong>-->
|
||||||
|
<!-- <span style="float: right;" t-esc="net_salary"/>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <div style="margin-bottom: 8px;">-->
|
||||||
|
<!-- <strong>Other Income:</strong>-->
|
||||||
|
<!-- <span style="float: right;" t-esc="other_income"/>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<div style="margin-bottom: 20px; font-weight: bold; border-top: 1px solid #ddd; padding-top: 8px;">
|
||||||
|
<strong>Gross Total Income:</strong>
|
||||||
|
<span style="float: right;" t-esc="gross_total_income"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Deductions -->
|
||||||
|
<h4 style="border-bottom: 2px #ddd; padding-bottom: 5px; margin-bottom: 15px;">
|
||||||
|
<strong>Less</strong> Deductions under Chapter VIA
|
||||||
|
<span style="float: right;">0</span>
|
||||||
|
</h4>
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="width: 100%; margin-bottom: 20px;">-->
|
||||||
|
<!-- <thead>-->
|
||||||
|
<!-- <tr style="background-color: #f8f9fa;">-->
|
||||||
|
<!-- <th style="font-weight: bold; text-align: left;">Investment</th>-->
|
||||||
|
<!-- <th style="font-weight: bold; text-align: left;">Section</th>-->
|
||||||
|
<!-- <th style="font-weight: bold; text-align: right;">Gross</th>-->
|
||||||
|
<!-- <th style="font-weight: bold; text-align: right;">Qualifying</th>-->
|
||||||
|
<!-- <th style="font-weight: bold; text-align: right;">Deductible</th>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </thead>-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>National Pension Scheme (Employer contribution)</td>-->
|
||||||
|
<!-- <td>80CCD(2)</td>-->
|
||||||
|
<!-- <td style="text-align: right;" t-esc="'{:,.0f}'.format(deductions.get('nps_employer', 0))"/>-->
|
||||||
|
<!-- <td style="text-align: right;" t-esc="'{:,.0f}'.format(deductions.get('nps_employer', 0))"/>-->
|
||||||
|
<!-- <td style="text-align: right;" t-esc="'{:,.0f}'.format(deductions.get('nps_employer', 0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Others</td>-->
|
||||||
|
<!-- <td>-</td>-->
|
||||||
|
<!-- <td style="text-align: right;"-->
|
||||||
|
<!-- t-esc="'{:,.0f}'.format(deductions.get('total_deductions', 0) - deductions.get('nps_employer', 0))"/>-->
|
||||||
|
<!-- <td style="text-align: right;"-->
|
||||||
|
<!-- t-esc="'{:,.0f}'.format(deductions.get('total_deductions', 0) - deductions.get('nps_employer', 0))"/>-->
|
||||||
|
<!-- <td style="text-align: right;"-->
|
||||||
|
<!-- t-esc="'{:,.0f}'.format(deductions.get('total_deductions', 0) - deductions.get('nps_employer', 0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
|
||||||
|
<!-- Tax Computation -->
|
||||||
|
<h4 style="font-weight: bold; border-bottom: 2px solid #ddd; padding-bottom: 5px; margin-bottom: 15px;">
|
||||||
|
Tax Calculation
|
||||||
|
</h4>
|
||||||
|
<table class="table table-sm" style="width: 100%; margin-bottom: 20px;">
|
||||||
|
<tr>
|
||||||
|
<td style="width: 70%;">
|
||||||
|
<strong>Taxable Income:</strong>
|
||||||
|
</td>
|
||||||
|
<td style="width: 30%; text-align: right;">
|
||||||
|
<t t-esc="taxable_income"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="width: 70%;">
|
||||||
|
Round off to nearest 10 Rupee:
|
||||||
|
</td>
|
||||||
|
<td style="width: 30%; text-align: right;">
|
||||||
|
<t t-esc="roundoff_taxable_income"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Tax Payable on Total Income:</strong>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
<t t-esc="tax_payable"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Less: Rebate u/s 87A (Tax Credit)</strong>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
<t t-esc="rebate_87a"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Add: Surcharge</strong>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
0
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Add: Health and Education Cess:</strong>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
<t t-esc="cess"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Less: Relief under section 89(1)</strong>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
0
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<strong>Less: Details of Tax Collected at Source</strong>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
0
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr style="border-top: 2px solid #ddd; font-weight: bold;">
|
||||||
|
<td>
|
||||||
|
<strong>Total Tax Payable:</strong>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: right;">
|
||||||
|
<t t-esc="total_tax"/>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- Tax Breakdown -->
|
||||||
|
<h4 style="font-weight: bold; border-bottom: 2px solid #ddd; padding-bottom: 5px; margin-bottom: 15px;">
|
||||||
|
Tax Deduction Details
|
||||||
|
</h4>
|
||||||
|
<table class="table table-bordered table-sm" style="width: 100%; margin-bottom: 20px;">
|
||||||
|
<thead>
|
||||||
|
<tr style="background-color: #f8f9fa;">
|
||||||
|
<th style="font-weight: bold; text-align: left;">Particulars</th>
|
||||||
|
<th style="font-weight: bold; text-align: right;">Taxable Income</th>
|
||||||
|
<th style="font-weight: bold; text-align: right;">Income Tax</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>Total annual income and tax</td>
|
||||||
|
<td style="text-align: right;" t-esc="taxable_income"/>
|
||||||
|
<td style="text-align: right;" t-esc="total_tax"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Less: Tax deducted current employer (up to previous month)</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Less: Tax deducted from previous Employer / Self Tax Paid</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr style="font-weight: bold;">
|
||||||
|
<td>Balance Tax for the year</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;" t-esc="total_tax"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Less: Adhoc tax deducted in Off-Cycle in current month</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-weight: bold;">
|
||||||
|
<td><strong>Balance Tax</strong></td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;" t-esc="total_tax"/>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><strong>Tax deducted from current month salary</strong></td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Per month Tax (balance / No. of months incl. current month)</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-weight: bold; border-top: 2px solid #ddd;">
|
||||||
|
<td>Adhoc Tax to be deducted from current month salary</td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;" t-esc="total_tax"/>
|
||||||
|
</tr>
|
||||||
|
<tr style="font-weight: bold; border-top: 2px solid #ddd;">
|
||||||
|
<td><strong>Total Tax deducted from current month salary + adhoc + off-cycle</strong></td>
|
||||||
|
<td style="text-align: right;">0</td>
|
||||||
|
<td style="text-align: right;" t-esc="total_tax"/>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<div style="margin-top: 30px; display: flex; justify-content: space-between;">
|
||||||
|
<div>
|
||||||
|
<strong>Report Time:</strong>
|
||||||
|
<t t-esc="report_time"/>
|
||||||
|
</div>
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<strong>User:</strong>
|
||||||
|
<t t-esc="data.get('user', '')"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
<!-- <template id="generate_income_tax_statement_rpt">-->
|
||||||
|
<!-- <t t-call="web.basic_layout">-->
|
||||||
|
<!-- <main class="page">-->
|
||||||
|
<!-- <t t-set="data" t-value="report_data['data']"/>-->
|
||||||
|
<!-- <t t-set="profile" t-value="data.get('profile')"/>-->
|
||||||
|
<!-- <t t-set="regime_info" t-value="data.get('regime_info')"/>-->
|
||||||
|
<!-- <t t-set="salary_components" t-value="data.get('salary_components')"/>-->
|
||||||
|
<!-- <t t-set="deductions" t-value="data.get('deductions')"/>-->
|
||||||
|
<!-- <t t-set="income_details" t-value="data.get('income_details')"/>-->
|
||||||
|
<!-- <t t-set="taxable_income" t-value="data.get('taxable_income')"/>-->
|
||||||
|
<!-- <t t-set="tax_computation" t-value="data.get('tax_computation')"/>-->
|
||||||
|
<!-- <t t-set="regime_used" t-value="data.get('regime_used')"/>-->
|
||||||
|
<!-- <t t-set="comparison" t-value="data.get('comparison')"/>-->
|
||||||
|
|
||||||
|
<!-- <!– Report Title –>-->
|
||||||
|
<!-- <div class="text-center" style="margin-bottom: 25px;">-->
|
||||||
|
<!-- <h3 style="font-size:20px; font-weight:bold; text-decoration: underline;">INCOME TAX COMPUTATION STATEMENT</h3>-->
|
||||||
|
<!-- <p style="font-size:14px; margin-top: 5px;">-->
|
||||||
|
<!-- Assessment Year:-->
|
||||||
|
<!-- <t t-esc="data.get('assessment_year')"/>-->
|
||||||
|
<!-- |-->
|
||||||
|
<!-- Financial Year:-->
|
||||||
|
<!-- <t t-esc="data.get('financial_year')"/>-->
|
||||||
|
<!-- |-->
|
||||||
|
<!-- <t t-esc="regime_info.get('tax_regime')"/>-->
|
||||||
|
<!-- </p>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <!– Employee Info –>-->
|
||||||
|
<!-- <table class="table table-sm" style="margin-bottom: 25px; font-size: 13px;">-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td><strong>Employee Name</strong></td>-->
|
||||||
|
<!-- <td><t t-esc="profile.get('name')"/></td>-->
|
||||||
|
<!-- <td><strong>PAN</strong></td>-->
|
||||||
|
<!-- <td><t t-esc="profile.get('pan', '')"/></td>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td><strong>Age</strong></td>-->
|
||||||
|
<!-- <td><t t-esc="profile.get('age')"/></td>-->
|
||||||
|
<!-- <td><strong>Residential Status</strong></td>-->
|
||||||
|
<!-- <td><t t-esc="profile.get('residential_status')"/></td>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td><strong>Parent's Age</strong></td>-->
|
||||||
|
<!-- <td><t t-esc="profile.get('parent_age')"/></td>-->
|
||||||
|
<!-- <td><strong>User</strong></td>-->
|
||||||
|
<!-- <td><t t-esc="data.get('user')"/></td>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="font-size: 13px;">-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Regime Lock Status</td>-->
|
||||||
|
<!-- <td>-->
|
||||||
|
<!-- <t t-esc="regime_info.get('lock_regime')"/>-->
|
||||||
|
<!-- </td>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Current Tax Regime</td>-->
|
||||||
|
<!-- <td>-->
|
||||||
|
<!-- <t t-esc="regime_info.get('tax_regime')"/>-->
|
||||||
|
<!-- </td>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
|
||||||
|
<!-- <!– Head of Income –>-->
|
||||||
|
<!-- <div style="page-break-inside: avoid; margin-bottom:20px;">-->
|
||||||
|
<!-- <h4 style="background:#f2f2f2; padding:5px; border-left:4px solid #007bff;">Head of Income</h4>-->
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="font-size: 13px;">-->
|
||||||
|
<!-- <thead style="background:#e9ecef;">-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <th>Particulars</th>-->
|
||||||
|
<!-- <th class="text-right">Actual</th>-->
|
||||||
|
<!-- <th class="text-right">Projected</th>-->
|
||||||
|
<!-- <th class="text-right">Total</th>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </thead>-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Basic</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('basic', {}).get('actual',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('basic', {}).get('projected',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('basic', {}).get('total',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>House Rent</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('house_rent', {}).get('actual',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('house_rent', {}).get('projected',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('house_rent', {}).get('total',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>LTA</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('lta', {}).get('actual',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('lta', {}).get('projected',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('lta', {}).get('total',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Special Allowance</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('special_allowance', {}).get('actual',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('special_allowance', {}).get('projected',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('special_allowance', {}).get('total',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Perquisites</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('perquisites', {}).get('actual',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('perquisites', {}).get('projected',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('perquisites', {}).get('total',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Reimbursement</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('reimbursement', {}).get('actual',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('reimbursement', {}).get('projected',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('reimbursement', {}).get('total',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr style="font-weight:bold; background:#f8f9fa;">-->
|
||||||
|
<!-- <td>Gross Salary</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('gross_salary', {}).get('actual',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('gross_salary', {}).get('projected',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(salary_components.get('gross_salary', {}).get('total',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <!– Deductions –>-->
|
||||||
|
<!-- <div style="page-break-inside: avoid; margin-bottom:20px;">-->
|
||||||
|
<!-- <h4 style="background:#f2f2f2; padding:5px; border-left:4px solid #007bff;">Deductions</h4>-->
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="font-size: 13px;">-->
|
||||||
|
<!-- <thead style="background:#e9ecef;">-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <th>Particulars</th>-->
|
||||||
|
<!-- <th class="text-right">Amount (₹)</th>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </thead>-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Professional Tax</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('professional_tax',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Standard Deduction</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('standard_deduction',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>NPS Employer Contribution</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('nps_employer',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>HRA Exemption</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('hra_exemption',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Interest on Home Loan</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('interest_home_loan',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Deduction under 80C</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('ded_80C',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Deduction under 80CCD(1B)</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('ded_80CCD1B',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Deduction under 80D (Self)</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('ded_80D_self',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Deduction under 80D (Parents)</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('ded_80D_parents',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Deduction under 80G</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('ded_80G',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Other Deductions</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('ded_other',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr style="font-weight:bold; background:#f8f9fa;">-->
|
||||||
|
<!-- <td>Total Deductions</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(deductions.get('total_deductions',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <!– Income Details –>-->
|
||||||
|
<!-- <div style="page-break-inside: avoid; margin-bottom:20px;">-->
|
||||||
|
<!-- <h4 style="background:#f2f2f2; padding:5px; border-left:4px solid #007bff;">Income Details</h4>-->
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="font-size: 13px;">-->
|
||||||
|
<!-- <thead style="background:#e9ecef;">-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <th>Particulars</th>-->
|
||||||
|
<!-- <th class="text-right">Amount (₹)</th>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </thead>-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Gross Salary</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(income_details.get('gross_salary',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Other Income</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(income_details.get('other_income',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>House Property Income</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(income_details.get('house_property_income',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr style="font-weight:bold; background:#f8f9fa;">-->
|
||||||
|
<!-- <td>Total Income</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(income_details.get('total_income',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <!– Taxable Income –>-->
|
||||||
|
<!-- <div style="page-break-inside: avoid; margin-bottom:20px;">-->
|
||||||
|
<!-- <h4 style="background:#f2f2f2; padding:5px; border-left:4px solid #007bff;">Taxable Income</h4>-->
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="font-size: 13px;">-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Taxable Income (Old Regime)</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(taxable_income.get('old_regime',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Taxable Income (New Regime)</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(taxable_income.get('new_regime',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr style="font-weight:bold; background:#f8f9fa;">-->
|
||||||
|
<!-- <td>Taxable Income (Current Regime)</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(taxable_income.get('current_regime',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <!– Tax Regime Comparison –>-->
|
||||||
|
<!-- <div style="page-break-inside: avoid; margin-bottom:20px;">-->
|
||||||
|
<!-- <h4 style="background:#f2f2f2; padding:5px; border-left:4px solid #6f42c1;">Tax Regime Comparison</h4>-->
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="font-size: 13px;">-->
|
||||||
|
<!-- <thead style="background:#e9ecef;">-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <th>Particulars</th>-->
|
||||||
|
<!-- <th class="text-right">Old Regime (₹)</th>-->
|
||||||
|
<!-- <th class="text-right">New Regime (₹)</th>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </thead>-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Total Tax Payable</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(comparison.get('old_regime_tax',0))"/>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(comparison.get('new_regime_tax',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Tax Savings</td>-->
|
||||||
|
<!-- <td class="text-right" colspan="2" t-esc="'{:,.2f}'.format(comparison.get('tax_savings',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr style="font-weight:bold; background:#f8f9fa;">-->
|
||||||
|
<!-- <td>Beneficial Regime</td>-->
|
||||||
|
<!-- <td class="text-center" colspan="2" t-esc="comparison.get('beneficial_regime','').capitalize() + ' Regime'"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
|
||||||
|
<!-- <!– Tax Computation –>-->
|
||||||
|
<!-- <div style="page-break-inside: avoid; margin-bottom:20px;">-->
|
||||||
|
<!-- <h4 style="background:#f2f2f2; padding:5px; border-left:4px solid #dc3545;">Tax Computation</h4>-->
|
||||||
|
<!-- <table class="table table-bordered table-sm" style="font-size: 13px;">-->
|
||||||
|
<!-- <tbody>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Taxable Income</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(tax_computation.get('taxable_income',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Slab Tax</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(tax_computation.get('slab_tax',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Rebate under Section 87A</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(tax_computation.get('rebate_87a',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Surcharge</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(tax_computation.get('surcharge',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Marginal Relief</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(tax_computation.get('marginal_relief',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr>-->
|
||||||
|
<!-- <td>Health & Education Cess (4%)</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(tax_computation.get('cess_4pct',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- <tr style="font-weight:bold; background:#f8f9fa;">-->
|
||||||
|
<!-- <td>Total Tax Payable</td>-->
|
||||||
|
<!-- <td class="text-right" t-esc="'{:,.2f}'.format(tax_computation.get('total_tax',0))"/>-->
|
||||||
|
<!-- </tr>-->
|
||||||
|
<!-- </tbody>-->
|
||||||
|
<!-- </table>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </main>-->
|
||||||
|
<!-- </t>-->
|
||||||
|
<!-- </template>-->
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<report
|
||||||
|
id="action_report_it_tax_statement"
|
||||||
|
model="emp.it.declaration"
|
||||||
|
string="IT Tax Statement"
|
||||||
|
report_type="qweb-pdf"
|
||||||
|
name="your_module_name.report_it_tax_statement"
|
||||||
|
file="your_module_name.report_it_tax_statement"
|
||||||
|
print_report_name="'IT_Tax_Statement_%s' % (object.employee_id.name)"
|
||||||
|
/>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
||||||
|
|
||||||
|
|
||||||
|
access_payroll_period_user,payroll.period,model_payroll_period,,1,1,1,1
|
||||||
|
access_payroll_period_line_user,payroll.period.line,model_payroll_period_line,,1,1,1,1
|
||||||
|
|
||||||
|
access_it_investment_type,it.investment.type,model_it_investment_type,,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_past_employment_investment_type,past_employment.investment.type,model_past_employment_investment_type,,1,1,1,1
|
||||||
|
access_us80c_investment_type,us80c.investment.type,model_us80c_investment_type,,1,1,1,1
|
||||||
|
access_us80d_investment_type,us80d.investment.type,model_us80d_investment_type,,1,1,1,1
|
||||||
|
access_us10_investment_type,us10.investment.type,model_us10_investment_type,,1,1,1,1
|
||||||
|
access_us80g_investment_type,us80g.investment.type,model_us80g_investment_type,,1,1,1,1
|
||||||
|
access_chapter_via_investment_type,chapter.via.investment.type,model_chapter_via_investment_type,,1,1,1,1
|
||||||
|
access_us17_investment_type,us17.investment.type,model_us17_investment_type,,1,1,1,1
|
||||||
|
access_other_il_investment_type,other.il.investment.type,model_other_il_investment_type,,1,1,1,1
|
||||||
|
access_other_declaration_investment_type,other.declaration.investment.type,model_other_declaration_investment_type,,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_investment_costings,investment.costings,model_investment_costings,,1,1,1,1
|
||||||
|
|
||||||
|
access_past_employment_costing_type,past_employment.costing.type,model_past_employment_costing_type,,1,1,1,1
|
||||||
|
access_us80c_costing_type,us80c.costing.type,model_us80c_costing_type,,1,1,1,1
|
||||||
|
access_us80d_costing_type,us80d.costing.type,model_us80d_costing_type,,1,1,1,1
|
||||||
|
access_us10_costing_type,us10.costing.type,model_us10_costing_type,,1,1,1,1
|
||||||
|
access_us80g_costing_type,us80g.costing.type,model_us80g_costing_type,,1,1,1,1
|
||||||
|
access_chapter_via_costing_type,chapter.via.costing.type,model_chapter_via_costing_type,,1,1,1,1
|
||||||
|
access_us17_costing_type,us17.costing.type,model_us17_costing_type,,1,1,1,1
|
||||||
|
access_other_il_costing_type,other.il.costing.type,model_other_il_costing_type,,1,1,1,1
|
||||||
|
access_other_declaration_costing_type,other.declaration.costing.type,model_other_declaration_costing_type,,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_emp_it_declaration_user,emp.it.declarations,model_emp_it_declaration,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_children_education,access.children.education,model_children_education,base.group_user,1,1,1,1
|
||||||
|
access_children_education_costing,access.children.education.costing,model_children_education_costing,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
access_us80c_insurance_line,access.us80c.insurance.line,model_us80c_insurance_line,,1,1,1,1
|
||||||
|
access_employee_life_insurance,access.employee.life.insurance,model_employee_life_insurance,,1,1,1,1
|
||||||
|
|
||||||
|
access_nsc_declaration_line_user,nsc.declaration.line,model_nsc_declaration_line,base.group_user,1,1,1,1
|
||||||
|
access_nsc_entry_user,nsc.entry,model_nsc_entry,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_self_occupied_property_user,self.occupied.property,model_self_occupied_property,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
access_letout_house_property_user,access.letout.house.property.user,model_letout_house_property,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_nsc_interest_line_user,nsc.interest.line,model_nsc_interest_line,base.group_user,1,1,1,1
|
||||||
|
access_nsc_interest_entry_user,nsc.interest.entry,model_nsc_interest_entry,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
access_house_rent_declaration_user,access.house.rent.declaration.user,model_house_rent_declaration,base.group_user,1,1,1,1
|
||||||
|
|
||||||
|
access_it_tax_statement,it.tax.statement,model_it_tax_statement,base.group_user,1,0,0,0
|
||||||
|
access_it_tax_statement_wizard,it.tax.statement.wizard,model_it_tax_statement_wizard,base.group_user,1,0,0,0
|
||||||
|
|
||||||
|
access_it_tax_statement_manager,it.tax.statement,model_it_tax_statement,hr.group_hr_manager,1,1,1,1
|
||||||
|
access_it_tax_statement_wizard_manager,it.tax.statement.wizard,model_it_tax_statement_wizard,hr.group_hr_manager,1,1,1,1
|
||||||
|
|
||||||
|
|
||||||
|
access_it_slab_master,it.slab.master,model_it_slab_master,base.group_user,1,1,1,1
|
||||||
|
access_it_slab_master_rules,it.slab.master.rules,model_it_slab_master_rules,base.group_user,1,1,1,1
|
||||||
|
|
|
@ -0,0 +1,355 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="emp_it_declaration_list" model="ir.ui.view">
|
||||||
|
<field name="name">emp.it.declaration.list</field>
|
||||||
|
<field name="model">emp.it.declaration</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
|
||||||
|
<field name="period_id"/>
|
||||||
|
<field name="total_investment"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="view_emp_it_declaration_form" model="ir.ui.view">
|
||||||
|
<field name="name">emp.it.declarations.form</field>
|
||||||
|
<field name="model">emp.it.declaration</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="IT Declaration">
|
||||||
|
<sheet>
|
||||||
|
<div class="oe_title mb24">
|
||||||
|
<div class="o_row">
|
||||||
|
<field name="employee_id" widget="res_partner_many2one" placeholder="Employee Name..." readonly="costing_details_generated"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="period_id" readonly="costing_details_generated"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="total_investment"/>
|
||||||
|
<field name="costing_details_generated" invisible="1" force_save="1"/>
|
||||||
|
<field name="house_rent_costing_id"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<field name="tax_regime" nolabel="1" widget="radio" options="{'horizontal': true}"/>
|
||||||
|
<br/>
|
||||||
|
<button name="generate_declarations" type="object" class="btn-primary" string="Generate" confirm="Upon Confirming you won't be able to change the Period & Employee" help="Generate Data to upload the declaration Costing" invisible="costing_details_generated"/>
|
||||||
|
<field name="is_section_open" invisible="1"/> <!-- Store toggle state -->
|
||||||
|
|
||||||
|
<group invisible="not costing_details_generated">
|
||||||
|
<!-- Styled full-width button -->
|
||||||
|
<div style="background-color: #1167A8; padding: 10px; color: white; font-weight: bold; display: flex; justify-content: space-between; align-items: center; cursor: pointer;">
|
||||||
|
<span><field name="display_period_label" readonly="1" nolabel="1" style="color: white; font-weight: bold;"/></span>
|
||||||
|
<button name="toggle_section_visibility"
|
||||||
|
type="object"
|
||||||
|
style="background: none; border: none; color: white; font-size: 16px;"
|
||||||
|
icon="fa-chevron-up"/>
|
||||||
|
</div>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<!-- Collapsible section -->
|
||||||
|
<div invisible="not is_section_open">
|
||||||
|
<notebook>
|
||||||
|
<page string="Total Investment Costing">
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="investment_costing_ids" nolabel="1">
|
||||||
|
<list editable="bottom" create="0" delete="0" edit="0">
|
||||||
|
<field name="investment_type_id"/>
|
||||||
|
<field name="amount"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</div>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
|
||||||
|
<notebook invisible="not costing_details_generated">
|
||||||
|
<!-- <page name="investment_costings" string="Total Investment">-->
|
||||||
|
<!-- <field name="investment_costing_ids" readonly="1" force_save="1">-->
|
||||||
|
<!-- <list editable="bottom" create="0" delete="0" edit="0">-->
|
||||||
|
<!-- <field name="investment_type_id" width="50%"/>-->
|
||||||
|
<!-- <field name="amount" width="50%" class="text-start"/>-->
|
||||||
|
<!-- </list>-->
|
||||||
|
<!-- </field>-->
|
||||||
|
<!-- </page>-->
|
||||||
|
<page name="past_employment_costings" string="PAST EMPLOYMENT">
|
||||||
|
|
||||||
|
<field name="past_employment_costings" invisible="tax_regime != 'old'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<field name="past_employment_costings_new" invisible="tax_regime != 'new'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
|
||||||
|
<page name="us_80c_costings" string="US 80C" invisible="tax_regime != 'old'">
|
||||||
|
|
||||||
|
<field name="us80c_costings">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="action_id" column_invisible="1"/>
|
||||||
|
<button name="open_action_wizard"
|
||||||
|
string="Action"
|
||||||
|
type="object"
|
||||||
|
icon="fa-external-link"
|
||||||
|
invisible="not action_id" width="60px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="200px"/>
|
||||||
|
<field name="proof" width="100px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
|
||||||
|
</page>
|
||||||
|
<page name="us_80d_costings" string="US 80D" invisible="tax_regime != 'old'">
|
||||||
|
<group>
|
||||||
|
<field name="us80d_selection_type" widget="radio" options="{'horizontal': true}" required="tax_regime == 'old' and costing_details_generated"/>
|
||||||
|
<field name="us80d_health_checkup"/>
|
||||||
|
</group>
|
||||||
|
<field name="us80d_costings" invisible="us80d_selection_type != 'self_family'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<field name="us80d_costings_parents" invisible="us80d_selection_type != 'self_family_parent'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
|
||||||
|
</field>
|
||||||
|
<field name="us80d_costings_senior_parents" invisible="us80d_selection_type != 'self_family_senior_parent'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page name="us_10_costing" string="US 10" invisible="tax_regime != 'old'">
|
||||||
|
<field name="us10_costings">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page name="us_80g_costing" string="US 80G" invisible="tax_regime != 'old'">
|
||||||
|
<field name="us80g_costings">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
|
||||||
|
<page name="chapter_via_costings" string="CHAPTER VIA">
|
||||||
|
<field name="chapter_via_costings" invisible="tax_regime != 'old'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<field name="chapter_via_costings_new" invisible="tax_regime != 'new'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
|
||||||
|
</page>
|
||||||
|
<page name="us_17_costings" string="US 17" invisible="tax_regime != 'old'">
|
||||||
|
<field name="us17_costings">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page name="house_rent_costings" string="HOUSE RENT" invisible="tax_regime != 'old'">
|
||||||
|
<!-- <field name="house_rent_costing_line_ids"/>-->
|
||||||
|
<field name="house_rent_costings" context="{
|
||||||
|
'default_costing_type': house_rent_costing_id
|
||||||
|
}">
|
||||||
|
<list string="House Rent Declarations">
|
||||||
|
<field name="hra_exemption_type"/>
|
||||||
|
<field name="rent_amount"/>
|
||||||
|
<field name="from_date"/>
|
||||||
|
<field name="to_date"/>
|
||||||
|
<field name="landlord_pan_status"/>
|
||||||
|
</list>
|
||||||
|
<form string="House Rent Declaration" class="o_form">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="it_declaration_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="costing_type" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="hra_exemption_type" widget="radio"/>
|
||||||
|
<field name="landlord_pan_status" widget="radio"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<notebook>
|
||||||
|
<page string="Rent Details">
|
||||||
|
<group col="2">
|
||||||
|
<field name="rent_amount"/>
|
||||||
|
<field name="from_date"/>
|
||||||
|
<field name="to_date"/>
|
||||||
|
</group>
|
||||||
|
<field name="remarks" placeholder="Any additional information..."/>
|
||||||
|
</page>
|
||||||
|
|
||||||
|
<page string="Landlord Information">
|
||||||
|
<group col="2">
|
||||||
|
<field name="landlord_pan_no" invisible="landlord_pan_status == 'declaration'" required="landlord_pan_status == 'has_pan'"/>
|
||||||
|
<field name="landlord_name_address"/>
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
|
||||||
|
<page string="Proof Attachment">
|
||||||
|
<group>
|
||||||
|
<field name="attachment" filename="attachment_filename"/>
|
||||||
|
</group>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page name="other_i_or_l_costings" string="OTHER INCOME/LOSS">
|
||||||
|
<field name="other_il_costings" invisible="tax_regime != 'old'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="action_id" column_invisible="1" force_save="1"/>
|
||||||
|
<button name="open_action_wizard"
|
||||||
|
string="Action"
|
||||||
|
type="object"
|
||||||
|
icon="fa-external-link"
|
||||||
|
invisible="not action_id" width="60px"/>
|
||||||
|
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="200px"/>
|
||||||
|
<field name="proof" width="100px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<field name="other_il_costings_new" invisible="tax_regime != 'new'">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="action_id" column_invisible="1" force_save="1"/>
|
||||||
|
<button name="open_action_wizard"
|
||||||
|
string="Action"
|
||||||
|
type="object"
|
||||||
|
icon="fa-external-link"
|
||||||
|
invisible="not action_id" width="60px"/>
|
||||||
|
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="200px"/>
|
||||||
|
<field name="proof" width="100px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
|
||||||
|
</page>
|
||||||
|
<page name="other_declaration_costings" string="Other Declarations" invisible="tax_regime != 'old'">
|
||||||
|
<field name="other_declaration_costings">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="investment_type_line_id" width="600px" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="declaration_amount" width="130px"/>
|
||||||
|
<field name="proof_amount" width="100px" readonly="1" force_save="1"/>
|
||||||
|
<field name="remarks" width="250px"/>
|
||||||
|
<field name="proof" width="120px"/>
|
||||||
|
<field name="limit" readonly="1" force_save="1"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="action_emp_it_declaration" model="ir.actions.act_window">
|
||||||
|
<field name="name">IT Declarations</field>
|
||||||
|
<field name="path">income-tax-declaration</field>
|
||||||
|
<field name="res_model">emp.it.declaration</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="menu_it_declarations" name="IT Declarations"
|
||||||
|
parent="hr_payroll.menu_hr_payroll_root"
|
||||||
|
action="action_emp_it_declaration" sequence="99"/>
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<data>
|
||||||
|
<record id="view_it_investment_type_list" model="ir.ui.view">
|
||||||
|
<field name="name">it.investment.type.list</field>
|
||||||
|
<field name="model">it.investment.type</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="investment_type"/>
|
||||||
|
<field name="active"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_it_investment_type_form" model="ir.ui.view">
|
||||||
|
<field name="name">it.investment.type.form</field>
|
||||||
|
<field name="model">it.investment.type</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Investment Type">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="sequence" invisible="1"/>
|
||||||
|
<field name="investment_type"/>
|
||||||
|
|
||||||
|
<field name="active"/>
|
||||||
|
</group>
|
||||||
|
<notebook>
|
||||||
|
<page string="Past Employment" invisible="investment_type != 'past_employment'">
|
||||||
|
<field name="past_employment_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="investment_code"/>
|
||||||
|
<field name="compute_method"/>
|
||||||
|
<field name="compute_code"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="US 80C" invisible="investment_type != 'us_80c'">
|
||||||
|
<field name="us80c_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="investment_code"/>
|
||||||
|
<field name="compute_method"/>
|
||||||
|
<field name="compute_code"/>
|
||||||
|
<field name="require_action"/>
|
||||||
|
<field name="action_id" readonly="not require_action" required="require_action"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="US 80D" invisible="investment_type != 'us_80d'">
|
||||||
|
<field name="us80d_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="for_family" string="Family"/>
|
||||||
|
<field name="for_parents" string="Parents"/>
|
||||||
|
<field name="for_senior_parent" string="Senior Parents"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="US 10" invisible="investment_type != 'us_10'">
|
||||||
|
<field name="us10_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="US 80G" invisible="investment_type != 'us_80g'">
|
||||||
|
<field name="us80g_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="Chapter VIA" invisible="investment_type != 'chapter_via'">
|
||||||
|
<field name="chapter_via_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="US 17" invisible="investment_type != 'us_17'">
|
||||||
|
<field name="us17_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="Other Income or Loss" invisible="investment_type != 'other_i_or_l'">
|
||||||
|
<field name="other_il_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="require_action"/>
|
||||||
|
<field name="action_id" readonly="not require_action" required="require_action"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
<page string="Other Declaration" invisible="investment_type != 'other_declaration'">
|
||||||
|
<field name="other_declaration_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="sequence" widget="handle"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
<field name="limit"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Action -->
|
||||||
|
<record id="action_it_investment_type" model="ir.actions.act_window">
|
||||||
|
<field name="name">Investment Types</field>
|
||||||
|
<field name="res_model">it.investment.type</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="o_view_nocontent_smiling_face">
|
||||||
|
Create the different Investment Types here.
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="menu_it_investment_type" name="Investment Types"
|
||||||
|
parent="menu_it_payroll_declarations"
|
||||||
|
action="action_it_investment_type" sequence="20"/>
|
||||||
|
|
||||||
|
|
||||||
|
</data>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<!-- <menuitem id="menu_it_tax_statement_root" name="IT Tax Statement" parent="hr.menu_hr_root" sequence="100"/>-->
|
||||||
|
<record id="view_it_tax_statement_wizard_list" model="ir.ui.view">
|
||||||
|
<field name="name">it.tax.statement.wizard.list</field>
|
||||||
|
<field name="model">it.tax.statement.wizard</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="employee_id"/>
|
||||||
|
<field name="period_id"/>
|
||||||
|
<field name="period_line"/>
|
||||||
|
<field name="tax_regime"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="view_it_tax_statement_wizard_form" model="ir.ui.view">
|
||||||
|
<field name="name">it.tax.statement.wizard.form</field>
|
||||||
|
<field name="model">it.tax.statement.wizard</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form>
|
||||||
|
<header>
|
||||||
|
<button name="action_generate_report"
|
||||||
|
string="Generate Tax Statement"
|
||||||
|
type="object"
|
||||||
|
class="oe_stat_button"
|
||||||
|
icon="fa-file-text"/>
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="employee_id" options="{'no_edit': True, 'no_create': True}"/>
|
||||||
|
<field name="contract_id" readonly="1" force_save="1" invisible="0"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="taxpayer_age"/>
|
||||||
|
<field name="residential_status"/>
|
||||||
|
<field name="parent_age"/>
|
||||||
|
<field name="emp_doj" force_save="1" invisible="0" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="period_id" options="{'no_edit': True, 'no_create': True, 'no_open': True}"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="period_line" domain="[('period_id', '=', period_id),('to_date','<',datetime.datetime.now()),('from_date','>',emp_doj)]" options="{'no_edit': True, 'no_create': True, 'no_open': True}" invisible="not emp_doj"/>
|
||||||
|
<field name="period_line" domain="[('period_id', '=', period_id),('to_date','<',datetime.datetime.now())]" options="{'no_edit': True, 'no_create': True, 'no_open': True}" invisible="emp_doj"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="tax_regime" nolabel="1" widget="radio" options="{'horizontal': true}" on_change="1"/>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<record id="action_it_tax_statement_wizard" model="ir.actions.act_window">
|
||||||
|
<field name="name">Generate Tax Statement</field>
|
||||||
|
<field name="res_model">it.tax.statement.wizard</field>
|
||||||
|
<field name="path">tax-statement</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="o_view_nocontent_smiling_face">
|
||||||
|
Create a new employment type
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="menu_it_tax_statement_root" name="IT Tax Statement"
|
||||||
|
parent="hr_payroll.menu_hr_payroll_root"
|
||||||
|
action="action_it_tax_statement_wizard" sequence="99"/>
|
||||||
|
|
||||||
|
<record id="it_statement_paper_format" model="report.paperformat">
|
||||||
|
<field name="name">A4 - statement</field>
|
||||||
|
<field name="default" eval="True"/>
|
||||||
|
<field name="format">A4</field>
|
||||||
|
<field name="page_height">0</field>
|
||||||
|
<field name="page_width">0</field>
|
||||||
|
<field name="orientation">Portrait</field>
|
||||||
|
<field name="margin_top">10</field>
|
||||||
|
<field name="margin_bottom">10</field>
|
||||||
|
<field name="margin_left">7</field>
|
||||||
|
<field name="margin_right">7</field>
|
||||||
|
<field name="header_line" eval="False"/>
|
||||||
|
<field name="header_spacing">10</field>
|
||||||
|
<field name="dpi">90</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="income_tax_statement_action_report" model="ir.actions.report">
|
||||||
|
<field name="name">Download Income Tax</field>
|
||||||
|
<field name="model">it.tax.statement.wizard</field>
|
||||||
|
<field name="report_type">qweb-pdf</field>
|
||||||
|
<field name="report_name">employee_it_declaration.generate_income_tax_statement_rpt</field>
|
||||||
|
<field name="report_file">employee_it_declaration.generate_income_tax_statement_rpt</field>
|
||||||
|
<field name="binding_model_id" ref="employee_it_declaration.model_it_tax_statement_wizard"/>
|
||||||
|
<field name="print_report_name">'INCOMETAX - %s' % (object.display_name)</field>
|
||||||
|
<field name="paperformat_id" ref="it_statement_paper_format"/>
|
||||||
|
<field name="binding_type">report</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
<odoo>
|
||||||
|
<record id="view_payroll_period_form" model="ir.ui.view">
|
||||||
|
<field name="name">payroll.period.form</field>
|
||||||
|
<field name="model">payroll.period</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Payroll Period">
|
||||||
|
<header>
|
||||||
|
<button name="action_generate_month_lines" type="object" string="Generate Periods" class="btn-primary"/>
|
||||||
|
</header>
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="from_date"/>
|
||||||
|
<field name="to_date"/>
|
||||||
|
<field name="name" readonly="1" force_save="1"/>
|
||||||
|
</group>
|
||||||
|
<field name="period_line_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="from_date"/>
|
||||||
|
<field name="to_date"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_payroll_period_tree" model="ir.ui.view">
|
||||||
|
<field name="name">payroll.period.tree</field>
|
||||||
|
<field name="model">payroll.period</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="from_date"/>
|
||||||
|
<field name="to_date"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_payroll_period" model="ir.actions.act_window">
|
||||||
|
<field name="name">Payroll Periods</field>
|
||||||
|
<field name="res_model">payroll.period</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
<menuitem id="menu_it_payroll_declarations" name="Payroll" parent="hr_payroll.menu_hr_payroll_configuration"/>
|
||||||
|
<menuitem id="menu_payroll_period" name="Payroll Periods" parent="menu_it_payroll_declarations" action="action_payroll_period"/>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<odoo>
|
||||||
|
<template id="report_it_tax_statement">
|
||||||
|
<t t-call="web.html_container">
|
||||||
|
<t t-call="web.external_layout">
|
||||||
|
<div class="page">
|
||||||
|
<h2>IT Tax Statement</h2>
|
||||||
|
<p><strong>Employee:</strong> <t t-esc="doc.employee_id.name"/></p>
|
||||||
|
<p><strong>Period:</strong> <t t-esc="doc.period_id.name"/></p>
|
||||||
|
<p><strong>Tax Regime:</strong> <t t-esc="dict(doc._fields['tax_regime'].selection).get(doc.tax_regime)"/></p>
|
||||||
|
<table class="table table-sm">
|
||||||
|
<thead>
|
||||||
|
<tr><th>Section</th><th>Amount</th></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<t t-foreach="doc.investment_costing_ids" t-as="line">
|
||||||
|
<tr>
|
||||||
|
<td><t t-esc="line.investment_type_id.name"/></td>
|
||||||
|
<td><t t-esc="line.amount"/></td>
|
||||||
|
</tr>
|
||||||
|
</t>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<p><strong>Total:</strong> <t t-esc="sum(doc.investment_costing_ids.mapped('amount'))"/></p>
|
||||||
|
</div>
|
||||||
|
</t>
|
||||||
|
</t>
|
||||||
|
</template>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
<!-- Menu Items -->
|
||||||
|
<menuitem id="menu_it_slab_controller" name="Slab" parent="hr_payroll.menu_hr_payroll_configuration"/>
|
||||||
|
|
||||||
|
<!-- Window Action -->
|
||||||
|
<record id="action_it_slab_master" model="ir.actions.act_window">
|
||||||
|
<field name="name">Income Tax Slabs</field>
|
||||||
|
<field name="path">slab-master</field>
|
||||||
|
<field name="res_model">it.slab.master</field>
|
||||||
|
<field name="view_mode">list,form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<menuitem id="menu_it_slab_master_item"
|
||||||
|
name="Slab Master"
|
||||||
|
parent="menu_it_slab_controller"
|
||||||
|
action="action_it_slab_master"/>
|
||||||
|
|
||||||
|
<!-- list View -->
|
||||||
|
<record id="view_it_slab_master_list" model="ir.ui.view">
|
||||||
|
<field name="name">it.slab.master.list</field>
|
||||||
|
<field name="model">it.slab.master</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="regime"/>
|
||||||
|
<field name="age_category"/>
|
||||||
|
<field name="residence_type"/>
|
||||||
|
<field name="standard_deduction"/>
|
||||||
|
<field name="active"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Form View -->
|
||||||
|
<record id="view_it_slab_master_form" model="ir.ui.view">
|
||||||
|
<field name="name">it.slab.master.form</field>
|
||||||
|
<field name="model">it.slab.master</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form>
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="regime"/>
|
||||||
|
<field name="age_category"/>
|
||||||
|
<field name="residence_type"/>
|
||||||
|
<field name="standard_deduction"/>
|
||||||
|
<field name="active"/>
|
||||||
|
</group>
|
||||||
|
<notebook>
|
||||||
|
<page string="Slab Rules">
|
||||||
|
<field name="rules">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="min_income"/>
|
||||||
|
<field name="max_income"/>
|
||||||
|
<field name="tax_rate"/>
|
||||||
|
<field name="fixed_amount"/>
|
||||||
|
<field name="excess_threshold"/>
|
||||||
|
<field name="surcharge_rate"/>
|
||||||
|
<field name="cess_rate"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</page>
|
||||||
|
</notebook>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
from . import children_education_costing
|
||||||
|
from . import employee_life_insurance
|
||||||
|
from . import nsc_declaration
|
||||||
|
from . import self_occupied_property
|
||||||
|
from . import letout_house_property
|
||||||
|
from . import nsc_income_loss
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
|
||||||
|
class ChildrenEducation(models.Model):
|
||||||
|
_name = "children.education"
|
||||||
|
_description = "Children Education"
|
||||||
|
_rec_name = 'it_declaration_id'
|
||||||
|
|
||||||
|
it_declaration_id = fields.Many2one('emp.it.declaration')
|
||||||
|
children_ids = fields.One2many(
|
||||||
|
'children.education.costing',
|
||||||
|
'child_education_id',
|
||||||
|
string="Children",
|
||||||
|
)
|
||||||
|
total_count = fields.Integer(string="Total Tuition Fee", compute="_compute_total_count", store=True)
|
||||||
|
us80c_id = fields.Many2one('us80c.costing.type')
|
||||||
|
|
||||||
|
@api.depends('children_ids.tuition_fee')
|
||||||
|
def _compute_total_count(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.total_count = sum(child.tuition_fee for child in rec.children_ids)
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals):
|
||||||
|
record = super().create(vals)
|
||||||
|
context = self._context or {}
|
||||||
|
|
||||||
|
if not record.children_ids:
|
||||||
|
record.children_ids = [
|
||||||
|
(0, 0, {'child_id': 'CHILD 1'}),
|
||||||
|
(0, 0, {'child_id': 'CHILD 2'}),
|
||||||
|
]
|
||||||
|
return record
|
||||||
|
|
||||||
|
# def write(self, vals):
|
||||||
|
# print(vals)
|
||||||
|
# self.us80c_id.declaration_amount = self.total_count if self.us80c_id.limit > self.total_count else self.us80c_id.limit
|
||||||
|
# return super().write(vals)
|
||||||
|
|
||||||
|
class ChildrenEducationCosting(models.Model):
|
||||||
|
_name = 'children.education.costing'
|
||||||
|
_description = "Children Education Costing"
|
||||||
|
|
||||||
|
child_id = fields.Char('Child ID')
|
||||||
|
name = fields.Char('Name of Child')
|
||||||
|
chile_class = fields.Char('Class / Grade')
|
||||||
|
organization = fields.Char('School / College')
|
||||||
|
tuition_fee = fields.Integer('Tuition Fee')
|
||||||
|
child_education_id = fields.Many2one('children.education', string="Education Record", ondelete='cascade')
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!-- children_education_views.xml -->
|
||||||
|
<odoo>
|
||||||
|
<record id="view_children_education_form" model="ir.ui.view">
|
||||||
|
<field name="name">children.education.form</field>
|
||||||
|
<field name="model">children.education</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Children Education">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="it_declaration_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="us80c_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="total_count" readonly="1"/>
|
||||||
|
</group>
|
||||||
|
<field name="children_ids" nolabel="1">
|
||||||
|
<list editable="bottom" create="0" delete="0">
|
||||||
|
<field name="child_id" readonly="1" force_save="1"/>
|
||||||
|
<field name="name"/>
|
||||||
|
<field name="chile_class"/>
|
||||||
|
<field name="organization"/>
|
||||||
|
<field name="tuition_fee"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_children_education_list" model="ir.ui.view">
|
||||||
|
<field name="name">children.education.list</field>
|
||||||
|
<field name="model">children.education</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="it_declaration_id"/>
|
||||||
|
<field name="total_count"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_children_education" model="ir.actions.act_window">
|
||||||
|
<field name="name">Children Education</field>
|
||||||
|
<field name="res_model">children.education</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
from odoo import models, fields, api, _
|
||||||
|
|
||||||
|
|
||||||
|
class US80CInsuranceLine(models.Model):
|
||||||
|
_name = 'us80c.insurance.line'
|
||||||
|
_description = 'US80C Insurance Line'
|
||||||
|
|
||||||
|
it_declaration_id = fields.Many2one('emp.it.declaration', string="IT Declaration")
|
||||||
|
us80c_id = fields.Many2one('us80c.costing.type', string="80C Costing Type")
|
||||||
|
|
||||||
|
life_insurance_ids = fields.One2many(
|
||||||
|
'employee.life.insurance',
|
||||||
|
'parent_id',
|
||||||
|
string="Life Insurance Entries"
|
||||||
|
)
|
||||||
|
total_premium_amount = fields.Float(string="Total Premium", compute='_compute_totals', store=True)
|
||||||
|
total_capital_sum_assured = fields.Float(string="Total Capital Sum Assured", compute='_compute_totals', store=True)
|
||||||
|
total_max_percentage = fields.Float(string="Total Max %", compute='_compute_totals', store=True)
|
||||||
|
total_exempt_amount = fields.Float(string="Total Exempt Amount", compute='_compute_totals', store=True)
|
||||||
|
|
||||||
|
@api.depends('life_insurance_ids')
|
||||||
|
def _compute_totals(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.total_premium_amount = sum(line.premium_amount for line in rec.life_insurance_ids)
|
||||||
|
rec.total_capital_sum_assured = sum(line.capital_sum_assured for line in rec.life_insurance_ids)
|
||||||
|
rec.total_max_percentage = sum(line.max_percentage for line in rec.life_insurance_ids)
|
||||||
|
rec.total_exempt_amount = sum(line.exempt_amount for line in rec.life_insurance_ids)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EmployeeLifeInsurance(models.Model):
|
||||||
|
_name = 'employee.life.insurance'
|
||||||
|
_description = 'Employee Life Insurance'
|
||||||
|
|
||||||
|
parent_id = fields.Many2one('us80c.insurance.line', string="Parent Line") # Link to parent
|
||||||
|
|
||||||
|
name_of_insurance_company = fields.Char(string="Name of Insurance Company")
|
||||||
|
insured_in_favour_of = fields.Selection([
|
||||||
|
('self', 'Self'),
|
||||||
|
('spouse', 'Spouse'),
|
||||||
|
('child', 'Child'),
|
||||||
|
('dependent', 'Dependent'),
|
||||||
|
], string="Insured in Favour of")
|
||||||
|
name_of_insured = fields.Char(string="Name of Insured")
|
||||||
|
policy_number = fields.Char(string="Policy Number")
|
||||||
|
premium_amount = fields.Float(string="Premium Amount")
|
||||||
|
payment_date = fields.Date(string="Payment Date")
|
||||||
|
capital_sum_assured = fields.Float(string="Capital Sum Assured")
|
||||||
|
policy_date = fields.Date(string="Policy Date")
|
||||||
|
max_percentage = fields.Float(string="Max Percentage")
|
||||||
|
exempt_amount = fields.Float(string="Exempt Amount")
|
||||||
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
<odoo>
|
||||||
|
<record id="view_us80c_insurance_line_form" model="ir.ui.view">
|
||||||
|
<field name="name">us80c.insurance.line.form</field>
|
||||||
|
<field name="model">us80c.insurance.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="US80C Insurance Line">
|
||||||
|
<group>
|
||||||
|
<field name="it_declaration_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="us80c_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
<field name="life_insurance_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="name_of_insurance_company" width="200px"/>
|
||||||
|
<field name="insured_in_favour_of" width="100px"/>
|
||||||
|
<field name="name_of_insured" width="150px"/>
|
||||||
|
<field name="policy_number" width="100px"/>
|
||||||
|
<field name="premium_amount" width="70px"/>
|
||||||
|
<field name="payment_date" width="70px"/>
|
||||||
|
<field name="capital_sum_assured" width="80px"/>
|
||||||
|
<field name="policy_date" width="70px"/>
|
||||||
|
<field name="max_percentage" width="70px"/>
|
||||||
|
<field name="exempt_amount" width="70px"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="total_premium_amount" readonly="1"/>
|
||||||
|
<field name="total_capital_sum_assured" readonly="1"/>
|
||||||
|
<field name="total_max_percentage" readonly="1"/>
|
||||||
|
<field name="total_exempt_amount" readonly="1"/>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_us80c_insurance_line_list" model="ir.ui.view">
|
||||||
|
<field name="name">us80c.insurance.line.list</field>
|
||||||
|
<field name="model">us80c.insurance.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list string="Insurance Lines">
|
||||||
|
<field name="it_declaration_id"/>
|
||||||
|
<field name="us80c_id"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_us80c_insurance_line" model="ir.actions.act_window">
|
||||||
|
<field name="name">Life Insurance</field>
|
||||||
|
<field name="res_model">us80c.insurance.line</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
import math
|
||||||
|
|
||||||
|
class LetoutHouseProperty(models.Model):
|
||||||
|
_name = 'letout.house.property'
|
||||||
|
_description = 'Letout House Property Details'
|
||||||
|
|
||||||
|
it_declaration_id = fields.Many2one('emp.it.declaration', string="IT Declaration")
|
||||||
|
other_il_id = fields.Many2one('other.il.costing.type', string="Other Income/Loss Costing Type")
|
||||||
|
|
||||||
|
address = fields.Char(string="Address of Property")
|
||||||
|
loan_after_april_1999 = fields.Selection([('yes','Yes'),('no','No')],default='yes',
|
||||||
|
string="House Loan Taken After 01-Apr-1999 & Construction Completed Within 3 Years"
|
||||||
|
)
|
||||||
|
|
||||||
|
rent_received = fields.Integer(string="Rent Received Per Annum")
|
||||||
|
period_from = fields.Date(string="Period From")
|
||||||
|
period_to = fields.Date(string="Period To")
|
||||||
|
|
||||||
|
property_tax = fields.Integer(string="Less : Property Tax")
|
||||||
|
water_tax = fields.Integer(string="Less : Water Tax")
|
||||||
|
net_annual_value = fields.Integer(string="Net Annual Value of the Property", readonly=True)
|
||||||
|
|
||||||
|
deduction_for_repairs = fields.Integer(string="Less : Deduction for Repairs 30% if Net Annual Value of the Property", readonly=True)
|
||||||
|
interest_paid_to = fields.Integer(string="Less : Interest on Borrowed Capital Paid To")
|
||||||
|
|
||||||
|
income_loss = fields.Integer(string="Income / Loss on House Property", readonly=True)
|
||||||
|
lender_name = fields.Char(string="Lender Name")
|
||||||
|
lender_pan = fields.Char(string="Lender PAN")
|
||||||
|
|
||||||
|
@api.onchange('rent_received','property_tax','water_tax','interest_paid_to')
|
||||||
|
def onchange_property_water_income_tax(self):
|
||||||
|
for record in self:
|
||||||
|
net_annual_value = record.rent_received - record.property_tax - record.water_tax
|
||||||
|
deduction = net_annual_value * 0.30
|
||||||
|
income_loss = net_annual_value - deduction - record.interest_paid_to
|
||||||
|
|
||||||
|
print(net_annual_value)
|
||||||
|
print(deduction)
|
||||||
|
print(income_loss)
|
||||||
|
record.net_annual_value = net_annual_value
|
||||||
|
record.deduction_for_repairs = round(deduction)
|
||||||
|
record.income_loss = round(income_loss)
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_letout_house_property_form" model="ir.ui.view">
|
||||||
|
<field name="name">letout.house.property.form</field>
|
||||||
|
<field name="model">letout.house.property</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Letout House Property">
|
||||||
|
<sheet>
|
||||||
|
|
||||||
|
<!-- Header Section -->
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="it_declaration_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="other_il_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!-- Property Information -->
|
||||||
|
<separator string="Property Information" colspan="2"/>
|
||||||
|
<group>
|
||||||
|
<field name="address" required="1"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<div class="oe_row">
|
||||||
|
<label for="loan_after_april_1999"
|
||||||
|
string="House Loan Taken After 01-Apr-1999 & Construction Completed Within 3 Years &nbsp;"/>
|
||||||
|
<field name="loan_after_april_1999" nolabel="1" widget="radio"
|
||||||
|
options="{'horizontal': true}" class="ml-2" required="1"/>
|
||||||
|
</div>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
|
||||||
|
<!-- Rental and Period Info -->
|
||||||
|
<group>
|
||||||
|
<separator string="Rental and Period Info"/>
|
||||||
|
<field name="rent_received"/>
|
||||||
|
<field name="period_from" required="1"/>
|
||||||
|
<field name="period_to" required="1"/>
|
||||||
|
<br/>
|
||||||
|
<separator string="Lender Information"/>
|
||||||
|
<field name="lender_name"/>
|
||||||
|
<field name="lender_pan"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!-- Deductions & Value -->
|
||||||
|
<group string="Deductions and Property Value">
|
||||||
|
<field name="property_tax"/>
|
||||||
|
<field name="water_tax"/>
|
||||||
|
<field name="net_annual_value" readonly="1" force_save="1"/>
|
||||||
|
<field name="deduction_for_repairs" readonly="1" force_save="1"/>
|
||||||
|
<field name="interest_paid_to"/>
|
||||||
|
<field name="income_loss" readonly="1" force_save="1"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_letout_house_property_list" model="ir.ui.view">
|
||||||
|
<field name="name">letout.house.property.list</field>
|
||||||
|
<field name="model">letout.house.property</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list string="Letout House Property">
|
||||||
|
<field name="address"/>
|
||||||
|
<field name="rent_received"/>
|
||||||
|
<field name="net_annual_value"/>
|
||||||
|
<field name="income_loss"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_letout_house_property" model="ir.actions.act_window">
|
||||||
|
<field name="name">Letout House Property</field>
|
||||||
|
<field name="res_model">letout.house.property</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
<field name="help" type="html">
|
||||||
|
<p class="o_view_nocontent_smiling_face">
|
||||||
|
Add a new Letout House Property entry
|
||||||
|
</p>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
|
||||||
|
|
||||||
|
class NSCDeclarationLine(models.Model):
|
||||||
|
_name = 'nsc.declaration.line'
|
||||||
|
_description = 'NSC Declaration Line'
|
||||||
|
|
||||||
|
it_declaration_id = fields.Many2one('emp.it.declaration', string="IT Declaration", required=True)
|
||||||
|
us80c_id = fields.Many2one('us80c.costing.type', string="80C Costing Type", required=True)
|
||||||
|
|
||||||
|
nsc_entry_ids = fields.One2many('nsc.entry', 'parent_id', string="NSC Entries")
|
||||||
|
total_nsc_amount = fields.Float(string="Total NSC Amount", compute="_compute_total_amount", store=True)
|
||||||
|
|
||||||
|
@api.depends('nsc_entry_ids.nsc_amount')
|
||||||
|
def _compute_total_amount(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.total_nsc_amount = sum(entry.nsc_amount for entry in rec.nsc_entry_ids)
|
||||||
|
|
||||||
|
|
||||||
|
class NSCEntry(models.Model):
|
||||||
|
_name = 'nsc.entry'
|
||||||
|
_description = 'NSC Entry'
|
||||||
|
|
||||||
|
parent_id = fields.Many2one('nsc.declaration.line', string="NSC Declaration")
|
||||||
|
nsc_number = fields.Char(string="NSC Number")
|
||||||
|
nsc_amount = fields.Float(string="NSC Amount")
|
||||||
|
nsc_payment_date = fields.Date(string="NSC Payment Date")
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<odoo>
|
||||||
|
<record id="view_nsc_declaration_line_form" model="ir.ui.view">
|
||||||
|
<field name="name">nsc.declaration.line.form</field>
|
||||||
|
<field name="model">nsc.declaration.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="NSC Declaration">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="it_declaration_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="us80c_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
<field name="nsc_entry_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="nsc_number" width="500px"/>
|
||||||
|
<field name="nsc_amount"/>
|
||||||
|
<field name="nsc_payment_date"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="total_nsc_amount" readonly="1"/>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_nsc_declaration_line_list" model="ir.ui.view">
|
||||||
|
<field name="name">nsc.declaration.line.list</field>
|
||||||
|
<field name="model">nsc.declaration.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="it_declaration_id"/>
|
||||||
|
<field name="us80c_id"/>
|
||||||
|
<field name="total_nsc_amount"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_nsc_declaration_line" model="ir.actions.act_window">
|
||||||
|
<field name="name">NSC Declarations</field>
|
||||||
|
<field name="res_model">nsc.declaration.line</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
|
||||||
|
|
||||||
|
class NSCInterestLine(models.Model):
|
||||||
|
_name = 'nsc.interest.line'
|
||||||
|
_description = 'NSC Interest Line'
|
||||||
|
|
||||||
|
|
||||||
|
it_declaration_id = fields.Many2one('emp.it.declaration', string="IT Declaration", required=True)
|
||||||
|
other_il_id = fields.Many2one('other.il.costing.type', string="Other Income/Loss Costing Type")
|
||||||
|
|
||||||
|
nsc_entry_ids = fields.One2many('nsc.interest.entry', 'parent_id', string="NSC Entries")
|
||||||
|
total_nsc_amount = fields.Integer(string="Total NSC Amount", compute="_compute_total_amount", store=True)
|
||||||
|
total_nsc_interest_amount = fields.Integer(string="NSC Interest Amount",compute="_compute_total_amount", store=True)
|
||||||
|
|
||||||
|
@api.depends('nsc_entry_ids.nsc_amount')
|
||||||
|
def _compute_total_amount(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.total_nsc_amount = sum(entry.nsc_amount for entry in rec.nsc_entry_ids)
|
||||||
|
rec.total_nsc_interest_amount = sum(entry.nsc_interest_amount for entry in rec.nsc_entry_ids)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class NSCEntry(models.Model):
|
||||||
|
_name = 'nsc.interest.entry'
|
||||||
|
_description = 'NSC Entry'
|
||||||
|
|
||||||
|
parent_id = fields.Many2one('nsc.interest.line', string="NSC Interest")
|
||||||
|
nsc_number = fields.Char(string="NSC Number")
|
||||||
|
nsc_amount = fields.Integer(string="NSC Amount")
|
||||||
|
nsc_payment_date = fields.Date(string="NSC Payment Date")
|
||||||
|
nsc_interest_amount = fields.Integer(string="NSC Interest Amount")
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
|
||||||
|
<odoo>
|
||||||
|
<record id="view_nsc_interest_line_form" model="ir.ui.view">
|
||||||
|
<field name="name">nsc.interest.line.form</field>
|
||||||
|
<field name="model">nsc.interest.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="National Saving Certificate">
|
||||||
|
<sheet>
|
||||||
|
<group>
|
||||||
|
<field name="it_declaration_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
<field name="other_il_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
<field name="nsc_entry_ids">
|
||||||
|
<list editable="bottom">
|
||||||
|
<field name="nsc_number" width="500px"/>
|
||||||
|
<field name="nsc_payment_date"/>
|
||||||
|
<field name="nsc_amount"/>
|
||||||
|
<field name="nsc_interest_amount"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="total_nsc_amount" readonly="1" force_save="1"/>
|
||||||
|
<field name="total_nsc_interest_amount" readonly="1" force_save="1"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="view_nsc_interest_line_list" model="ir.ui.view">
|
||||||
|
<field name="name">nsc.interest.line.list</field>
|
||||||
|
<field name="model">nsc.interest.line</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="it_declaration_id"/>
|
||||||
|
<field name="other_il_id"/>
|
||||||
|
<field name="total_nsc_amount"/>
|
||||||
|
<field name="total_nsc_interest_amount"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<record id="action_nsc_interest_line" model="ir.actions.act_window">
|
||||||
|
<field name="name">NSC Interest</field>
|
||||||
|
<field name="res_model">nsc.interest.line</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
</record>
|
||||||
|
</odoo>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
from odoo import models, fields, api
|
||||||
|
|
||||||
|
|
||||||
|
class SelfOccupiedProperty(models.Model):
|
||||||
|
_name = 'self.occupied.property'
|
||||||
|
_description = 'Self Occupied House Property Details'
|
||||||
|
|
||||||
|
it_declaration_id = fields.Many2one('emp.it.declaration', string="IT Declaration")
|
||||||
|
other_il_id = fields.Many2one('other.il.costing.type', string="Other Income/Loss Costing Type")
|
||||||
|
|
||||||
|
address = fields.Text(string="Address of Property")
|
||||||
|
loan_after_april_1999 = fields.Selection([('yes','Yes'),('no','No')],default='yes',
|
||||||
|
string="House Loan Taken After 01-Apr-1999 & Construction Completed Within 3 Years"
|
||||||
|
)
|
||||||
|
|
||||||
|
period_from = fields.Date(string="Period From")
|
||||||
|
period_to = fields.Date(string="Period To")
|
||||||
|
|
||||||
|
interest_paid_to = fields.Integer(string="Less: Interest on Borrowed Capital Paid To")
|
||||||
|
income_loss = fields.Integer(string="Income / Loss on House Property")
|
||||||
|
|
||||||
|
lender_name = fields.Char(string="Lender Name")
|
||||||
|
lender_pan = fields.Char(string="Lender PAN")
|
||||||
|
|
||||||
|
@api.onchange('interest_paid_to')
|
||||||
|
def onchange_interest_paid_to(self):
|
||||||
|
for rec in self:
|
||||||
|
rec.income_loss = -(rec.interest_paid_to)
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
<odoo>
|
||||||
|
<!-- Form View -->
|
||||||
|
<record id="view_self_occupied_property_form" model="ir.ui.view">
|
||||||
|
<field name="name">self.occupied.property.form</field>
|
||||||
|
<field name="model">self.occupied.property</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<form string="Self Occupied House Property">
|
||||||
|
<sheet>
|
||||||
|
<!-- Header Section -->
|
||||||
|
<group>
|
||||||
|
<group>
|
||||||
|
<field name="it_declaration_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<field name="other_il_id" readonly="1" force_save="1" options="{'no_open': True, 'no_quick_create': True}"/>
|
||||||
|
</group>
|
||||||
|
</group>
|
||||||
|
<!-- Parent References -->
|
||||||
|
<!-- Property Info -->
|
||||||
|
<separator string="Property Information" colspan="2"/>
|
||||||
|
<group>
|
||||||
|
<field name="address"/>
|
||||||
|
</group>
|
||||||
|
<group>
|
||||||
|
<div class="oe_row">
|
||||||
|
<label for="loan_after_april_1999"
|
||||||
|
string="House Loan Taken After 01-Apr-1999 & Construction Completed Within 3 Years &nbsp; "/>
|
||||||
|
<field name="loan_after_april_1999" nolabel="1" widget="radio"
|
||||||
|
options="{'horizontal': true}" class="ml-2"/>
|
||||||
|
</div>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<group>
|
||||||
|
<!-- Period & Interest Info -->
|
||||||
|
|
||||||
|
<group string="Period & Interest Details">
|
||||||
|
<field name="period_from"/>
|
||||||
|
<field name="period_to"/>
|
||||||
|
<field name="interest_paid_to"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
<!-- Financial & Lender Info -->
|
||||||
|
|
||||||
|
<group string="Financial & Lender Information">
|
||||||
|
<field name="income_loss" readonly="1" force_save="1"/>
|
||||||
|
<field name="lender_name"/>
|
||||||
|
<field name="lender_pan"/>
|
||||||
|
</group>
|
||||||
|
|
||||||
|
</group>
|
||||||
|
</sheet>
|
||||||
|
</form>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- list View -->
|
||||||
|
<record id="view_self_occupied_property_list" model="ir.ui.view">
|
||||||
|
<field name="name">self.occupied.property.list</field>
|
||||||
|
<field name="model">self.occupied.property</field>
|
||||||
|
<field name="arch" type="xml">
|
||||||
|
<list>
|
||||||
|
<field name="it_declaration_id"/>
|
||||||
|
<field name="address"/>
|
||||||
|
<field name="loan_after_april_1999"/>
|
||||||
|
<field name="period_from"/>
|
||||||
|
<field name="period_to"/>
|
||||||
|
<field name="interest_paid_to"/>
|
||||||
|
<field name="income_loss"/>
|
||||||
|
</list>
|
||||||
|
</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
<!-- Action -->
|
||||||
|
<record id="action_self_occupied_property" model="ir.actions.act_window">
|
||||||
|
<field name="name">Self Occupied Properties</field>
|
||||||
|
<field name="res_model">self.occupied.property</field>
|
||||||
|
<field name="view_mode">form</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
|
</odoo>
|
||||||
Loading…
Reference in New Issue