[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:
@@ -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>
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)],
|
||||
|
||||
@@ -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)",
|
||||
|
||||
Reference in New Issue
Block a user