Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Indian l10n modification for hr_payroll #649

Draft
wants to merge 3 commits into
base: 18.0
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,4 @@ dmypy.json

# Pyre type checker
.pyre/
.vscode
1 change: 1 addition & 0 deletions l10n_in_hr_payroll_extension/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import models
10 changes: 10 additions & 0 deletions l10n_in_hr_payroll_extension/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
'name': "Indian Payroll Extension",
'depends': ['l10n_in_hr_payroll'],
'installable': True,
'license': 'LGPL-3',
'data': [
'views/res_config_settings_views.xml',
'views/hr_contract_views.xml',
],
}
3 changes: 3 additions & 0 deletions l10n_in_hr_payroll_extension/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from . import res_company
from . import res_config_settings
from . import hr_contract
118 changes: 118 additions & 0 deletions l10n_in_hr_payroll_extension/models/hr_contract.py

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make code more readable so avoid using record instead of use contract

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I will take care of it from now.

Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
from odoo import api, fields, models


class HrContract(models.Model):
_inherit = 'hr.contract'

l10n_in_basic_salary = fields.Monetary(string="Basic Salary", help="Basic salary calculated from the wage", compute="_compute_l10n_in_basic_salary", inverse="_inverse_l10n_in_basic_salary", currency_field="currency_id")
l10n_in_house_rent_allowance = fields.Monetary(string="House Rent Allowance", compute="_compute_l10n_in_house_rent_allowance", inverse="_inverse_l10n_in_house_rent_allowance", currency_field="currency_id")
l10n_in_standard_allowance = fields.Monetary(string="Standard Allowance", default=lambda self: self.env.company.l10n_in_standard_allowance, currency_field="currency_id")
l10n_in_performance_bonus = fields.Monetary(string="Performance Bonus", compute="_compute_l10n_in_performance_bonus", inverse="_inverse_l10n_in_performance_bonus", currency_field="currency_id")
l10n_in_leave_travel_allowance = fields.Monetary(string="Leave Travel Allowance", compute="_compute_l10n_in_leave_travel_allowance", inverse="_inverse_l10n_in_leave_travel_allowance", currency_field="currency_id")
l10n_in_leave_allowance = fields.Monetary(string="Leave Allowance", compute="_compute_leave_allowance", inverse="_inverse_leave_allowance", currency_field="currency_id")
l10n_in_leave_days = fields.Float(string="Leave Days", default=lambda self: self.env.company.l10n_in_leave_days)
l10n_in_gratuity = fields.Monetary(string="Gratuity", currency_field="currency_id", default=lambda self: self.env.company.l10n_in_gratuity)
l10n_in_supplementary_allowance = fields.Monetary(string="Supplementary Allowance", compute="_compute_l10n_in_supplementary_allowance", inverse="_inverse_l10n_in_supplementary_allowance", currency_field="currency_id", default=lambda self: self.env.company.l10n_in_supplementary_allowance)

l10n_in_basic_salary_percent = fields.Float(string="Basic Salary Percentage", help="basic salary percentage of wage", default=lambda self: self.env.company.l10n_in_basic_salary_percent)
l10n_in_house_rent_allowance_percent = fields.Float(string="House Rent Allowance Percentage", help="this is the percentage of basic salary", default=lambda self: self.env.company.l10n_in_house_rent_allowance_percent)
l10n_in_standard_allowance_percent = fields.Float(string="Standard Allowance Percentage", compute="_compute_l10n_in_standard_allowance_percent", inverse="_inverse_l10n_in_standard_allowance_percent")
l10n_in_performance_bonus_percent = fields.Float(string="Performance Bonus Percentage", default=lambda self: self.env.company.l10n_in_performance_bonus_percent)
l10n_in_leave_travel_allowance_percent = fields.Float(string="Leave Travel Allowance Percentage", default=lambda self: self.env.company.l10n_in_leave_travel_allowance_percent)
l10n_in_leave_allowance_per_day_percent = fields.Float(string="Leave allowance per day percentage")
l10n_in_leave_allowance_percent = fields.Float(string="Leave Allowance Percentage")
l10n_in_gratuity_percent = fields.Float(string="Gratuity Percentage", compute="_compute_l10n_in_gratuity_percent", inverse="_inverse_l10n_in_gratuity_percent")
l10n_in_supplementary_allowance_percent = fields.Float(string="Supplementary Allowance Percentage")

