[MERGE] (l10n_be_)hr_payroll: Clean data and code

1/ hr_contract_salary: Remove hr.contract.advantage.template model

   It was a failed attempt to make somethig generic. Sometimes we are not the only ones to choose.

   Closes #28727

2/ hr_payroll: Retrieve localdict default value from a method

3/ l10n_be_hr_payroll: Merge both miscellaneous onss rules

   This is useless to have 2 separate rules.

4/ l10n_be_hr_payroll: Move withholding tax reductions into the same rule

   Compute the 'precompte professionnel' directly instead of having more than
   10 rules just for that.

5/ l10n_be_hr_payroll: Update 'Bonus à l'emploi' up to 01/09/2018

   See: https://www.socialsecurity.be/employer/instructions/dmfa/fr/latest/instructions/deductions/workers_reductions/workbonus.html

6/ l10n_be_hr_payroll: Remove duplicated salary rule

   This rule is a reduction for the ONSS contribution, not a reduction for
   the précompte professionnel.

   The reduction for the ONSS contribution is already implemented.

7/ l10n_be_hr_payroll: Rename C.P. 218 into CP 200

   The CP 218 is deprecated since 2015. See https://www.jesuisemployeur.be/banque-d-info/actualites/la-cp-218-devient-la-cp-200-qu-en-est-il-des-entreprises-qui-relevent-actuellement-des-cp-100-et-200

8/ l10n_be_hr_payroll: Use the magic formula for the PP computation

   The 'Précompte Professionel' can be deducted from a formula if you're
   patient enough to read https://finances.belgium.be/sites/default/files/downloads/700-formule-cle-20180101.pdf

   This commit remove all the hr.salary.rules from the official tables
   and use the formula instead. This should improve the performances too.

9/ hr_payroll: Show only localizations on res_config

10/ hr_payroll: Install the correct module when enabling accounting

   Closes #29207

11/ l10n_br_hr_payroll_account: Remove useless dependency

12/ l10n_in_hr_payroll: Add dependency to l10n_in

13/ l10n_be_hr_payroll: Add dependency to l10n_be

TaskID: 1915125

