[IMP] hr_payroll: Manage multi company on payslips/contracts

Purpose
=======

Currently the payroll doens't manage the multi company

Specification
=============

1/ Add ir.rules on hr.contract and hr.payslip to prevent users
   to access a record in another company.
2/ Add ir.rules on hr.payroll.structure to prevent users to access
   a record for another country.
3/ Remove company_id fields on models that doesn't require it, as
   hr.salary.rule.category.
4/ Make the accounting fields on the salary rules company dependent.
5/ Specify the country on the salary structures on the
   l10n_**_hr_payroll modules.
6/ Add demo data and modify the salary package tour.
7/ Make the car_atn and company_car_total_depreciated_costs fields
   compute_sudo=True, as one car can be assigned on several contract,
   for different companies

Closes #26866
Closes #25231
Closes #24683
Closes #23814
This commit is contained in:
Yannick Tivisse
2019-01-21 12:33:03 +01:00
parent 4764a70af7
commit 1684ec555d
17 changed files with 59 additions and 36 deletions
+8
View File
@@ -10,5 +10,13 @@
<record id="base.default_user" model="res.users">
<field name="groups_id" eval="[(4,ref('hr_contract.group_hr_contract_manager'))]"/>
</record>
<record id="ir_rule_hr_contract_multi_company" model="ir.rule">
<field name="name">HR Contract: Multi Company</field>
<field name="model_id" ref="model_hr_contract"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
</data>
</odoo>
@@ -87,7 +87,6 @@
<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"/>
<field name="company_id" ref="base.main_company"/>
</record>
<!-- Decimal Precision -->
@@ -88,7 +88,6 @@
<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="company_id" ref="base.main_company"/>
<field name="parent_id" ref="structure_base"/>
</record>
@@ -96,7 +95,6 @@
<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="company_id" ref="base.main_company"/>
<field name="parent_id" ref="structure_001"/>
</record>
+1 -1
View File
@@ -47,7 +47,7 @@ class HrPayslip(models.Model):
\n* When user cancel payslip the status is \'Rejected\'.""")
line_ids = fields.One2many('hr.payslip.line', 'slip_id', string='Payslip Lines', readonly=True,
states={'draft': [('readonly', False)], 'verify': [('readonly', False)]})
company_id = fields.Many2one('res.company', string='Company', required=True, readonly=True, copy=False,
company_id = fields.Many2one('res.company', string='Company', readonly=True, copy=False, required=True,
default=lambda self: self.env['res.company']._company_default_get(),
states={'draft': [('readonly', False)], 'verify': [('readonly', False)]})
worked_days_line_ids = fields.One2many('hr.payslip.worked_days', 'payslip_id',
+1 -8
View File
@@ -27,8 +27,7 @@ class HrPayrollStructure(models.Model):
name = fields.Char(required=True)
code = fields.Char(string='Reference', required=True)
company_id = fields.Many2one('res.company', string='Company', required=True,
copy=False, default=lambda self: self.env['res.company']._company_default_get())
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)
@@ -70,8 +69,6 @@ class HrContributionRegister(models.Model):
_name = 'hr.contribution.register'
_description = 'Contribution Register'
company_id = fields.Many2one('res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get())
partner_id = fields.Many2one('res.partner', string='Partner')
name = fields.Char(required=True)
register_line_ids = fields.One2many('hr.payslip.line', 'register_id',
@@ -89,8 +86,6 @@ class HrSalaryRuleCategory(models.Model):
help="Linking a salary category to its parent is used only for the reporting purpose.")
children_ids = fields.One2many('hr.salary.rule.category', 'parent_id', string='Children')
note = fields.Text(string='Description')
company_id = fields.Many2one('res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get())
@api.constrains('parent_id')
def _check_parent_id(self):
@@ -120,8 +115,6 @@ class HrSalaryRule(models.Model):
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)
company_id = fields.Many2one('res.company', string='Company',
default=lambda self: self.env['res.company']._company_default_get())
condition_select = fields.Selection([
('none', 'Always True'),
('range', 'Range'),
@@ -55,5 +55,19 @@
<field name="perm_read" eval="0"/>
</record>
<record id="ir_rule_hr_payroll_structure_multi_company" model="ir.rule">
<field name="name">HR Payroll Structure: Multi Company</field>
<field name="model_id" ref="model_hr_payroll_structure"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('country_id', '=', False), ('country_id', '=', user.company_id.country_id.id)]</field>
</record>
<record id="ir_rule_hr_payslip_multi_company" model="ir.rule">
<field name="name">HR Payslip: Multi Company</field>
<field name="model_id" ref="model_hr_payslip"/>
<field name="global" eval="True"/>
<field name="domain_force">['|', ('company_id', '=', False), ('company_id', 'child_of', [user.company_id.id])]</field>
</record>
</data>
</odoo>
-1
View File
@@ -32,7 +32,6 @@ class TestPayslipBase(TransactionCase):
self.developer_pay_structure = self.env['hr.payroll.structure'].create({
'name': 'Salary Structure for Software Developer',
'code': 'SD',
'company_id': self.ref('base.main_company'),
'rule_ids': [(4, self.hra_rule_id), (4, self.conv_rule_id),
(4, self.prof_tax_rule_id), (4, self.pf_rule_id),
(4, self.mv_rule_id)],
+1 -1
View File
@@ -228,7 +228,7 @@
<page string="Accounting Information">
<group>
<group string="Miscellaneous">
<field name="company_id" groups="base.group_multi_company"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
<field name="payslip_run_id" domain="[('state','=','draft')]"/>
</group>
<group name="accounting" string="Accounting">
@@ -2,6 +2,7 @@
<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>
@@ -10,7 +11,7 @@
<field name="name"/>
<field name="code"/>
<field name="rule_ids"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
<field name="country_id" options="{'no_create': True}"/>
</tree>
</field>
</record>
@@ -48,7 +49,7 @@
<tree string="Salary Structure">
<field name="name"/>
<field name="code"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
<field name="country_id" options="{'no_create': True}"/>
</tree>
</field>
</record>
@@ -74,7 +75,7 @@
<field name="code"/>
<field name="parent_id"/>
<field name="report_id"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
<field name="country_id" options="{'no_create': True}"/>
</group>
<notebook colspan="4">
<page name="salary_rules" string="Salary Rules">
@@ -161,7 +162,6 @@
<field name="arch" type="xml">
<tree string="Contribution Registers">
<field name="name" />
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
</tree>
</field>
</record>
@@ -190,7 +190,6 @@
<field name="arch" type="xml">
<search string="Contribution Registers">
<field name="name" string="Contribution Registers"/>
<field name="company_id" groups="base.group_multi_company"/>
</search>
</field>
</record>
@@ -203,7 +202,6 @@
<group name="general_info">
<field name="name"/>
<field name="partner_id"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}" class="oe_inline"/>
</group>
<newline/>
<group name="description">
@@ -283,7 +281,6 @@
<field name="name"/>
<field name="code"/>
<field name="category_id" invisible="True"/>
<field name="company_id" groups="base.group_multi_company" options="{'no_create': True}"/>
</tree>
</field>
</record>
@@ -303,7 +300,6 @@
<field name="sequence" />
<field name="active"/>
<field name="appears_on_payslip"/>
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
</group>
<notebook colspan="6">
<page name="general" string="General">
@@ -46,7 +46,6 @@ class TestHrPayrollAccount(common.TransactionCase):
self.hr_structure_softwaredeveloper = self.env['hr.payroll.structure'].create({
'name': 'Salary Structure for Software Developer',
'code': 'SD',
'company_id': self.ref('base.main_company'),
'parent_id': self.ref('hr_payroll.structure_base'),
'rule_ids': [(6, 0, [
self.ref('hr_payroll.hr_salary_rule_houserentallowance1'),
@@ -25,5 +25,8 @@ Belgian Payroll Rules.
'data/l10n_be_hr_payroll_data.xml',
'views/res_config_settings_views.xml',
],
'demo':[
'data/l10n_be_hr_payroll_demo.xml'
],
'auto_install': True,
}
@@ -511,7 +511,7 @@ result = -min(ip_amount * tax_rate, 11745)
ref('hr_salary_rule_ip_part'),
ref('hr_salary_rule_gross_with_ip')
])]" name="rule_ids"/>
<field name="company_id" ref="base.main_company"/>
<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">
@@ -529,7 +529,7 @@ result = -min(ip_amount * tax_rate, 11745)
ref('hr_payroll_rules_suppl_net'),
ref('hr_payroll_rules_retained_net'),
])]" name="rule_ids"/>
<field name="company_id" ref="base.main_company"/>
<field name="country_id" ref="base.be"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
</record>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_company_be" model="res.company">
<field name="name">My Belgian Company</field>
<field name="country_id" ref="base.be"/>
<field name="currency_id" ref="base.EUR"/>
</record>
<record id="base.user_admin" model="res.users">
<field name="company_ids" eval="[(4, ref('l10n_be_hr_payroll.res_company_be'))]"/>
</record>
<record id="base.user_demo" model="res.users">
<field name="company_ids" eval="[(4, ref('l10n_be_hr_payroll.res_company_be'))]"/>
</record>
</odoo>
@@ -11,8 +11,8 @@ class HrContract(models.Model):
default=lambda self: self.env['fleet.vehicle'].search([('driver_id', '=', self.employee_id.address_home_id.id)], limit=1),
tracking=True,
help="Employee's company car.")
car_atn = fields.Float(compute='_compute_car_atn_and_costs', string='ATN Company Car', store=True)
company_car_total_depreciated_cost = fields.Float(compute='_compute_car_atn_and_costs', store=True)
car_atn = fields.Float(compute='_compute_car_atn_and_costs', string='ATN Company Car', store=True, compute_sudo=True)
company_car_total_depreciated_cost = fields.Float(compute='_compute_car_atn_and_costs', store=True, compute_sudo=True)
available_cars_amount = fields.Integer(compute='_compute_available_cars_amount', string='Number of available cars')
new_car = fields.Boolean('Request a new car')
# YTI: Check if could be removed
@@ -1231,7 +1231,7 @@
<field name="code">Fr-Base</field>
<field name="name">Cotisations de base Employe Francais</field>
<field eval="[(6, 0, [ref('hr_payroll.hr_rule_basic'), ref('hr_payroll.hr_rule_taxable'),ref('hr_payroll.hr_rule_net'), ref('hr_rule_secu'), ref('hr_rule_tranche_a'), ref('hr_rule_tranche_b'), ref('hr_rule_tranche_c'), ref('hr_rule_tranche_1'), ref('hr_rule_tranche_2'), ref('hr_rule_total'), ref('hr_rule_total_charges_salariales'), ref('hr_rule_total_retenues'), ref('hr_rule_cumul_imposable'), ref('hr_rule_total_charges_patronales'), ref('hr_payroll_rules_C1_employe'), ref('hr_payroll_rules_C2_employe'), ref('hr_payroll_rules_C3_employe'), ref('hr_payroll_rules_C4_employe'), ref('hr_payroll_rules_C5_employe'), ref('hr_payroll_rules_C7_employe'), ref('hr_payroll_rules_C8_employe'), ref('hr_payroll_rules_C9_employe'), ref('hr_payroll_rules_C10_employe'), ref('hr_payroll_rules_C11_employe'), ref('hr_payroll_rules_C22_employe'), ref('hr_payroll_rules_C23_employe'), ref('hr_payroll_rules_C24_employe'), ref('hr_payroll_rules_C25_employe'), ref('hr_payroll_rules_C26_employe'), ref('hr_payroll_rules_C27_employe'), ref('hr_payroll_rules_C28_employe'), ref('hr_payroll_rules_C29_employe'), ref('hr_payroll_rules_C30_employe'), ref('hr_payroll_rules_C40_employe')])]" name="rule_ids"/>
<field name="company_id" ref="base.main_company"/>
<field name="country_id" ref="base.fr"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
</record>
@@ -1240,7 +1240,7 @@
<field name="code">Fr-NC</field>
<field name="name">Employe non-cadre</field>
<field eval="[(6, 0, [ref('hr_payroll_rules_C12_employe'), ref('hr_payroll_rules_C13_employe'), ref('hr_payroll_rules_C14_employe'), ref('hr_payroll_rules_C15_employe')])]" name="rule_ids"/>
<field name="company_id" ref="base.main_company"/>
<field name="country_id" ref="base.fr"/>
<field name="parent_id" ref="hr_payroll_salary_structure_base"/>
</record>
@@ -1249,7 +1249,7 @@
<field name="code">Fr-C</field>
<field name="name">Employe cadre</field>
<field eval="[(6, 0, [ref('hr_payroll_rules_C16_employe'), ref('hr_payroll_rules_C17_employe'), ref('hr_payroll_rules_C18_employe'), ref('hr_payroll_rules_C19_employe'), ref('hr_payroll_rules_C20_employe'), ref('hr_payroll_rules_C21_employe'), ref('hr_payroll_rules_C38_employe'), ref('hr_payroll_rules_C39_employe')])]" name="rule_ids"/>
<field name="company_id" ref="base.main_company"/>
<field name="country_id" ref="base.fr"/>
<field name="parent_id" ref="hr_payroll_salary_structure_base"/>
</record>
</odoo>
@@ -6,7 +6,7 @@
<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="company_id" ref="base.main_company"/>
<field name="country_id" ref="base.in"/>
<field name="parent_id" ref="hr_payroll.structure_base"/>
</record>
</odoo>
@@ -59,7 +59,7 @@ odoo.define('web.test.x2many', function (require) {
trigger: '[data-toggle="tab"]:contains(Participants)'
}, {
content: "click to add participants",
trigger: '.tab-pane:eq(2).active .o_field_x2many_list_row_add a'
trigger: '.o_form_sheet .tab-pane:eq(2).active .o_field_x2many_list_row_add a'
}, {
content: "select Admin",
trigger: 'tr:has(td:containsExact(Mitchell Admin)) .o_list_record_selector input[type="checkbox"]'
@@ -70,7 +70,7 @@ odoo.define('web.test.x2many', function (require) {
}, { // save
content: "save discussion",
trigger: 'button.o_form_button_save',
extra_trigger: '.tab-pane:eq(2) .o_field_widget tbody tr:has(td:containsExact(Mitchell Admin))',
extra_trigger: '.o_form_sheet .tab-pane:eq(2) .o_field_widget tbody tr:has(td:containsExact(Mitchell Admin))',
}, { // edit
content: "edit discussion",
trigger: 'button.o_form_button_edit',
@@ -79,7 +79,7 @@ odoo.define('web.test.x2many', function (require) {
trigger: 'a[role=tab]:first',
}, {
content: "create new message a",
trigger: '.tab-pane:eq(0) .o_field_x2many_list_row_add a'
trigger: '.o_form_sheet .tab-pane:eq(0) .o_field_x2many_list_row_add a'
}, {
content: "insert body a",
trigger: '.modal-body textarea:first',
@@ -330,7 +330,7 @@ odoo.define('web.test.x2many', function (require) {
{
content: "switch to the second form view to test one2many with editable list (toggle menu dropdown)",
trigger: 'nav .o_menu_sections .dropdown-toggle:containsExact(Discussions)',
trigger: 'nav .o_menu_sections .dropdown-toggle:containsExact(Discussions), li.o_extra_menu_items a i.fa-plus',
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
}, {
content: "switch to the second form view to test one2many with editable list (open submenu)",
@@ -447,7 +447,7 @@ odoo.define('web.test.x2many', function (require) {
{
content: "switch to the third form view to test onchange changing one2many (toggle menu dropdown)",
trigger: 'nav .o_menu_sections .dropdown-toggle:containsExact(Discussions)',
trigger: 'nav .o_menu_sections .dropdown-toggle:containsExact(Discussions), li.o_extra_menu_items a i.fa-plus',
extra_trigger: '.tab-pane:eq(0) .o_field_widget tbody .o_data_row:eq(2)',
}, {
content: "switch to the thied form view to test onchange changing one2many (open submenu)",