[REF] hr_payroll: Remove parent_id hierarchy + Add structures categorization

1/ Remove the parent-children relation on salary structures

Currently it is difficult to see what rules are applied on salary structures.

Most of the structures are inheriting 3 rules (Basic, Gross, Net) from the
'Base for new structures', and those rules are not shown. Same issue if a
structure has another one as parent (as in the French localization).

This bring more annoying issues:

- Since the saas-12.1, we can already set different accounts for different
  companies on the salary rules for which we want to post journal entries.
  But for the parent rules, like the 'NET' amount, it's impossible to post
  the journal entries on different account for different salary structures.
  (eg: for CP200 employees and CP200 workers). As the rules are following
  a M2M relation on the structure, we have to remove the parent_id and to
  recreate all the rules in the final structure.
- If we are not at ease with the M2M relation (which is the case for most
  of the end users), we will simply modify the rule on the parent structure.
  This was already done on the French localization on which we modified the
  code, sequence and the name. This could have some desastrous consequences
  as this will break the order on which the rules are computed for other
  structures for the sequence, or break other integration with the payroll
  as we also modify the code, for example the salary configurator.

As this parent-children relation on structure could cause several issues
difficult to spot and as this is quite difficult to correctly visualize the
structure composition, it is better to remove it and define all the rules
inside the structure itself. This improves also the code readability as we
are not trying to recursively retrieve the rules and find a proper sequence
inside them.

2/ Make the rules on the salary structure a o2m instead of a m2m

The issues described just above indicates that it would be better to remove
the M2M relation between salary structures and salary rules, and make it
a O2M relation instead. That way, no more confusion and misconfiguration of
the rules fields (code, sequence, accounts, ...).

3/ Remove the parent-children relation on rules

A salary rule can have a parent salary rule. This mechanism, which is
not obvious at all for an end user allows to specify a parent rules.
If the condition is met for the parent rule (eg: the employee has at least
1 child), all the children rules could be applied (eg: Deduction of 90 euros
if the number of children is between 1 and 1).

Visually it doesn't make a lot of sense, as it displays one line with an
amount of 0 for the parent, and one line with the real amount for each
applied child. On the other hand, no child rule is linked to the structure
and an end user has to click on the parent rule, to see the children and
understand that something mystic and hidden is existing.

This is equivalent to define as many classic rules as we have children, or
even better, define 1 rule that will compute the real amount directly,
as the number of children can be accessed from the localdict when computing
the salary line.

This commit also removed the relation.

4/ Clean some brols in the code (technical)

The 3 first points of the spec allow us to clean a little the code readability
and complexity.

5/ Adapt all the localizations for these changes

All the localizations are impacted by those changes. What is done in this commit
is mainly:

- l10n_be_hr_payroll: Make 3 separated files for the 3 existing structures (the
  fourth one, belgian worker, is not correct and is removed). For each
  structure, define explicitely the rules (in the correct order by sequence).
  This multiplies the total number of rules as some of them were shared (like
  the withholding tax rule for example), but all the code that is supposed to be
  modified each year/quarter/whenever the government decides to modify the law
  has been moved into a python file, and is available the computation context.
  This will also allow us to update the computation rules without having to
  update the module.
- l10n_fr_hr_payroll: There were 3 rules following this scheme:
                              Base for new structure
                                        |
                                 Basic structure
                                        |
                              ----------------------
                              |                    |
                           Cadre                Non-Cadre
  All the rules parent rules have been duplicated into the 2 remaining
  structures, cadre and non-cadre. There were a lot of parent-children relations
  between the rules that have been adapted to the new model.
- l10n_in_hr_payroll: There was a lot of rules in data, and a structure in demo
  data, which was using 4 or 5 of these rules. As the rules doesn't seem to make
  a lot of sense altogether, everything was moved in demo data.

6/ Introduce a new Salary Structure Type model

Currently we have a model hr.contract.type with a M2O on the contracts. This has
never been used in 9 years and is removed in this commit. On the other hand, we
would like to define a new model hr.payroll.structure.type (eg: CP200 Employee),
which will line all the salary structures the Belgian localization could bring
(Classic salary, double holidays, 13th month, ...). This field is defined on the
structure, and is displayed on the contract (as the same place than the contract
type we just removed).

On this model we could also define some fields like:
- The default pay period: Selection field, default = monthly. This is applied on
  the contract when selecting the structure.
- The Working Schedule, m2o. This is applied on the contract when selecting the
  structure

For example, on the 'commission paritaire' for teachers, we could set the
default pay period to 'Every 15 days' and the working schedule to '19 hours /
week'. Every contract under this structure would take those values.

Migration
=========

For a migration point of view:
- All the rules that had a parent_rule_id should be set to
  appears_on_payslip=False. The column parent_rule_id can be dropped afterward.
- All the rules that are coming from a parent structure or higher should be
  duplicated and the field 'struct_id' should be set on the current structure.
  The column parent_id can be dropped afterward.
- All the rules that were defined on the structure should have the field
  'struct_id' defined on them.
- The rules that are not linked to a structure should be unlinked.
- The column type_id on the contract could be dropped, no need to keep the
  values too.
- A default structure type is defined in data ('Employee'). This could be set to
  all the existing structure for the newly created 'type_id' field.