closes odoo/odoo#29246
This commit is contained in:
Robot Odoo
2018-12-06 17:47:54 +01:00
committed by GitHub
17 changed files with 263 additions and 1844 deletions
-24
View File
@@ -29,27 +29,3 @@ class HrContract(models.Model):
"""
structures = self.mapped('struct_id')
return structures._get_parent_structure() if structures else self.env['hr.payroll.structure']
@api.multi
def get_attribute(self, code, attribute):
return self.env['hr.contract.advantage.template'].search([('code', '=', code)], limit=1)[attribute]
@api.multi
def set_attribute_value(self, code, active):
for contract in self:
if active:
value = self.env['hr.contract.advantage.template'].search([('code', '=', code)], limit=1).default_value
contract[code] = value
else:
contract[code] = 0.0
class HrContractAdvandageTemplate(models.Model):
_name = 'hr.contract.advantage.template'
_description = "Employee's Advantage on Contract"
name = fields.Char('Name', required=True)
code = fields.Char('Code', required=True)
lower_bound = fields.Float('Lower Bound', help="Lower bound authorized by the employer for this advantage")
upper_bound = fields.Float('Upper Bound', help="Upper bound authorized by the employer for this advantage")
default_value = fields.Float('Default value for this advantage')
+6 -1
View File
@@ -10,6 +10,7 @@ from odoo import api, fields, models, tools, _
from odoo.addons import decimal_precision as dp
from odoo.addons.hr_payroll.models.browsable_object import BrowsableObject, InputLine, WorkedDays, Payslips
from odoo.exceptions import UserError, ValidationError
from odoo.tools import float_round
class HrPayslip(models.Model):
@@ -174,6 +175,10 @@ class HrPayslip(models.Model):
return res
def _get_base_local_dict(self):
return {
'float_round': float_round
}
# YTI TODO: pass recordset as argument
@api.model
@@ -204,7 +209,7 @@ class HrPayslip(models.Model):
payslips = Payslips(self.employee_id.id, self, self.env)
rules = BrowsableObject(self.employee_id.id, rules_dict, self.env)
baselocaldict = {'categories': categories, 'rules': rules, 'payslip': payslips, 'worked_days': worked_days, 'inputs': inputs}
baselocaldict = {**self._get_base_local_dict(), **{'categories': categories, 'rules': rules, 'payslip': payslips, 'worked_days': worked_days, 'inputs': inputs}}
#get the ids of the structures on the contracts and their parent id as well
if len(contracts) == 1 and self.struct_id:
structures = self.struct_id._get_parent_structure()
@@ -7,7 +7,7 @@ from odoo import fields, models
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
module_account_accountant = fields.Boolean(string='Account Accountant')
module_l10n_fr_hr_payroll = fields.Boolean(string='French Payroll')
module_l10n_be_hr_payroll = fields.Boolean(string='Belgium Payroll')
module_l10n_in_hr_payroll = fields.Boolean(string='Indian Payroll')
module_hr_payroll_account = fields.Boolean(string='Payroll with Accounting')
@@ -9,7 +9,5 @@ access_hr_payslip_input_user,hr.payslip.input.user,model_hr_payslip_input,hr_pay
access_hr_payslip_worked_days_officer,hr.payslip.worked_days.officer,model_hr_payslip_worked_days,hr_payroll.group_hr_payroll_user,1,1,1,1
access_hr_payslip_run,hr.payslip.run,model_hr_payslip_run,hr_payroll.group_hr_payroll_manager,1,1,1,1
access_hr_salary_rule_user,hr.salary.rule.user,model_hr_salary_rule,hr_payroll.group_hr_payroll_user,1,1,1,1
access_hr_contract_advantage_template,hr.contract.advantage.template.user,model_hr_contract_advantage_template,hr_payroll.group_hr_payroll_user,1,1,1,1
access_hr_contract_advantage_template_hr_user,hr.contract.advantage.template.hr.user,model_hr_contract_advantage_template,hr.group_hr_user,1,0,0,0
access_hr_benefit,access_hr_benefit,model_hr_benefit,group_hr_payroll_user,1,1,1,1
access_hr_benefit_type,access_hr_benefit_type,model_hr_benefit_type,group_hr_payroll_user,1,1,1,1
access_hr_benefit_type,access_hr_benefit_type,model_hr_benefit_type,group_hr_payroll_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
9 access_hr_payslip_worked_days_officer hr.payslip.worked_days.officer model_hr_payslip_worked_days hr_payroll.group_hr_payroll_user 1 1 1 1
10 access_hr_payslip_run hr.payslip.run model_hr_payslip_run hr_payroll.group_hr_payroll_manager 1 1 1 1
11 access_hr_salary_rule_user hr.salary.rule.user model_hr_salary_rule hr_payroll.group_hr_payroll_user 1 1 1 1
access_hr_contract_advantage_template hr.contract.advantage.template.user model_hr_contract_advantage_template hr_payroll.group_hr_payroll_user 1 1 1 1
access_hr_contract_advantage_template_hr_user hr.contract.advantage.template.hr.user model_hr_contract_advantage_template hr.group_hr_user 1 0 0 0
12 access_hr_benefit access_hr_benefit model_hr_benefit group_hr_payroll_user 1 1 1 1
13 access_hr_benefit_type access_hr_benefit_type model_hr_benefit_type group_hr_payroll_user 1 1 1 1
@@ -24,58 +24,4 @@
</xpath>
</field>
</record>
<record id="hr_contract_advantage_template_view_form" model="ir.ui.view">
<field name="name">hr.contract.advantage.template.form</field>
<field name="model">hr.contract.advantage.template</field>
<field name="arch" type="xml">
<form>
<sheet>
<div class="oe_title">
<h1>
<field name="name" placeholder="Advantage Name"/>
</h1>
</div>
<group>
<group>
<field name="code"/>
</group>
</group>
<group>
<group>
<field name="default_value"/>
<field name="lower_bound"/>
<field name="upper_bound"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="hr_contract_advantage_template_view_tree" model="ir.ui.view">
<field name="name">hr.contract.advantage.template.tree</field>
<field name="model">hr.contract.advantage.template</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="code"/>
<field name="lower_bound"/>
<field name="upper_bound"/>
<field name="default_value"/>
</tree>
</field>
</record>
<record id="hr_contract_advantage_template_action" model="ir.actions.act_window">
<field name="name">Contract Advantage Templates</field>
<field name="res_model">hr.contract.advantage.template</field>
<field name="view_type">form</field>
</record>
<menuitem
id="hr_contract_advantage_template_menu_action"
action="hr_contract_advantage_template_action"
parent="menu_hr_payroll_configuration"
sequence="50"/>
</odoo>
@@ -4,7 +4,7 @@
<field name="name">Payroll</field>
<field name="res_model">ir.module.module</field>
<field name="view_mode">kanban,tree,form</field>
<field name="context" eval="{'search_default_category_id': ref('base.module_category_localization'), 'search_default_name': 'Payroll'}"/>
<field name="context" eval="{'search_default_category_id': ref('base.module_category_payroll_localization'), 'search_default_name': 'Payroll'}"/>
<field name="search_view_id" ref="base.view_module_filter"/>
</record>
@@ -37,10 +37,10 @@
<div class="row mt16 o_settings_container" id="hr_payroll_accountant">
<div class="col-lg-6 col-12 o_setting_box">
<div class="o_setting_left_pane">
<field name="module_account_accountant" widget="upgrade_boolean"/>
<field name="module_hr_payroll_account"/>
</div>
<div class="o_setting_right_pane">
<label for="module_account_accountant" string="Payroll Entries"/>
<label for="module_hr_payroll_account" string="Payroll Entries"/>
<div class="text-muted">
Post payroll slips in accounting
</div>
+3 -3
View File
@@ -3,8 +3,8 @@
{
'name': 'Belgium - Payroll',
'category': 'Human Resources',
'depends': ['hr_payroll'],
'category': 'Payroll Localization',
'depends': ['hr_payroll', 'l10n_be'],
'description': """
Belgian Payroll Rules.
======================
@@ -23,6 +23,6 @@ Belgian Payroll Rules.
'data': [
'views/l10n_be_hr_payroll_view.xml',
'data/l10n_be_hr_payroll_data.xml',
'data/hr.salary.rule.csv',
'views/res_config_settings_views.xml',
],
}
File diff suppressed because it is too large Load Diff
@@ -75,16 +75,6 @@ result = contract.wage_with_holidays
<field name="code">ChA</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_salary_rule_category_family_reductions" model="hr.salary.rule.category">
<field name="name">Reduction for special family charges</field>
<field name="code">FamRed</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_salary_rule_pp_reductions" model="hr.salary.rule.category">
<field name="name">Withholding Tax Reduction</field>
<field name="code">PPRed</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_salary_rule_category_spec_soc_contribution" model="hr.salary.rule.category">
<field name="name">Special social contribution</field>
<field name="code">SSC</field>
@@ -144,14 +134,14 @@ if contract.mobile:
<field name="code">EmpBonus.1</field>
<field name="sequence">42</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT &lt;= 2510.47</field>
<field name="condition_python">result = categories.BRUT &lt;= 2560.57</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
salary = categories.BRUT
if salary &lt;= 1609.47:
result = 197.67
elif salary &lt;= 2510.47:
result = 197.67 - (0.2194 * (salary - 1609.47))
if salary &lt;= 1641.62:
result = 201.62
elif salary &lt;= 2560.57:
result = 201.62 - (0.2194 * (salary - 1641.62))
</field>
</record>
<record id="hr_salary_rule_employment_bonus_workers" model="hr.salary.rule">
@@ -160,14 +150,14 @@ elif salary &lt;= 2510.47:
<field name="code">EmpBonus.2</field>
<field name="sequence">42</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT + categories.ONSS &lt;= 2510.47</field>
<field name="condition_python">result = categories.BRUT + &lt;= 2560.57</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
salary = categories.BRUT
if salary &lt;= 1609.47:
result = 213.48
elif salary &lt;= 2510.47:
result = 213.48 - (0.2369 * (salary - 1609.47))
if salary &lt;= 1641.62:
result = 217.75
elif salary &lt;= 2560.57:
result = 217.75 - (0.2370 * (salary - 1641.62))
</field>
</record>
@@ -197,240 +187,143 @@ result = - categories.GROSSIP * contract.ip_wage_rate / 100.0
</field>
</record>
<record id="hr_payroll_rules_mis_ex_onss_1" model="hr.salary.rule">
<record id="hr_payroll_rules_mis_ex_onss" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_category_spec_soc_contribution"/>
<field name="name">Special social cotisation</field>
<field name="code">M.ONSS.1</field>
<field name="code">M.ONSS</field>
<field name="amount_select">fix</field>
<field name="sequence">165</field>
<field name="condition_select">python</field>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_python">result = (((employee.marital in ['divorced', 'single', 'widower']) or (employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='without income')) and (employee.resident_bool!=True))</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
wage = categories.BASIC
if wage &gt;= 0.01 and wage &lt;= 1095.09:
if employee.resident_bool:
result = 0.0
elif wage &gt;= 1095.10 and wage &lt;= 1945.38:
result = 0.0
elif wage &gt;= 1945.39 and wage &lt;= 2190.18:
result = -min((wage - 1945.38) * 0.076, 18.60)
elif wage &gt;= 2190.19 and wage &lt;= 6038.82:
result = -min(18.60 + (wage - 2190.18) * 0.011, 60.94)
else:
result = -60.94
</field>
</record>
<record id="hr_payroll_rules_mis_ex_onss_2" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_category_spec_soc_contribution"/>
<field name="name">Special social cotisation</field>
<field name="code">M.ONSS.2</field>
<field name="amount_select">fix</field>
<field name="sequence">165</field>
<field name="condition_select">python</field>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_python">result = (((employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income')) and (employee.resident_bool!=True))</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
wage = categories.BASIC
if wage &gt;= 0.01 and wage &lt;= 1095.09:
result = 0.0
elif wage &gt;= 1095.10 and wage &lt;= 1945.38:
result = -9.30
elif wage &gt;= 1945.39 and wage &lt;= 2190.18:
result = -min(max((wage - 1945.38) * 0.076, 9.30), 18.60)
elif wage &gt;= 2190.19 and wage &lt;= 6038.82:
result = -min(18.60 + (wage - 2190.18) * 0.011, 51.64)
else:
result = -51.64
elif employee.marital in ['divorced', 'single', 'widower'] or (employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='without income'):
if wage &gt;= 0.01 and wage &lt;= 1095.09:
result = 0.0
elif wage &gt;= 1095.10 and wage &lt;= 1945.38:
result = 0.0
elif wage &gt;= 1945.39 and wage &lt;= 2190.18:
result = -min((wage - 1945.38) * 0.076, 18.60)
elif wage &gt;= 2190.19 and wage &lt;= 6038.82:
result = -min(18.60 + (wage - 2190.18) * 0.011, 60.94)
else:
result = -60.94
elif employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income':
if wage &gt;= 0.01 and wage &lt;= 1095.09:
result = 0.0
elif wage &gt;= 1095.10 and wage &lt;= 1945.38:
result = -9.30
elif wage &gt;= 1945.39 and wage &lt;= 2190.18:
result = -min(max((wage - 1945.38) * 0.076, 9.30), 18.60)
elif wage &gt;= 2190.19 and wage &lt;= 6038.82:
result = -min(18.60 + (wage - 2190.18) * 0.011, 51.64)
else:
result = -51.64
</field>
</record>
<record id="hr_payroll_rules_bareme" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">B.I.</field>
<field name="amount_select">fix</field>
<field name="code">P.P</field>
<field name="sequence">120</field>
<field name="condition_select">python</field>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_python">result = (((employee.marital in ['divorced', 'single', 'widower']) or (employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income')) and (employee.resident_bool!=True))</field>
</record>
<record id="hr_payroll_rules_baremeII" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">B.II</field>
<field name="amount_select">fix</field>
<field name="sequence">120</field>
<field name="condition_select">python</field>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_python">result = ((employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='without income') and (employee.resident_bool!=True))</field>
</record>
<record id="hr_payroll_rules_baremeIII" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">B.III</field>
<field name="amount_select">fix</field>
<field name="sequence">120</field>
<field name="condition_select">python</field>
<field name="condition_python">result = employee.resident_bool==True</field>
<field name="appears_on_payslip" eval="False"/>
</record>
<record id="hr_salary_rule_pp_reduction_employees" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_pp_reductions"/>
<field name="name">Withholding Tax Reduction for Low Salaries (ONSS)</field>
<field name="code">PPRed.1</field>
<field name="sequence">132</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT &lt;= 2431.27</field>
<field name="condition_select">none</field>
<field name="appears_on_payslip" eval="True"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">
salary = categories.BRUT
percentage = 0.2803
if salary &lt;= 1577.89:
result = 193.79 * percentage
elif salary &lt;= 2461.27:
result = (193.79 - (0.2194 * (salary - 1577.89))) * percentage
</field>
</record>
<record id="hr_salary_rule_pp_reduction_workers" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_pp_reductions"/>
<field name="name">Withholding Tax Reduction for Low Salaries (ONSS)</field>
<field name="code">PPRed.2</field>
<field name="sequence">133</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT &lt;= 2431.27</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
salary = categories.BRUT
percentage = 0.2803
if salary &lt;= 1577.89:
result = 209.29 * percentage
elif salary &lt;= 2461.27:
result = (209.29 - (0.2369 * (salary - 1577.89))) * percentage
</field>
</record>
<record id="hr_payroll_rules_child_alw" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_child_alw"/>
<field name="name">Child Allowance Belgium</field>
<field name="code">Child.Allowance</field>
<field name="sequence">140</field>
<field name="amount_select">fix</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(employee.dependent_children) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
</record>
<record id="hr_payroll_rules_child" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_child_alw"/>
<field name="parent_rule_id" ref="hr_payroll_rules_child_alw"/>
<field name="name">Child Allowance Belgium</field>
<field name="code">Ch.A</field>
<field name="amount_select">fix</field>
<field name="sequence">141</field>
<field name="note">The recipient of income is an isolated or spouse beneficiary's income has also
earned income (Schedule I / II scale)
def compute_basic_bareme(value):
if value &lt;= 12600.0:
basic_bareme = value * 0.2675
elif value &lt;= 18610.0:
basic_bareme = 3370.5 + 0.428 * (value - 12600.0)
elif value &lt;= 39660.0:
basic_bareme = 5942.78 + 0.4815 * (value - 18610.0)
else:
basic_bareme = 16078.36 + 0.535 * (value - 39660.0)
return float_round(basic_bareme, precision_rounding=0.01)
A. When the gross monthly earnings do not exceed € 7,500, the withholding tax is determined according to the Schedule I.
The following reductions are then deducted from the payroll tax determined in accordance with this schedule:
def convert_to_month(value):
return float_round(value / 12.0, precision_rounding=0.01, rounding_method='DOWN')
a) Reduction for dependent children</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(employee.dependent_children) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
</record>
<record id="hr_salary_rule_other_family_charges_reductions" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_category_family_reductions"/>
<field name="name">Other family charges reductions</field>
<field name="code">Oth.Fam.Red</field>
<field name="sequence">143</field>
<field name="amount_select">fix</field>
<field name="condition_select">python</field>
<field name="condition_python">result = True</field>
</record>
<record id="hr_salary_rule_reduction_isolated" model="hr.salary.rule">
<field name="category_id" ref='hr_salary_rule_category_family_reductions'/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Reduction for isolated people</field>
<field name="code">Red.Iso</field>
<field name="sequence">144</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.marital in ['divorced', 'single', 'widower']) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = min(25.00, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
</record>
<record id="hr_salary_rule_reduction_isolated_parent" model="hr.salary.rule">
<field name="category_id" ref='hr_salary_rule_category_family_reductions'/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Reduction for isolated parent</field>
<field name="code">Red.Iso.Par</field>
<field name="sequence">144</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.marital == 'widower' or (employee.marital in ['divorced', 'single', 'widower'] and employee.dependent_children)) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = min(36.00, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
</record>
<record id="hr_salary_rule_reduction_disabled" model="hr.salary.rule">
<field name="category_id" ref='hr_salary_rule_category_family_reductions'/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Reduction for disabled employee</field>
<field name="code">Red.Dis</field>
<field name="sequence">145</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.disabled) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = min(36.00, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
</record>
<record id="hr_salary_rule_reduction_seniors" model="hr.salary.rule">
<field name="category_id" ref='hr_salary_rule_category_family_reductions'/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Reduction for dependent seniors</field>
<field name="code">Red.Seniors</field>
<field name="sequence">146</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.other_dependent_people and employee.dependent_seniors) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = min(73.0 * employee.dependent_seniors, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
</record>
<record id="hr_salary_rule_reduction_juniors" model="hr.salary.rule">
<field name="category_id" ref='hr_salary_rule_category_family_reductions'/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Reduction for dependent juniors</field>
<field name="code">Red.Juniors</field>
<field name="sequence">147</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.other_dependent_people and employee.dependent_juniors) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = min(36.0 * employee.dependent_juniors, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
</record>
<record id="hr_salary_rule_reduction_insufficient_net" model="hr.salary.rule">
<field name="category_id" ref='hr_salary_rule_category_family_reductions'/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Reduction for low spouse revenue</field>
<field name="code">Red.Spouse.Net</field>
<field name="sequence">148</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income' and employee.spouse_net_revenue &lt;= 225.0) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = min(110.50, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
</record>
<record id="hr_salary_rule_reduction_insufficient_other_net" model="hr.salary.rule">
<field name="category_id" ref='hr_salary_rule_category_family_reductions'/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Reduction for low spouse other revenue</field>
<field name="code">Red.Spouse.Oth.Net</field>
<field name="sequence">149</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income' and not employee.spouse_net_revenue and employee.spouse_other_net_revenue &lt;= 450.0) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = min(220.0, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
</record>
<record id="hr_payroll_rules_spouse_handicap" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="parent_rule_id" ref="hr_salary_rule_other_family_charges_reductions"/>
<field name="name">Disabled Spouse Allowance</field>
<field name="code">Sp.handicap</field>
<field name="sequence">150</field>
<field name="condition_select">python</field>
<field name="condition_python">result = (employee.disabled_spouse_bool==True) and (categories.PP + categories.PPRed + categories.FamRed + categories.ChA &lt; 0.0)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">min(36.0, - (categories.PP + categories.PPRed + categories.FamRed + categories.ChA))</field>
# PART 1: Withholding tax amount computation
withholding_tax_amount = 0.0
lower_bound = categories.GROSS - categories.GROSS % 15
# yearly_gross_revenue = Revenu Annuel Brut
yearly_gross_revenue = lower_bound * 12.0
# yearly_net_taxable_amount = Revenu Annuel Net Imposable
if yearly_gross_revenue &lt;= 15733.33:
yearly_net_taxable_revenue = yearly_gross_revenue * (1.0 - 0.3)
else:
yearly_net_taxable_revenue = yearly_gross_revenue - 4720.0
# BAREME III: Non resident
if employee.resident_bool:
basic_bareme = compute_basic_bareme(yearly_net_taxable_revenue)
withholding_tax_amount = convert_to_month(basic_bareme)
else:
# BAREME I: Isolated or spouse with income
if employee.marital in ['divorced', 'single', 'widower'] or (employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income'):
basic_bareme = max(compute_basic_bareme(yearly_net_taxable_revenue) - 1690.6, 0.0)
withholding_tax_amount = convert_to_month(basic_bareme)
# BAREME II: spouse without income
if employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='without income':
yearly_net_taxable_revenue_for_spouse = min(yearly_net_taxable_revenue * 0.3, 10710.0)
basic_bareme_1 = compute_basic_bareme(yearly_net_taxable_revenue_for_spouse)
basic_bareme_2 = compute_basic_bareme(yearly_net_taxable_revenue - yearly_net_taxable_revenue_for_spouse)
withholding_tax_amount = convert_to_month(max(basic_bareme_1 + basic_bareme_2 - 3381.2, 0))
# Reduction for isolated people and for other family charges
if employee.marital in ['divorced', 'single', 'widower'] or (employee.spouse_net_revenue &gt; 0.0 or employee.spouse_other_net_revenue &gt; 0.0):
if employee.marital in ['divorced', 'single', 'widower']:
withholding_tax_amount -= 25.0
if employee.marital == 'widower' or (employee.marital in ['divorced', 'single', 'widower'] and employee.dependent_children):
withholding_tax_amount -= 36.0
if employee.disabled:
withholding_tax_amount -= 36.0
if employee.other_dependent_people and employee.dependent_seniors:
withholding_tax_amount -= 73.0 * employee.dependent_seniors
if employee.other_dependent_people and employee.dependent_juniors:
withholding_tax_amount -= 36.0 * employee.dependent_juniors
if employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income' and employee.spouse_net_revenue &lt;= 225.0:
withholding_tax_amount -= 112.5
if employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='with income' and not employee.spouse_net_revenue and employee.spouse_other_net_revenue &lt;= 450.0:
withholding_tax_amount -= 225.0
if employee.spouse_net_revenue == 0.0 and employee.spouse_other_net_revenue == 0.0:
if employee.disabled:
withholding_tax_amount -= 36.0
if employee.disabled_spouse_bool:
withholding_tax_amount -= 36.0
if employee.other_dependent_people and employee.dependent_seniors:
withholding_tax_amount -= 73.0 * employee.dependent_seniors
if employee.other_dependent_people and employee.dependent_juniors:
withholding_tax_amount -= 36.0 * employee.dependent_juniors
# Child Allowances
if employee.dependent_children:
if employee.dependent_children == 1:
withholding_tax_amount -= 36.0
if employee.dependent_children == 2:
withholding_tax_amount -= 97.0
if employee.dependent_children == 3:
withholding_tax_amount -= 253.0
if employee.dependent_children == 4:
withholding_tax_amount -= 454.0
if employee.dependent_children == 5:
withholding_tax_amount -= 677.0
if employee.dependent_children == 6:
withholding_tax_amount -= 902.0
if employee.dependent_children == 7:
withholding_tax_amount -= 1128.0
if employee.dependent_children &gt;= 8:
withholding_tax_amount -= 1371.0 + (employee.dependent_children - 8) * 251.0
result = - max(withholding_tax_amount, 0.0)
</field>
</record>
<record id="hr_payroll_rules_parent_company_car" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
@@ -594,7 +487,7 @@ result = -min(ip_amount * tax_rate, 11745)
<field name="amount_python_compute">result = -contract.retained_net_amount</field>
</record>
<record id="hr_payroll_salary_structure_employee" model="hr.payroll.structure">
<field name="code">C.P.218</field>
<field name="code">CP 200</field>
<field name="name">Belgian Employee</field>
<field eval="[(6, 0, [
ref('hr_payroll_rules_parent_company_car'),
@@ -607,18 +500,12 @@ result = -min(ip_amount * tax_rate, 11745)
ref('hr_salary_rule_employment_bonus_employees'),
ref('hr_payroll_rules_employee'),
ref('hr_payroll_rules_bareme'),
ref('hr_payroll_rules_baremeII'),
ref('hr_payroll_rules_baremeIII'),
ref('hr_salary_rule_other_family_charges_reductions'),
ref('hr_payroll_rules_child_alw'),
ref('hr_payroll_rules_ch_worker'),
ref('hr_payroll_rules_reim_travel'),
ref('hr_payroll_rules_mis_ex_onss_1'),
ref('hr_payroll_rules_mis_ex_onss_2'),
ref('hr_payroll_rules_mis_ex_onss'),
ref('hr_salary_rule_representation_fees'),
ref('hr_payroll_rules_suppl_net'),
ref('hr_payroll_rules_retained_net'),
ref('hr_salary_rule_pp_reduction_employees'),
ref('hr_salary_rule_ip'),
ref('hr_salary_rule_ip_deduction'),
ref('hr_salary_rule_ip_part'),
@@ -635,80 +522,25 @@ result = -min(ip_amount * tax_rate, 11745)
ref('hr_payroll_rules_onss_rule'),
ref('hr_salary_rule_employment_bonus_workers'),
ref('hr_payroll_rules_bareme'),
ref('hr_payroll_rules_baremeII'),
ref('hr_payroll_rules_baremeIII'),
ref('hr_payroll_rules_child_alw'),
ref('hr_salary_rule_other_family_charges_reductions'),
ref('hr_payroll_rules_ch_worker'),
ref('hr_payroll_rules_reim_travel'),
ref('hr_payroll_rules_mis_ex_onss_1'),
ref('hr_payroll_rules_mis_ex_onss_2'),
ref('hr_payroll_rules_mis_ex_onss'),
ref('hr_salary_rule_representation_fees'),
ref('hr_payroll_rules_suppl_net'),
ref('hr_payroll_rules_retained_net'),
ref('hr_salary_rule_pp_reduction_workers')
])]" name="rule_ids"/>
<field name="company_id" ref="base.main_company"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
</record>
<!-- Salary advantages definition -->
<record id="hr_contract_advantage_template_meal_voucher_amount" model="hr.contract.advantage.template">
<field name="name">Check Value Meal</field>
<field name="code">meal_voucher_amount</field>
<field name="default_value">7.45</field>
</record>
<record id="hr_contract_advantage_template_internet" model="hr.contract.advantage.template">
<field name="name">Internet</field>
<field name="code">internet</field>
<field name="default_value">38.0</field>
</record>
<record id="hr_contract_advantage_template_mobile" model="hr.contract.advantage.template">
<field name="name">Mobile</field>
<field name="code">mobile</field>
<field name="default_value">30.0</field>
</record>
<record id="hr_contract_advantage_template_mobile_plus" model="hr.contract.advantage.template">
<field name="name">Mobile +</field>
<field name="code">mobile_plus</field>
<field name="default_value">50.0</field>
</record>
<record id="hr_contract_advantage_template_additional_net_amount" model="hr.contract.advantage.template">
<field name="name">Net supplements</field>
<field name="code">additional_net_amount</field>
</record>
<record id="hr_contract_advantage_template_retained_net_amount" model="hr.contract.advantage.template">
<field name="name">Net retained</field>
<field name="code">retained_net_amount</field>
</record>
<record id="hr_contract_advantage_template_commission_on_target" model="hr.contract.advantage.template">
<field name="name">Commission on target</field>
<field name="code">commission_on_target</field>
<field name="default_value">0.0</field>
</record>
<record id="hr_contract_advantage_template_fuel_card" model="hr.contract.advantage.template">
<field name="name">Fuel card</field>
<field name="code">fuel_card</field>
<field name="default_value">150.0</field>
<field name="lower_bound">0.0</field>
<field name="upper_bound">500.0</field>
</record>
<record id="hr_contract_advantage_template_holidays" model="hr.contract.advantage.template">
<field name="name">Leaves duration</field>
<field name="code">holidays</field>
<field name="default_value">20.0</field>
<field name="lower_bound">0.0</field>
<field name="upper_bound">35.0</field>
</record>
<record id="hr_contract_advantage_template_representation_fees" model="hr.contract.advantage.template">
<field name="name">Representation fees</field>
<field name="code">representation_fees</field>
<field name="default_value">150.0</field>
</record>
<record id="hr_contract_advantage_template_eco_checks" model="hr.contract.advantage.template">
<field name="name">Eco-checks</field>
<field name="code">eco_checks</field>
<field name="default_value">250.0</field>
</record>
<!-- Default advantage values -->
<function model="ir.default" name="set" eval="('hr.contract', 'holidays', 20.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'commission_on_target', 0.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'fuel_card', 150.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'representation_fees', 150.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'internet', 38.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'mobile', 30.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'mobile_plus', 50.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'meal_voucher_amount', 7.45)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'eco_checks', 250.0)"/>
</odoo>
@@ -2,3 +2,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import l10n_be_hr_payroll
from . import res_config_settings
@@ -41,35 +41,27 @@ class HrContract(models.Model):
# Advantages
commission_on_target = fields.Monetary(string="Commission on Target",
default=lambda self: self.get_attribute('commission_on_target', 'default_value'),
track_visibility="onchange",
help="Monthly gross amount that the employee receives if the target is reached.")
fuel_card = fields.Monetary(string="Fuel Card",
default=lambda self: self.get_attribute('fuel_card', 'default_value'),
track_visibility="onchange",
help="Monthly amount the employee receives on his fuel card.")
internet = fields.Monetary(string="Internet",
default=lambda self: self.get_attribute('internet', 'default_value'),
track_visibility="onchange",
help="The employee's internet subcription will be paid up to this amount.")
representation_fees = fields.Monetary(string="Representation Fees",
default=lambda self: self.get_attribute('representation_fees', 'default_value'),
track_visibility="onchange",
help="Monthly net amount the employee receives to cover his representation fees.")
mobile = fields.Monetary(string="Mobile",
default=lambda self: self.get_attribute('mobile', 'default_value'),
track_visibility="onchange",
help="The employee's mobile subscription will be paid up to this amount.")
mobile_plus = fields.Monetary(string="International Communication",
default=lambda self: self.get_attribute('mobile_plus', 'default_value'),
track_visibility="onchange",
help="The employee's mobile subscription for international communication will be paid up to this amount.")
meal_voucher_amount = fields.Monetary(string="Meal Vouchers",
default=lambda self: self.get_attribute('meal_voucher_amount', 'default_value'),
track_visibility="onchange",
help="Amount the employee receives in the form of meal vouchers per worked day.")
holidays = fields.Float(string='Legal Leaves',
default=lambda self: self.get_attribute('holidays', 'default_value'),
help="Number of days of paid leaves the employee gets per year.")
holidays_editable = fields.Boolean(string="Editable Leaves", default=True)
holidays_compensation = fields.Monetary(compute='_compute_holidays_compensation', string="Holidays Compensation")
@@ -82,7 +74,6 @@ class HrContract(models.Model):
track_visibility="onchange",
help="Monthly net amount that is retained on the employee's salary.")
eco_checks = fields.Monetary("Eco Vouchers",
default=lambda self: self.get_attribute('eco_checks', 'default_value'),
help="Yearly amount the employee receives in the form of eco vouchers.")
ip = fields.Boolean(default=False, track_visibility="onchange")
ip_wage_rate = fields.Float(string="IP percentage", help="Should be between 0 and 100 %")
@@ -227,19 +218,12 @@ class HrContract(models.Model):
if self.mobile_plus and not self.mobile:
raise ValidationError(_('You should have a mobile subscription to select an international communication amount.'))
def _get_internet_amount(self, has_internet):
if has_internet:
return self.get_attribute('internet', 'default_value')
else:
return 0.0
def _get_mobile_amount(self, has_mobile, international_communication):
if has_mobile and international_communication:
return self.get_attribute('mobile', 'default_value') + self.get_attribute('mobile_plus', 'default_value')
elif has_mobile:
return self.get_attribute('mobile', 'default_value')
else:
return 0.0
return self.env['ir.default'].sudo().get('hr.contract', 'mobile') + self.env['ir.default'].sudo().get('hr.contract', 'mobile_plus')
if has_mobile:
return self.env['ir.default'].sudo().get('hr.contract', 'mobile')
return 0.0
def _get_gross_from_employer_costs(self, yearly_cost):
contract = self
@@ -0,0 +1,17 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
default_holidays = fields.Float(string="Legal Leaves", default_model="hr.contract")
default_commission_on_target = fields.Float(string="Commission on Target", default_model="hr.contract")
default_fuel_card = fields.Float(string="Fuel Card", default_model="hr.contract")
default_representation_fees = fields.Float(string="Representation Fees", default_model="hr.contract")
default_internet = fields.Float(string="Internet", default_model="hr.contract")
default_mobile = fields.Float(string="Mobile", default_model="hr.contract")
default_mobile_plus = fields.Float(string="International Communication", default_model="hr.contract")
default_meal_voucher_amount = fields.Float(string="Meal Vouchers", default_model="hr.contract")
default_eco_checks = fields.Float(string="Eco Vouchers", default_model="hr.contract")
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_config_settings_view_form" model="ir.ui.view">
<field name="name">res.config.settings.view.form.inherit.l10n_be_hr_payroll</field>
<field name="model">res.config.settings</field>
<field name="priority" eval="45"/>
<field name="inherit_id" ref="hr_payroll.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='hr_payroll_accountant']" position="after">
<h2>Belgian Locatization</h2>
<div class="row mt16 o_settings_container" id="l10n_be_hr_payroll">
<div class="col-lg-6 col-12 o_setting_box">
<div class="o_setting_left_pane"/>
<div class="o_setting_right_pane">
<label for="default_holidays" string="Advantages"/>
<div class="text-muted">
Configure Default Values for Belgian Advantages
</div>
<group class="mt16">
<label for="default_holidays"/>
<div class="o_row">
<field name="default_holidays" nolabel="1"/>
<span>days / year</span>
</div>
<label for="default_commission_on_target"/>
<div class="o_row">
<field name="default_commission_on_target" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_fuel_card"/>
<div class="o_row">
<field name="default_fuel_card" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_representation_fees"/>
<div class="o_row">
<field name="default_representation_fees" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_internet"/>
<div class="o_row">
<field name="default_internet" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_mobile"/>
<div class="o_row">
<field name="default_mobile" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_internet"/>
<div class="o_row">
<field name="default_internet" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_mobile_plus"/>
<div class="o_row">
<field name="default_mobile_plus" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_meal_voucher_amount"/>
<div class="o_row">
<field name="default_meal_voucher_amount" nolabel="1"/>
<span>€ / month</span>
</div>
<label for="default_eco_checks"/>
<div class="o_row">
<field name="default_eco_checks" nolabel="1"/>
<span>€ / year</span>
</div>
</group>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>
@@ -4,7 +4,7 @@
{
'name': 'Belgium - Payroll with Accounting',
'category': 'Human Resources',
'depends': ['l10n_be_hr_payroll', 'hr_payroll_account', 'l10n_be'],
'depends': ['l10n_be_hr_payroll', 'hr_payroll_account'],
'description': """
Accounting Data for Belgian Payroll Rules.
==========================================
+1 -1
View File
@@ -3,7 +3,7 @@
{
'name': 'French Payroll',
'category': 'Human Resources',
'category': 'Payroll Localization',
'author': 'Yannick Buron (SYNERPGY)',
'depends': ['hr_payroll', 'l10n_fr'],
'description': """
+2 -2
View File
@@ -3,8 +3,8 @@
{
'name': 'Indian Payroll',
'category': 'Human Resources',
'depends': ['hr_payroll'],
'category': 'Payroll Localization',
'depends': ['hr_payroll', 'l10n_in'],
'description': """
Indian Payroll Salary Rules.
============================
@@ -12,6 +12,11 @@
<field name="visible" eval="0" />
</record>
<record model="ir.module.category" id="module_category_payroll_localization">
<field name="name">Payroll Localization</field>
<field name="visible" eval="0" />
</record>
<record model="ir.module.category" id="module_category_localization_account_charts">
<field name="parent_id" ref="module_category_localization" />
<field name="name">Account Charts</field>