552 lines
32 KiB
Python
552 lines
32 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import date
|
|
from dateutil.relativedelta import relativedelta
|
|
from odoo.tests import tagged
|
|
from odoo.addons.hr_payroll.tests.common import TestPayslipContractBase
|
|
|
|
|
|
@tagged('payroll_properties')
|
|
class TestPayrollProperties(TestPayslipContractBase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
|
|
cls.structure_type_A = cls.env['hr.payroll.structure.type'].create({
|
|
'name': 'Test - Developer A',
|
|
})
|
|
|
|
cls.structure_type_B = cls.env['hr.payroll.structure.type'].create({
|
|
'name': 'Test - Developer B',
|
|
})
|
|
|
|
cls.structure_A = cls.env['hr.payroll.structure'].create({
|
|
'name': 'Main Default Structure',
|
|
'type_id': cls.structure_type_A.id,
|
|
})
|
|
|
|
cls.structure_B = cls.env['hr.payroll.structure'].create({
|
|
'name': 'Secondary Structure',
|
|
'type_id': cls.structure_type.id,
|
|
})
|
|
|
|
cls.structure_C = cls.env['hr.payroll.structure'].create({
|
|
'name': 'Main Structure C',
|
|
'type_id': cls.structure_type_B.id,
|
|
})
|
|
|
|
cls.structure_type_A.default_struct_id = cls.structure_A
|
|
cls.structure_type_B.default_struct_id = cls.structure_C
|
|
|
|
cls.category1 = cls.env['hr.salary.rule.section'].create({
|
|
'name': 'Category 1'
|
|
})
|
|
|
|
cls.category2 = cls.env['hr.salary.rule.section'].create({
|
|
'name': 'Category 2'
|
|
})
|
|
|
|
cls.category3 = cls.env['hr.salary.rule.section'].create({
|
|
'name': 'Category 3'
|
|
})
|
|
|
|
cls.structure_type.default_struct_id = cls.structure_A
|
|
|
|
cls.mr_property = cls.env['hr.employee'].create({
|
|
'name': 'Mr. Property',
|
|
'sex': 'male',
|
|
'birthday': '1984-05-01',
|
|
'country_id': cls.env.ref('base.us').id,
|
|
})
|
|
|
|
cls.Rule = cls.env['hr.salary.rule']
|
|
|
|
def create_property_salary_rule(self, struct_id, code, section, unit='monetary', default_value=0, suffix=False, dependent_input_id=None):
|
|
rule_vals = {
|
|
'name': 'Test Rule',
|
|
'code': code,
|
|
'category_id': self.env.ref('hr_payroll.ALW').id,
|
|
'condition_select': 'property_input',
|
|
'input_section': section.id,
|
|
'input_unit': unit,
|
|
'input_default_value': default_value,
|
|
'input_suffix': suffix,
|
|
'struct_id': struct_id.id
|
|
}
|
|
if dependent_input_id:
|
|
rule_vals['dependent_input_id'] = dependent_input_id.id
|
|
return self.env['hr.salary.rule'].create(rule_vals)
|
|
|
|
def generate_payslip(self, struct, date, employee, version=None):
|
|
test_payslip = self.env['hr.payslip'].create({
|
|
'name': 'Property Payslips',
|
|
'employee_id': employee.id if employee else self.richard_emp.id,
|
|
'version_id': version.id if version else employee.version_id.id,
|
|
'company_id': employee.company_id.id,
|
|
'struct_id': struct.id,
|
|
'date_from': date,
|
|
'date_to': date + relativedelta(months=1, days=-1),
|
|
})
|
|
|
|
test_payslip.compute_sheet()
|
|
|
|
return test_payslip
|
|
|
|
def test_add_property_to_version_definition(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_test_1', section=self.category1, default_value=100)
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 2) # Separator + property
|
|
self.assertEqual(version_def[0]['type'], 'separator')
|
|
self.assertEqual(version_def[0]['name'], f'separator_{self.category1.id}')
|
|
self.assertEqual(version_def[1]['name'], f'{rule.id}')
|
|
self.assertEqual(version_def[1]['type'], 'monetary')
|
|
self.assertEqual(version_def[1]['default'], 100.0)
|
|
|
|
payroll_def = self.structure_A.payslip_properties_definition
|
|
self.assertEqual(payroll_def, [])
|
|
|
|
def test_add_property_to_payslip_definition(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_test_1', section=self.category1, default_value=100)
|
|
self.structure_A._update_payroll_properties(rule, 'hr.payslip')
|
|
|
|
payslip_def = self.structure_A.payslip_properties_definition
|
|
self.assertEqual(len(payslip_def), 2) # Separator + property
|
|
self.assertEqual(payslip_def[0]['type'], 'separator')
|
|
self.assertEqual(payslip_def[0]['name'], f'separator_{self.category1.id}')
|
|
self.assertEqual(payslip_def[1]['name'], f'{rule.id}')
|
|
self.assertEqual(payslip_def[1]['type'], 'monetary')
|
|
self.assertEqual(payslip_def[1]['default'], 100.0)
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def, [])
|
|
|
|
def test_no_duplicate_property_in_version_definition(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_test_dup', section=self.category1, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
version_def_initial = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def_initial), 2)
|
|
|
|
# Add again
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
version_def_after = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def_after), 2)
|
|
self.assertEqual(version_def_initial, version_def_after)
|
|
|
|
def test_boolean_property_type_in_version_definition(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_bool', section=self.category1, unit='boolean')
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def[1]['type'], 'boolean')
|
|
self.assertEqual(version_def[1]['default'], False)
|
|
|
|
def test_property_suffix(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_monetary', section=self.category1, suffix="Per month", unit='monetary')
|
|
rule_percentage = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_percentage', section=self.category1, suffix="Per month", unit='percentage')
|
|
self.structure_A._update_payroll_properties(rule + rule_percentage, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def[1]['suffix'], 'Per month')
|
|
self.assertEqual(version_def[2]['suffix'], '% Per month')
|
|
|
|
def test_compute_input_used_in_definition(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_monetary', section=self.category1, unit='monetary')
|
|
rule_percentage = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_percentage', section=self.category1, unit='percentage')
|
|
|
|
self.assertFalse(rule.input_used_in_definition)
|
|
self.assertFalse(rule_percentage.input_used_in_definition)
|
|
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
self.env.flush_all()
|
|
(rule + rule_percentage)._compute_input_used_in_definition()
|
|
self.assertTrue(rule.input_used_in_definition)
|
|
self.assertFalse(rule_percentage.input_used_in_definition)
|
|
|
|
self.structure_A._update_payroll_properties(rule_percentage, 'hr.employee')
|
|
self.env.flush_all()
|
|
(rule + rule_percentage)._compute_input_used_in_definition()
|
|
self.assertTrue(rule.input_used_in_definition)
|
|
self.assertTrue(rule_percentage.input_used_in_definition)
|
|
|
|
def test_update_property_suffix(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_monetary', section=self.category1, unit='monetary')
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertFalse('suffix' in version_def[1])
|
|
|
|
rule.input_suffix = 'Test Suffix'
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def[1]['suffix'], 'Test Suffix')
|
|
|
|
def test_update_property_default_value(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_monetary', section=self.category1, unit='monetary', default_value=150)
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def[1]['default'], 150)
|
|
|
|
rule.input_default_value = 400
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def[1]['default'], 400)
|
|
|
|
def test_update_property_name(self):
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_monetary', section=self.category1, unit='monetary', default_value=150)
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def[1]['string'], "Test Rule")
|
|
|
|
rule.name = "Renamed rule"
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(version_def[1]['string'], "Renamed rule")
|
|
|
|
def test_multiple_rules_same_category_in_version_definition(self):
|
|
rule1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_multi1', section=self.category1, default_value=10)
|
|
rule2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_multi2', section=self.category1, default_value=20)
|
|
self.structure_A._update_payroll_properties(rule1 + rule2, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 3) # Separator + 2 properties
|
|
self.assertEqual(version_def[0]['type'], 'separator')
|
|
self.assertEqual(version_def[0]['name'], f'separator_{self.category1.id}')
|
|
prop_names = [prop['name'] for prop in version_def[1:]]
|
|
self.assertIn(str(rule1.id), prop_names)
|
|
self.assertIn(str(rule2.id), prop_names)
|
|
|
|
def test_multiple_categories_in_version_definition(self):
|
|
rule1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_cat1', section=self.category1, default_value=10)
|
|
rule2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_cat2', section=self.category2, default_value=20)
|
|
self.structure_A._update_payroll_properties(rule1 + rule2, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 4) # 2 separators + 2 properties
|
|
self.assertEqual(version_def[0]['name'], f'separator_{self.category1.id}')
|
|
self.assertEqual(version_def[1]['name'], str(rule1.id))
|
|
self.assertEqual(version_def[2]['name'], f'separator_{self.category2.id}')
|
|
self.assertEqual(version_def[3]['name'], str(rule2.id))
|
|
|
|
def test_salary_rule_section_sequence_ordering(self):
|
|
self.category1.sequence = 432
|
|
self.category2.sequence = 99
|
|
self.category3.sequence = 667
|
|
|
|
rule1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_cat1', section=self.category1, default_value=10)
|
|
rule2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_cat2', section=self.category2, default_value=20)
|
|
rule3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_cat3', section=self.category3, default_value=20)
|
|
self.structure_A._update_payroll_properties(rule1 + rule2 + rule3, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 6) # 3 separators + 3 properties
|
|
self.assertEqual(version_def[0]['name'], f'separator_{self.category2.id}')
|
|
self.assertEqual(version_def[1]['name'], str(rule2.id))
|
|
self.assertEqual(version_def[2]['name'], f'separator_{self.category1.id}')
|
|
self.assertEqual(version_def[3]['name'], str(rule1.id))
|
|
self.assertEqual(version_def[4]['name'], f'separator_{self.category3.id}')
|
|
self.assertEqual(version_def[5]['name'], str(rule3.id))
|
|
|
|
def test_property_inserted_in_right_section(self):
|
|
self.category1.sequence = 432
|
|
self.category2.sequence = 99
|
|
|
|
rule1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_cat1', section=self.category1, default_value=10)
|
|
rule2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_cat2', section=self.category2, default_value=20)
|
|
self.structure_A._update_payroll_properties(rule1, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 2) # 1 separators + 1 properties
|
|
self.assertEqual(version_def[0]['name'], f'separator_{self.category1.id}')
|
|
self.assertEqual(version_def[1]['name'], str(rule1.id))
|
|
|
|
self.structure_A._update_payroll_properties(rule2, 'hr.employee')
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 4) # 2 separators + 2 properties
|
|
self.assertEqual(version_def[0]['name'], f'separator_{self.category2.id}')
|
|
self.assertEqual(version_def[1]['name'], str(rule2.id))
|
|
self.assertEqual(version_def[2]['name'], f'separator_{self.category1.id}')
|
|
self.assertEqual(version_def[3]['name'], str(rule1.id))
|
|
|
|
def test_insert_position_existing_separator_in_version_definition(self):
|
|
# Pre-populate with existing separator and property
|
|
self.structure_A.version_properties_definition = [
|
|
{'name': f'separator_{self.category1.id}', 'type': 'separator', 'string': self.category1.name},
|
|
{'name': 'existing_prop', 'type': 'float', 'string': 'Existing Prop', 'default': 0.0},
|
|
{'name': f'separator_{self.category2.id}', 'type': 'separator', 'string': self.category2.name},
|
|
]
|
|
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_insert', section=self.category1, default_value=50)
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 4) # Original 3 + 1 new property
|
|
self.assertEqual(version_def[0]['type'], 'separator') # category1 separator
|
|
self.assertEqual(version_def[0]['name'], f'separator_{self.category1.id}')
|
|
self.assertEqual(version_def[1]['name'], 'existing_prop')
|
|
self.assertEqual(version_def[2]['name'], str(rule.id)) # Inserted before category2 separator
|
|
self.assertEqual(version_def[3]['type'], 'separator') # category2 separator
|
|
self.assertEqual(version_def[3]['name'], f'separator_{self.category2.id}')
|
|
|
|
def test_dependent_rules_in_version_definition(self):
|
|
parent_rule = self.create_property_salary_rule(struct_id=self.structure_A, code='parent_rule', section=self.category1, default_value=100)
|
|
dependent_rule = self.create_property_salary_rule(struct_id=self.structure_A, code='dep_rule', section=self.category2, default_value=200, dependent_input_id=parent_rule)
|
|
|
|
self.structure_A._update_payroll_properties(parent_rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertEqual(len(version_def), 4) # 2 separators + 2 properties
|
|
prop_names = [p['name'] for p in version_def if p.get('type') != 'separator']
|
|
self.assertIn(str(parent_rule.id), prop_names)
|
|
self.assertIn(str(dependent_rule.id), prop_names)
|
|
|
|
def test_properties_set_with_structure_type(self):
|
|
|
|
rule_1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
rule_2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_2', section=self.category2, default_value=150)
|
|
rule_3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_3', section=self.category2, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_2 + rule_3, 'hr.employee')
|
|
|
|
rule_4 = self.create_property_salary_rule(struct_id=self.structure_C, code='rule_c_1', section=self.category1, default_value=250)
|
|
rule_5 = self.create_property_salary_rule(struct_id=self.structure_C, code='rule_c_2', section=self.category1, default_value=300)
|
|
self.structure_C._update_payroll_properties(rule_4 + rule_5, 'hr.employee')
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.assertDictEqual(dict(self.mr_property.version_id.payroll_properties), {str(rule_1.id): 100.0, str(rule_2.id): 150.0, str(rule_3.id): 200.0})
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_B
|
|
self.assertDictEqual(dict(self.mr_property.version_id.payroll_properties), {str(rule_4.id): 250.0, str(rule_5.id): 300.0})
|
|
|
|
def test_property_get_operation_on_version(self):
|
|
rule_1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
rule_2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_2', section=self.category2, default_value=150)
|
|
rule_3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_3', section=self.category2, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_2 + rule_3, 'hr.employee')
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.assertEqual(self.mr_property.version_id._get_property_input_value('rule_a_1'), 100)
|
|
self.assertEqual(self.mr_property.version_id._get_property_input_value('rule_a_2'), 150)
|
|
self.assertEqual(self.mr_property.version_id._get_property_input_value('rule_a_3'), 200)
|
|
|
|
def test_property_set_operation_on_version(self):
|
|
rule_1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
rule_2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_2', section=self.category2, default_value=150)
|
|
rule_3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_3', section=self.category2, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_2 + rule_3, 'hr.employee')
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.mr_property.version_id._set_property_input_value('rule_a_1', 999)
|
|
self.assertEqual(self.mr_property.version_id._get_property_input_value('rule_a_1'), 999)
|
|
self.assertEqual(self.mr_property.version_id._get_property_input_value('rule_a_2'), 150)
|
|
self.assertEqual(self.mr_property.version_id._get_property_input_value('rule_a_3'), 200)
|
|
|
|
def test_properties_copy_and_update_on_version(self):
|
|
rule_1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
rule_2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_2', section=self.category2, default_value=150)
|
|
rule_3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_3', section=self.category2, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_2 + rule_3, 'hr.employee')
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.mr_property.version_id._set_property_input_value('rule_a_1', 999)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_2', 998)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_3', 997)
|
|
|
|
self.mr_property.create_version({
|
|
'date_version': date(2025, 1, 1)
|
|
})
|
|
|
|
self.assertEqual(self.mr_property.version_ids[0]._get_property_input_value('rule_a_1'), 999)
|
|
self.assertEqual(self.mr_property.version_ids[0]._get_property_input_value('rule_a_2'), 998)
|
|
self.assertEqual(self.mr_property.version_ids[0]._get_property_input_value('rule_a_3'), 997)
|
|
|
|
self.assertEqual(self.mr_property.version_ids[1]._get_property_input_value('rule_a_1'), 999)
|
|
self.assertEqual(self.mr_property.version_ids[1]._get_property_input_value('rule_a_2'), 998)
|
|
self.assertEqual(self.mr_property.version_ids[1]._get_property_input_value('rule_a_3'), 997)
|
|
|
|
self.mr_property.version_ids[1]._set_property_input_value('rule_a_1', 444)
|
|
|
|
self.assertEqual(self.mr_property.version_ids[0]._get_property_input_value('rule_a_1'), 999)
|
|
self.assertEqual(self.mr_property.version_ids[0]._get_property_input_value('rule_a_2'), 998)
|
|
self.assertEqual(self.mr_property.version_ids[0]._get_property_input_value('rule_a_3'), 997)
|
|
|
|
self.assertEqual(self.mr_property.version_ids[1]._get_property_input_value('rule_a_1'), 444)
|
|
self.assertEqual(self.mr_property.version_ids[1]._get_property_input_value('rule_a_2'), 998)
|
|
self.assertEqual(self.mr_property.version_ids[1]._get_property_input_value('rule_a_3'), 997)
|
|
|
|
def test_properties_computed_on_payslip(self):
|
|
"""
|
|
Given 3 property rules A, B and C, if A and C and common to both the version and the payslip property definition.
|
|
At payslip creation, the payslip should take the values of the version inputs A and C
|
|
"""
|
|
|
|
rule_1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
rule_2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_2', section=self.category2, default_value=150)
|
|
rule_3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_3', section=self.category2, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_2 + rule_3, 'hr.employee')
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_3, 'hr.payslip')
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.mr_property.version_id.contract_date_start = date(2025, 1, 1)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_1', 123)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_3', 456)
|
|
|
|
property_slip = self.generate_payslip(struct=self.structure_A, date=date(2025, 1, 1), employee=self.mr_property)
|
|
|
|
self.assertDictEqual(dict(property_slip.payslip_properties), {str(rule_1.id): 123.0, str(rule_3.id): 456.0})
|
|
|
|
def test_localdict_compute(self):
|
|
rule_1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
rule_2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_2', section=self.category2, default_value=150)
|
|
rule_3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_3', section=self.category2, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_2 + rule_3, 'hr.employee')
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_3, 'hr.payslip')
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.mr_property.version_id.contract_date_start = date(2025, 1, 1)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_1', 123)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_3', 456)
|
|
|
|
property_slip = self.generate_payslip(struct=self.structure_A, date=date(2025, 1, 1), employee=self.mr_property)
|
|
self.assertDictEqual(property_slip._get_localdict()['property_inputs'], {rule_1.id: 123.0, rule_2.id: 150.0, rule_3.id: 456.0})
|
|
|
|
def test_properties_payslip_lines(self):
|
|
|
|
rule_1 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
rule_2 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_2', section=self.category2, default_value=150)
|
|
rule_3 = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_3', section=self.category2, default_value=200)
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_2 + rule_3, 'hr.employee')
|
|
self.structure_A._update_payroll_properties(rule_1 + rule_3, 'hr.payslip')
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.mr_property.version_id.contract_date_start = date(2025, 1, 1)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_1', 123)
|
|
self.mr_property.version_id._set_property_input_value('rule_a_3', 456)
|
|
|
|
property_slip = self.generate_payslip(struct=self.structure_A, date=date(2025, 1, 1), employee=self.mr_property)
|
|
line_values = property_slip._get_line_values(self.structure_A.rule_ids.mapped('code'), compute_sum=True)
|
|
self.assertEqual(line_values['rule_a_1']['sum']['total'], 123)
|
|
self.assertEqual(line_values['rule_a_2']['sum']['total'], 150)
|
|
self.assertEqual(line_values['rule_a_3']['sum']['total'], 456)
|
|
|
|
def test_localdict_compute_with_folded_separator(self):
|
|
"""Check payslip computation when a separator has a value (it has been folded/unfolded in the UI)."""
|
|
rule = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_a_1', section=self.category1, default_value=100)
|
|
self.structure_A._update_payroll_properties(rule, 'hr.employee')
|
|
|
|
version_def = self.structure_A.version_properties_definition
|
|
self.assertTrue(version_def[0]['type'], 'separator')
|
|
version_def[0]['value'] = False
|
|
version_def[1]['value'] = 123
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.mr_property.version_id.contract_date_start = date(2025, 1, 1)
|
|
self.mr_property.version_id.write({'payroll_properties': version_def})
|
|
|
|
property_slip = self.generate_payslip(struct=self.structure_A, date=date(2025, 1, 1), employee=self.mr_property)
|
|
self.assertEqual({rule.id: 123.0}, property_slip._get_localdict()['property_inputs'])
|
|
|
|
def test_add_input_shows_in_payslip(self):
|
|
def _get_new_rule(show_employee, show_payslip):
|
|
return self.env['hr.salary.rule'].create({
|
|
'name': 'Test Rule',
|
|
'code': "VERYCOOLCODE",
|
|
'category_id': self.env.ref('hr_payroll.ALW').id,
|
|
'condition_select': 'property_input',
|
|
'input_section': self.category1.id,
|
|
'input_unit': "monetary",
|
|
'struct_id': self.structure_A.id,
|
|
'input_usage_employee': show_employee,
|
|
'input_usage_payslip': show_payslip,
|
|
})
|
|
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
self.mr_property.version_id.contract_date_start = date(2025, 1, 1)
|
|
payslip = self.generate_payslip(struct=self.structure_A, date=date(2025, 1, 1), employee=self.mr_property)
|
|
|
|
first_rule = _get_new_rule(True, True)
|
|
self.structure_A._update_payroll_properties(first_rule, 'hr.employee')
|
|
|
|
action = payslip.action_configure_payslip_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertIn(first_rule, available_properties)
|
|
|
|
second_rule = _get_new_rule(True, True)
|
|
self.structure_A._update_payroll_properties(second_rule, 'hr.payslip')
|
|
|
|
action = self.mr_property.action_configure_employee_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertIn(second_rule, available_properties)
|
|
|
|
third_rule = _get_new_rule(True, False)
|
|
action = self.mr_property.action_configure_employee_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertIn(third_rule, available_properties)
|
|
|
|
action = payslip.action_configure_payslip_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertNotIn(third_rule, available_properties)
|
|
|
|
fourth_rule = _get_new_rule(False, True)
|
|
action = payslip.action_configure_payslip_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertIn(fourth_rule, available_properties)
|
|
|
|
action = self.mr_property.action_configure_employee_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertNotIn(fourth_rule, available_properties)
|
|
|
|
fifth_rule = _get_new_rule(False, False)
|
|
action = self.mr_property.action_configure_employee_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertNotIn(fifth_rule, available_properties)
|
|
|
|
action = payslip.action_configure_payslip_inputs()
|
|
available_properties = self.env['hr.salary.rule'].search(action['domain'])
|
|
self.assertNotIn(fifth_rule, available_properties)
|
|
|
|
def test_add_dependent_salary_inputs(self):
|
|
"""
|
|
Test that dependent salary rules are available in the 'Add Inputs'
|
|
selection list if their prerequisite is already present on the record.
|
|
|
|
Scenario:
|
|
- Rule A is a top-level property input.
|
|
- Rule B depends on Rule A.
|
|
- Rule C is created after Rule A is already added to the employee's payroll_properties.
|
|
|
|
Expectation:
|
|
- Rule C should be visible in the selection domain.
|
|
- Rule A should be excluded (already present).
|
|
"""
|
|
self.mr_property.version_id.structure_type_id = self.structure_type_A
|
|
rule_A = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_A', section=self.category1, default_value=100)
|
|
rule_A.input_usage_employee = True
|
|
rule_B = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_B', section=self.category1, default_value=100, dependent_input_id=rule_A)
|
|
rule_B.input_usage_employee = True
|
|
action = self.mr_property.version_id.action_configure_template_inputs()
|
|
domain = action.get('domain', [])
|
|
matching_rules = self.env['hr.salary.rule'].search(domain)
|
|
|
|
self.assertIn(rule_A, matching_rules,
|
|
"Prerequisite Rule should be visible in the salary input selection.")
|
|
self.assertNotIn(rule_B, matching_rules,
|
|
"Dependent Rule 1 should not be visible in the salary input selection since it is dependent on Prerequisite Rule.")
|
|
|
|
self.structure_A._update_payroll_properties(rule_A, 'hr.employee')
|
|
rule_C = self.create_property_salary_rule(struct_id=self.structure_A, code='rule_C', section=self.category1, default_value=50, dependent_input_id=rule_A)
|
|
rule_C.input_usage_employee = True
|
|
action = self.mr_property.version_id.action_configure_template_inputs()
|
|
domain = action.get('domain', [])
|
|
matching_rules = self.env['hr.salary.rule'].search(domain)
|
|
|
|
self.assertIn(rule_C, matching_rules,
|
|
"Dependent Rule 2 should be visible in the salary input selection since it is dependent on visible Prerequisite Rule.")
|
|
self.assertNotIn(rule_A, matching_rules,
|
|
"Prerequisite Rule should not be visible in the salary input selection since it is already visible on the employee form.")
|
|
self.assertNotIn(rule_B, matching_rules,
|
|
"Dependent Rule 1 should not be visible in the salary input selection since it is already visible on the employee form.")
|