l10n_in_pf_employee_contribution = fields.Float(string="Employee Contribution", default=12)
l10n_in_pf_employer_contribution = fields.Float(string="Employer Contribution", default=12)
l10n_in_professional_tax = fields.Monetary(string="Professional Tax", default=200)
l10n_in_esic_employee_contribution = fields.Float(string="Employee Contribution", default=0.75)
l10n_in_esic_employer_contribution = fields.Float(string="Employer Contribution", default=3.25)
l10n_in_lwf_employee_contribution = fields.Monetary(string="Employee Contribution", currency_field="currency_id", default=6)
l10n_in_lwf_employer_contribution = fields.Monetary(string="Employer Contribution", currency_field="currency_id", default=12)
l10n_in_other_deduction = fields.Monetary(string="Other Deduction", currency_field="currency_id")

@api.depends("l10n_in_basic_salary_percent", "wage")
def _compute_l10n_in_basic_salary(self):
for contract in self:
contract.l10n_in_basic_salary = contract.wage * contract.l10n_in_basic_salary_percent

def _inverse_l10n_in_basic_salary(self):
for contract in self:
contract.l10n_in_basic_salary_percent = contract.l10n_in_basic_salary / contract.wage if contract.wage else 0

@api.depends("l10n_in_basic_salary", "l10n_in_house_rent_allowance_percent")
def _compute_l10n_in_house_rent_allowance(self):
for contract in self:
contract.l10n_in_house_rent_allowance = contract.l10n_in_basic_salary * contract.l10n_in_house_rent_allowance_percent

def _inverse_l10n_in_house_rent_allowance(self):
for contract in self:
contract.l10n_in_house_rent_allowance_percent = contract.l10n_in_house_rent_allowance / contract.l10n_in_basic_salary if contract.l10n_in_basic_salary else 0

@api.depends("l10n_in_standard_allowance", "wage")
def _compute_l10n_in_standard_allowance_percent(self):
for contract in self:
contract.l10n_in_standard_allowance_percent = contract.l10n_in_standard_allowance / contract.wage if contract.wage else 0

def _inverse_l10n_in_standard_allowance_percent(self):
for contract in self:
contract.l10n_in_standard_allowance = contract.l10n_in_standard_allowance_percent * contract.wage

@api.depends("l10n_in_performance_bonus_percent", "l10n_in_basic_salary")
def _compute_l10n_in_performance_bonus(self):
for contract in self:
contract.l10n_in_performance_bonus = contract.l10n_in_basic_salary * contract.l10n_in_performance_bonus_percent

def _inverse_l10n_in_performance_bonus(self):
for contract in self:
contract.l10n_in_performance_bonus_percent = contract.l10n_in_performance_bonus / contract.l10n_in_basic_salary if contract.l10n_in_basic_salary else 0

@api.depends("l10n_in_leave_travel_allowance_percent", "l10n_in_basic_salary")
def _compute_l10n_in_leave_travel_allowance(self):
for contract in self:
contract.l10n_in_leave_travel_allowance = contract.l10n_in_basic_salary * contract.l10n_in_leave_travel_allowance_percent

def _inverse_l10n_in_leave_travel_allowance(self):
for contract in self:
contract.l10n_in_leave_travel_allowance_percent = contract.l10n_in_leave_travel_allowance / contract.l10n_in_basic_salary if contract.l10n_in_basic_salary else 0

@api.depends('wage', 'l10n_in_leave_allowance_per_day_percent', 'l10n_in_leave_days')
def _compute_leave_allowance(self):
for contract in self:
contract.l10n_in_leave_allowance = contract.wage * contract.l10n_in_leave_allowance_per_day_percent * contract.l10n_in_leave_days

def _inverse_leave_allowance(self):
for contract in self:
if contract.l10n_in_basic_salary and contract.l10n_in_leave_days:
contract.l10n_in_leave_allowance_percent = contract.l10n_in_leave_allowance / contract.wage if contract.wage else 0
contract.l10n_in_leave_allowance_per_day_percent = contract.l10n_in_leave_allowance / (contract.wage * contract.l10n_in_leave_days) if contract.wage else 0