TaskID: 1942832
This commit is contained in:
Yannick Tivisse
2019-03-19 09:24:23 +01:00
parent edd659f9da
commit b631280999
41 changed files with 3343 additions and 2727 deletions
@@ -2,22 +2,6 @@
<odoo>
<data noupdate="1">
<!-- Contract Types -->
<record id="hr_contract_type_emp" model="hr.contract.type">
<field name="name">Employee</field>
<field name="sequence">5</field>
</record>
<record id="hr_contract_type_wrkr" model="hr.contract.type">
<field name="name">Worker</field>
<field name="sequence">10</field>
</record>
<record id="hr_contract_type_sub" model="hr.contract.type">
<field name="name">Subcontractor</field>
<field name="sequence">15</field>
</record>
<!-- Contract-related subtypes for messaging / Chatter -->
<record id="mt_contract_pending" model="mail.message.subtype">
<field name="name">To Renew</field>
@@ -3,7 +3,6 @@
<record id="hr_contract_admin" model="hr.contract">
<field name="name">Mitchell Admin Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y')+'-1-1'"/>
<field name="employee_id" ref="hr.employee_admin"/>
<field name="job_id" model="hr.job"
@@ -16,7 +15,6 @@
<record id="hr_contract_al" model="hr.contract">
<field name="name">Ronnie Hart Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y')+'-1-1'"/>
<field name="employee_id" ref="hr.employee_al"/>
<field name="job_id" model="hr.job"
@@ -29,7 +27,6 @@
<record id="hr_contract_mit" model="hr.contract">
<field name="name">Marketing Executive Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y')+'-3-1'"/>
<field name="employee_id" ref="hr.employee_mit"/>
<field name="job_id" model="hr.job"
@@ -42,7 +39,6 @@
<record id="hr_contract_stw" model="hr.contract">
<field name="name">Randall Lewis Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y')+'-2-1'"/>
<field name="date_end" eval="time.strftime('%Y')+'-12-1'"/>
<field name="employee_id" ref="hr.employee_stw"/>
@@ -56,7 +52,6 @@
<record id="hr_contract_qdp" model="hr.contract">
<field name="name">Demo Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y')+'-3-1'"/>
<field name="employee_id" ref="hr.employee_qdp"/>
<field name="job_id" model="hr.job"
@@ -69,7 +64,6 @@
<record id="hr_contract_han" model="hr.contract">
<field name="name">Walter Horton Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y')+'-3-1'"/>
<field name="employee_id" ref="hr.employee_han"/>
<field name="job_id" model="hr.job"
@@ -82,7 +76,6 @@
<record id="hr_contract_niv" model="hr.contract">
<field name="name">Sharlene Rhodes Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y-%m')+'-1'"/>
<field name="date_end" eval="time.strftime('%Y')+'-12-1'"/>
<field name="employee_id" ref="hr.employee_niv"/>
@@ -96,7 +89,6 @@
<record id="hr_contract_jth" model="hr.contract">
<field name="name">Toni Jimenez</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y-%m')+'-1'"/>
<field name="date_end" eval="time.strftime('%Y')+'-12-1'"/>
<field name="employee_id" ref="hr.employee_jth"/>
@@ -110,7 +102,6 @@
<record id="hr_contract_chs" model="hr.contract">
<field name="name">Jennie Fletcher Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y-%m')+'-1'"/>
<field name="employee_id" ref="hr.employee_chs"/>
<field name="job_id" model="hr.job"
@@ -123,7 +114,6 @@
<record id="hr_contract_jve" model="hr.contract">
<field name="name">Paul Williams Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y-%m')+'-1'"/>
<field name="employee_id" ref="hr.employee_jve"/>
<field name="job_id" model="hr.job"
@@ -136,7 +126,6 @@
<record id="hr_contract_fme" model="hr.contract">
<field name="name">Keith Byrd Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="'2015-1-1'"/>
<field name="date_end" eval="time.strftime('%Y-%m-%d')"/>
<field name="employee_id" ref="hr.employee_fme"/>
@@ -150,7 +139,6 @@
<record id="hr_contract_fpi" model="hr.contract">
<field name="name">Audrey Peterson Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="'2015-1-1'"/>
<field name="date_end" eval="'2017-12-1'"/>
<field name="employee_id" ref="hr.employee_fpi"/>
@@ -164,7 +152,6 @@
<record id="hr_contract_vad" model="hr.contract">
<field name="name">Tina Williamson Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="'2015-1-1'"/>
<field name="date_end" eval="'2018-2-1'"/>
<field name="employee_id" ref="hr.employee_vad"/>
-12
View File
@@ -48,18 +48,7 @@ class Employee(models.Model):
return self.search([])._get_contracts(date_from, date_to, states=states)
class ContractType(models.Model):
_name = 'hr.contract.type'
_description = 'Contract Type'
_order = 'sequence, id'
name = fields.Char(string='Contract Type', required=True)
sequence = fields.Integer(help="Gives the sequence when displaying a list of Contract.", default=10)
class Contract(models.Model):
_name = 'hr.contract'
_description = 'Contract'
_inherit = ['mail.thread', 'mail.activity.mixin']
@@ -68,7 +57,6 @@ class Contract(models.Model):
active = fields.Boolean(default=True)
employee_id = fields.Many2one('hr.employee', string='Employee')
department_id = fields.Many2one('hr.department', string="Department")
type_id = fields.Many2one('hr.contract.type', string="Employee Category", required=True, default=lambda self: self.env['hr.contract.type'].search([], limit=1))
job_id = fields.Many2one('hr.job', string='Job Position')
date_start = fields.Date('Start Date', required=True, default=fields.Date.today,
help="Start date of the contract.")
@@ -2,5 +2,4 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_hr_resource_manager,hr.employee.resource.manager,resource.model_resource_resource,hr.group_hr_manager,1,1,1,1
access_hr_resource_calendar_user,hr.employee.resource.calendar.user,resource.model_resource_calendar,hr.group_hr_user,1,1,1,1
access_hr_resource_calendar_attendance_user,hr.employee.resource.calendar.attendance.user,resource.model_resource_calendar_attendance,hr.group_hr_user,1,1,1,1
access_hr_contract_type_manager,hr.contract.type.manager,model_hr_contract_type,hr_contract.group_hr_contract_manager,1,1,1,1
access_hr_contract_manager,hr.contract.manager,model_hr_contract,hr_contract.group_hr_contract_manager,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_hr_resource_manager hr.employee.resource.manager resource.model_resource_resource hr.group_hr_manager 1 1 1 1
3 access_hr_resource_calendar_user hr.employee.resource.calendar.user resource.model_resource_calendar hr.group_hr_user 1 1 1 1
4 access_hr_resource_calendar_attendance_user hr.employee.resource.calendar.attendance.user resource.model_resource_calendar_attendance hr.group_hr_user 1 1 1 1
access_hr_contract_type_manager hr.contract.type.manager model_hr_contract_type hr_contract.group_hr_contract_manager 1 1 1 1
5 access_hr_contract_manager hr.contract.manager model_hr_contract hr_contract.group_hr_contract_manager 1 1 1 1
@@ -83,7 +83,6 @@
<group expand="0" string="Group By">
<filter string="Employee" name="employee" domain="[]" context="{'group_by':'employee_id'}"/>
<filter string="Job" name="job" domain="[]" context="{'group_by':'job_id'}"/>
<filter string="Employee Category" name="contract_type" domain="[]" context="{'group_by':'type_id'}"/>
<filter string="State" name='group_by_state' domain="[]" context="{'group_by': 'state'}"/>
</group>
</search>
@@ -117,7 +116,6 @@
<field name="job_id"/>
</group>
<group>
<field name="type_id"/>
<field name="reported_to_secretariat" widget="toggle_button" options='{"active": "Reported to the social secretariat", "inactive": "To report to the social secretariat"}'/>
</group>
</group>
@@ -174,7 +172,6 @@
<field name="name"/>
<field name="employee_id"/>
<field name="job_id"/>
<field name="type_id"/>
<field name="resource_calendar_id"/>
<field name="date_start"/>
<field name="date_end"/>
@@ -239,64 +236,12 @@
</field>
</record>
<record id="hr_contract_type_view_form" model="ir.ui.view">
<field name="name">hr.contract.type.form</field>
<field name="model">hr.contract.type</field>
<field name="arch" type="xml">
<form string="Contract Type">
<sheet>
<group>
<field name="name"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="hr_contract_type_view_tree" model="ir.ui.view">
<field name="name">hr.contract.type.tree</field>
<field name="model">hr.contract.type</field>
<field name="arch" type="xml">
<tree string="Contract Type">
<field name="sequence" widget="handle"/>
<field colspan="4" name="name"/>
</tree>
</field>
</record>
<record id="hr_contract_type_view_search" model="ir.ui.view">
<field name="name">hr.contract.type.search</field>
<field name="model">hr.contract.type</field>
<field name="arch" type="xml">
<search string="Search Contract Type">
<field name="name" string="Contract Type"/>
<field name="sequence" string="Sequence"/>
</search>
</field>
</record>
<record id="action_hr_contract_type" model="ir.actions.act_window">
<field name="name">Contract Types</field>
<field name="res_model">hr.contract.type</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="hr_contract_type_view_search"/>
</record>
<menuitem
id="menu_human_resources_configuration_contract"
name="Contracts"
parent="hr.menu_human_resources_configuration"
sequence="3"/>
<menuitem
id="hr_menu_contract_type"
name="Types"
action="action_hr_contract_type"
parent="hr_contract.menu_human_resources_configuration_contract"
sequence="3"
groups="base.group_no_one"/>
<menuitem
id="hr_menu_contract"
name="Contracts"
+4 -40
View File
@@ -2,6 +2,10 @@
<odoo>
<data noupdate="0">
<record id="structure_type_employee" model="hr.payroll.structure.type">
<field name="name">Employee</field>
</record>
<record id="resource.resource_calendar_std" model="resource.calendar">
<field name="full_time_required_hours">40</field>
</record>
@@ -49,46 +53,6 @@
<field name="code">COMP</field>
</record>
<record id="hr_rule_basic" model="hr.salary.rule">
<field name="name">Basic Salary</field>
<field name="sequence" eval="1"/>
<field name="code">BASIC</field>
<field name="category_id" ref="hr_payroll.BASIC"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.wage</field>
</record>
<record id="hr_rule_taxable" model="hr.salary.rule">
<field name="name">Gross</field>
<field name="sequence" eval="100"/>
<field name="code">GROSS</field>
<field name="category_id" ref="hr_payroll.GROSS"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC + categories.ALW</field>
</record>
<record id="hr_rule_net" model="hr.salary.rule">
<field name="name">Net Salary</field>
<field name="sequence" eval="200"/>
<field name="code">NET</field>
<field name="category_id" ref="hr_payroll.NET"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC + categories.ALW + categories.DED</field>
<field name="register_id" ref="contrib_register_employees"/>
</record>
<!-- Salary Structure -->
<record id="structure_base" model="hr.payroll.structure">
<field name="code">BASE</field>
<field name="name">Base for new structures</field>
<field eval="[(6, 0, [ref('hr_rule_basic'), ref('hr_rule_taxable'),ref('hr_rule_net')])]" name="rule_ids"/>
</record>
<!-- Decimal Precision -->
<record forcecreate="True" id="decimal_payroll" model="decimal.precision">
+34 -39
View File
@@ -19,7 +19,15 @@
<field name="name">Meal Voucher Register</field>
</record>
<!-- Salary Rules -->
<!-- Salary Structure -->
<record id="structure_002" model="hr.payroll.structure">
<field name="code">MEGG</field>
<field name="name">Marketing Executive for Gilles Gravie</field>
<field name="type_id" ref="structure_type_employee"/>
</record>
<!-- Salary Rules for Marketing Executive for Gilles Gravie-->
<record id="hr_salary_rule_houserentallowance1" model="hr.salary.rule">
<field name="amount_select">percentage</field>
@@ -30,6 +38,7 @@
<field name="register_id" ref="hr_houserent_register"/>
<field name="name">House Rent Allowance</field>
<field name="sequence" eval="5"/>
<field name="struct_id" ref="structure_002"/>
</record>
<record id="hr_salary_rule_convanceallowance1" model="hr.salary.rule">
@@ -39,36 +48,17 @@
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Conveyance Allowance</field>
<field name="sequence" eval="10"/>
</record>
<record id="hr_salary_rule_professionaltax1" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field eval="150" name="sequence"/>
<field eval="-200.0" name="amount_fix"/>
<field name="code">PT</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="register_id" ref="hr_professional_tax_register"/>
<field name="name">Professional Tax</field>
</record>
<record id="hr_salary_rule_providentfund1" model="hr.salary.rule">
<field name="amount_select">percentage</field>
<field eval="120" name="sequence"/>
<field eval="-12.5" name="amount_percentage"/>
<field name="amount_percentage_base">contract.wage</field>
<field name="code">PF</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="register_id" ref="hr_provident_fund_register"/>
<field name="name">Provident Fund</field>
<field name="struct_id" ref="structure_002"/>
</record>
<record id="hr_salary_rule_ca_gravie" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field eval="600.0" name="amount_fix"/>
<field name="amount_fix" eval="600.0"/>
<field name="code">CAGG</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Conveyance Allowance For Gravie</field>
<field name="sequence" eval="15"/>
<field name="struct_id" ref="structure_002"/>
</record>
<record id="hr_salary_rule_meal_voucher" model="hr.salary.rule">
@@ -80,22 +70,30 @@
<field name="register_id" ref="hr_meal_voucher_register"/>
<field name="name">Meal Voucher</field>
<field name="sequence" eval="16"/>
<field name="struct_id" ref="structure_002"/>
</record>
<!-- Salary Structure -->
<record id="structure_001" model="hr.payroll.structure">
<field name="code">ME</field>
<field name="name">Marketing Executive</field>
<field eval="[(6, 0, [ref('hr_salary_rule_houserentallowance1'), ref('hr_salary_rule_convanceallowance1'),ref('hr_salary_rule_professionaltax1'),ref('hr_salary_rule_providentfund1')])]" name="rule_ids"/>
<field name="parent_id" ref="structure_base"/>
<record id="hr_salary_rule_providentfund1" model="hr.salary.rule">
<field name="amount_select">percentage</field>
<field name="sequence" eval="120"/>
<field name="amount_percentage" eval="-12.5"/>
<field name="amount_percentage_base">contract.wage</field>
<field name="code">PF</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="register_id" ref="hr_provident_fund_register"/>
<field name="name">Provident Fund</field>
<field name="struct_id" ref="structure_002"/>
</record>
<record id="structure_002" model="hr.payroll.structure">
<field name="code">MEGG</field>
<field name="name">Marketing Executive for Gilles Gravie</field>
<field eval="[(6, 0, [ref('hr_salary_rule_ca_gravie'), ref('hr_salary_rule_meal_voucher')])]" name="rule_ids"/>
<field name="parent_id" ref="structure_001"/>
<record id="hr_salary_rule_professionaltax1" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field name="sequence" eval="150"/>
<field name="amount_fix" eval="-200.0"/>
<field name="code">PT</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="register_id" ref="hr_professional_tax_register"/>
<field name="name">Professional Tax</field>
<field name="struct_id" ref="structure_002"/>
</record>
<!-- Employee -->
@@ -113,10 +111,9 @@
<record id="hr_contract_firstcontract1" model="hr.contract">
<field name="name">Marketing Executive Contract</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y-%m')+'-1'"/>
<field name="date_end" eval="time.strftime('%Y')+'-12-31'"/>
<field name="struct_id" ref="hr_payroll.structure_001"/>
<field name="struct_id" ref="hr_payroll.structure_002"/>
<field name="employee_id" ref="hr_employee_payroll"/>
<field name="notes">Default contract for marketing executives</field>
<field eval="4000.0" name="wage"/>
@@ -125,7 +122,6 @@
<record id="hr_contract_gilles_gravie" model="hr.contract">
<field name="name">Contract For Gilles Gravie</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y-%m')+'-1'"/>
<field name="date_end" eval="time.strftime('%Y')+'-12-31'"/>
<field name="struct_id" ref="hr_payroll.structure_002"/>
@@ -136,7 +132,6 @@
<record id="hr_contract_admin" model="hr.contract">
<field name="name">Contract For Mitchell Admin</field>
<field name="type_id" ref="hr_contract.hr_contract_type_emp"/>
<field name="date_start" eval="time.strftime('%Y-%m')+'-1'"/>
<field name="date_end" eval="time.strftime('%Y')+'-12-31'"/>
<field name="struct_id" ref="hr_payroll.structure_002"/>
+9 -10
View File
@@ -4,11 +4,13 @@
from odoo import api, fields, models
from datetime import date
class HrContract(models.Model):
_inherit = 'hr.contract'
_description = 'Employee Contract'
struct_id = fields.Many2one('hr.payroll.structure', string='Salary Structure')
structure_type_id = fields.Many2one(related='struct_id.type_id')
schedule_pay = fields.Selection([
('monthly', 'Monthly'),
('quarterly', 'Quarterly'),
@@ -20,7 +22,6 @@ class HrContract(models.Model):
], string='Scheduled Pay', index=True, default='monthly',
help="Defines the frequency of the wage payment.")
resource_calendar_id = fields.Many2one(required=True, help="Employee's working schedule.")
hours_per_week = fields.Float(related='resource_calendar_id.hours_per_week')
full_time_required_hours = fields.Float(related='resource_calendar_id.full_time_required_hours')
is_fulltime = fields.Boolean(related='resource_calendar_id.is_fulltime')
@@ -29,6 +30,13 @@ class HrContract(models.Model):
def _check_contracts(self):
self._get_leaves()._check_contracts()
@api.onchange('struct_id')
def _onchange_struct_id(self):
if self.struct_id.type_id.default_schedule_pay:
self.schedule_pay = self.struct_id.type_id.default_schedule_pay
if self.struct_id.type_id.default_resource_calendar_id:
self.resource_calendar_id = self.struct_id.type_id.default_resource_calendar_id
@api.multi
def _get_leaves(self):
return self.env['hr.leave'].search([
@@ -36,12 +44,3 @@ class HrContract(models.Model):
('date_from', '<=', max([end or date.max for end in self.mapped('date_end')])),
('date_to', '>=', min(self.mapped('date_start'))),
])
@api.multi
def get_all_structures(self):
"""
@return: the structures linked to the given contracts, ordered by hierachy (parent=False first,
then first level children and so on) and without duplicata
"""
structures = self.mapped('struct_id')
return structures._get_parent_structure() if structures else self.env['hr.payroll.structure']
+3 -7
View File
@@ -1,11 +1,11 @@
# -*- coding:utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models, _
from odoo.addons.resource.models.resource import Intervals
from datetime import datetime, timedelta
from datetime import datetime
import pytz
from odoo import api, fields, models
class HrEmployee(models.Model):
_inherit = 'hr.employee'
@@ -13,14 +13,12 @@ class HrEmployee(models.Model):
slip_ids = fields.One2many('hr.payslip', 'employee_id', string='Payslips', readonly=True)
payslip_count = fields.Integer(compute='_compute_payslip_count', string='Payslip Count', groups="hr_payroll.group_hr_payroll_user")
registration_number = fields.Char('Registration Number of the Employee', copy=False)
_sql_constraints = [
('unique_registration_number', 'UNIQUE(registration_number, company_id)', 'No duplication of registration numbers is allowed')
]
@api.multi
def _compute_payslip_count(self):
for employee in self:
employee.payslip_count = len(employee.slip_ids)
@@ -33,7 +31,6 @@ class HrEmployee(models.Model):
('state', 'in', ['draft', 'confirmed'])
]))
@api.multi
def write(self, vals):
res = super(HrEmployee, self).write(vals)
if vals.get('contract_id'):
@@ -51,7 +48,6 @@ class HrEmployee(models.Model):
attendance_type = self.env.ref('hr_payroll.benefit_type_attendance')
vals_list = []
leaves = self.env['hr.leave']
date_start = _format_datetime(date_start)
date_stop = _format_datetime(date_stop)
+49 -71
View File
@@ -143,7 +143,7 @@ class HrPayslip(models.Model):
number = payslip.number or self.env['ir.sequence'].next_by_code('salary.slip')
# delete old payslip lines
payslip.line_ids.unlink()
lines = [(0, 0, line) for line in payslip._get_payslip_lines(payslip.contract_id)]
lines = [(0, 0, line) for line in payslip._get_payslip_lines()]
payslip.write({'line_ids': lines, 'number': number, 'state': 'verify', 'compute_date': fields.Date.today()})
return True
@@ -181,89 +181,67 @@ class HrPayslip(models.Model):
'float_round': float_round
}
# YTI TODO: pass recordset as argument
@api.model
def _get_payslip_lines(self, contracts):
# YTI TODO: Move into browsable_object.py ?
def _get_payslip_lines(self):
def _sum_salary_rule_category(localdict, category, amount):
if category.parent_id:
localdict = _sum_salary_rule_category(localdict, category.parent_id, amount)
localdict['categories'].dict[category.code] = category.code in localdict['categories'].dict and localdict['categories'].dict[category.code] + amount or amount
localdict['categories'].dict[category.code] = localdict['categories'].dict.get(category.code, 0) + amount
return localdict
self.ensure_one()
#we keep a dict with the result because a value can be overwritten by another rule with the same code
result_dict = {}
result = {}
rules_dict = {}
worked_days_dict = {}
inputs_dict = {}
blacklist = []
worked_days_dict = {line.code: line for line in self.worked_days_line_ids if line.code}
inputs_dict = {line.code: line for line in self.input_line_ids if line.code}
for code in self.worked_days_line_ids.mapped('code'):
worked_days_dict[code] = self.worked_days_line_ids.filtered(lambda l: l.code == code)
for code in self.input_line_ids.mapped('code'):
inputs_dict[code] = self.input_line_ids.filtered(lambda l: l.code == code)
employee = self.employee_id
contract = self.contract_id
categories = BrowsableObject(self.employee_id.id, {}, self.env)
inputs = InputLine(self.employee_id.id, inputs_dict, self.env)
worked_days = WorkedDays(self.employee_id.id, worked_days_dict, self.env)
payslips = Payslips(self.employee_id.id, self, self.env)
rules = BrowsableObject(self.employee_id.id, rules_dict, self.env)
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()
else:
structures = contracts.get_all_structures()
#get the rules of the structure and thier children
rule_ids = structures.get_all_rules()
#run the rules by sequence
sorted_rule_ids = [id for id, sequence in sorted(rule_ids, key=lambda x:x[1])]
sorted_rules = self.env['hr.salary.rule'].browse(sorted_rule_ids)
for contract in contracts:
employee = contract.employee_id
localdict = dict(baselocaldict, employee=employee, contract=contract)
for rule in sorted_rules:
key = rule.code + '-' + str(contract.id)
localdict['result'] = None
localdict['result_qty'] = 1.0
localdict['result_rate'] = 100
#check if the rule can be applied
if rule._satisfy_condition(localdict) and rule.id not in blacklist:
#compute the amount of the rule
amount, qty, rate = rule._compute_rule(localdict)
#check if there is already a rule computed with that code
previous_amount = rule.code in localdict and localdict[rule.code] or 0.0
#set/overwrite the amount computed for this rule in the localdict
tot_rule = amount * qty * rate / 100.0
localdict[rule.code] = tot_rule
rules_dict[rule.code] = rule
#sum the amount for its salary category
localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount)
#create/overwrite the rule in the temporary results
result_dict[key] = {
'sequence': rule.sequence,
'code': rule.code,
'name': rule.name,
'note': rule.note,
'salary_rule_id': rule.id,
'contract_id': contract.id,
'employee_id': contract.employee_id.id,
'amount': amount,
'quantity': qty,
'rate': rate,
}
else:
#blacklist this rule and its children
blacklist += [id for id, seq in rule._recursive_search_of_rules()]
return list(result_dict.values())
localdict = {
**self._get_base_local_dict(),
**{
'categories': BrowsableObject(employee.id, {}, self.env),
'rules': BrowsableObject(employee.id, rules_dict, self.env),
'payslip': Payslips(employee.id, self, self.env),
'worked_days': WorkedDays(employee.id, worked_days_dict, self.env),
'inputs': InputLine(employee.id, inputs_dict, self.env),
'employee': employee,
'contract': contract
}
}
for rule in sorted(self.struct_id.rule_ids, key=lambda x: x.sequence):
localdict.update({
'result': None,
'result_qty': 1.0,
'result_rate': 100})
if rule._satisfy_condition(localdict):
amount, qty, rate = rule._compute_rule(localdict)
#check if there is already a rule computed with that code
previous_amount = rule.code in localdict and localdict[rule.code] or 0.0
#set/overwrite the amount computed for this rule in the localdict
tot_rule = amount * qty * rate / 100.0
localdict[rule.code] = tot_rule
rules_dict[rule.code] = rule
# sum the amount for its salary category
localdict = _sum_salary_rule_category(localdict, rule.category_id, tot_rule - previous_amount)
# create/overwrite the rule in the temporary results
result[rule.code] = {
'sequence': rule.sequence,
'code': rule.code,
'name': rule.name,
'note': rule.note,
'salary_rule_id': rule.id,
'contract_id': contract.id,
'employee_id': employee.id,
'amount': amount,
'quantity': qty,
'rate': rate,
}
return result.values()
@api.onchange('employee_id', 'contract_id', 'date_from', 'date_to')
def onchange_employee(self):
if (not self.employee_id) or (not self.date_from) or (not self.date_to):
return
+64 -67
View File
@@ -8,40 +8,59 @@ from odoo.tools.safe_eval import safe_eval
from odoo.addons import decimal_precision as dp
class HrPayrollStructure(models.Model):
"""
Salary structure used to defined
- Basic
- Allowances
- Deductions
"""
_name = 'hr.payroll.structure'
_description = 'Salary Structure'
@api.model
def _get_parent(self):
return self.env.ref('hr_payroll.structure_base', False)
@api.model
def _get_default_report_id(self):
return self.env.ref('hr_payroll.action_report_payslip', False)
@api.model
def _get_default_rule_ids(self):
return [
(0, 0, {
'name': 'Basic Salary',
'sequence': 1,
'code': 'BASIC',
'category_id': self.env.ref('hr_payroll.BASIC').id,
'condition_select': 'none',
'amount_select': 'code',
'amount_python_compute': 'result = contract.wage',
}),
(0, 0, {
'name': 'Gross',
'sequence': 100,
'code': 'GROSS',
'category_id': self.env.ref('hr_payroll.GROSS').id,
'condition_select': 'none',
'amount_select': 'code',
'amount_python_compute': 'result = categories.BASIC + categories.ALW',
}),
(0, 0, {
'name': 'Net Salary',
'sequence': 200,
'code': 'NET',
'category_id': self.env.ref('hr_payroll.NET').id,
'condition_select': 'none',
'amount_select': 'code',
'amount_python_compute': 'result = categories.BASIC + categories.ALW + categories.DED',
'register_id': self.env.ref('hr_payroll.contrib_register_employees').id
})
]
name = fields.Char(required=True)
code = fields.Char(string='Reference', required=True)
type_id = fields.Many2one('hr.payroll.structure.type', default=lambda self: self.env.ref('hr_payroll.structure_type_employee', raise_if_not_found=False))
country_id = fields.Many2one('res.country', string='Country')
note = fields.Text(string='Description')
parent_id = fields.Many2one('hr.payroll.structure', string='Parent', default=_get_parent)
children_ids = fields.One2many('hr.payroll.structure', 'parent_id', string='Children', copy=True)
rule_ids = fields.Many2many('hr.salary.rule', 'hr_structure_salary_rule_rel', 'struct_id', 'rule_id', string='Salary Rules')
rule_ids = fields.One2many(
'hr.salary.rule', 'struct_id',
string='Salary Rules', default=_get_default_rule_ids)
report_id = fields.Many2one('ir.actions.report',
string="Report", required=True, domain="[('model','=','hr.payslip'),('report_type','=','qweb-pdf')]", default=_get_default_report_id)
payslip_name = fields.Char(string="Payslip Name", translate=True,
help="Name to be set on a payslip. Example: 'End of the year bonus'. If not set, the default value is 'Salary Slip'")
@api.constrains('parent_id')
def _check_parent_id(self):
if not self._check_recursion():
raise ValidationError(_('You cannot create a recursive salary structure.'))
@api.multi
@api.returns('self', lambda value: value.id)
def copy(self, default=None):
@@ -49,23 +68,24 @@ class HrPayrollStructure(models.Model):
default = dict(default or {}, code=_("%s (copy)") % (self.code))
return super(HrPayrollStructure, self).copy(default)
@api.multi
def get_all_rules(self):
"""
@return: returns a list of tuple (id, sequence) of rules that are maybe to apply
"""
all_rules = []
for struct in self:
all_rules += struct.rule_ids._recursive_search_of_rules()
return list(set(all_rules))
@api.multi
def _get_parent_structure(self):
parent = self.mapped('parent_id')
if parent:
parent = parent._get_parent_structure()
return parent | self
class HrPayrollStructureType(models.Model):
_name = 'hr.payroll.structure.type'
_description = 'Salary Structure Type'
name = fields.Char('Structure Type')
default_schedule_pay = fields.Selection([
('monthly', 'Monthly'),
('quarterly', 'Quarterly'),
('semi-annually', 'Semi-annually'),
('annually', 'Annually'),
('weekly', 'Weekly'),
('bi-weekly', 'Bi-weekly'),
('bi-monthly', 'Bi-monthly'),
], string='Default Scheduled Pay', default='monthly',
help="Defines the frequency of the wage payment.")
default_resource_calendar_id = fields.Many2one(
'resource.calendar', 'Default Working Hours')
class HrContributionRegister(models.Model):
_name = 'hr.contribution.register'
@@ -104,6 +124,7 @@ class HrSalaryRule(models.Model):
code = fields.Char(required=True,
help="The code of salary rules can be used as reference in computation of other rules. "
"In that case, it is case sensitive.")
struct_id = fields.Many2one('hr.payroll.structure', string="Salary Structure")
sequence = fields.Integer(required=True, index=True, default=5,
help='Use to arrange calculation sequence')
quantity = fields.Char(default='1.0',
@@ -116,7 +137,6 @@ class HrSalaryRule(models.Model):
help="If the active field is set to false, it will allow you to hide the salary rule without removing it.")
appears_on_payslip = fields.Boolean(string='Appears on Payslip', default=True,
help="Used to display the salary rule on payslip.")
parent_rule_id = fields.Many2one('hr.salary.rule', string='Parent Salary Rule', index=True)
condition_select = fields.Selection([
('none', 'Always True'),
('range', 'Range'),
@@ -168,74 +188,51 @@ class HrSalaryRule(models.Model):
result = contract.wage * 0.10''')
amount_percentage_base = fields.Char(string='Percentage based on', help='result will be affected to a variable')
child_ids = fields.One2many('hr.salary.rule', 'parent_rule_id', string='Child Salary Rule', copy=True)
register_id = fields.Many2one('hr.contribution.register', string='Contribution Register',
help="Eventual third party involved in the salary payment of the employees.")
note = fields.Text(string='Description')
@api.constrains('parent_rule_id')
def _check_parent_rule_id(self):
if not self._check_recursion(parent='parent_rule_id'):
raise ValidationError(_('Error! You cannot create recursive hierarchy of Salary Rules.'))
@api.multi
def _recursive_search_of_rules(self):
"""
@return: returns a list of tuple (id, sequence) which are all the children of the passed rule_ids
"""
children_rules = []
for rule in self.filtered(lambda rule: rule.child_ids):
children_rules += rule.child_ids._recursive_search_of_rules()
return [(rule.id, rule.sequence) for rule in self] + children_rules
#TODO should add some checks on the type of result (should be float)
@api.multi
def _compute_rule(self, localdict):
"""
:param localdict: dictionary containing the environement in which to compute the rule
:return: returns a tuple build as the base/amount computed, the quantity and the rate
:param localdict: dictionary containing the current computation environment
:return: returns a tuple (amount, qty, rate)
:rtype: (float, float, float)
"""
self.ensure_one()
if self.amount_select == 'fix':
try:
return self.amount_fix, float(safe_eval(self.quantity, localdict)), 100.0
return self.amount_fix or 0.0, float(safe_eval(self.quantity, localdict)), 100.0
except Exception as e:
raise UserError(_('Wrong quantity defined for salary rule %s (%s).\nError: %s') % (self.name, self.code, e))
elif self.amount_select == 'percentage':
if self.amount_select == 'percentage':
try:
return (float(safe_eval(self.amount_percentage_base, localdict)),
float(safe_eval(self.quantity, localdict)),
self.amount_percentage)
self.amount_percentage or 0.0)
except Exception as e:
raise UserError(_('Wrong percentage base or quantity defined for salary rule %s (%s).\nError: %s') % (self.name, self.code, e))
else:
else: # python code
try:
safe_eval(self.amount_python_compute, localdict, mode='exec', nocopy=True)
safe_eval(self.amount_python_compute or 0.0, localdict, mode='exec', nocopy=True)
return float(localdict['result']), localdict.get('result_qty', 1.0), localdict.get('result_rate', 100.0)
except Exception as e:
raise UserError(_('Wrong python code defined for salary rule %s (%s).\nError: %s') % (self.name, self.code, e))
@api.multi
def _satisfy_condition(self, localdict):
"""
@param contract_id: id of hr.contract to be tested
@return: returns True if the given rule match the condition for the given contract. Return False otherwise.
"""
self.ensure_one()
if self.condition_select == 'none':
return True
elif self.condition_select == 'range':
if self.condition_select == 'range':
try:
result = safe_eval(self.condition_range, localdict)
return self.condition_range_min <= result and result <= self.condition_range_max or False
return self.condition_range_min <= result <= self.condition_range_max
except:
raise UserError(_('Wrong range condition defined for salary rule %s (%s).') % (self.name, self.code))
else: # python code
try:
safe_eval(self.condition_python, localdict, mode='exec', nocopy=True)
return localdict.get('result', False)
return localdict.get('result', False)
except:
raise UserError(_('Wrong python condition defined for salary rule %s (%s).') % (self.name, self.code))
@@ -13,3 +13,4 @@ access_hr_benefit,access_hr_benefit,model_hr_benefit,group_hr_payroll_user,1,1,1
access_hr_benefit_type_officer,access_hr_benefit_type_officer,model_hr_benefit_type,group_hr_payroll_user,1,0,0,0
access_hr_benefit_employee,hr.benefit.employee,model_hr_user_benefit_employee,group_hr_payroll_user,1,1,1,1
access_hr_benefit_type_manager,access_hr_benefit_type_manager,model_hr_benefit_type,group_hr_payroll_manager,1,1,1,1
access_hr_payroll_structure_type,hr.payroll.structure.type,model_hr_payroll_structure_type,hr_payroll.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
13 access_hr_benefit_type_officer access_hr_benefit_type_officer model_hr_benefit_type group_hr_payroll_user 1 0 0 0
14 access_hr_benefit_employee hr.benefit.employee model_hr_user_benefit_employee group_hr_payroll_user 1 1 1 1
15 access_hr_benefit_type_manager access_hr_benefit_type_manager model_hr_benefit_type group_hr_payroll_manager 1 1 1 1
16 access_hr_payroll_structure_type hr.payroll.structure.type model_hr_payroll_structure_type hr_payroll.group_hr_payroll_user 1 1 1 1
-3
View File
@@ -43,7 +43,6 @@ class TestPayslipBase(TransactionCase):
'date_start': Date.today(),
'name': 'Contract for Richard',
'wage': 5000.0,
'type_id': self.ref('hr_contract.hr_contract_type_emp'),
'employee_id': self.richard_emp.id,
'struct_id': self.developer_pay_structure.id,
})
@@ -91,7 +90,6 @@ class TestPayslipContractBase(TestPayslipBase):
'name': 'First CDD Contract for Richard',
'resource_calendar_id': self.calendar_40h.id,
'wage': 5000.0,
'type_id': self.ref('hr_contract.hr_contract_type_emp'),
'employee_id': self.richard_emp.id,
'struct_id': self.developer_pay_structure.id,
'state': 'close',
@@ -103,7 +101,6 @@ class TestPayslipContractBase(TestPayslipBase):
'name': 'Contract for Richard',
'resource_calendar_id': self.calendar_35h.id,
'wage': 5000.0,
'type_id': self.ref('hr_contract.hr_contract_type_emp'),
'employee_id': self.richard_emp.id,
'struct_id': self.developer_pay_structure.id,
'state': 'open',
@@ -97,7 +97,6 @@ class TestPayslipMultiContract(TestPayslipContractBase):
'name': 'Contract for Richard',
'resource_calendar_id': self.calendar_40h.id,
'wage': 5000.0,
'type_id': self.ref('hr_contract.hr_contract_type_emp'),
'employee_id': self.richard_emp.id,
'struct_id': self.developer_pay_structure.id,
'state': 'open',
@@ -6,12 +6,11 @@
<field name="model">hr.contract</field>
<field name="inherit_id" ref="hr_contract.hr_contract_view_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='type_id']" position="after">
<field name="struct_id" required="1"/>
</xpath>
<xpath expr="//field[@name='type_id']" position="before">
<xpath expr="//field[@name='reported_to_secretariat']" position="before">
<field name="company_id" groups="base.group_multi_company"/>
<field name="currency_id" invisible="1"/>
<field name="struct_id" required="1"/>
<field name="structure_type_id" readonly="1"/>
</xpath>
<xpath expr="//field[@name='resource_calendar_id']" position="after">
<field name="schedule_pay"/>
@@ -113,6 +113,13 @@
sequence="30"
/>
<menuitem
id="menu_hr_payroll_structure_type"
name="Structure Types"
action="action_hr_payroll_structure_type"
parent="menu_hr_salary_configuration"
sequence="31"/>
<menuitem
id="menu_action_hr_contribution_register_form"
action="action_contribution_register_form"
@@ -2,13 +2,13 @@
<odoo>
<!-- Salary structure -->
<!-- YTI TODO: One salary structure list view seems to unused -->
<record id="view_hr_payroll_structure_list_view" model="ir.ui.view">
<field name="name">hr.payroll.structure.tree</field>
<field name="model">hr.payroll.structure</field>
<field name="arch" type="xml">
<tree string="Employee Function">
<field name="name"/>
<field name="type_id" invisible="1"/>
<field name="code"/>
<field name="rule_ids"/>
<field name="country_id" options="{'no_create': True}"/>
@@ -41,25 +41,15 @@
</field>
</record>
<record id="view_hr_payroll_structure_tree" model="ir.ui.view">
<field name="name">hr.payroll.structure.tree</field>
<field name="model">hr.payroll.structure</field>
<field name="field_parent">children_ids</field>
<field name="arch" type="xml">
<tree string="Salary Structure">
<field name="name"/>
<field name="code"/>
<field name="country_id" options="{'no_create': True}"/>
</tree>
</field>
</record>
<record id="view_hr_payroll_structure_filter" model="ir.ui.view">
<field name="name">hr.payroll.structure.select</field>
<field name="model">hr.payroll.structure</field>
<field name="arch" type="xml">
<search string="Payroll Structures">
<field name="name" string="Payroll Structures" filter_domain="['|',('name','ilike',self),('code','ilike',self)]"/>
<group col="8" colspan="4" expand="0" string="Group By">
<filter string="Structure Type" name="group_by_type_id" context="{'group_by': 'type_id'}"/>
</group>
</search>
</field>
</record>
@@ -73,14 +63,13 @@
<group name="salary_details" col="4">
<field name="name"/>
<field name="code"/>
<field name="parent_id"/>
<field name="report_id"/>
<field name="payslip_name"/>
<field name="type_id"/>
<field name="country_id" options="{'no_create': True}"/>
</group>
<notebook colspan="4">
<page name="salary_rules" string="Salary Rules">
<field name="rule_ids" domain="[('parent_rule_id','=',False)]">
<field name="rule_ids">
<tree>
<field name="name"/>
<field name="code"/>
@@ -101,6 +90,57 @@
<field name="res_model">hr.payroll.structure</field>
<field name="view_type">form</field>
<field name="view_mode">tree,kanban,form</field>
<field name="context">{'search_default_group_by_type_id': 1}</field>
</record>
<record id="hr_payroll_structure_type_view_form" model="ir.ui.view">
<field name="name">hr.payroll.structure.type.form</field>
<field name="model">hr.payroll.structure.type</field>
<field name="arch" type="xml">
<form string="Structure Type">
<sheet>
<group>
<group>
<field name="name"/>
</group>
<group>
<field name="default_schedule_pay"/>
<field name="default_resource_calendar_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="hr_payroll_structure_type_view_tree" model="ir.ui.view">
<field name="name">hr.payroll.structure.type.tree</field>
<field name="model">hr.payroll.structure.type</field>
<field name="arch" type="xml">
<tree string="Structure Type">
<field name="name"/>
<field name="default_schedule_pay"/>
<field name="default_resource_calendar_id"/>
</tree>
</field>
</record>
<record id="hr_payroll_structure_type_view_search" model="ir.ui.view">
<field name="name">hr.payroll.structure.type.search</field>
<field name="model">hr.payroll.structure.type</field>
<field name="arch" type="xml">
<search string="Search Structure Type">
<field name="name" string="Contract Type"/>
</search>
</field>
</record>
<record id="action_hr_payroll_structure_type" model="ir.actions.act_window">
<field name="name">Structure Types</field>
<field name="res_model">hr.payroll.structure.type</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="hr_payroll_structure_type_view_search"/>
</record>
<!-- Salary Category-->
@@ -229,7 +269,6 @@
</record>
<!-- Salary Rules -->
<record id="hr_salary_rule_list" model="ir.ui.view">
<field name="name">hr.salary.rule.list</field>
<field name="model">hr.salary.rule</field>
@@ -238,6 +277,7 @@
<field name="name"/>
<field name="code"/>
<field name="category_id"/>
<field name="struct_id" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="register_id"/>
</tree>
@@ -272,19 +312,6 @@
</field>
</record>
<record id="hr_salary_rule_tree" model="ir.ui.view">
<field name="name">hr.salary.rule.tree</field>
<field name="model">hr.salary.rule</field>
<field name="field_parent">child_ids</field>
<field eval="20" name="priority"/>
<field name="arch" type="xml">
<tree string="Salary Rules">
<field name="name"/>
<field name="code"/>
<field name="category_id" invisible="True"/>
</tree>
</field>
</record>
<record id="hr_salary_rule_form" model="ir.ui.view">
<field name="name">hr.salary.rule.form</field>
<field name="model">hr.salary.rule</field>
@@ -298,7 +325,8 @@
<group name="main_details" col="4">
<field name="code"/>
<field name="sequence" />
<field name="sequence"/>
<field name="struct_id"/>
<field name="active"/>
<field name="appears_on_payslip"/>
</group>
@@ -322,11 +350,6 @@
<field name="register_id"/>
</group>
</page>
<page name="rules" string="Child Rules">
<field name="parent_rule_id"/>
<separator string="Children Definition"/>
<field name="child_ids"/>
</page>
<page name="description" string="Description">
<field name="note"/>
</page>
@@ -343,9 +366,11 @@
<search string="Search Salary Rule">
<field name="name" string="Salary Rules" filter_domain="['|',('name','ilike',self),('code','ilike',self)]"/>
<field name="category_id"/>
<field name="struct_id"/>
<field name="condition_range_min"/>
<group col="8" colspan="4" expand="0" string="Group By">
<filter string="Category" name="head" context="{'group_by':'category_id'}"/>
<filter string="Salary Structure" name="group_by_struct_id" context="{'group_by': 'struct_id'}"/>
</group>
</search>
</field>
@@ -356,15 +381,7 @@
<field name="res_model">hr.salary.rule</field>
<field name="view_type">form</field>
<field name="view_mode">tree,kanban,form</field>
<field name="domain">[('parent_rule_id','=',False)]</field>
<field name="context">{'search_default_group_by_struct_id': 1}</field>
<field name="search_view_id" ref="view_hr_rule_filter"/>
</record>
<act_window name="All Children Rules"
domain="[('parent_rule_id', '=', active_id)]"
res_model="hr.salary.rule"
src_model="hr.salary.rule"
view_id="hr_salary_rule_list"
id="act_children_salary_rules"/>
</odoo>
@@ -43,28 +43,14 @@ class TestHrPayrollAccount(common.TransactionCase):
'bank_account_id': self.res_partner_bank.bank_id.id,
})
self.hr_structure_softwaredeveloper = self.env['hr.payroll.structure'].create({
'name': 'Salary Structure for Software Developer',
'code': 'SD',
'parent_id': self.ref('hr_payroll.structure_base'),
'rule_ids': [(6, 0, [
self.ref('hr_payroll.hr_salary_rule_houserentallowance1'),
self.ref('hr_payroll.hr_salary_rule_convanceallowance1'),
self.ref('hr_payroll.hr_salary_rule_professionaltax1'),
self.ref('hr_payroll.hr_salary_rule_providentfund1'),
self.ref('hr_payroll.hr_salary_rule_meal_voucher'),
])],
})
# Create account journal.
self.hr_contract_john = self.env['hr.contract'].create({
'date_end': fields.Date.to_string(datetime.now() + timedelta(days=365)),
'date_start': fields.Date.today(),
'name': 'Contract for John',
'wage': 5000.0,
'type_id': self.ref('hr_contract.hr_contract_type_emp'),
'employee_id': self.hr_employee_john.id,
'struct_id': self.hr_structure_softwaredeveloper.id,
'struct_id': self.env.ref('hr_payroll.structure_002').id,
'journal_id': self.ref('hr_payroll_account.expenses_journal'),
})
@@ -20,7 +20,7 @@
<field name="model">hr.salary.rule</field>
<field name="inherit_id" ref="hr_payroll.hr_salary_rule_form"/>
<field name="arch" type="xml">
<xpath expr="//page[@name='rules']" position="after">
<xpath expr="//page[@name='description']" position="after">
<page string="Accounting">
<group colspan="4">
<field name="account_debit" />
@@ -25,6 +25,9 @@ Belgian Payroll Rules.
'views/reports.xml',
'views/l10n_be_hr_payroll_view.xml',
'data/l10n_be_hr_payroll_data.xml',
'data/cp200/employee_double_holidays_data.xml',
'data/cp200/employee_salary_data.xml',
'data/cp200/employee_thirteen_month_data.xml',
'data/report_paperformat.xml',
'views/res_config_settings_views.xml',
'wizard/l10n_be_individual_account_wizard_views.xml',
@@ -0,0 +1,233 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- YTI TODO set 1 -->
<data noupdate="0">
<!-- Salary Structure -->
<record id="hr_payroll_structure_cp200_double_holiday" model="hr.payroll.structure">
<field name="code">CP 200 DH</field>
<field name="name">Double Holidays Belgian Employee</field>
<field name="country_id" ref="base.be"/>
<field name="report_id" ref="l10n_be_hr_payroll.action_report_double_holiday_13th_month"/>
<field name="payslip_name">Double Holidays Slip</field>
<field name="type_id" ref="l10n_be_hr_payroll.structure_type_employee_cp200"/>
</record>
<!-- Salary Rules -->
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_be_hr_payroll.hr_payroll_structure_cp200_double_holiday')),
('code', '=', 'BASIC')]"/>
<value eval="{'amount_python_compute': 'result = contract.wage_with_holidays'}"/>
</function>
<!-- 92% of monthly gross salary -->
<record id="cp200_employees_double_holiday_pay_basic" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_dp"/>
<field name="name">Double Holiday Pay</field>
<field name="code">D.P</field>
<field name="sequence">2</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC * 0.92</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_atn_internet" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
<field name="name">ATN Internet</field>
<field name="code">ATN.INT</field>
<field name="sequence">16</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.internet)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 5.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_atn_mobile" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
<field name="name">ATN Mobile</field>
<field name="code">ATN.MOB</field>
<field name="sequence">17</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.mobile)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 12.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_gross_salary" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_salary"/>
<field name="name">Gross Salary</field>
<field name="code">SALARY</field>
<field name="sequence">20</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = categories.BASIC
if contract.internet:
result += 5.0
if contract.mobile:
result += 12.0
</field>
<field name="appears_on_payslip" eval="False"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<!-- 85% of monthly gross salary is used to compute social contributions -->
<record id="cp200_employees_double_holiday_pay_salary" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_salary"/>
<field name="name">Gross Salary</field>
<field name="code">SALARY</field>
<field name="sequence">21</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SALARY * 0.85</field>
<field name="appears_on_payslip" eval="False"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_onss_rule" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_onss"/>
<field name="name">Social contribution</field>
<field name="code">ONSS</field>
<field name="sequence">41</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">SALARY</field>
<field name="amount_percentage">-13.07</field>
<field name="register_id" ref="contrib_register_onss"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_employment_bonus_employees" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_employment_bonus"/>
<field name="name">Employment Bonus</field>
<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;= 2560.57</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = compute_employment_bonus_employees(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_reim_travel" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.DED"/>
<field name="name">Reimbursement of travel expenses</field>
<field name="code">Tr.E</field>
<field name="amount_select">code</field>
<field name="sequence">65</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.others_reimbursed_amount)</field>
<field name="amount_python_compute">result = contract.others_reimbursed_amount</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_gross_with_ip" model="hr.salary.rule">
<field name="name">Total Gross</field>
<field name="sequence">90</field>
<field name="code">GROSSIP</field>
<field name="category_id" ref="l10n_be_hr_payroll.hr_salary_rule_category_gross_with_ip"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC + categories.ALW</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_ip_part" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_category_ip_part"/>
<field name="name">Intellectual Property</field>
<field name="code">IP.PART</field>
<field name="sequence">91</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = - categories.GROSSIP * contract.ip_wage_rate / 100.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_pay_gross" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.GROSS"/>
<field name="name">Gross</field>
<field name="code">GROSS</field>
<field name="sequence">101</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.DP + categories.ALW</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_pay_p_p" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">P.P</field>
<field name="sequence">102</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = compute_double_holiday_withholding_taxes(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_atn_internet_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Internet</field>
<field name="code">ATN.INT.2</field>
<field name="sequence">161</field>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.internet</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -5.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employee_double_holiday_atn_mobile_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Mobile</field>
<field name="code">ATN.MOB.2</field>
<field name="sequence">162</field>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.mobile</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -12.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_ip" model="hr.salary.rule">
<field name="category_id" ref="l10n_be_hr_payroll.hr_payroll_head_div_net"/>
<field name="name">Intellectual Property</field>
<field name="code">IP</field>
<field name="amount_select">code</field>
<field name="sequence">172</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_python_compute">result = categories.GROSSIP * contract.ip_wage_rate / 100.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_ip_deduction" model="hr.salary.rule">
<field name="category_id" ref="l10n_be_hr_payroll.hr_payroll_head_div_net"/>
<field name="name">Intellectual Property Income Deduction</field>
<field name="code">IP.DED</field>
<field name="amount_select">code</field>
<field name="sequence">173</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_python_compute">result = compute_ip_deduction(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
<record id="cp200_employees_double_holiday_pay_net" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.NET"/>
<field name="name">Net</field>
<field name="code">NET</field>
<field name="sequence">201</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.DP + categories.ALW + categories.DED</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_double_holiday"/>
</record>
</data>
</odoo>
@@ -0,0 +1,251 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- YTI TODO: Set noupdate 1 -->
<data noupdate="0">
<!-- Salary Structure -->
<record id="hr_payroll_structure_cp200_employee_salary" model="hr.payroll.structure">
<field name="code">CP 200</field>
<field name="name">Belgian Employee</field>
<field name="country_id" ref="base.be"/>
<field name="type_id" ref="l10n_be_hr_payroll.structure_type_employee_cp200"/>
</record>
<!-- Salary Rules -->
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_be_hr_payroll.hr_payroll_structure_cp200_employee_salary')),
('code', '=', 'BASIC')]"/>
<value eval="{'amount_python_compute': 'result = contract.wage_with_holidays'}"/>
</function>
<record id="cp200_employees_salary_atn_internet" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
<field name="name">ATN Internet</field>
<field name="code">ATN.INT</field>
<field name="sequence">16</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.internet)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 5.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_atn_mobile" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
<field name="name">ATN Mobile</field>
<field name="code">ATN.MOB</field>
<field name="sequence">17</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.mobile)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 12.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_gross_salary" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_salary"/>
<field name="name">Gross Salary</field>
<field name="code">SALARY</field>
<field name="sequence">20</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = categories.BASIC
if contract.internet:
result += 5.0
if contract.mobile:
result += 12.0
</field>
<field name="appears_on_payslip" eval="False"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_onss_rule" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_onss"/>
<field name="name">Social contribution</field>
<field name="code">ONSS</field>
<field name="sequence">41</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">SALARY</field>
<field name="amount_percentage">-13.07</field>
<field name="register_id" ref="contrib_register_onss"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_employment_bonus_employees" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_employment_bonus"/>
<field name="name">Employment Bonus</field>
<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;= 2560.57</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = compute_employment_bonus_employees(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_reim_travel" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.DED"/>
<field name="name">Reimbursement of travel expenses</field>
<field name="code">Tr.E</field>
<field name="amount_select">code</field>
<field name="sequence">65</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.others_reimbursed_amount)</field>
<field name="amount_python_compute">result = contract.others_reimbursed_amount</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_company_car" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
<field name="name">ATN Company Car</field>
<field name="code">ATN.CAR</field>
<field name="sequence">70</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.transport_mode_car and contract.car_atn)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.car_atn</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_gross_with_ip" model="hr.salary.rule">
<field name="name">Total Gross</field>
<field name="sequence">90</field>
<field name="code">GROSSIP</field>
<field name="category_id" ref="l10n_be_hr_payroll.hr_salary_rule_category_gross_with_ip"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC + categories.ALW</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_ip_part" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_category_ip_part"/>
<field name="name">Intellectual Property</field>
<field name="code">IP.PART</field>
<field name="sequence">91</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = - categories.GROSSIP * contract.ip_wage_rate / 100.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_withholding_taxes" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">P.P</field>
<field name="sequence">120</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">result = compute_withholding_taxes(payslip, categories, worked_days, inputs)
</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_company_car_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Company Car</field>
<field name="code">ATN.CAR.2</field>
<field name="sequence">160</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.transport_mode_car and contract.car_atn)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -contract.car_atn</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_atn_internet_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Internet</field>
<field name="code">ATN.INT.2</field>
<field name="sequence">161</field>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.internet</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -5.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_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</field>
<field name="amount_select">fix</field>
<field name="sequence">165</field>
<field name="appears_on_payslip" eval="False"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = compute_special_social_cotisations(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_ch_worker" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">Retain on Meal Voucher</field>
<field name="code">MEAL_V_EMP</field>
<field name="sequence">165</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.meal_voucher_amount)</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">-100.0</field>
<field name="amount_percentage_base">contract.meal_voucher_amount - contract.meal_voucher_paid_by_employer</field>
<field name="quantity">worked_days.WORK100 and worked_days.WORK100.number_of_days</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="contrib_register_meal_vouchers"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_atn_mobile_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Mobile</field>
<field name="code">ATN.MOB.2</field>
<field name="sequence">162</field>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.mobile</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -12.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_representation_fees" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">Representation Fees</field>
<field name="code">REP.FEES</field>
<field name="amount_select">code</field>
<field name="sequence">171</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.representation_fees)</field>
<field name="amount_python_compute">result = contract.representation_fees</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_ip" model="hr.salary.rule">
<field name="category_id" ref="l10n_be_hr_payroll.hr_payroll_head_div_net"/>
<field name="name">Intellectual Property</field>
<field name="code">IP</field>
<field name="amount_select">code</field>
<field name="sequence">172</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_python_compute">result = categories.GROSSIP * contract.ip_wage_rate / 100.0</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
<record id="cp200_employees_salary_ip_deduction" model="hr.salary.rule">
<field name="category_id" ref="l10n_be_hr_payroll.hr_payroll_head_div_net"/>
<field name="name">Intellectual Property Income Deduction</field>
<field name="code">IP.DED</field>
<field name="amount_select">code</field>
<field name="sequence">173</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_python_compute">result = compute_ip_deduction(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_employee_salary"/>
</record>
</data>
</odoo>
@@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- YTI TODO SET TO 1 -->
<data noupdate="0">
<!-- Salary Structure -->
<record id="hr_payroll_structure_cp200_thirteen_month" model="hr.payroll.structure">
<field name="code">CP 200 EOYB</field>
<field name="name">13th Month</field>
<field name="country_id" ref="base.be"/>
<field name="report_id" ref="l10n_be_hr_payroll.action_report_double_holiday_13th_month"/>
<field name="payslip_name">13th Month Slip</field>
<field name="type_id" ref="l10n_be_hr_payroll.structure_type_employee_cp200"/>
</record>
<!-- Salary Rules -->
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_be_hr_payroll.hr_payroll_structure_cp200_thirteen_month')),
('code', '=', 'BASIC')]"/>
<value eval="{'amount_python_compute': 'result = contract.wage_with_holidays'}"/>
</function>
<record id="cp200_employees_thirteen_month_gross_salary" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_salary"/>
<field name="name">Gross Salary</field>
<field name="code">SALARY</field>
<field name="sequence">20</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = categories.BASIC
if contract.internet:
result += 5.0
if contract.mobile:
result += 12.0
</field>
<field name="appears_on_payslip" eval="False"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_thirteen_month"/>
</record>
<record id="cp200_employees_thirteen_month_onss_rule" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_onss"/>
<field name="name">Social contribution</field>
<field name="code">ONSS</field>
<field name="sequence">41</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">SALARY</field>
<field name="amount_percentage">-13.07</field>
<field name="register_id" ref="contrib_register_onss"/>
<field name="struct_id" ref="hr_payroll_structure_cp200_thirteen_month"/>
</record>
<record id="cp200_employees_thirteen_month_p_p" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">P.P</field>
<field name="sequence">102</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = compute_thirteen_month_withholding_taxes(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_thirteen_month"/>
</record>
<record id="cp200_employees_thirteen_month_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</field>
<field name="amount_select">fix</field>
<field name="sequence">165</field>
<field name="appears_on_payslip" eval="False"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = compute_special_social_cotisations(payslip, categories, worked_days, inputs)</field>
<field name="struct_id" ref="hr_payroll_structure_cp200_thirteen_month"/>
</record>
</data>
</odoo>
@@ -1,12 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="hr_payroll.hr_rule_basic" model="hr.salary.rule">
<field name="amount_python_compute">
result = contract.wage_with_holidays
</field>
<record id="structure_type_employee_cp200" model="hr.payroll.structure.type">
<field name="name">CP200: Belgian Employee</field>
</record>
<!-- CONTRIBUTION REGISTERS -->
<!-- CONTRIBUTION REGISTERS -->
<record id="res_partner_onss" model="res.partner">
<field name="name">Office National de Sécurité Sociale (ONSS)</field>
<field name="supplier">1</field>
@@ -36,7 +34,7 @@ result = contract.wage_with_holidays
<field name="partner_id" ref="res_partner_meal_vouchers"/>
</record>
<!-- HR SALARY RULE CATEGORIES-->
<!-- HR SALARY RULE CATEGORIES-->
<record id="hr_payroll_head_salary" model="hr.salary.rule.category">
<field name="name">Gross</field>
<field name="code">BRUT</field>
@@ -80,632 +78,20 @@ result = contract.wage_with_holidays
<field name="code">SSC</field>
<field name="parent_id" ref="hr_payroll.DED"/>
</record>
<record id="hr_salary_rule_category_ip_part" model="hr.salary.rule.category">
<field name="name">IP. Part.</field>
<field name="code">IP. PART</field>
<field name="parent_id" ref="hr_payroll.ALW"/>
</record>
<record id="hr_salary_rule_category_gross_with_ip" model="hr.salary.rule.category">
<field name="name">Total Gross</field>
<field name="code">GROSSIP</field>
</record>
<record id="hr_payroll_head_dp" model="hr.salary.rule.category">
<field name="name">Double Holiday Pay</field>
<field name="code">DP</field>
</record>
<!-- HR SALARY RULES-->
<record id="hr_payroll_rules_maj" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_salary"/>
<field name="name">Worker Salary. Premium pay of 108%</field>
<field name="code">SALARY</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC * 1.08</field>
</record>
<record id="hr_payroll_rules_employee" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_salary"/>
<field name="name">Gross Salary</field>
<field name="code">SALARY</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = categories.BASIC
if contract.internet:
result += 5.0
if contract.mobile:
result += 12.0
</field>
<field name="sequence">20</field>
<field name="appears_on_payslip" eval="False"/>
</record>
<record id="hr_payroll_rules_onss_rule" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_onss"/>
<field name="name">Social contribution</field>
<field name="code">ONSS</field>
<field name="sequence">41</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">SALARY</field>
<field name="amount_percentage">-13.07</field>
<field name="register_id" ref="contrib_register_onss"/>
</record>
<record id="hr_salary_rule_employment_bonus_employees" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_employment_bonus"/>
<field name="name">Employment Bonus</field>
<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;= 2560.57</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
salary = categories.BRUT
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">
<field name="category_id" ref="hr_payroll_head_employment_bonus"/>
<field name="name">Employment Bonus</field>
<field name="code">EmpBonus.2</field>
<field name="sequence">42</field>
<field name="condition_select">python</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;= 1641.62:
result = 217.75
elif salary &lt;= 2560.57:
result = 217.75 - (0.2370 * (salary - 1641.62))
</field>
</record>
<record id="hr_salary_rule_gross_with_ip" model="hr.salary.rule">
<field name="name">Total Gross</field>
<field name="sequence">90</field>
<field name="code">GROSSIP</field>
<field name="category_id" ref="l10n_be_hr_payroll.hr_salary_rule_category_gross_with_ip"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC + categories.ALW</field>
</record>
<record id="hr_salary_rule_ip_part" model="hr.salary.rule">
<field name="category_id" ref="hr_salary_rule_category_ip_part"/>
<field name="name">Intellectual Property</field>
<field name="code">IP.PART</field>
<field name="sequence">91</field>
<field name="condition_select">python</field>
<field name="condition_python">
result = bool(contract.ip)
</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = - categories.GROSSIP * contract.ip_wage_rate / 100.0
</field>
</record>
<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</field>
<field name="amount_select">fix</field>
<field name="sequence">165</field>
<field name="appears_on_payslip" eval="False"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">
wage = categories.BASIC
if employee.resident_bool:
result = 0.0
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">P.P</field>
<field name="sequence">120</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">
def compute_basic_bareme(value):
if value &lt;= 12860.0:
basic_bareme = value * 0.2675
elif value &lt;= 19630.0:
basic_bareme = 3440.05 + 0.428 * (value - 12860.00)
elif value &lt;= 40470.00:
basic_bareme = 6337.61 + 0.4815 * (value - 19630.00)
else:
basic_bareme = 16372.07 + 0.535 * (value - 40470.0)
return float_round(basic_bareme, precision_rounding=0.01)
def convert_to_month(value):
return float_round(value / 12.0, precision_rounding=0.01, rounding_method='DOWN')
# 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;= 16033.33:
yearly_net_taxable_revenue = yearly_gross_revenue * (1.0 - 0.3)
else:
yearly_net_taxable_revenue = yearly_gross_revenue - 4810.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) - 2065.1, 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, 10930.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 - 4130.20, 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 -= 26.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 -= 80 * 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;= 230.0:
withholding_tax_amount -= 115.0
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;= 459.0:
withholding_tax_amount -= 229.5
if employee.marital in ['married', 'cohabitant'] and 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 -= 80.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 -= 104.0
if employee.dependent_children == 3:
withholding_tax_amount -= 275.0
if employee.dependent_children == 4:
withholding_tax_amount -= 483.0
if employee.dependent_children == 5:
withholding_tax_amount -= 713.0
if employee.dependent_children == 6:
withholding_tax_amount -= 944.0
if employee.dependent_children == 7:
withholding_tax_amount -= 1174.0
if employee.dependent_children &gt;= 8:
withholding_tax_amount -= 1428.0 + (employee.dependent_children - 8) * 256.0
result = - max(withholding_tax_amount, 0.0)
</field>
</record>
<record id="hr_salary_rule_double_holiday_pay_p_p" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">P.P</field>
<field name="sequence">102</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
taux = [(8460.0, 0), (10830.0, 0.1917),
(13775.0, 0.2120), (16520.0, 0.2625),
(18690.0, 0.3130), (20870.0, 0.3433),
(25230.0, 0.3634), (27450.0, 0.3937),
(36360.0, 0.4239), (47480.0, 0.4744)]
def find_taux(x):
for a, b in taux:
if x &lt;= a:
return b
return 0.535
# Up to 12 children
children_exoneration = [0.0, 13329.0, 16680.0, 21820.0, 27560.0, 33300.0, 39040.0, 44780.0, 50520.0, 56260.0, 62000.0, 67740.0, 73480.0]
# Only if no more than 5 children
children_reduction = [(0, 0), (22940.0, 0.075), (22940.0, 0.2), (25235.0, 0.35), (29825.0, 0.55), (32120.0, 0.75)]
n = employee.dependent_children
yearly_revenue = categories.GROSS * 12.0
if 0 &lt; n &lt; 13 and yearly_revenue &lt;= children_exoneration[n]:
yearly_revenue = yearly_revenue - (children_exoneration[n] - yearly_revenue)
if n &lt;= 5 and yearly_revenue &lt;= children_reduction[n][0]:
withholding_tax_amount = yearly_revenue * find_taux(yearly_revenue) * (1 - children_reduction[n][1])
else:
withholding_tax_amount = yearly_revenue * find_taux(yearly_revenue)
result = -withholding_tax_amount / 12.0
</field>
</record>
<record id="hr_salary_rule_bonus_pay_p_p" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_pp"/>
<field name="name">Withholding Tax</field>
<field name="code">P.P</field>
<field name="sequence">102</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
taux = [(8460.0, 0), (10830.0, 0.2322),
(13775.0, 0.2523), (16520.0, 0.3028),
(18690.0, 0.2533), (20870.0, 0.3836),
(25230.0, 0.4038), (27450.0, 0.4341),
(36360.0, 0.4644), (47480.0, 0.5148)]
def find_taux(x):
for a, b in taux:
if x &lt;= a:
return b
return 0.535
# Up to 12 children
children_exoneration = [0.0, 13329.0, 16680.0, 21820.0, 27560.0, 33300.0, 39040.0, 44780.0, 50520.0, 56260.0, 62000.0, 67740.0, 73480.0]
# Only if no more than 5 children
children_reduction = [(0, 0), (22940.0, 0.075), (22940.0, 0.2), (25235.0, 0.35), (29825.0, 0.55), (32120.0, 0.75)]
n = employee.dependent_children
yearly_revenue = categories.GROSS * 12.0
if 0 &lt; n &lt; 13 and yearly_revenue &lt;= children_exoneration[n]:
yearly_revenue = yearly_revenue - (children_exoneration[n] - yearly_revenue)
if n &lt;= 5 and yearly_revenue &lt;= children_reduction[n][0]:
withholding_tax_amount = yearly_revenue * find_taux(yearly_revenue) * (1 - children_reduction[n][1])
else:
withholding_tax_amount = yearly_revenue * find_taux(yearly_revenue)
result = -withholding_tax_amount / 12.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"/>
<field name="name">ATN Company Car</field>
<field name="code">ATN.CAR</field>
<field name="sequence">70</field>
<field name="condition_select">python</field>
<field name="condition_python">
result = bool(contract.transport_mode_car and contract.car_atn)
</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = contract.car_atn
</field>
</record>
<record id="hr_salary_rule_atn_internet" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
<field name="name">ATN Internet</field>
<field name="code">ATN.INT</field>
<field name="sequence">16</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.internet)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 5.0</field>
</record>
<record id="hr_salary_rule_atn_mobile" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_impos"/>
<field name="name">ATN Mobile</field>
<field name="code">ATN.MOB</field>
<field name="sequence">17</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.mobile)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 12.0</field>
</record>
<record id="hr_payroll_rules_company_car_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Company Car</field>
<field name="code">ATN.CAR.2</field>
<field name="sequence">160</field>
<field name="condition_select">python</field>
<field name="condition_python">
result = bool(contract.transport_mode_car and contract.car_atn)
</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">
result = -contract.car_atn
</field>
</record>
<record id="hr_salary_rule_atn_internet_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Internet</field>
<field name="code">ATN.INT.2</field>
<field name="sequence">161</field>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.internet</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -5.0</field>
</record>
<record id="hr_salary_rule_atn_mobile_2" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">ATN Mobile</field>
<field name="code">ATN.MOB.2</field>
<field name="sequence">162</field>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.mobile</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -12.0</field>
</record>
<record id="hr_salary_rule_commission_on_target" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">Commission on Target</field>
<field name="code">COM</field>
<field name="sequence">170</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.commission_on_target)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.warrant_value_employee / 12.0</field>
<field name="appears_on_payslip" eval="False"/>
</record>
<record id="hr_payroll_rules_ch_worker" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">Retain on Meal Voucher</field>
<field name="code">MEAL_V_EMP</field>
<field name="sequence">165</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.meal_voucher_amount)</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">-100.0</field>
<field name="amount_percentage_base">contract.meal_voucher_amount - contract.meal_voucher_paid_by_employer</field>
<field name="quantity">worked_days.WORK100 and worked_days.WORK100.number_of_days</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="contrib_register_meal_vouchers"/>
</record>
<record id="hr_payroll_rules_reim_travel" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.DED"/>
<field name="name">Reimbursement of travel expenses</field>
<field name="code">Tr.E</field>
<field name="amount_select">code</field>
<field name="sequence">65</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.others_reimbursed_amount)</field>
<field name="amount_python_compute">result = contract.others_reimbursed_amount</field>
</record>
<record id="hr_salary_rule_representation_fees" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">Representation Fees</field>
<field name="code">REP.FEES</field>
<field name="amount_select">code</field>
<field name="sequence">171</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.representation_fees)</field>
<field name="amount_python_compute">result = contract.representation_fees</field>
</record>
<record id="hr_salary_rule_ip" model="hr.salary.rule">
<field name="category_id" ref="l10n_be_hr_payroll.hr_payroll_head_div_net"/>
<field name="name">Intellectual Property</field>
<field name="code">IP</field>
<field name="amount_select">code</field>
<field name="sequence">172</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_python_compute">result = categories.GROSSIP * contract.ip_wage_rate / 100.0</field>
</record>
<record id="hr_salary_rule_ip_deduction" model="hr.salary.rule">
<field name="category_id" ref="l10n_be_hr_payroll.hr_payroll_head_div_net"/>
<field name="name">Intellectual Property Income Deduction</field>
<field name="code">IP.DED</field>
<field name="amount_select">code</field>
<field name="sequence">173</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.ip)</field>
<field name="amount_python_compute">
tax_rate = 0.15
ip_amount = categories.GROSSIP * contract.ip_wage_rate / 100.0
if ip_amount &gt;= 0.0 and ip_amount &lt;= 15660:
tax_rate = tax_rate / 2.0
elif ip_amount &gt; 15660 and ip_amount &lt;=31320:
tax_rate = tax_rate * 3.0 / 4.0
result = -min(ip_amount * tax_rate, 11745)
</field>
</record>
<record id="hr_payroll_rules_suppl_net" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">Net Supplement</field>
<field name="code">Net.S</field>
<field name="amount_select">code</field>
<field name="sequence">185</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.additional_net_amount)</field>
<field name="amount_python_compute">result = contract.additional_net_amount</field>
</record>
<record id="hr_payroll_rules_retained_net" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_div_net"/>
<field name="name">Net retained</field>
<field name="code">Net.R</field>
<field name="amount_select">code</field>
<field name="sequence">190</field>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.retained_net_amount)</field>
<field name="amount_python_compute">result = -contract.retained_net_amount</field>
</record>
<!-- 92% of monthly gross salary -->
<record id="hr_salary_rule_double_holiday_pay_basic" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_dp"/>
<field name="name">Double Holiday Pay</field>
<field name="code">D.P</field>
<field name="sequence">2</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BASIC * 0.92</field>
</record>
<!-- 85% of monthly gross salary is used to compute social contributions -->
<record id="hr_salary_rule_double_holiday_pay_salary" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll_head_salary"/>
<field name="name">Gross Salary</field>
<field name="code">SALARY</field>
<field name="sequence">21</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SALARY * 0.85</field>
<field name="appears_on_payslip" eval="False"/>
</record>
<record id="hr_salary_rule_double_holiday_pay_gross" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.GROSS"/>
<field name="name">Gross</field>
<field name="code">GROSS</field>
<field name="sequence">101</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.DP + categories.ALW</field>
</record>
<record id="hr_salary_rule_double_holiday_pay_net" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.NET"/>
<field name="name">Net</field>
<field name="code">NET</field>
<field name="sequence">201</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.DP + categories.ALW + categories.DED</field>
</record>
<record id="hr_payroll_salary_structure_employee" model="hr.payroll.structure">
<field name="code">CP 200</field>
<field name="name">Belgian Employee</field>
<field eval="[(6, 0, [
ref('hr_payroll_rules_parent_company_car'),
ref('hr_payroll_rules_company_car_2'),
ref('hr_salary_rule_atn_mobile_2'),
ref('hr_salary_rule_atn_internet_2'),
ref('hr_salary_rule_atn_internet'),
ref('hr_salary_rule_atn_mobile'),
ref('hr_payroll_rules_onss_rule'),
ref('hr_salary_rule_employment_bonus_employees'),
ref('hr_payroll_rules_employee'),
ref('hr_payroll_rules_bareme'),
ref('hr_payroll_rules_ch_worker'),
ref('hr_payroll_rules_reim_travel'),
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_ip'),
ref('hr_salary_rule_ip_deduction'),
ref('hr_salary_rule_ip_part'),
ref('hr_salary_rule_gross_with_ip')
])]" name="rule_ids"/>
<field name="country_id" ref="base.be"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
</record>
<record id="hr_payroll_salary_structure_worker" model="hr.payroll.structure">
<field name="code">C.P.219</field>
<field name="name">Belgian Worker</field>
<field eval="[(6, 0, [
ref('hr_payroll_rules_maj'),
ref('hr_payroll_rules_onss_rule'),
ref('hr_salary_rule_employment_bonus_workers'),
ref('hr_payroll_rules_bareme'),
ref('hr_payroll_rules_ch_worker'),
ref('hr_payroll_rules_reim_travel'),
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'),
])]" name="rule_ids"/>
<field name="country_id" ref="base.be"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
</record>
<record id="hr_payroll_salary_structure_double_holiday_pay" model="hr.payroll.structure">
<field name="code">CP 200 DH</field>
<field name="name">Double Holidays Belgian Employee</field>
<field eval="[(6, 0, [
ref('hr_salary_rule_atn_mobile_2'),
ref('hr_salary_rule_atn_internet_2'),
ref('hr_salary_rule_atn_internet'),
ref('hr_salary_rule_atn_mobile'),
ref('hr_salary_rule_double_holiday_pay_basic'),
ref('hr_salary_rule_double_holiday_pay_gross'),
ref('hr_payroll_rules_employee'),
ref('hr_salary_rule_double_holiday_pay_salary'),
ref('hr_payroll_rules_onss_rule'),
ref('hr_salary_rule_double_holiday_pay_p_p'),
ref('hr_payroll_rules_suppl_net'),
ref('hr_payroll_rules_retained_net'),
ref('hr_salary_rule_ip'),
ref('hr_salary_rule_ip_deduction'),
ref('hr_salary_rule_ip_part'),
ref('hr_salary_rule_gross_with_ip'),
ref('hr_payroll_rules_reim_travel'),
ref('hr_salary_rule_employment_bonus_employees'),
ref('hr_salary_rule_double_holiday_pay_net'),
])]" name="rule_ids"/>
<field name="country_id" ref="base.be"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
<field name="report_id" ref="l10n_be_hr_payroll.action_report_double_holiday_13th_month"/>
<field name="payslip_name">Double Holidays Slip</field>
</record>
<record id="hr_payroll_salary_structure_end_of_year_bonus" model="hr.payroll.structure">
<field name="code">CP 200 EOYB</field>
<field name="name">13th Month</field>
<field eval="[(6, 0, [
ref('hr_payroll_rules_onss_rule'),
ref('hr_payroll_rules_employee'),
ref('hr_salary_rule_bonus_pay_p_p'),
ref('hr_payroll_rules_mis_ex_onss'),
])]" name="rule_ids"/>
<field name="country_id" ref="base.be"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
<field name="report_id" ref="l10n_be_hr_payroll.action_report_double_holiday_13th_month"/>
<field name="payslip_name">13th Month Slip</field>
</record>
<!-- Default advantage values -->
<function model="ir.default" name="set" eval="('hr.contract', 'holidays', 0.0)"/>
<function model="ir.default" name="set" eval="('hr.contract', 'commission_on_target', 0.0)"/>
@@ -4,3 +4,4 @@
from . import l10n_be_hr_payroll
from . import res_config_settings
from . import res_users
from . import hr_payslip
@@ -0,0 +1,226 @@
#-*- coding:utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
from odoo.tools import float_round
class Payslip(models.Model):
_inherit = 'hr.payslip'
def _get_base_local_dict(self):
res = super()._get_base_local_dict()
res.update({
'compute_ip_deduction': compute_ip_deduction,
'compute_withholding_taxes': compute_withholding_taxes,
'compute_employment_bonus_employees': compute_employment_bonus_employees,
'compute_special_social_cotisations': compute_special_social_cotisations,
'compute_double_holiday_withholding_taxes': compute_double_holiday_withholding_taxes,
'compute_thirteen_month_withholding_taxes': compute_thirteen_month_withholding_taxes,
})
return res
def compute_withholding_taxes(payslip, categories, worked_days, inputs):
def compute_basic_bareme(value):
if value <= 12860.0:
basic_bareme = value * 0.2675
elif value <= 19630.0:
basic_bareme = 3440.05 + 0.428 * (value - 12860.00)
elif value <= 40470.00:
basic_bareme = 6337.61 + 0.4815 * (value - 19630.00)
else:
basic_bareme = 16372.07 + 0.535 * (value - 40470.0)
return float_round(basic_bareme, precision_rounding=0.01)
def convert_to_month(value):
return float_round(value / 12.0, precision_rounding=0.01, rounding_method='DOWN')
employee = payslip.contract_id.employee_id
# 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 <= 16033.33:
yearly_net_taxable_revenue = yearly_gross_revenue * (1.0 - 0.3)
else:
yearly_net_taxable_revenue = yearly_gross_revenue - 4810.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) - 2065.1, 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, 10930.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 - 4130.20, 0))
# Reduction for isolated people and for other family charges
if employee.marital in ['divorced', 'single', 'widower'] or (employee.spouse_net_revenue > 0.0 or employee.spouse_other_net_revenue > 0.0):
if employee.marital in ['divorced', 'single', 'widower']:
withholding_tax_amount -= 26.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 -= 80 * 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 <= 230.0:
withholding_tax_amount -= 115.0
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 <= 459.0:
withholding_tax_amount -= 229.5
if employee.marital in ['married', 'cohabitant'] and 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 -= 80.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 -= 104.0
if employee.dependent_children == 3:
withholding_tax_amount -= 275.0
if employee.dependent_children == 4:
withholding_tax_amount -= 483.0
if employee.dependent_children == 5:
withholding_tax_amount -= 713.0
if employee.dependent_children == 6:
withholding_tax_amount -= 944.0
if employee.dependent_children == 7:
withholding_tax_amount -= 1174.0
if employee.dependent_children >= 8:
withholding_tax_amount -= 1428.0 + (employee.dependent_children - 8) * 256.0
return - max(withholding_tax_amount, 0.0)
def compute_special_social_cotisations(payslip, categories, worked_days, inputs):
employee = payslip.contract_id.employee_id
wage = categories.BASIC
if employee.resident_bool:
result = 0.0
elif employee.marital in ['divorced', 'single', 'widower'] or (employee.marital in ['married', 'cohabitant'] and employee.spouse_fiscal_status=='without income'):
if 0.01 <= wage <= 1095.09:
result = 0.0
elif 1095.10 <= wage <= 1945.38:
result = 0.0
elif 1945.39 <= wage <= 2190.18:
result = -min((wage - 1945.38) * 0.076, 18.60)
elif 2190.19 <= wage <= 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 0.01 <= wage <= 1095.09:
result = 0.0
elif 1095.10 <= wage <= 1945.38:
result = -9.30
elif 1945.39 <= wage <= 2190.18:
result = -min(max((wage - 1945.38) * 0.076, 9.30), 18.60)
elif 2190.19 <= wage <= 6038.82:
result = -min(18.60 + (wage - 2190.18) * 0.011, 51.64)
else:
result = -51.64
return result
def compute_ip_deduction(payslip, categories, worked_days, inputs):
tax_rate = 0.15
ip_amount = categories.GROSSIP * payslip.contract_id.ip_wage_rate / 100.0
if 0.0 <= ip_amount <= 15660:
tax_rate = tax_rate / 2.0
elif 15660.0 < ip_amount <= 31320:
tax_rate = tax_rate * 3.0 / 4.0
return - min(ip_amount * tax_rate, 11745)
def compute_employment_bonus_employees(payslip, categories, worked_days, inputs):
salary = categories.BRUT
if salary <= 1641.62:
result = 201.62
elif salary <= 2560.57:
result = 201.62 - (0.2194 * (salary - 1641.62))
return result
def compute_double_holiday_withholding_taxes(payslip, categories, worked_days, inputs):
rates = [
(8460.0, 0), (10830.0, 0.1917),
(13775.0, 0.2120), (16520.0, 0.2625),
(18690.0, 0.3130), (20870.0, 0.3433),
(25230.0, 0.3634), (27450.0, 0.3937),
(36360.0, 0.4239), (47480.0, 0.4744)]
employee = payslip.contract_id.employee_id
def find_rates(x):
for a, b in rates:
if x <= a:
return b
return 0.535
# Up to 12 children
children_exoneration = [0.0, 13329.0, 16680.0, 21820.0, 27560.0, 33300.0, 39040.0, 44780.0, 50520.0, 56260.0, 62000.0, 67740.0, 73480.0]
# Only if no more than 5 children
children_reduction = [(0, 0), (22940.0, 0.075), (22940.0, 0.2), (25235.0, 0.35), (29825.0, 0.55), (32120.0, 0.75)]
n = employee.dependent_children
yearly_revenue = categories.GROSS * 12.0
if 0 < n < 13 and yearly_revenue <= children_exoneration[n]:
yearly_revenue = yearly_revenue - (children_exoneration[n] - yearly_revenue)
if n <= 5 and yearly_revenue <= children_reduction[n][0]:
withholding_tax_amount = yearly_revenue * find_rates(yearly_revenue) * (1 - children_reduction[n][1])
else:
withholding_tax_amount = yearly_revenue * find_rates(yearly_revenue)
return -withholding_tax_amount / 12.0
def compute_thirteen_month_withholding_taxes(payslip, categories, worked_days, inputs):
employee = payslip.contract_id.employee_id
rates = [
(8460.0, 0), (10830.0, 0.2322),
(13775.0, 0.2523), (16520.0, 0.3028),
(18690.0, 0.2533), (20870.0, 0.3836),
(25230.0, 0.4038), (27450.0, 0.4341),
(36360.0, 0.4644), (47480.0, 0.5148)]
def find_rates(x):
for a, b in rates:
if x <= a:
return b
return 0.535
# Up to 12 children
children_exoneration = [0.0, 13329.0, 16680.0, 21820.0, 27560.0, 33300.0, 39040.0, 44780.0, 50520.0, 56260.0, 62000.0, 67740.0, 73480.0]
# Only if no more than 5 children
children_reduction = [(0, 0), (22940.0, 0.075), (22940.0, 0.2), (25235.0, 0.35), (29825.0, 0.55), (32120.0, 0.75)]
n = employee.dependent_children
yearly_revenue = categories.GROSS * 12.0
if 0 < n < 13 and yearly_revenue <= children_exoneration[n]:
yearly_revenue = yearly_revenue - (children_exoneration[n] - yearly_revenue)
if n <= 5 and yearly_revenue <= children_reduction[n][0]:
withholding_tax_amount = yearly_revenue * find_rates(yearly_revenue) * (1 - children_reduction[n][1])
else:
withholding_tax_amount = yearly_revenue * find_rates(yearly_revenue)
return -withholding_tax_amount / 12.0
@@ -6,6 +6,7 @@ from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
# YTI TODO: Split me into 2 files
class HrContract(models.Model):
_inherit = 'hr.contract'
@@ -61,12 +62,6 @@ class HrContract(models.Model):
help="Number of days of paid leaves the employee gets per year.")
wage_with_holidays = fields.Monetary(compute='_compute_wage_with_holidays', inverse='_inverse_wage_with_holidays',
tracking=True, string="Wage update with holidays retenues")
additional_net_amount = fields.Monetary(string="Net Supplements",
tracking=True,
help="Monthly net amount the employee receives.")
retained_net_amount = fields.Monetary(sting="Net Retained",
tracking=True,
help="Monthly net amount that is retained on the employee's salary.")
eco_checks = fields.Monetary("Eco Vouchers",
help="Yearly amount the employee receives in the form of eco vouchers.")
ip = fields.Boolean(default=False, tracking=True)
@@ -26,16 +26,6 @@
<field name="representation_fees" nolabel="1"/>
<span>/ month</span>
</div>
<label for="additional_net_amount"/>
<div class="o_row">
<field name="additional_net_amount" nolabel="1"/>
<span>/ month</span>
</div>
<label for="retained_net_amount"/>
<div class="o_row">
<field name="retained_net_amount" nolabel="1"/>
<span>/ month</span>
</div>
<label for="commission_on_target"/>
<div class="o_row">
<field name="commission_on_target" nolabel="1"/>
@@ -1,22 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- HR SALARY RULES-->
<record id="l10n_be_hr_payroll.hr_payroll_rules_onss_rule" model="hr.salary.rule">
<field name="account_debit" search="[('code', 'like', '4540%')]"/>
</record>
<record id="hr_payroll.hr_rule_basic" model="hr.salary.rule">
<field name="account_debit" search="[('code', 'like', '6202%')]"/>
</record>
<record id="hr_payroll.hr_rule_net" model="hr.salary.rule">
<field name="account_credit" search="[('code', 'like', '4552%')]"/>
</record>
<record id="l10n_be_hr_payroll.hr_payroll_rules_ch_worker" model="hr.salary.rule">
<field name="account_debit" search="[('code', 'like', '4597%')]"/>
</record>
<record id="l10n_be_hr_payroll.hr_payroll_rules_suppl_net" model="hr.salary.rule">
<field name="account_debit" search="[('code', 'like', '4552%')]"/>
</record>
<record id="l10n_be_hr_payroll.hr_payroll_rules_retained_net" model="hr.salary.rule">
<field name="account_debit" search="[('code', 'like', '4552%')]"/>
</record>
<!-- YTI: Previously was setting accounts on rules -->
</odoo>
@@ -3,7 +3,7 @@
<!-- Employee Contract -->
<record id="hr_contract.hr_contract_admin" model="hr.contract">
<field name="struct_id" ref="hr_payroll.structure_001"/>
<field name="struct_id" ref="hr_payroll.structure_002"/>
</record>
<record id="hr_contract.hr_contract_qdp" model="hr.contract">
@@ -27,6 +27,8 @@ TODO:
""",
'data': [
'data/l10n_fr_hr_payroll_data.xml',
'data/l10n_fr_hr_payroll_employe_cadre_data.xml',
'data/l10n_fr_hr_payroll_employe_non_cadre_data.xml',
'views/l10n_fr_hr_payroll_view.xml',
'views/res_config_settings_views.xml',
'report/report_l10n_fr_fiche_paye.xml',
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,933 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Salary Structure -->
<record id="hr_payroll_salary_structure_employe_cadre" model="hr.payroll.structure">
<field name="code">Fr-C</field>
<field name="name">Employe cadre</field>
<field name="country_id" ref="base.fr"/>
</record>
<!-- HR SALARY RULES-->
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_fr_hr_payroll.hr_payroll_salary_structure_employe_cadre')),
('code', '=', 'BASIC')]"/>
<value eval="{
'code': 'BASE',
'sequence': 1}"/>
</function>
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_fr_hr_payroll.hr_payroll_salary_structure_employe_cadre')),
('code', '=', 'GROSS')]"/>
<value eval="{
'name': 'Salaire Brut',
'code': 'BRUT',
'sequence': 1000,
'category_id': ref('hr_payroll.GROSS'),
'amount_python_compute': 'result = categories.BASE + categories.INDM - categories.DED',
}"/>
</function>
<record id="rule_employee_cadre_secu" model="hr.salary.rule">
<field name="name">Plafond Securite Sociale</field>
<field name="code">SECU</field>
<field name="sequence">1010</field>
<field name="category_id" ref="SECU"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.employee_id.company_id.plafond_secu</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_tranche_a" model="hr.salary.rule">
<field name="name">Plafond Tranche A</field>
<field name="code">TA</field>
<field name="sequence">1011</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_tranche_b" model="hr.salary.rule">
<field name="name">Plafond Tranche B</field>
<field name="code">TB</field>
<field name="sequence">1012</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU * 4</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_tranche_c" model="hr.salary.rule">
<field name="name">Plafond Tranche C</field>
<field name="code">TC</field>
<field name="sequence">1013</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU * 8</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_tranche_1" model="hr.salary.rule">
<field name="name">Plafond Tranche 1</field>
<field name="code">T1</field>
<field name="sequence">1014</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_tranche_2" model="hr.salary.rule">
<field name="name">Plafond Tranche 2</field>
<field name="code">T2</field>
<field name="sequence">1015</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU * 3</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C1_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Assurance maladie, maternite, invalidite, deces, solidaritee des personnes agees et handicapees</field>
<field name="code">C1</field>
<field name="sequence">2040</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.75</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C1_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Assurance maladie, maternite, invalidite, deces, solidaritee des personnes agees et handicapees</field>
<field name="code">C1P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2045</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">13.10</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C2_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Vieillesse plafonnee</field>
<field name="code">C2</field>
<field name="sequence">2050</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">6.65</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C2_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Vieillesse plafonnee</field>
<field name="code">C2P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2055</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">8.3</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C3_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Vieillesse deplafonnee</field>
<field name="code">C3</field>
<field name="sequence">2060</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.1</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C3_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Vieillesse deplafonnee</field>
<field name="code">C3P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2065</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.6</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C4_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Allocations familiales</field>
<field name="code">C4</field>
<field name="sequence">2070</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C4_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Allocations familiales</field>
<field name="code">C4P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2075</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">5.4</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C10_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Assurance chomage</field>
<field name="code">C10</field>
<field name="sequence">2080</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">2.40</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C10_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Assurance chomage</field>
<field name="code">C10P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2085</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">4</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C11_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGS (FNGS)</field>
<field name="code">C11</field>
<field name="sequence">2090</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C11_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGS (FNGS)</field>
<field name="code">C11P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2095</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.3</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C16_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">ARRCO Cadre Tranche A</field>
<field name="code">C16</field>
<field name="sequence">2140</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">3</field>
<field name="amount_percentage_base">min(categories.BRUT,TA)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C16_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">ARRCO Cadre Tranche A</field>
<field name="code">C16P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2145</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">4.5</field>
<field name="amount_percentage_base">min(categories.BRUT,TA)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C17_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGIRC et GMP Cadre Tranche B</field>
<field name="code">C17</field>
<field name="sequence">2150</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > TA</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">7.7</field>
<field name="amount_percentage_base">min(categories.BRUT-TA,TB-TA)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C17_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGIRC et GMP Cadre Tranche B</field>
<field name="code">C17P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2155</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > TA</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">12.6</field>
<field name="amount_percentage_base">min(categories.BRUT-TA,TB-TA)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C38_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGIRC Cadre Tranche C</field>
<field name="code">C38</field>
<field name="sequence">2160</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > TB</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">min(categories.BRUT-TB,TC-TB)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C38_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGIRC Cadre Tranche C</field>
<field name="code">C38P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2165</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > TB</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">min(categories.BRUT-TB,TC-TB)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C39_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGFF Cadre Tranche A</field>
<field name="code">C18</field>
<field name="sequence">2170</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.8</field>
<field name="amount_percentage_base">min(categories.BRUT,TA)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C39_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGFF Cadre Tranche A</field>
<field name="code">C18P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2175</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.2</field>
<field name="amount_percentage_base">min(categories.BRUT,TA)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C18_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGFF Non-cadre Tranche B</field>
<field name="code">C18</field>
<field name="sequence">2180</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > TA</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.9</field>
<field name="amount_percentage_base">min(categories.BRUT-TA,TB-TA)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C18_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGFF Cadre Tranche B</field>
<field name="code">C18P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2185</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > TA</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.3</field>
<field name="amount_percentage_base">min(categories.BRUT-TA,TB-TA)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C19_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">CET</field>
<field name="code">C19</field>
<field name="sequence">2190</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.13</field>
<field name="amount_percentage_base">min(categories.BRUT,TC)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C19_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">CET</field>
<field name="code">C19P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2195</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.22</field>
<field name="amount_percentage_base">min(categories.BRUT,TC)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C20_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">APEC</field>
<field name="code">C20</field>
<field name="sequence">2200</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.024</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C20_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">APEC</field>
<field name="code">C20P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2205</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.036</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C21_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Assurance deces cadres</field>
<field name="code">C21</field>
<field name="sequence">2210</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">min(categories.BRUT,TA)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C21_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Assurance deces cadres</field>
<field name="code">C21P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2215</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.5</field>
<field name="amount_percentage_base">min(categories.BRUT,TA)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C5_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Accident du travail</field>
<field name="code">C5</field>
<field name="sequence">2220</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C5_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Accident du travail</field>
<field name="code">C5P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2225</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C40_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Taxe Prevoyance</field>
<field name="code">C40</field>
<field name="sequence">2238</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.PREV != 0</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.PREV</field>
<field name="register_id" ref="hr_prevoyance_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C40_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Taxe Prevoyance</field>
<field name="code">C40P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2239</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.PREV != 0</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">8</field>
<field name="amount_percentage_base">categories.PREV</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C7_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">FNAL -20 Employes</field>
<field name="code">C7</field>
<field name="sequence">2240</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C7_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">FNAL -20 Employes</field>
<field name="code">C7P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2245</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.1</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C8_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">FNAL +20 Employes</field>
<field name="code">C8</field>
<field name="sequence">2250</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C8_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">FNAL +20 Employes</field>
<field name="code">C8P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2255</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.5</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C9_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Versement Transport</field>
<field name="code">C9</field>
<field name="sequence">2260</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="amount_select">percentage</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C9_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Versement Transport</field>
<field name="code">C9P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2265</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="amount_select">percentage</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C22_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Effort a la construction</field>
<field name="code">C22</field>
<field name="sequence">2270</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C22_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Effort a la construction</field>
<field name="code">C22P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2275</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.45</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C23_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Taxe d'apprentissage</field>
<field name="code">C23</field>
<field name="sequence">2280</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C23_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Taxe d'apprentissage</field>
<field name="code">C23P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2285</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.5</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C24_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Contribution additionnelle au developpement de l'apprentissage</field>
<field name="code">C24</field>
<field name="sequence">2290</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C24_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Contribution additionnelle au developpement de l'apprentissage</field>
<field name="code">C24P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2295</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.18</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C25_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Formation professionnelle 10- salaries</field>
<field name="code">C25</field>
<field name="sequence">2300</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">9</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C25_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Formation professionnelle 10- salaries</field>
<field name="code">C25P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2305</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">9</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.55</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C26_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Formation professionnelle 10-19 salaries</field>
<field name="code">C26</field>
<field name="sequence">2310</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C26_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Formation professionnelle 10-19 salaries</field>
<field name="code">C26P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2315</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.05</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C27_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Formation professionnelle 20+ salaries</field>
<field name="code">C27</field>
<field name="sequence">2320</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C27_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Formation professionnelle 20+ salaries</field>
<field name="code">C27P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2325</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.60</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C29_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">CSG deductible</field>
<field name="code">C29</field>
<field name="sequence">2500</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">5.1</field>
<field name="amount_percentage_base">(categories.BRUT + categories.PREV)*0.9825</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_total_charges_salariales" model="hr.salary.rule">
<field name="name">Total des charges salariales</field>
<field name="sequence">2510</field>
<field name="code">SALC</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="True"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.SALC</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C30_employe" model="hr.salary.rule">
<field name="category_id" ref="RETENUES"/>
<field name="name">CRDS</field>
<field name="code">C30</field>
<field name="sequence">2560</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.5</field>
<field name="amount_percentage_base">(categories.BRUT + categories.PREV)*0.9825</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employe_cadre_C28_employe" model="hr.salary.rule">
<field name="category_id" ref="RETENUES"/>
<field name="name">CSG non deductible</field>
<field name="code">C28</field>
<field name="sequence">2550</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">2.4</field>
<field name="amount_percentage_base">(categories.BRUT + categories.PREV)*0.9825</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_total_retenues" model="hr.salary.rule">
<field name="name">Total Retenues</field>
<field name="sequence">99999</field>
<field name="category_id" ref="other_totals"/>
<field name="code">RET</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="appears_on_payslip" eval="True"/>
<field name="amount_python_compute">result = categories.RETENUES</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_cumul_imposable" model="hr.salary.rule">
<field name="name">Cumul Imposable</field>
<field name="sequence">99999</field>
<field name="category_id" ref="C_IMP"/>
<field name="code">C_IMP</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="appears_on_payslip" eval="False"/>
<field name="amount_python_compute">result = BRUT - categories.SALC</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_fr_hr_payroll.hr_payroll_salary_structure_employe_cadre')),
('code', '=', 'NET')]"/>
<value eval="{
'name': 'Net',
'sequence': 100000,
'category_id': ref('hr_payroll.NET'),
'amount_python_compute': 'result = BRUT - categories.RETENUES',
}"/>
</function>
<record id="rule_employee_cadre_total_charges_patronales" model="hr.salary.rule">
<field name="name">Total Charges Patronales</field>
<field name="sequence">150000</field>
<field name="code">TCOMP</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.COMP</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
<record id="rule_employee_cadre_total" model="hr.salary.rule">
<field name="name">Cout total pour l'entreprise</field>
<field name="sequence">200000</field>
<field name="code">TOTAL</field>
<field name="category_id" ref="TOTAL"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BRUT + categories.COMP</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_cadre"/>
</record>
</odoo>
@@ -0,0 +1,819 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Salary Structure -->
<record id="hr_payroll_salary_structure_employe_non_cadre" model="hr.payroll.structure">
<field name="code">Fr-NC</field>
<field name="name">Employe non-cadre</field>
<field name="country_id" ref="base.fr"/>
</record>
<!-- HR SALARY RULES-->
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_fr_hr_payroll.hr_payroll_salary_structure_employe_non_cadre')),
('code', '=', 'BASIC')]"/>
<value eval="{
'code': 'BASE',
'sequence': 1}"/>
</function>
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_fr_hr_payroll.hr_payroll_salary_structure_employe_non_cadre')),
('code', '=', 'GROSS')]"/>
<value eval="{
'name': 'Salaire Brut',
'code': 'BRUT',
'sequence': 1000,
'category_id': ref('hr_payroll.GROSS'),
'amount_python_compute': 'result = categories.BASE + categories.INDM - categories.DED',
}"/>
</function>
<record id="rule_employe_non_cadre_secu" model="hr.salary.rule">
<field name="name">Plafond Securite Sociale</field>
<field name="code">SECU</field>
<field name="sequence">1010</field>
<field name="category_id" ref="SECU"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.employee_id.company_id.plafond_secu</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_tranche_a" model="hr.salary.rule">
<field name="name">Plafond Tranche A</field>
<field name="code">TA</field>
<field name="sequence">1011</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_tranche_b" model="hr.salary.rule">
<field name="name">Plafond Tranche B</field>
<field name="code">TB</field>
<field name="sequence">1012</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU * 4</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_tranche_c" model="hr.salary.rule">
<field name="name">Plafond Tranche C</field>
<field name="code">TC</field>
<field name="sequence">1013</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU * 8</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_tranche_1" model="hr.salary.rule">
<field name="name">Plafond Tranche 1</field>
<field name="code">T1</field>
<field name="sequence">1014</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_tranche_2" model="hr.salary.rule">
<field name="name">Plafond Tranche 2</field>
<field name="code">T2</field>
<field name="sequence">1015</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = SECU * 3</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C1_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Assurance maladie, maternite, invalidite, deces, solidaritee des personnes agees et handicapees</field>
<field name="code">C1</field>
<field name="sequence">2040</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.75</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C1_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Assurance maladie, maternite, invalidite, deces, solidaritee des personnes agees et handicapees</field>
<field name="code">C1P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2045</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">13.10</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C2_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Vieillesse plafonnee</field>
<field name="code">C2</field>
<field name="sequence">2050</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">6.65</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C2_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Vieillesse plafonnee</field>
<field name="code">C2P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2055</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">8.3</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C3_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Vieillesse deplafonnee</field>
<field name="code">C3</field>
<field name="sequence">2060</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.1</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C3_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Vieillesse deplafonnee</field>
<field name="code">C3P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2065</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.6</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C4_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Allocations familiales</field>
<field name="code">C4</field>
<field name="sequence">2070</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C4_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Allocations familiales</field>
<field name="code">C4P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2075</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">5.4</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C10_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Assurance chomage</field>
<field name="code">C10</field>
<field name="sequence">2080</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">2.40</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C10_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Assurance chomage</field>
<field name="code">C10P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2085</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">4</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C11_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGS (FNGS)</field>
<field name="code">C11</field>
<field name="sequence">2090</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C11_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGS (FNGS)</field>
<field name="code">C11P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2095</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.3</field>
<field name="amount_percentage_base">min(categories.BRUT,TB)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C12_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">ARRCO Non-cadre Tranche 1</field>
<field name="code">C12</field>
<field name="sequence">2100</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">3</field>
<field name="amount_percentage_base">min(categories.BRUT,T1)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C12_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">ARRCO Non-cadre Tranche 1</field>
<field name="code">C12P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2105</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">4.5</field>
<field name="amount_percentage_base">min(categories.BRUT,T1)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C14_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">ARRCO Non-cadre Tranche 2</field>
<field name="code">C14</field>
<field name="sequence">2110</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > T1</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">8</field>
<field name="amount_percentage_base">min(categories.BRUT-T1,T2-T1)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C14_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">ARRCO Non-cadre Tranche 2</field>
<field name="code">C14P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2115</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > T1</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">12</field>
<field name="amount_percentage_base">min(categories.BRUT-T1,T2-T1)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C13_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGFF Non-cadre Tranche 1</field>
<field name="code">C13</field>
<field name="sequence">2120</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.8</field>
<field name="amount_percentage_base">min(categories.BRUT,T1)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C13_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGFF Non-cadre Tranche 1</field>
<field name="code">C13P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2125</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.2</field>
<field name="amount_percentage_base">min(categories.BRUT,T1)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C15_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">AGFF Non-cadre Tranche 2</field>
<field name="code">C15</field>
<field name="sequence">2130</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > T1</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.9</field>
<field name="amount_percentage_base">min(categories.BRUT-T1,T2-T1)</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C15_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">AGFF Non-cadre Tranche 2</field>
<field name="code">C15P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2135</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.BRUT > T1</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.3</field>
<field name="amount_percentage_base">min(categories.BRUT-T1,T2-T1)</field>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C5_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Accident du travail</field>
<field name="code">C5</field>
<field name="sequence">2220</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_retraite_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C5_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Accident du travail</field>
<field name="code">C5P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2225</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C40_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Taxe Prevoyance</field>
<field name="code">C40</field>
<field name="sequence">2238</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.PREV != 0</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.PREV</field>
<field name="register_id" ref="hr_prevoyance_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C40_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Taxe Prevoyance</field>
<field name="code">C40P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2239</field>
<field name="condition_select">python</field>
<field name="condition_python">result = categories.PREV != 0</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">8</field>
<field name="amount_percentage_base">categories.PREV</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C7_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">FNAL -20 Employes</field>
<field name="code">C7</field>
<field name="sequence">2240</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C7_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">FNAL -20 Employes</field>
<field name="code">C7P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2245</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.1</field>
<field name="amount_percentage_base">min(categories.BRUT,SECU)</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C8_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">FNAL +20 Employes</field>
<field name="code">C8</field>
<field name="sequence">2250</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C8_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">FNAL +20 Employes</field>
<field name="code">C8P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2255</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.5</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C9_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Versement Transport</field>
<field name="code">C9</field>
<field name="sequence">2260</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="amount_select">percentage</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C9_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Versement Transport</field>
<field name="code">C9P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2265</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="amount_select">percentage</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C22_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Effort a la construction</field>
<field name="code">C22</field>
<field name="sequence">2270</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C22_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Effort a la construction</field>
<field name="code">C22P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2275</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.45</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C23_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Taxe d'apprentissage</field>
<field name="code">C23</field>
<field name="sequence">2280</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C23_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Taxe d'apprentissage</field>
<field name="code">C23P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2285</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.5</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C24_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Contribution additionnelle au developpement de l'apprentissage</field>
<field name="code">C24</field>
<field name="sequence">2290</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C24_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Contribution additionnelle au developpement de l'apprentissage</field>
<field name="code">C24P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2295</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.18</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C25_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Formation professionnelle 10- salaries</field>
<field name="code">C25</field>
<field name="sequence">2300</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">9</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C25_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Formation professionnelle 10- salaries</field>
<field name="code">C25P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2305</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_max">9</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.55</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C26_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Formation professionnelle 10-19 salaries</field>
<field name="code">C26</field>
<field name="sequence">2310</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C26_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Formation professionnelle 10-19 salaries</field>
<field name="code">C26P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2315</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">10</field>
<field name="condition_range_max">19</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.05</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C27_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">Formation professionnelle 20+ salaries</field>
<field name="code">C27</field>
<field name="sequence">2320</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C27_employer" model="hr.salary.rule">
<field name="category_id" ref="hr_payroll.COMP"/>
<field name="name">Formation professionnelle 20+ salaries</field>
<field name="code">C27P</field>
<field name="appears_on_payslip" eval="False"/>
<field name="sequence">2325</field>
<field name="condition_select">range</field>
<field name="condition_range">contract.employee_id.company_id.nombre_employes</field>
<field name="condition_range_min">20</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">1.60</field>
<field name="amount_percentage_base">categories.BRUT</field>
<field name="register_id" ref="hr_cci_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C29_employe" model="hr.salary.rule">
<field name="category_id" ref="SALC"/>
<field name="name">CSG deductible</field>
<field name="code">C29</field>
<field name="sequence">2500</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">5.1</field>
<field name="amount_percentage_base">(categories.BRUT + categories.PREV)*0.9825</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_total_charges_salariales" model="hr.salary.rule">
<field name="name">Total des charges salariales</field>
<field name="sequence">2510</field>
<field name="code">SALC</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="True"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.SALC</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C30_employe" model="hr.salary.rule">
<field name="category_id" ref="RETENUES"/>
<field name="name">CRDS</field>
<field name="code">C30</field>
<field name="sequence">2560</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">0.5</field>
<field name="amount_percentage_base">(categories.BRUT + categories.PREV)*0.9825</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_C28_employe" model="hr.salary.rule">
<field name="category_id" ref="RETENUES"/>
<field name="name">CSG non deductible</field>
<field name="code">C28</field>
<field name="sequence">2550</field>
<field name="condition_select">none</field>
<field name="amount_select">percentage</field>
<field name="amount_percentage">2.4</field>
<field name="amount_percentage_base">(categories.BRUT + categories.PREV)*0.9825</field>
<field name="appears_on_payslip" eval="True"/>
<field name="register_id" ref="hr_urssaf_register"/>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_total_retenues" model="hr.salary.rule">
<field name="name">Total Retenues</field>
<field name="sequence">99999</field>
<field name="category_id" ref="other_totals"/>
<field name="code">RET</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="appears_on_payslip" eval="True"/>
<field name="amount_python_compute">result = categories.RETENUES</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_cumul_imposable" model="hr.salary.rule">
<field name="name">Cumul Imposable</field>
<field name="sequence">99999</field>
<field name="category_id" ref="C_IMP"/>
<field name="code">C_IMP</field>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="appears_on_payslip" eval="False"/>
<field name="amount_python_compute">result = BRUT - categories.SALC</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<function model="hr.salary.rule" name="write">
<value model="hr.salary.rule" search="[
('struct_id', '=', ref('l10n_fr_hr_payroll.hr_payroll_salary_structure_employe_non_cadre')),
('code', '=', 'NET')]"/>
<value eval="{
'name': 'Net',
'sequence': 100000,
'category_id': ref('hr_payroll.NET'),
'amount_python_compute': 'result = BRUT - categories.RETENUES',
}"/>
</function>
<record id="rule_employe_non_cadre_total_charges_patronales" model="hr.salary.rule">
<field name="name">Total Charges Patronales</field>
<field name="sequence">150000</field>
<field name="code">TCOMP</field>
<field name="category_id" ref="other_totals"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.COMP</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
<record id="rule_employe_non_cadre_total" model="hr.salary.rule">
<field name="name">Cout total pour l'entreprise</field>
<field name="sequence">200000</field>
<field name="code">TOTAL</field>
<field name="category_id" ref="TOTAL"/>
<field name="appears_on_payslip" eval="False"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = categories.BRUT + categories.COMP</field>
<field name="struct_id" ref="hr_payroll_salary_structure_employe_non_cadre"/>
</record>
</odoo>
+4 -14
View File
@@ -8,16 +8,6 @@ class FichePayeParser(models.AbstractModel):
_name = 'report.l10n_fr_hr_payroll.report_l10n_fr_fiche_paye'
_description = "French Pay Slip"
def get_payslip_lines(self, objs):
res = []
ids = []
for item in objs:
if item.appears_on_payslip is True and not item.salary_rule_id.parent_rule_id:
ids.append(item.id)
if ids:
res = self.env['hr.payslip.line'].browse(ids)
return res
def get_total_by_rule_category(self, obj, code):
category_total = 0
category_id = self.env['hr.salary.rule.category'].search([('code', '=', code)], limit=1).id
@@ -27,8 +17,9 @@ class FichePayeParser(models.AbstractModel):
category_total += line.total
return category_total
def get_employer_line(self, obj, parent_line):
return self.env['hr.payslip.line'].search([('slip_id', '=', obj.id), ('salary_rule_id.parent_rule_id.id', '=', parent_line.salary_rule_id.id)], limit=1)
def _get_employer_line(self, line):
code = line.code or ''
return line.slip_id.line_ids.filtered(lambda line: line.code == '%sP' % code)
@api.model
def _get_report_values(self, docids, data=None):
@@ -39,7 +30,6 @@ class FichePayeParser(models.AbstractModel):
'data': data,
'docs': payslip,
'lang': "fr_FR",
'get_payslip_lines': self.get_payslip_lines,
'get_total_by_rule_category': self.get_total_by_rule_category,
'get_employer_line': self.get_employer_line,
'get_employer_line': self._get_employer_line,
}
@@ -74,34 +74,35 @@
</tr>
</thead>
<tbody>
<tr t-foreach="get_payslip_lines(o.line_ids)" t-as="p">
<tr t-foreach="o.line_ids.filtered(lambda line: line.appears_on_payslip)" t-as="line">
<td>
<span t-esc="p.code or ''"/>
<span t-esc="line.code or ''"/>
</td>
<td>
<span t-esc="p.name or ''"/>
<span t-esc="line.name or ''"/>
</td>
<td>
<t t-if="p.amount_select== 'percentage'">
<span t-esc="p.amount or ''"/>
<t t-if="line.amount_select== 'percentage'">
<span t-esc="line.amount or ''"/>
</t>
<t t-if="p.amount_select== 'fix'">
<span t-esc="p.quantity or ''"/>
<t t-if="line.amount_select== 'fix'">
<span t-esc="line.quantity or ''"/>
</t>
</td>
<td>
<t t-if="p.amount_select == 'percentage'">
<span t-esc="p.rate or ''"/>
<t t-if="line.amount_select == 'percentage'">
<span t-esc="line.rate or ''"/>
</t>
</td>
<td>
<span t-esc="p.total or ''"/>
<span t-esc="line.total or ''"/>
</td>
<t t-set="employer_line" t-value="get_employer_line(line)"/>
<td>
<span t-esc="employer_line.rate if employer_line else ''"/>
</td>
<td>
<span t-esc="get_employer_line(o, p) and get_employer_line(o, p).rate or ''"/>
</td>
<td>
<span t-esc="get_employer_line(o,p) and get_employer_line(o,p).total or ''"/>
<span t-esc="employer_line.total if employer_line else ''"/>
</td>
</tr>
</tbody>
+13 -14
View File
@@ -22,18 +22,17 @@ Indian Payroll Salary Rules.
- Yearly Salary by Head and Yearly Salary by Employee Report
""",
'data': [
'views/l10n_in_hr_payroll_view.xml',
'data/l10n_in_hr_payroll_data.xml',
'data/hr.salary.rule.csv',
'security/ir.model.access.csv',
'views/l10n_in_hr_payroll_report.xml',
'data/l10n_in_hr_payroll_sequence_data.xml',
'views/report_payslip_details_template.xml',
'views/report_hr_salary_employee_bymonth_template.xml',
'wizard/hr_salary_employee_bymonth_view.xml',
'wizard/hr_yearly_salary_detail_view.xml',
'views/report_hr_yearly_salary_detail_template.xml',
'views/report_payroll_advice_template.xml',
],
'demo': ['demo/l10n_in_hr_payroll_demo.xml'],
'views/l10n_in_hr_payroll_view.xml',
'data/l10n_in_hr_payroll_data.xml',
'security/ir.model.access.csv',
'views/l10n_in_hr_payroll_report.xml',
'data/l10n_in_hr_payroll_sequence_data.xml',
'views/report_payslip_details_template.xml',
'views/report_hr_salary_employee_bymonth_template.xml',
'wizard/hr_salary_employee_bymonth_view.xml',
'wizard/hr_yearly_salary_detail_view.xml',
'views/report_hr_yearly_salary_detail_template.xml',
'views/report_payroll_advice_template.xml',
],
'demo': ['data/l10n_in_hr_payroll_demo.xml'],
}
@@ -1,5 +0,0 @@
"id","amount_select","condition_range_min","condition_range_max","amount_percentage","amount_fix","name","category_id/id","sequence","code","parent_rule_id/id","condition_select","condition_range","amount_percentage_base"
1,"fix",1,1,,100,"Education Allowance For One Child",hr_payroll.ALW,23,"CHEAONE","hr_payroll_rule_child1","range","employee.children",
2,"fix",2,10,,200,"Education Allowance For Two Children",hr_payroll.ALW,24,"CHEATWO","hr_payroll_rule_child1","range","employee.children",
3,"fix",1,1,,300,"Child Hostel Allowance For One Child",hr_payroll.ALW,26,"CHOONE","hr_payroll_rule_child2","range","employee.children",
4,"fix",2,10,,600,"Child Hostel Allowance For Two Children",hr_payroll.ALW,27,"CHOTWO","hr_payroll_rule_child2","range","employee.children",
1 id amount_select condition_range_min condition_range_max amount_percentage amount_fix name category_id/id sequence code parent_rule_id/id condition_select condition_range amount_percentage_base
2 1 fix 1 1 100 Education Allowance For One Child hr_payroll.ALW 23 CHEAONE hr_payroll_rule_child1 range employee.children
3 2 fix 2 10 200 Education Allowance For Two Children hr_payroll.ALW 24 CHEATWO hr_payroll_rule_child1 range employee.children
4 3 fix 1 1 300 Child Hostel Allowance For One Child hr_payroll.ALW 26 CHOONE hr_payroll_rule_child2 range employee.children
5 4 fix 2 10 600 Child Hostel Allowance For Two Children hr_payroll.ALW 27 CHOTWO hr_payroll_rule_child2 range employee.children
@@ -53,469 +53,4 @@
<record id="hr_other_deduction_register" model="hr.contribution.register">
<field name="name">Register for Other Deduction from Employer</field>
</record>
<!-- Hr Salary Rules for allowance-->
<record id="hr_salary_rule_da" model="hr.salary.rule">
<field name="code">DA</field>
<field name="name">Dearness Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">contract.wage</field>
<field name="amount_percentage" eval="50"/>
<field name="sequence" eval="13"/>
<field name="note">Dearness allowance (D.A.) is part of a person's salary. It is calculated as a percent of the basic salary. This amount is then added to the basic salary along with house rent allowance to get the total salary. Or you can say that The Dearness Allowance is a part of the total compensation a person receives for having performed his or her job.</field>
</record>
<record id="hr_salary_rule_houserentallowancemetro_nonmetro" model="hr.salary.rule">
<field name="code">HRAMN</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and
((contract.wage + categories.DA) * contract.house_rent_allowance_metro_nonmetro / 100)
or (contract.wage * contract.house_rent_allowance_metro_nonmetro / 100))</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">House Rent Allowance</field>
<field name="register_id" ref="hr_houserent_allowance_register"/>
<field name="sequence" eval="51"/>
<field name="note">HRA is an allowance given by the employer to the employee for taking care of his rental or accommodation expenses.</field>
</record>
<record id="hr_salary_trans_allownce" model="hr.salary.rule">
<field name="code">TCA</field>
<field name="name">Transport/Conveyance Allownace</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="800.0" name="amount_fix"/>
<field name="sequence" eval="14"/>
<field name="note">A conveyance allowance refers to an amount of money reimbursed to someone for the operation of a vehicle or the riding of a vehicle. The allowance is typically a designated amount or percentage of total transportation expenses that is referenced in a country's tax laws or code. Organizations and private or public businesses may also offer a conveyance allowance in addition to reimbursing employees or members for transportation expenses. In this instance, the conveyance allowance may identify an unusual transport occurrence that may not be covered by a designated travel expense report such as travel to a specific job site that requires a daily bus or taxi ride.</field>
</record>
<record id="hr_salary_rule_special" model="hr.salary.rule">
<field name="code">SA</field>
<field name="name">Grade/Special/Management/Supplementary Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.supplementary_allowance)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.supplementary_allowance</field>
<field name="sequence" eval="20"/>
<field name="note">This allowance is normally given as an additional benefit to employees and is fully taxable.</field>
</record>
<record id="hr_payroll_rule_child1" model="hr.salary.rule">
<field name="code">CHEA</field>
<field name="name">Child Education Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(employee.children)</field>
<field name="amount_select">fix</field>
<field name="sequence" eval="18"/>
<field name="note">Per school going child 1200 per annum is non-taxable.Maximum for 2 children, so max 2400 per annum becomes non-taxable.</field>
</record>
<record id="hr_payroll_rule_child2" model="hr.salary.rule">
<field name="code">CHEAH</field>
<field name="name">Child Hostel Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(employee.children)</field>
<field name="amount_select">fix</field>
<field name="note">In case the children are in hostel, the exemption available for child.</field>
<field name="sequence" eval="19"/>
</record>
<record id="hr_payroll_rule_city1" model="hr.salary.rule">
<field name="code">CBDA</field>
<field name="name">City Compensatory Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="sequence" eval="21"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and ((contract.wage + categories.DA) * 0.10)
or (contract.wage * 0.10))</field>
<field name="note">This allowance is paid to Employees who are posted in big cities. The purpose is to compensate the high cost of living in cities like Mumbai, Delhi, etc. However it is Fully Taxable.</field>
</record>
<record id="hr_payroll_rule_metrocity" model="hr.salary.rule">
<field name="code">CMETRO</field>
<field name="name">City Allowance for Metro city</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="sequence" eval="22"/>
<field name="amount_select">fix</field>
<field name="amount_fix">850.0</field>
</record>
<record id="hr_payroll_rule_nonmetrocity" model="hr.salary.rule">
<field name="code">CNMETRO</field>
<field name="name">City Allowance for Non Metro city</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="sequence" eval="25"/>
<field name="amount_select">fix</field>
<field name="amount_fix">800.0</field>
</record>
<record id="hr_salary_rule_arrears" model="hr.salary.rule">
<field name="code">ARRE</field>
<field name="name">Arrears</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.ARS and inputs.ARS.amount</field>
<field eval="0.0" name="amount_fix"/>
<field name="sequence" eval="28"/>
<field name="note">Generally arrears are fully taxable, but employee may claim exemption u/s 89(1).
One would need to compute income tax on the arrears if it would have been received in actual year.
Now difference of income tax between payment year and actual year would be allowed for deduction.</field>
</record>
<record id="hr_salary_rule_lta" model="hr.salary.rule">
<field name="code">LTA</field>
<field name="name">Leave Travel Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">contract.wage</field>
<field name="amount_percentage" eval="8.33"/>
<field name="sequence" eval="29"/>
<field name="note">As per Income tax rules of India, if transport bills for LTA are not provided,the amount will be taxed. E.g. If an employee has LTA allowance as Rs 50,000 in his CTC(cost to company),and he provides proofs of Rs 40,000 (boarding pass,air tickets, taxi vouchers) then income tax will be deducted for rest of the Rs 10,000. Does not matter whats the amount of LTA in an employee’s package, income tax laws only permits domestic air tickets only for LTA claim.</field>
</record>
<record id="hr_salary_rule_le" model="hr.salary.rule">
<field name="code">LE</field>
<field name="name">Leave Encashment</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.LE and inputs.LE.amount</field>
<field name="sequence" eval="30"/>
<field name="note">Payment by way of leave encashment received by Central and State Govt.employees at the time of retirement in respect of the period of earned leave at credit is fully exempt. In case of other employees, the exemption is to be limited to minimum of all below:
1.The actual amount received
2.The cash equivalent of leave balance (max 30 days per year of service)
3.Maximum of 10 months of leave encashment, based on last 10 months average salary
4.Rs. 3 Lakh</field>
</record>
<record id="hr_salary_rule_performance" model="hr.salary.rule">
<field name="code">PI</field>
<field name="name">Performance Incentive</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.PERF and inputs.PERF.amount</field>
<field name="sequence" eval="31"/>
<field name="note">This would be fully taxable based on incentive.</field>
</record>
<record id="hr_salary_rule_bonus" model="hr.salary.rule">
<field name="code">BONUS</field>
<field name="name">Bonus</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.BNS and inputs.BNS.amount</field>
<field name="sequence" eval="41"/>
<field name="note">This would be fully taxable based on Bonus.</field>
</record>
<record id="hr_salary_rule_medical_allow" model="hr.salary.rule">
<field name="code">MEDA</field>
<field name="name">Medical Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="1250.0" name="amount_fix"/>
<field name="sequence" eval="43"/>
<field name="note">This component is on-taxable up to 15000 per year (or Rs 1250 per month) on producing medical bills.</field>
</record>
<record id="hr_salary_rule_medical" model="hr.salary.rule">
<field name="code">MEDA</field>
<field name="name">Medical Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.MR and inputs.MR.amount</field>
<field name="sequence" eval="32"/>
<field name="note">This component is on-taxable up to 15000 per year (or Rs 1250 per month) on producing medical bills.</field>
</record>
<record id="hr_salary_rule_food_coupon" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field eval="50" name="amount_fix"/>
<field name="quantity">worked_days.WORK100.number_of_days</field>
<field name="code">FC</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Food Allowance</field>
<field name="register_id" ref="hr_food_coupen_register"/>
<field name="sequence" eval="33"/>
</record>
<record id="hr_salary_rule_journals" model="hr.salary.rule">
<field name="code">PERJ</field>
<field name="name">Periodical Journals</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.PJ and inputs.PJ.amount</field>
<field name="sequence" eval="34"/>
<field name="note">Some employers may provide component for buying magazines, journals and books as a part of knowledge enhancement for business growth.This part would become non taxable on providing original bills.</field>
</record>
<record id="hr_salary_rule_uniform_senior" model="hr.salary.rule">
<field name="code">UNIFS</field>
<field name="name">Uniform/Dress Allowance for Senior Executive</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="1000" name="amount_fix"/>
<field name="sequence" eval="35"/>
<field name="note">Some sections of employees mat get allowance for purchase of office dress/uniform.In such case, the component would become non-taxable.</field>
</record>
<record id="hr_salary_rule_uniform_junior" model="hr.salary.rule">
<field name="code">UNIFJ</field>
<field name="name">Uniform/Dress Allowance for Junior Executive</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="600" name="amount_fix"/>
<field name="sequence" eval="42"/>
<field name="note">Some sections of employees mat get allowance for purchase of office dress/uniform.In such case, the component would become non-taxable.</field>
</record>
<record id="hr_salary_rule_telephone" model="hr.salary.rule">
<field name="code">TELR</field>
<field name="name">Telephone Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.TR and inputs.TR.amount</field>
<field name="sequence" eval="36"/>
<field name="note">In some of the cases, companies may provide a component for telephone bills.Employees may provide actual phone usage bills to reimburse this component and make it non-taxable.
</field>
</record>
<record id="hr_salary_rule_prof_develope" model="hr.salary.rule">
<field name="code">PDA</field>
<field name="name">Professional Development Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="0.0" name="amount_fix"/>
<field name="sequence" eval="37"/>
</record>
<record id="hr_payroll_rule_car" model="hr.salary.rule">
<field name="code">CAR</field>
<field name="name">Car Expenses Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.CEI and inputs.CEI.amount</field>
<field name="sequence" eval="38"/>
<field name="note">In case company provides component for this and employee use self owned car for official and personal purposes, Rs 1800 per month would be non-taxable on showing bills for fuel or can maintenance. This amount would be Rs 2400 in case car is more capacity than 1600cc.</field>
</record>
<record id="hr_salary_rule_internet" model="hr.salary.rule">
<field name="code">INT</field>
<field name="name">Internet Expense</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.IE and inputs.IE.amount</field>
<field name="sequence" eval="39"/>
<field name="note">Employer may also provide reimbursement of internet expenses and thus this would become non taxable.</field>
</record>
<record id="hr_salary_rule_driver" model="hr.salary.rule">
<field name="code">DRI</field>
<field name="name">Driver Salary</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.driver_salay)</field>
<field name="amount_select">fix</field>
<field eval="900.0" name="amount_fix"/>
<field name="sequence" eval="40"/>
<field name="note">Rs. 900 per month (non taxable)</field>
</record>
<!--hr salary rules for Deductions -->
<record id="hr_payslip_rule_tds" model="hr.salary.rule">
<field name="code">TDS</field>
<field name="name">Tax Deducted at Source</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.tds)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -(contract.tds)</field>
<field name="register_id" ref="hr_tds_register"/>
<field name="sequence" eval="140"/>
<field name="note">As per income tax rules, all payment which are taxable in nature should be done after deduction of taxes at the source itself. Hence employer compute income tax on salary payment and deduct it every month. This TDS is based on employee’s saving/investment declaration at the start of year. If investments for tax saving is not done, large amount may be deducted in last few months.</field>
</record>
<record id="hr_payslip_line_professional_tax" model="hr.salary.rule">
<field name="code">PTD</field>
<field name="name">Professional Tax</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.wage &gt;= 3000 </field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (-200 if contract.wage &gt;= 12000
else -150 if ((contract.wage &gt;= 9000) and (contract.wage &lt;= 11999))
else -80 if ((contract.wage &gt;= 6000) and (contract.wage &lt;= 8999))
else -20 if ((contract.wage &gt;= 3000) and (contract.wage &lt;= 5999))
else -0)</field>
<field name="register_id" ref="hr_professional_tax_deduction_register"/>
<field eval="145" name="sequence"/>
<field name="note">Workers living in states that impose the professional tax must submit a payment each half-year for the right to practice a profession or trade. It applies equally to employees who work for the national or state government, and those employed by private corporations. The professional tax uses a six-month accounting system, which divides the year into two periods, beginning on April 1 and October 1.</field>
</record>
<record id="hr_payslip_rule_epf" model="hr.salary.rule">
<field name="code">EPMF</field>
<field name="name">Employee's PF Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.12)
or - (contract.wage * 0.12))</field>
<field name= "note">Employer contribution does not become part of employee’s income and hence income tax is not payable on this part.</field>
<field name="register_id" ref="hr_register_provident_fund"/>
<field name="sequence" eval="150"/>
</record>
<record id="hr_payslip_rule_enps" model="hr.salary.rule">
<field name="code">ENPFC</field>
<field name="name">Employee's NPS Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.10)
or - (contract.wage * 0.10))</field>
<field name="sequence" eval="155"/>
<field name="register_id" ref="hr_nps_contribution_register"/>
<field name="note">Employee can claim deduction even of employer's contribution to NPS.</field>
</record>
<record id="hr_payslip_rule_vpf" model="hr.salary.rule">
<field name="code">VPF</field>
<field name="name">Voluntary Provident Fund Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.voluntary_provident_fund)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and
- ((contract.wage + categories.DA) * contract.voluntary_provident_fund / 100)
or - (contract.wage * contract.voluntary_provident_fund / 100))</field>
<field name="sequence" eval="160"/>
<field name="register_id" ref="hr_vpf_contribution_register"/>
<field name="note">VPF is a safe option wherein you can contribute more than the PF ceiling of 12% that has been mandated by the government.This additional amount enjoys all the benefits of PF except that the employer is not liable to contribute any extra amount apart from 12%.An added advantage is that the interest rate is equal to the interest rate of PF and he withdrawal is tax free. Please note that the maximum contribution towards VPF is 100% of your Basic.The highest rate of interest (close to 9%) makes it a very attractive saving scheme. Because of these advantages many employees chose not to close their PF account even after getting employment else where other than India.Employees also get a major tax break on their entire contribution to the fund up to a ceiling of Rs. 70,000/-</field>
</record>
<record id="hr_payslip_rule_cpt" model="hr.salary.rule">
<field name="code">CPT</field>
<field name="name">Deduction for Company Provided Transport</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">none</field>
<field name="amount_select">fix</field>
<field eval="-1500.0" name="amount_fix"/>
<field name="register_id" ref="hr_company_transport_register"/>
<field name="sequence" eval="165"/>
<field name="appears_on_payslip" eval="False"/>
<field name="note">Company provided transport amount is based on company.</field>
</record>
<record id="hr_salary_rule_food_coupon_ded" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field eval="-50" name="amount_fix"/>
<field name="quantity">worked_days.WORK100.number_of_days</field>
<field name="code">FD</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="name">Deduction Towards Food Coupons</field>
<field name="register_id" ref="hr_food_coupen_register"/>
<field name="sequence" eval="166"/>
</record>
<record id="hr_payslip_rule_lwf_employee" model="hr.salary.rule">
<field name="code">LWFE</field>
<field name="name">Employee's Deduction Towards State Labour Welfare Fund</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-3.0" name="amount_fix"/>
<field name="sequence" eval="170"/>
<field name="register_id" ref="hr_labour_Welfare_fund_register"/>
<field name="note">The LWF is applicable to all the members of the organisation except the Management staff (Staffs having authority to sign on the cheque/official documents on behalf of the organisation). for e.x. Employee Contribution is Rs. 3.00 and Employer contribution Rs. 6.00 Total Rs 9.00 and deposited to the LWF office.It is half yearly contribution (June and December).</field>
</record>
<record id="hr_payslip_rule_lwf_employer" model="hr.salary.rule">
<field name="code">LWF</field>
<field name="name">Employer's Deduction Towards State Labour Welfare Fund </field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-6.0" name="amount_fix"/>
<field name="sequence" eval="171"/>
<field name="register_id" ref="hr_labour_Welfare_fund_register"/>
<field name="appears_on_payslip" eval="False"/>
<field name="note">The LWF is applicable to all the members of the organisation except the Management staff (Staffs having authority to sign on the cheque/official documents on behalf of the organisation). for e.x. Employee Contribution is Rs. 3.00 and Employer contribution Rs. 6.00 Total Rs 9.00 and deposited to the LWF office.It is half yearly contribution (June and December).</field>
</record>
<record id="hr_payslip_rule_cgti" model="hr.salary.rule">
<field name="code">CGTI</field>
<field name="name">Deduction Towards Company Provided Group Term Insurance</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-1000.0" name="amount_fix"/>
<field name="register_id" ref="hr_group_term_insurance_register"/>
<field name="sequence" eval="175"/>
<field name="note">Group term insurance provides a solid foundation to a comprehensive employee benifit program,backed up by government asistance in the form of valuable tax incentives to both employees and employers.</field>
</record>
<record id="hr_payslip_rule_dla" model="hr.salary.rule">
<field name="code">DLA</field>
<field name="name">Deduction Towards Leave Availed</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.LAI and - (inputs.LAI.amount)</field>
<field name="register_id" ref="hr_leave_availed_register"/>
<field name="sequence" eval="180"/>
</record>
<record id="hr_payslip_rule_cmt" model="hr.salary.rule">
<field name="code">CMT</field>
<field name="name">Deduction Towards Company Provided Medical Insurance</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.medical_insurance)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = - (contract.medical_insurance)</field>
<field eval="-50.0" name="amount_fix"/>
<field name="appears_on_payslip" eval="False"/>
<field name="register_id" ref="hr_medical_insurance_register"/>
<field name="sequence" eval="185"/>
</record>
<record id="hr_payslip_rule_ode" model="hr.salary.rule">
<field name="code">ODE</field>
<field name="name">Other Deduction from Employer</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-200.0" name="amount_fix"/>
<field name="appears_on_payslip" eval="False"/>
<field name="register_id" ref="hr_other_deduction_register"/>
<field name="sequence" eval="187"/>
</record>
<record id="hr_payslip_rule_ernps" model="hr.salary.rule">
<field name="code">ENPC</field>
<field name="name">Employer's NPS Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.10)
or - (contract.wage * 0.10))</field>
<field name="sequence" eval="190"/>
<field name="register_id" ref="hr_nps_contribution_register"/>
<field name="appears_on_payslip" eval="False"/>
<field name= "note">Any amount contributed by your employer to your NPS account is treated as part of your salary and is included in your income but you can claim deduction under Section 80C for this too.thus, effectively making it exempt from tax within the limit of 10% of your basic salary. This is very useful and tax efficient for you particularly if you fall in the maximum tax.</field>
</record>
<record id="hr_payslip_rule_erpf" model="hr.salary.rule">
<field name="code">EPF</field>
<field name="name">Employer's PF Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.12)
or - (contract.wage * 0.12))</field>
<field name="sequence" eval="195"/>
<field name="register_id" ref="hr_register_provident_fund"/>
<field name="appears_on_payslip" eval="False"/>
<field name="note">Both the employees and employer contribute to the fund at the rate of 12% of the basic wages, dearness allowance and retaining allowance, if any, payable to employees per month.</field>
</record>
</odoo>
@@ -0,0 +1,516 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Salary Structure -->
<record id="hr_payroll_salary_structure_ind_emp" model="hr.payroll.structure">
<field name="code">NE</field>
<field name="name">Non-Executive Employee</field>
<field name="country_id" ref="base.in"/>
</record>
<!-- Hr Salary Rules for allowance-->
<record id="hr_salary_rule_da" model="hr.salary.rule">
<field name="code">DA</field>
<field name="name">Dearness Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">contract.wage</field>
<field name="amount_percentage" eval="50"/>
<field name="sequence" eval="13"/>
<field name="note">Dearness allowance (D.A.) is part of a person's salary. It is calculated as a percent of the basic salary. This amount is then added to the basic salary along with house rent allowance to get the total salary. Or you can say that The Dearness Allowance is a part of the total compensation a person receives for having performed his or her job.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_houserentallowancemetro_nonmetro" model="hr.salary.rule">
<field name="code">HRAMN</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and
((contract.wage + categories.DA) * contract.house_rent_allowance_metro_nonmetro / 100)
or (contract.wage * contract.house_rent_allowance_metro_nonmetro / 100))</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">House Rent Allowance</field>
<field name="register_id" ref="hr_houserent_allowance_register"/>
<field name="sequence" eval="51"/>
<field name="note">HRA is an allowance given by the employer to the employee for taking care of his rental or accommodation expenses.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_trans_allownce" model="hr.salary.rule">
<field name="code">TCA</field>
<field name="name">Transport/Conveyance Allownace</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="800.0" name="amount_fix"/>
<field name="sequence" eval="14"/>
<field name="note">A conveyance allowance refers to an amount of money reimbursed to someone for the operation of a vehicle or the riding of a vehicle. The allowance is typically a designated amount or percentage of total transportation expenses that is referenced in a country's tax laws or code. Organizations and private or public businesses may also offer a conveyance allowance in addition to reimbursing employees or members for transportation expenses. In this instance, the conveyance allowance may identify an unusual transport occurrence that may not be covered by a designated travel expense report such as travel to a specific job site that requires a daily bus or taxi ride.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_special" model="hr.salary.rule">
<field name="code">SA</field>
<field name="name">Grade/Special/Management/Supplementary Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.supplementary_allowance)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = contract.supplementary_allowance</field>
<field name="sequence" eval="20"/>
<field name="note">This allowance is normally given as an additional benefit to employees and is fully taxable.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payroll_rule_child1" model="hr.salary.rule">
<field name="code">CHEA</field>
<field name="name">Child Education Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(employee.children)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 100 if employee.children == 1 else 200</field>
<field name="sequence" eval="18"/>
<field name="note">Per school going child 1200 per annum is non-taxable.Maximum for 2 children, so max 2400 per annum becomes non-taxable.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payroll_rule_child2" model="hr.salary.rule">
<field name="code">CHEAH</field>
<field name="name">Child Hostel Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(employee.children)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = 300 if employee.children == 1 else 600</field>
<field name="note">In case the children are in hostel, the exemption available for child.</field>
<field name="sequence" eval="19"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payroll_rule_city1" model="hr.salary.rule">
<field name="code">CBDA</field>
<field name="name">City Compensatory Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="sequence" eval="21"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and ((contract.wage + categories.DA) * 0.10)
or (contract.wage * 0.10))</field>
<field name="note">This allowance is paid to Employees who are posted in big cities. The purpose is to compensate the high cost of living in cities like Mumbai, Delhi, etc. However it is Fully Taxable.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payroll_rule_metrocity" model="hr.salary.rule">
<field name="code">CMETRO</field>
<field name="name">City Allowance for Metro city</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="sequence" eval="22"/>
<field name="amount_select">fix</field>
<field name="amount_fix">850.0</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payroll_rule_nonmetrocity" model="hr.salary.rule">
<field name="code">CNMETRO</field>
<field name="name">City Allowance for Non Metro city</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="sequence" eval="25"/>
<field name="amount_select">fix</field>
<field name="amount_fix">800.0</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_arrears" model="hr.salary.rule">
<field name="code">ARRE</field>
<field name="name">Arrears</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.ARS and inputs.ARS.amount</field>
<field eval="0.0" name="amount_fix"/>
<field name="sequence" eval="28"/>
<field name="note">Generally arrears are fully taxable, but employee may claim exemption u/s 89(1).
One would need to compute income tax on the arrears if it would have been received in actual year.
Now difference of income tax between payment year and actual year would be allowed for deduction.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_lta" model="hr.salary.rule">
<field name="code">LTA</field>
<field name="name">Leave Travel Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">percentage</field>
<field name="amount_percentage_base">contract.wage</field>
<field name="amount_percentage" eval="8.33"/>
<field name="sequence" eval="29"/>
<field name="note">As per Income tax rules of India, if transport bills for LTA are not provided,the amount will be taxed. E.g. If an employee has LTA allowance as Rs 50,000 in his CTC(cost to company),and he provides proofs of Rs 40,000 (boarding pass,air tickets, taxi vouchers) then income tax will be deducted for rest of the Rs 10,000. Does not matter whats the amount of LTA in an employee’s package, income tax laws only permits domestic air tickets only for LTA claim.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_le" model="hr.salary.rule">
<field name="code">LE</field>
<field name="name">Leave Encashment</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.LE and inputs.LE.amount</field>
<field name="sequence" eval="30"/>
<field name="note">Payment by way of leave encashment received by Central and State Govt.employees at the time of retirement in respect of the period of earned leave at credit is fully exempt. In case of other employees, the exemption is to be limited to minimum of all below:
1.The actual amount received
2.The cash equivalent of leave balance (max 30 days per year of service)
3.Maximum of 10 months of leave encashment, based on last 10 months average salary
4.Rs. 3 Lakh</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_performance" model="hr.salary.rule">
<field name="code">PI</field>
<field name="name">Performance Incentive</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.PERF and inputs.PERF.amount</field>
<field name="sequence" eval="31"/>
<field name="note">This would be fully taxable based on incentive.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_bonus" model="hr.salary.rule">
<field name="code">BONUS</field>
<field name="name">Bonus</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.BNS and inputs.BNS.amount</field>
<field name="sequence" eval="41"/>
<field name="note">This would be fully taxable based on Bonus.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_medical_allow" model="hr.salary.rule">
<field name="code">MEDA</field>
<field name="name">Medical Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="1250.0" name="amount_fix"/>
<field name="sequence" eval="43"/>
<field name="note">This component is on-taxable up to 15000 per year (or Rs 1250 per month) on producing medical bills.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_medical" model="hr.salary.rule">
<field name="code">MEDA</field>
<field name="name">Medical Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.MR and inputs.MR.amount</field>
<field name="sequence" eval="32"/>
<field name="note">This component is on-taxable up to 15000 per year (or Rs 1250 per month) on producing medical bills.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_food_coupon" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field eval="50" name="amount_fix"/>
<field name="quantity">worked_days.WORK100.number_of_days</field>
<field name="code">FC</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="name">Food Allowance</field>
<field name="register_id" ref="hr_food_coupen_register"/>
<field name="sequence" eval="33"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_journals" model="hr.salary.rule">
<field name="code">PERJ</field>
<field name="name">Periodical Journals</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.PJ and inputs.PJ.amount</field>
<field name="sequence" eval="34"/>
<field name="note">Some employers may provide component for buying magazines, journals and books as a part of knowledge enhancement for business growth.This part would become non taxable on providing original bills.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_uniform_senior" model="hr.salary.rule">
<field name="code">UNIFS</field>
<field name="name">Uniform/Dress Allowance for Senior Executive</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="1000" name="amount_fix"/>
<field name="sequence" eval="35"/>
<field name="note">Some sections of employees mat get allowance for purchase of office dress/uniform.In such case, the component would become non-taxable.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_uniform_junior" model="hr.salary.rule">
<field name="code">UNIFJ</field>
<field name="name">Uniform/Dress Allowance for Junior Executive</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="600" name="amount_fix"/>
<field name="sequence" eval="42"/>
<field name="note">Some sections of employees mat get allowance for purchase of office dress/uniform.In such case, the component would become non-taxable.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_telephone" model="hr.salary.rule">
<field name="code">TELR</field>
<field name="name">Telephone Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.TR and inputs.TR.amount</field>
<field name="sequence" eval="36"/>
<field name="note">In some of the cases, companies may provide a component for telephone bills.Employees may provide actual phone usage bills to reimburse this component and make it non-taxable.
</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_prof_develope" model="hr.salary.rule">
<field name="code">PDA</field>
<field name="name">Professional Development Allowance</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">fix</field>
<field eval="0.0" name="amount_fix"/>
<field name="sequence" eval="37"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payroll_rule_car" model="hr.salary.rule">
<field name="code">CAR</field>
<field name="name">Car Expenses Reimbursement</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.CEI and inputs.CEI.amount</field>
<field name="sequence" eval="38"/>
<field name="note">In case company provides component for this and employee use self owned car for official and personal purposes, Rs 1800 per month would be non-taxable on showing bills for fuel or can maintenance. This amount would be Rs 2400 in case car is more capacity than 1600cc.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_internet" model="hr.salary.rule">
<field name="code">INT</field>
<field name="name">Internet Expense</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.IE and inputs.IE.amount</field>
<field name="sequence" eval="39"/>
<field name="note">Employer may also provide reimbursement of internet expenses and thus this would become non taxable.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_driver" model="hr.salary.rule">
<field name="code">DRI</field>
<field name="name">Driver Salary</field>
<field name="category_id" ref="hr_payroll.ALW"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.driver_salay)</field>
<field name="amount_select">fix</field>
<field eval="900.0" name="amount_fix"/>
<field name="sequence" eval="40"/>
<field name="note">Rs. 900 per month (non taxable)</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<!--hr salary rules for Deductions -->
<record id="hr_payslip_rule_tds" model="hr.salary.rule">
<field name="code">TDS</field>
<field name="name">Tax Deducted at Source</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.tds)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = -(contract.tds)</field>
<field name="register_id" ref="hr_tds_register"/>
<field name="sequence" eval="140"/>
<field name="note">As per income tax rules, all payment which are taxable in nature should be done after deduction of taxes at the source itself. Hence employer compute income tax on salary payment and deduct it every month. This TDS is based on employee’s saving/investment declaration at the start of year. If investments for tax saving is not done, large amount may be deducted in last few months.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_line_professional_tax" model="hr.salary.rule">
<field name="code">PTD</field>
<field name="name">Professional Tax</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = contract.wage &gt;= 3000 </field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (-200 if contract.wage &gt;= 12000
else -150 if ((contract.wage &gt;= 9000) and (contract.wage &lt;= 11999))
else -80 if ((contract.wage &gt;= 6000) and (contract.wage &lt;= 8999))
else -20 if ((contract.wage &gt;= 3000) and (contract.wage &lt;= 5999))
else -0)</field>
<field name="register_id" ref="hr_professional_tax_deduction_register"/>
<field eval="145" name="sequence"/>
<field name="note">Workers living in states that impose the professional tax must submit a payment each half-year for the right to practice a profession or trade. It applies equally to employees who work for the national or state government, and those employed by private corporations. The professional tax uses a six-month accounting system, which divides the year into two periods, beginning on April 1 and October 1.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_epf" model="hr.salary.rule">
<field name="code">EPMF</field>
<field name="name">Employee's PF Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.12)
or - (contract.wage * 0.12))</field>
<field name= "note">Employer contribution does not become part of employee’s income and hence income tax is not payable on this part.</field>
<field name="register_id" ref="hr_register_provident_fund"/>
<field name="sequence" eval="150"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_enps" model="hr.salary.rule">
<field name="code">ENPFC</field>
<field name="name">Employee's NPS Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.10)
or - (contract.wage * 0.10))</field>
<field name="sequence" eval="155"/>
<field name="register_id" ref="hr_nps_contribution_register"/>
<field name="note">Employee can claim deduction even of employer's contribution to NPS.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_vpf" model="hr.salary.rule">
<field name="code">VPF</field>
<field name="name">Voluntary Provident Fund Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.voluntary_provident_fund)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and
- ((contract.wage + categories.DA) * contract.voluntary_provident_fund / 100)
or - (contract.wage * contract.voluntary_provident_fund / 100))</field>
<field name="sequence" eval="160"/>
<field name="register_id" ref="hr_vpf_contribution_register"/>
<field name="note">VPF is a safe option wherein you can contribute more than the PF ceiling of 12% that has been mandated by the government.This additional amount enjoys all the benefits of PF except that the employer is not liable to contribute any extra amount apart from 12%.An added advantage is that the interest rate is equal to the interest rate of PF and he withdrawal is tax free. Please note that the maximum contribution towards VPF is 100% of your Basic.The highest rate of interest (close to 9%) makes it a very attractive saving scheme. Because of these advantages many employees chose not to close their PF account even after getting employment else where other than India.Employees also get a major tax break on their entire contribution to the fund up to a ceiling of Rs. 70,000/-</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_cpt" model="hr.salary.rule">
<field name="code">CPT</field>
<field name="name">Deduction for Company Provided Transport</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">none</field>
<field name="amount_select">fix</field>
<field eval="-1500.0" name="amount_fix"/>
<field name="register_id" ref="hr_company_transport_register"/>
<field name="sequence" eval="165"/>
<field name="appears_on_payslip" eval="False"/>
<field name="note">Company provided transport amount is based on company.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_salary_rule_food_coupon_ded" model="hr.salary.rule">
<field name="amount_select">fix</field>
<field eval="-50" name="amount_fix"/>
<field name="quantity">worked_days.WORK100.number_of_days</field>
<field name="code">FD</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="name">Deduction Towards Food Coupons</field>
<field name="register_id" ref="hr_food_coupen_register"/>
<field name="sequence" eval="166"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_lwf_employee" model="hr.salary.rule">
<field name="code">LWFE</field>
<field name="name">Employee's Deduction Towards State Labour Welfare Fund</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-3.0" name="amount_fix"/>
<field name="sequence" eval="170"/>
<field name="register_id" ref="hr_labour_Welfare_fund_register"/>
<field name="note">The LWF is applicable to all the members of the organisation except the Management staff (Staffs having authority to sign on the cheque/official documents on behalf of the organisation). for e.x. Employee Contribution is Rs. 3.00 and Employer contribution Rs. 6.00 Total Rs 9.00 and deposited to the LWF office.It is half yearly contribution (June and December).</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_lwf_employer" model="hr.salary.rule">
<field name="code">LWF</field>
<field name="name">Employer's Deduction Towards State Labour Welfare Fund </field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-6.0" name="amount_fix"/>
<field name="sequence" eval="171"/>
<field name="register_id" ref="hr_labour_Welfare_fund_register"/>
<field name="appears_on_payslip" eval="False"/>
<field name="note">The LWF is applicable to all the members of the organisation except the Management staff (Staffs having authority to sign on the cheque/official documents on behalf of the organisation). for e.x. Employee Contribution is Rs. 3.00 and Employer contribution Rs. 6.00 Total Rs 9.00 and deposited to the LWF office.It is half yearly contribution (June and December).</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_cgti" model="hr.salary.rule">
<field name="code">CGTI</field>
<field name="name">Deduction Towards Company Provided Group Term Insurance</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-1000.0" name="amount_fix"/>
<field name="register_id" ref="hr_group_term_insurance_register"/>
<field name="sequence" eval="175"/>
<field name="note">Group term insurance provides a solid foundation to a comprehensive employee benifit program,backed up by government asistance in the form of valuable tax incentives to both employees and employers.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_dla" model="hr.salary.rule">
<field name="code">DLA</field>
<field name="name">Deduction Towards Leave Availed</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">none</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = inputs.LAI and - (inputs.LAI.amount)</field>
<field name="register_id" ref="hr_leave_availed_register"/>
<field name="sequence" eval="180"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_cmt" model="hr.salary.rule">
<field name="code">CMT</field>
<field name="name">Deduction Towards Company Provided Medical Insurance</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="condition_select">python</field>
<field name="condition_python">result = bool(contract.medical_insurance)</field>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = - (contract.medical_insurance)</field>
<field eval="-50.0" name="amount_fix"/>
<field name="appears_on_payslip" eval="False"/>
<field name="register_id" ref="hr_medical_insurance_register"/>
<field name="sequence" eval="185"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_ode" model="hr.salary.rule">
<field name="code">ODE</field>
<field name="name">Other Deduction from Employer</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">fix</field>
<field eval="-200.0" name="amount_fix"/>
<field name="appears_on_payslip" eval="False"/>
<field name="register_id" ref="hr_other_deduction_register"/>
<field name="sequence" eval="187"/>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_ernps" model="hr.salary.rule">
<field name="code">ENPC</field>
<field name="name">Employer's NPS Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.10)
or - (contract.wage * 0.10))</field>
<field name="sequence" eval="190"/>
<field name="register_id" ref="hr_nps_contribution_register"/>
<field name="appears_on_payslip" eval="False"/>
<field name= "note">Any amount contributed by your employer to your NPS account is treated as part of your salary and is included in your income but you can claim deduction under Section 80C for this too.thus, effectively making it exempt from tax within the limit of 10% of your basic salary. This is very useful and tax efficient for you particularly if you fall in the maximum tax.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
<record id="hr_payslip_rule_erpf" model="hr.salary.rule">
<field name="code">EPF</field>
<field name="name">Employer's PF Contribution</field>
<field name="category_id" ref="hr_payroll.DED"/>
<field name="amount_select">code</field>
<field name="amount_python_compute">result = (payslip.company_id.dearness_allowance and - ((contract.wage + categories.DA) * 0.12)
or - (contract.wage * 0.12))</field>
<field name="sequence" eval="195"/>
<field name="register_id" ref="hr_register_provident_fund"/>
<field name="appears_on_payslip" eval="False"/>
<field name="note">Both the employees and employer contribute to the fund at the rate of 12% of the basic wages, dearness allowance and retaining allowance, if any, payable to employees per month.</field>
<field name="struct_id" ref="hr_payroll_salary_structure_ind_emp"/>
</record>
</odoo>
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Salary Structure -->
<record id="hr_payroll_salary_structure_ind_emp" model="hr.payroll.structure">
<field name="code">NE</field>
<field name="name">Non-Executive Employee</field>
<field eval="[(6, 0, [ref('hr_salary_rule_medical'), ref('hr_salary_rule_da'), ref('hr_salary_rule_lta'), ref('hr_salary_rule_telephone'), ref('hr_salary_rule_internet'), ref('hr_payroll_rule_child1')])]" name="rule_ids"/>
<field name="country_id" ref="base.in"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
</record>
</odoo>