diff --git a/addons_extensions/employee_it_declaration/models/employee_payslip_download_wiz.py b/addons_extensions/employee_it_declaration/models/employee_payslip_download_wiz.py
index 9c5664a17..358b0da2f 100644
--- a/addons_extensions/employee_it_declaration/models/employee_payslip_download_wiz.py
+++ b/addons_extensions/employee_it_declaration/models/employee_payslip_download_wiz.py
@@ -14,7 +14,6 @@ class EmployeePayslipDownloadWizard(models.TransientModel):
'hr.employee',
required=True,
default=lambda self: self.env.user.employee_id.id,
- readonly=True,
)
download_type = fields.Selection(
selection=[
@@ -39,6 +38,13 @@ class EmployeePayslipDownloadWizard(models.TransientModel):
string='Available Payslips',
compute='_compute_payslip_count',
)
+ is_hr_manager = fields.Boolean(compute="_compute_is_hr_manager")
+
+ def _compute_is_hr_manager(self):
+ for rec in self:
+ import pdb
+ pdb.set_trace()
+ rec.is_hr_manager = self.env.user.has_group('hr.group_hr_manager')
@api.onchange('download_type', 'period_id')
def _onchange_download_type_period_id(self):
diff --git a/addons_extensions/employee_it_declaration/models/it_tax_statement_wiz.py b/addons_extensions/employee_it_declaration/models/it_tax_statement_wiz.py
index 574227e74..6ebe1fd82 100644
--- a/addons_extensions/employee_it_declaration/models/it_tax_statement_wiz.py
+++ b/addons_extensions/employee_it_declaration/models/it_tax_statement_wiz.py
@@ -18,9 +18,9 @@ class ITTaxStatementWizard(models.TransientModel):
contract_id = fields.Many2one('hr.contract', related='employee_id.contract_id', required=True)
currency_id = fields.Many2one('res.currency', related='employee_id.company_id.currency_id')
- period_id = fields.Many2one('payroll.period', required=True)
- period_line = fields.Many2one('payroll.period.line',
- domain="[('period_id', '=', period_id), ('to_date', '<', fields.Date.today())]")
+ period_id = fields.Many2one('payroll.period', required=True)
+ period_line = fields.Many2one('payroll.period.line',
+ domain="[('period_id', '=', period_id), ('to_date', '<', fields.Date.today())]")
# Taxpayer profile
taxpayer_name = fields.Char(related='employee_id.name')
@@ -95,33 +95,38 @@ class ITTaxStatementWizard(models.TransientModel):
('old', 'Old Regime'),
('new', 'New Regime')
], string="Beneficial Regime", readonly=True)
+ is_hr_manager = fields.Boolean(compute="_compute_is_hr_manager")
- def _get_age_category(self, age):
- if age < 60:
- return 'below_60'
- elif age < 80:
- return '60_to_80'
- return 'above_80'
-
- def _get_effective_period_start(self):
- self.ensure_one()
- period_start = self.period_id.from_date if self.period_id else False
- if not period_start:
- return False
- if self.emp_doj and self.period_id.to_date and self.period_id.from_date <= self.emp_doj <= self.period_id.to_date:
- return max(period_start, self.emp_doj.replace(day=1))
- return period_start
-
- def _get_effective_period_lines(self):
- self.ensure_one()
- if not self.period_id:
- return self.env['payroll.period.line']
-
- period_lines = self.period_id.period_line_ids.sorted('from_date')
- effective_start = self._get_effective_period_start()
- if not effective_start:
- return period_lines
- return period_lines.filtered(lambda line: line.to_date and line.to_date >= effective_start)
+ def _compute_is_hr_manager(self):
+ for rec in self:
+ rec.is_hr_manager = self.env.user.has_group('hr.group_hr_manager')
+
+ def _get_age_category(self, age):
+ if age < 60:
+ return 'below_60'
+ elif age < 80:
+ return '60_to_80'
+ return 'above_80'
+
+ def _get_effective_period_start(self):
+ self.ensure_one()
+ period_start = self.period_id.from_date if self.period_id else False
+ if not period_start:
+ return False
+ if self.emp_doj and self.period_id.to_date and self.period_id.from_date <= self.emp_doj <= self.period_id.to_date:
+ return max(period_start, self.emp_doj.replace(day=1))
+ return period_start
+
+ def _get_effective_period_lines(self):
+ self.ensure_one()
+ if not self.period_id:
+ return self.env['payroll.period.line']
+
+ period_lines = self.period_id.period_line_ids.sorted('from_date')
+ effective_start = self._get_effective_period_start()
+ if not effective_start:
+ return period_lines
+ return period_lines.filtered(lambda line: line.to_date and line.to_date >= effective_start)
def _find_applicable_slab(self, regime, period_id, age, residence_type):
"""Find the applicable tax slab without forcing both regimes to exist."""
@@ -136,7 +141,7 @@ class ITTaxStatementWizard(models.TransientModel):
('residence_type', '=', 'both')
], limit=1)
- def _get_applicable_slab(self, regime, period_id, age, residence_type):
+ def _get_applicable_slab(self, regime, period_id, age, residence_type):
"""Get the applicable tax slab based on regime, age, and residence type"""
age_category = self._get_age_category(age)
slab_master = self._find_applicable_slab(regime, period_id, age, residence_type)
@@ -145,21 +150,21 @@ class ITTaxStatementWizard(models.TransientModel):
"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
-
- @api.onchange('employee_id', 'period_id')
- def _onchange_employee_id_period_id(self):
- domain_by_record = {}
- for rec in self:
- domain = [('period_id', '=', rec.period_id.id), ('to_date', '<', fields.Date.today())] if rec.period_id else []
- if rec.emp_doj:
- domain.append(('to_date', '>=', rec.emp_doj.replace(day=1)))
-
- if rec.period_line and rec.period_line not in rec._get_effective_period_lines():
- rec.period_line = False
- domain_by_record[rec.id] = domain
- if len(self) == 1:
- return {'domain': {'period_line': domain_by_record.get(self.id, [])}}
+ return slab_master
+
+ @api.onchange('employee_id', 'period_id')
+ def _onchange_employee_id_period_id(self):
+ domain_by_record = {}
+ for rec in self:
+ domain = [('period_id', '=', rec.period_id.id), ('to_date', '<', fields.Date.today())] if rec.period_id else []
+ if rec.emp_doj:
+ domain.append(('to_date', '>=', rec.emp_doj.replace(day=1)))
+
+ if rec.period_line and rec.period_line not in rec._get_effective_period_lines():
+ rec.period_line = False
+ domain_by_record[rec.id] = domain
+ if len(self) == 1:
+ return {'domain': {'period_line': domain_by_record.get(self.id, [])}}
def _get_standard_deduction(self, regime, slab_master=False):
if slab_master:
@@ -329,7 +334,7 @@ class ITTaxStatementWizard(models.TransientModel):
return list(grouped.values())
- def fetch_salary_components(self):
+ def fetch_salary_components(self):
"""fetch salary components from payroll data"""
for rec in self:
data = {
@@ -345,10 +350,10 @@ class ITTaxStatementWizard(models.TransientModel):
}
if not rec.employee_id or not rec.contract_id or not rec.period_id or not rec.period_line:
return data
- period_lines = rec._get_effective_period_lines()
-
- for line in period_lines:
- components = rec._get_salary_components_for_period_line(line)
+ period_lines = rec._get_effective_period_lines()
+
+ for line in period_lines:
+ components = rec._get_salary_components_for_period_line(line)
if line.from_date and rec.period_line.from_date and line.from_date <= rec.period_line.from_date:
data['basic_salary']['actual'].append(components['basic_salary'])
data['hra_salary']['actual'].append(components['hra_salary'])
@@ -412,7 +417,7 @@ class ITTaxStatementWizard(models.TransientModel):
)
rec.standard_deduction = rec._get_standard_deduction(rec.tax_regime, slab_master)
- def fetch_deduction_components(self):
+ def fetch_deduction_components(self):
for rec in self:
data = {
'professional_tax': {'actual': [], 'projected': []},
@@ -421,12 +426,12 @@ class ITTaxStatementWizard(models.TransientModel):
if not rec.employee_id or not rec.contract_id or not rec.period_id or not rec.period_line:
return data
- for line in rec._get_effective_period_lines():
- rule_amounts = rec._get_rule_amounts_for_period_line(line, ['PT', 'PFE'])
- bucket = 'actual' if line.from_date <= rec.period_line.from_date else 'projected'
- data['professional_tax'][bucket].append(rule_amounts['PT'])
- data['nps_employer_contribution'][bucket].append(rule_amounts['PFE'])
- return data
+ for line in rec._get_effective_period_lines():
+ rule_amounts = rec._get_rule_amounts_for_period_line(line, ['PT', 'PFE'])
+ bucket = 'actual' if line.from_date <= rec.period_line.from_date else 'projected'
+ data['professional_tax'][bucket].append(rule_amounts['PT'])
+ data['nps_employer_contribution'][bucket].append(rule_amounts['PFE'])
+ return data
@api.onchange('employee_id')
@@ -521,6 +526,14 @@ class ITTaxStatementWizard(models.TransientModel):
tax_with_surcharge = total_before_mr - mr
return surcharge, mr, tax_with_surcharge
+ def fetch_current_employer_deducted_tax(self):
+ for rec in self:
+ payslip_ids = self.env['hr.payslip'].sudo().search([('employee_id','=',rec.employee_id.id),('state','in',['done','paid']),('date_from','>=',rec.period_id.from_date),('date_to','<=',rec.period_id.to_date)])
+ amount_deducted = 0.0
+ for payslip in payslip_ids:
+ amount_deducted += sum(payslip.line_ids.filtered(lambda l:l.salary_rule_id.code == 'TDS').mapped('amount'))
+
+ return amount_deducted
def _compute_tax_old_regime(self, taxable, slab_master=False):
# Get applicable slab
slab_master = slab_master or self._get_applicable_slab(
@@ -549,6 +562,8 @@ class ITTaxStatementWizard(models.TransientModel):
total_tax = tax_with_surcharge + cess
+ current_employer_deducted_tax = self.fetch_current_employer_deducted_tax()
+
return {
'taxable_income': taxable,
'slab_tax': slab_tax,
@@ -558,7 +573,9 @@ class ITTaxStatementWizard(models.TransientModel):
'marginal_relief': marginal_relief,
'tax_with_surcharge': tax_with_surcharge,
'cess_4pct': cess,
- 'total_tax': total_tax
+ 'total_tax': total_tax,
+ 'current_employer_deducted_tax': current_employer_deducted_tax,
+ 'balance_tax': total_tax - (-current_employer_deducted_tax)
}
def _compute_tax_new_regime(self, taxable, slab_master=False):
@@ -587,6 +604,7 @@ class ITTaxStatementWizard(models.TransientModel):
cess = tax_with_surcharge * cess_rate[0] / 100
total_tax = tax_with_surcharge + cess
+ current_employer_deducted_tax = self.fetch_current_employer_deducted_tax()
return {
'taxable_income': taxable,
'slab_tax': slab_tax,
@@ -596,7 +614,9 @@ class ITTaxStatementWizard(models.TransientModel):
'marginal_relief': marginal_relief,
'tax_with_surcharge': tax_with_surcharge,
'cess_4pct': cess,
- 'total_tax': total_tax
+ 'total_tax': total_tax,
+ 'current_employer_deducted_tax': current_employer_deducted_tax,
+ 'balance_tax': total_tax - (-current_employer_deducted_tax)
}
def _compute_house_property_income(self):
@@ -759,19 +779,19 @@ class ITTaxStatementWizard(models.TransientModel):
'target': 'current',
}
- def _prepare_income_tax_data(self, include_comparison=False):
- """Prepare data for the tax statement report"""
- today = date.today()
- display_fy_start = self.period_id.from_date
- fy_end = self.period_id.to_date
- effective_fy_start = self._get_effective_period_start() or display_fy_start
- total_months = ((fy_end.year - effective_fy_start.year) * 12 +
- (fy_end.month - effective_fy_start.month) + 1)
-
- line_start = self.period_line.from_date
- current_month_index = ((line_start.year - effective_fy_start.year) * 12 +
- (line_start.month - effective_fy_start.month) + 1)
- values = self._get_tax_base_values(include_comparison=include_comparison)
+ def _prepare_income_tax_data(self, include_comparison=False):
+ """Prepare data for the tax statement report"""
+ today = date.today()
+ display_fy_start = self.period_id.from_date
+ fy_end = self.period_id.to_date
+ effective_fy_start = self._get_effective_period_start() or display_fy_start
+ total_months = ((fy_end.year - effective_fy_start.year) * 12 +
+ (fy_end.month - effective_fy_start.month) + 1)
+
+ line_start = self.period_line.from_date
+ current_month_index = ((line_start.year - effective_fy_start.year) * 12 +
+ (line_start.month - effective_fy_start.month) + 1)
+ values = self._get_tax_base_values(include_comparison=include_comparison)
salary_components_data = values['salary_components_data']
annual_gross_salary = values['annual_gross_salary']
gross_salary_actual = values['gross_salary_actual']
@@ -806,16 +826,16 @@ class ITTaxStatementWizard(models.TransientModel):
# Prepare data structure matching screenshot format
# Financial year (period_id)
- display_fy_start = self.period_id.from_date
- fy_end = self.period_id.to_date
- effective_fy_start = self._get_effective_period_start() or display_fy_start
- total_months = ((fy_end.year - effective_fy_start.year) * 12 +
- (fy_end.month - effective_fy_start.month) + 1)
-
- # Current month (period_line)
- line_start = self.period_line.from_date
- current_month_index = ((line_start.year - effective_fy_start.year) * 12 +
- (line_start.month - effective_fy_start.month) + 1)
+ display_fy_start = self.period_id.from_date
+ fy_end = self.period_id.to_date
+ effective_fy_start = self._get_effective_period_start() or display_fy_start
+ total_months = ((fy_end.year - effective_fy_start.year) * 12 +
+ (fy_end.month - effective_fy_start.month) + 1)
+
+ # Current month (period_line)
+ line_start = self.period_line.from_date
+ current_month_index = ((line_start.year - effective_fy_start.year) * 12 +
+ (line_start.month - effective_fy_start.month) + 1)
tax_result['roundoff_taxable_income'] = float(round(tax_result["taxable_income"] / 10) * 10)
birthday = self.employee_id.birthday
if birthday:
@@ -835,8 +855,8 @@ class ITTaxStatementWizard(models.TransientModel):
'total': total,
})
data = {
- 'financial_year': f"{display_fy_start.year}-{fy_end.year}",
- 'assessment_year': fy_end.year + 1,
+ 'financial_year': f"{display_fy_start.year}-{fy_end.year}",
+ 'assessment_year': fy_end.year,
'report_time': today.strftime('%d-%m-%Y %H:%M'),
'user': 'ESS',
'emp_code': self.employee_id.employee_id,
diff --git a/addons_extensions/employee_it_declaration/report/it_tax_template.xml b/addons_extensions/employee_it_declaration/report/it_tax_template.xml
index 70acae040..d44989933 100644
--- a/addons_extensions/employee_it_declaration/report/it_tax_template.xml
+++ b/addons_extensions/employee_it_declaration/report/it_tax_template.xml
@@ -38,6 +38,8 @@
Create a new employment type