@api.depends("l10n_in_gratuity", "l10n_in_basic_salary")
def _compute_l10n_in_gratuity_percent(self):
for contract in self:
contract.l10n_in_gratuity_percent = contract.l10n_in_gratuity / contract.l10n_in_basic_salary if contract.l10n_in_basic_salary else 0

def _inverse_l10n_in_gratuity_percent(self):
for contract in self:
contract.l10n_in_gratuity = contract.l10n_in_basic_salary * contract.l10n_in_gratuity_percent

@api.depends("wage", "l10n_in_basic_salary", "l10n_in_house_rent_allowance", "l10n_in_standard_allowance", "l10n_in_performance_bonus", "l10n_in_leave_travel_allowance", "l10n_in_leave_allowance", "l10n_in_gratuity")
def _compute_l10n_in_supplementary_allowance(self):
for contract in self:
total_allowance = sum([
contract.l10n_in_basic_salary,
contract.l10n_in_house_rent_allowance,
contract.l10n_in_standard_allowance,
contract.l10n_in_performance_bonus,
contract.l10n_in_leave_travel_allowance,
contract.l10n_in_leave_allowance,
contract.l10n_in_gratuity
])
if contract.wage:
contract.l10n_in_supplementary_allowance = contract.wage - total_allowance

def _inverse_l10n_in_supplementary_allowance(self):
for contract in self:
contract.l10n_in_supplementary_allowance_percent = contract.l10n_in_supplementary_allowance / contract.wage if contract.wage else 0
33 changes: 33 additions & 0 deletions l10n_in_hr_payroll_extension/models/res_company.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from odoo import fields, models


class ResCompany(models.Model):
_inherit = 'res.company'

l10n_in_org_tax_details = fields.Boolean(string="Organisation Tax Details")
l10n_in_org_pan_number = fields.Char(string="PAN Number")
l10n_in_org_tan_number = fields.Char(string="TAN Number")
l10n_in_org_tds_circle = fields.Char(string="TDS Circle/AO Code")

l10n_in_pf_employer_identification = fields.Char(string="Employer Identification")
l10n_in_pf_employee_contribution = fields.Float(string="Employee Contribution", default=12)
l10n_in_pf_employer_contribution = fields.Float(string="Employer Contribution", default=12)

l10n_in_professional_tax_number = fields.Char(string="Professional Tax Number")

l10n_in_esic_ip = fields.Char(string="ESIC IP")
l10n_in_esic_employee_contribution = fields.Float(string="Employee Contribution", default=0.75)
l10n_in_esic_employer_contribution = fields.Float(string="Employer Contribution", default=3.25)

l10n_in_lwf_employee_contribution = fields.Monetary(string="Employee Contribution", currency_field="currency_id", default=6)
l10n_in_lwf_employer_contribution = fields.Monetary(string="Employer Contribution", currency_field="currency_id", default=12)

# Salary Structure
l10n_in_basic_salary_percent = fields.Float(string="Basic Salary Percentage", default=0.50)
l10n_in_house_rent_allowance_percent = fields.Float(string="House Rent Allowance", help="You can define 50% for metro city and 40% for non-metro city.", default=0.50)
l10n_in_standard_allowance = fields.Float(string="Standard Allowance", default=4167)
l10n_in_performance_bonus_percent = fields.Float(string="Performance Bonus", default=0.20)
l10n_in_leave_travel_allowance_percent = fields.Float(string="Leave Travel Allowance", default=0.20)
l10n_in_leave_days = fields.Float(string="Leave Days", default=1)
l10n_in_gratuity = fields.Float(string="Gratuity")
l10n_in_supplementary_allowance = fields.Float(string="Supplementary Allowance")
38 changes: 38 additions & 0 deletions l10n_in_hr_payroll_extension/models/res_config_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
from odoo import fields, models


class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'

currency_id = fields.Many2one("res.currency", default=lambda self: self.env.company.currency_id)

l10n_in_org_tax_details = fields.Boolean(related='company_id.l10n_in_org_tax_details', readonly=False)
l10n_in_org_pan_number = fields.Char(related='company_id.l10n_in_org_pan_number', readonly=False)
l10n_in_org_tan_number = fields.Char(related='company_id.l10n_in_org_tan_number', readonly=False)
l10n_in_org_tds_circle = fields.Char(related='company_id.l10n_in_org_tds_circle', readonly=False)

l10n_in_is_provident_fund = fields.Boolean(string="Employee's Provident Fund", default=True)
l10n_in_pf_employer_identification = fields.Char(related='company_id.l10n_in_pf_employer_identification', readonly=False)
l10n_in_pf_employee_contribution = fields.Float(related="company_id.l10n_in_pf_employee_contribution", readonly=False)
l10n_in_pf_employer_contribution = fields.Float(related="company_id.l10n_in_pf_employer_contribution", readonly=False)

l10n_in_is_professional_tax = fields.Boolean(string="Professional Tax", default=True)
l10n_in_professional_tax_number = fields.Char(related='company_id.l10n_in_professional_tax_number', readonly=False)

l10n_in_is_esic = fields.Boolean(string="Employee's State Insurance Corporation", default=True)
l10n_in_esic_ip = fields.Char(string="ESIC IP", related='company_id.l10n_in_esic_ip', readonly=False)
l10n_in_esic_employee_contribution = fields.Float(related="company_id.l10n_in_esic_employee_contribution", readonly=False)
l10n_in_esic_employer_contribution = fields.Float(related="company_id.l10n_in_esic_employer_contribution", readonly=False)

l10n_in_is_lwf = fields.Boolean(string="Labour Welfare Fund", default=True)
l10n_in_lwf_employee_contribution = fields.Monetary(related="company_id.l10n_in_lwf_employee_contribution", readonly=False)
l10n_in_lwf_employer_contribution = fields.Monetary(related="company_id.l10n_in_lwf_employer_contribution", readonly=False)

l10n_in_basic_salary_percent = fields.Float(related="company_id.l10n_in_basic_salary_percent", readonly=False)
l10n_in_house_rent_allowance_percent = fields.Float(related="company_id.l10n_in_house_rent_allowance_percent", readonly=False)
l10n_in_standard_allowance = fields.Float(related="company_id.l10n_in_standard_allowance", readonly=False)
l10n_in_performance_bonus_percent = fields.Float(related="company_id.l10n_in_performance_bonus_percent", readonly=False)
l10n_in_leave_travel_allowance_percent = fields.Float(related="company_id.l10n_in_leave_travel_allowance_percent", readonly=False)
l10n_in_leave_days = fields.Float(related="company_id.l10n_in_leave_days", readonly=False)
l10n_in_gratuity = fields.Float(related="company_id.l10n_in_gratuity", readonly=False)
l10n_in_supplementary_allowance = fields.Float(related="company_id.l10n_in_supplementary_allowance", readonly=False)
1 change: 1 addition & 0 deletions l10n_in_hr_payroll_extension/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from . import test_hr_contract
29 changes: 29 additions & 0 deletions l10n_in_hr_payroll_extension/tests/test_hr_contract.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from odoo.tests.common import TransactionCase
from odoo.tests import tagged


@tagged('post_install', '-at_install')
class TestHrContract(TransactionCase):
@classmethod
def setUpClass(cls):
super().setUpClass()

cls.contract = cls.env['hr.contract'].create({
'name': "Test Contract",
'wage': 100000,
'l10n_in_basic_salary_percent': 50,
'l10n_in_house_rent_allowance_percent': 50,
'l10n_in_standard_allowance': 4167,
'l10n_in_performance_bonus_percent': 20,
'l10n_in_leave_travel_allowance_percent': 20,
'l10n_in_gratuity': 250,
})

def test_salary_component_amounts(self):
self.assertEqual(self.contract.l10n_in_basic_salary, 50000, "50% of 100000 should be 50000")
self.assertEqual(self.contract.l10n_in_house_rent_allowance, 25000, "50% of 50000(Basic Salary) should be 25000")
self.assertEqual(self.contract.l10n_in_standard_allowance_percent, 4.167, "4167 is a 4.17% of 100000(Wage)")
self.assertEqual(self.contract.l10n_in_performance_bonus, 10000, "20% of 50000(Basic Salary) should be 10000")
self.assertEqual(self.contract.l10n_in_leave_travel_allowance, 10000, "20% of 50000(Basic Salary) should be 10000")
self.assertEqual(self.contract.l10n_in_gratuity_percent, 0.50, "250 is a 0.50% of 50000(Basic Salary)")
self.assertEqual(self.contract.l10n_in_supplementary_allowance, 583, "supplementary should be remaining amount from wage")
Loading