forked from Mapan/odoo17e
324 lines
16 KiB
Python
324 lines
16 KiB
Python
# -*- coding:utf-8 -*-
|
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import date
|
|
from freezegun import freeze_time
|
|
|
|
from odoo import Command
|
|
from odoo.tests.common import TransactionCase
|
|
|
|
|
|
class TestPayrollCommon(TransactionCase):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super(TestPayrollCommon, cls).setUpClass()
|
|
with freeze_time('2023-01-01'):
|
|
today = date.today()
|
|
cls.belgian_company = cls.env['res.company'].create({
|
|
'name': 'My Belgian Company - Test',
|
|
'country_id': cls.env.ref('base.be').id,
|
|
'currency_id': cls.env.ref('base.EUR').id,
|
|
'l10n_be_company_number': '0477472701',
|
|
'l10n_be_revenue_code': '1293',
|
|
'street': 'Rue du Paradis',
|
|
'zip': '6870',
|
|
'city': 'Eghezee',
|
|
'vat': 'BE0897223670',
|
|
'phone': '061928374',
|
|
})
|
|
|
|
cls.env.user.company_ids |= cls.belgian_company
|
|
cls.env = cls.env(context=dict(cls.env.context, allowed_company_ids=cls.belgian_company.ids))
|
|
|
|
cls.holiday_leave_types = cls.env['hr.leave.type'].create([{
|
|
'name': 'Paid Time Off',
|
|
'requires_allocation': 'yes',
|
|
'employee_requests': 'no',
|
|
'allocation_validation_type': 'officer',
|
|
'leave_validation_type': 'both',
|
|
'responsible_ids': [Command.link(cls.env.ref('base.user_admin').id)],
|
|
'request_unit': 'day'
|
|
}])
|
|
|
|
cls.holiday_allocations = cls.env['hr.leave.allocation'].create([{
|
|
'name': 'Paid Time Off %s' % year,
|
|
'holiday_status_id': cls.holiday_leave_types.id,
|
|
'number_of_days': 20,
|
|
'holiday_type': 'company',
|
|
'mode_company_id': cls.belgian_company.id,
|
|
'date_from': date(year, 1, 1),
|
|
'date_to': date(year, 12, 31),
|
|
} for year in range(today.year - 2, today.year + 1)])
|
|
|
|
cls.resource_calendar = cls.env['resource.calendar'].create({
|
|
'name': 'Test Calendar',
|
|
'company_id': cls.belgian_company.id,
|
|
'hours_per_day': 7.6,
|
|
'tz': "Europe/Brussels",
|
|
'two_weeks_calendar': False,
|
|
'hours_per_week': 38,
|
|
'full_time_required_hours': 38
|
|
})
|
|
|
|
cls.resource_calendar_mid_time = cls.resource_calendar.copy({
|
|
'name': 'Calendar (Mid-Time)',
|
|
'full_time_required_hours': 38,
|
|
'attendance_ids': [
|
|
(0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Monday Lunch', 'dayofweek': '0', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Monday Afternoon', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Tuesday Lunch', 'dayofweek': '1', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Tuesday Afternoon', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'})
|
|
]
|
|
})
|
|
|
|
cls.resource_calendar_4_5 = cls.resource_calendar.copy({
|
|
'name': 'Calendar (4 / 5)',
|
|
'full_time_required_hours': 38,
|
|
'attendance_ids': [
|
|
(0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Monday Lunch', 'dayofweek': '0', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Monday Afternoon', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 16.6, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Tuesday Lunch', 'dayofweek': '1', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Tuesday Afternoon', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 16.6, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Wednesday Lunch', 'dayofweek': '2', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Wednesday Afternoon', 'dayofweek': '2', 'hour_from': 13, 'hour_to': 16.6, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Thursday Morning', 'dayofweek': '3', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Thursday Lunch', 'dayofweek': '3', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Thursday Afternoon', 'dayofweek': '3', 'hour_from': 13, 'hour_to': 16.6, 'day_period': 'afternoon'})
|
|
]
|
|
})
|
|
|
|
cls.resource_calendar_9_10 = cls.resource_calendar.copy({
|
|
'name': 'Calendar (9 / 10)',
|
|
'full_time_required_hours': 38,
|
|
'attendance_ids': [
|
|
(0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Monday Lunch', 'dayofweek': '0', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Monday Afternoon', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 16.6, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Tuesday Lunch', 'dayofweek': '1', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Tuesday Afternoon', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 16.6, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Wednesday Lunch', 'dayofweek': '2', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Wednesday Afternoon', 'dayofweek': '2', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Thursday Morning', 'dayofweek': '3', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Thursday Lunch', 'dayofweek': '3', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Thursday Afternoon', 'dayofweek': '3', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Friday Morning', 'dayofweek': '4', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
]
|
|
})
|
|
|
|
cls.resource_calendar_30_hours_per_week = cls.resource_calendar.copy({
|
|
'name': 'Calendar 30 Hours/Week',
|
|
'full_time_required_hours': 38,
|
|
'attendance_ids': [
|
|
(0, 0, {'name': 'Monday Morning', 'dayofweek': '0', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Monday Lunch', 'dayofweek': '0', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Monday Afternoon', 'dayofweek': '0', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Tuesday Morning', 'dayofweek': '1', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Tuesday Lunch', 'dayofweek': '1', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Tuesday Afternoon', 'dayofweek': '1', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Wednesday Morning', 'dayofweek': '2', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Wednesday Lunch', 'dayofweek': '2', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Wednesday Afternoon', 'dayofweek': '2', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'}),
|
|
(0, 0, {'name': 'Thursday Morning', 'dayofweek': '3', 'hour_from': 8, 'hour_to': 12, 'day_period': 'morning'}),
|
|
(0, 0, {'name': 'Thursday Lunch', 'dayofweek': '3', 'hour_from': 12, 'hour_to': 13, 'day_period': 'lunch'}),
|
|
(0, 0, {'name': 'Thursday Afternoon', 'dayofweek': '3', 'hour_from': 13, 'hour_to': 16.5, 'day_period': 'afternoon'})
|
|
]
|
|
})
|
|
|
|
cls.employee_georges = cls.env['hr.employee'].create({
|
|
'name': 'Georges',
|
|
'private_country_id': cls.env.ref('base.be').id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'company_id': cls.belgian_company.id,
|
|
'marital': "single",
|
|
'spouse_fiscal_status': "without_income",
|
|
'disabled': False,
|
|
'disabled_spouse_bool': False,
|
|
'is_non_resident': False,
|
|
'disabled_children_number': 0,
|
|
'other_dependent_people': False,
|
|
'other_senior_dependent': 0,
|
|
'other_disabled_senior_dependent': 0,
|
|
'other_juniors_dependent': 0,
|
|
'other_disabled_juniors_dependent': 0,
|
|
})
|
|
|
|
first_contract_georges = cls.env['hr.contract'].create({
|
|
'name': "Georges's contract",
|
|
'employee_id': cls.employee_georges.id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'company_id': cls.belgian_company.id,
|
|
'structure_type_id': cls.env.ref('hr_contract.structure_type_employee_cp200').id,
|
|
'date_start': date(today.year - 2, 1, 1),
|
|
'date_end': date(today.year - 2, 12, 31),
|
|
'wage': 2500.0,
|
|
'hourly_wage': 0.0,
|
|
'commission_on_target': 0.0,
|
|
'fuel_card': 150.0,
|
|
'internet': 38.0,
|
|
'representation_fees': 150.0,
|
|
'mobile': 30.0,
|
|
'has_laptop': False,
|
|
'meal_voucher_amount': 7.45,
|
|
'eco_checks': 250.0,
|
|
'ip': False,
|
|
'ip_wage_rate': 25.0,
|
|
'time_credit': False,
|
|
'fiscal_voluntarism': False,
|
|
'fiscal_voluntary_rate': 0.0,
|
|
'has_bicycle': False,
|
|
})
|
|
|
|
cls.georges_contracts = first_contract_georges
|
|
|
|
cls.georges_contracts |= first_contract_georges.copy({
|
|
'date_start': date(today.year - 1, 1, 1),
|
|
'date_end': date(today.year - 1, 5, 31),
|
|
'resource_calendar_id': cls.resource_calendar_mid_time.id,
|
|
'wage': 1250
|
|
})
|
|
|
|
cls.georges_contracts |= first_contract_georges.copy({
|
|
'date_start': date(today.year - 1, 6, 1),
|
|
'date_end': date(today.year - 1, 8, 31),
|
|
})
|
|
|
|
cls.georges_contracts |= first_contract_georges.copy({
|
|
'date_start': date(today.year - 1, 9, 1),
|
|
'date_end': date(today.year - 1, 12, 31),
|
|
'resource_calendar_id': cls.resource_calendar_4_5.id,
|
|
'wage': 2500 * 4 / 5
|
|
})
|
|
|
|
cls.georges_contracts.write({'state': 'close'}) # By default, the state is 'draft' when we create a new contract
|
|
|
|
contract = first_contract_georges.copy({
|
|
'date_start': date(today.year, 1, 1),
|
|
'date_end': False,
|
|
'resource_calendar_id': cls.resource_calendar_4_5.id,
|
|
'wage': 2500 * 4 / 5
|
|
})
|
|
contract.write({'state': 'open'}) # By default, the state is 'draft' when we create a new contract
|
|
cls.georges_contracts |= contract
|
|
|
|
cls.employee_john = cls.employee_georges.copy({
|
|
'name': 'John Doe',
|
|
'private_country_id': cls.env.ref('base.be').id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'contract_ids': []
|
|
})
|
|
|
|
first_contract_john = first_contract_georges.copy({
|
|
'name': "John's Contract",
|
|
'employee_id': cls.employee_john.id,
|
|
'resource_calendar_id': cls.resource_calendar.id
|
|
})
|
|
|
|
cls.john_contracts = first_contract_john
|
|
|
|
cls.john_contracts |= first_contract_john.copy({
|
|
'date_start': date(today.year - 1, 1, 1),
|
|
'date_end': date(today.year - 1, 3, 31)
|
|
})
|
|
|
|
cls.john_contracts |= first_contract_john.copy({
|
|
'date_start': date(today.year - 1, 4, 1),
|
|
'date_end': date(today.year - 1, 6, 30),
|
|
'resource_calendar_id': cls.resource_calendar_9_10.id,
|
|
'time_credit': True
|
|
})
|
|
|
|
cls.john_contracts |= first_contract_john.copy({
|
|
'date_start': date(today.year - 1, 7, 1),
|
|
'date_end': date(today.year - 1, 9, 30),
|
|
'resource_calendar_id': cls.resource_calendar_4_5.id,
|
|
'time_credit': True
|
|
})
|
|
|
|
cls.john_contracts.write({'state': 'close'}) # By default, the state is 'draft' when we create a new contract
|
|
|
|
contract = first_contract_john.copy({
|
|
'date_start': date(today.year - 1, 10, 1),
|
|
'date_end': False,
|
|
'resource_calendar_id': cls.resource_calendar_mid_time.id,
|
|
'time_credit': True
|
|
})
|
|
contract.write({'state': 'open'}) # By default, the state is 'draft' when we create a new contract
|
|
|
|
cls.john_contracts |= contract
|
|
|
|
cls.employee_a = cls.employee_georges.copy({
|
|
'name': 'A',
|
|
'private_country_id': cls.env.ref('base.be').id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'contract_ids': []
|
|
})
|
|
|
|
first_contract_a = first_contract_georges.copy({
|
|
'name': "A's Contract",
|
|
'employee_id': cls.employee_a.id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'date_start': date(today.year - 1, 1, 1),
|
|
'date_end': False
|
|
})
|
|
|
|
first_contract_a.write({'state': 'open'})
|
|
|
|
cls.a_contracts = first_contract_a
|
|
|
|
cls.employee_test = cls.employee_georges.copy({
|
|
'name': 'Employee Test',
|
|
'private_country_id': cls.env.ref('base.be').id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'contract_ids': []
|
|
})
|
|
|
|
first_contract_test = first_contract_georges.copy({
|
|
'name': "Employee Test's Contract",
|
|
'employee_id': cls.employee_test.id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'date_start': date(2017, 1, 1),
|
|
'date_end': False
|
|
})
|
|
|
|
first_contract_test.write({'state': 'open'})
|
|
|
|
cls.test_contracts = first_contract_test
|
|
|
|
cls.employee_withholding_taxes = cls.env['hr.employee'].create({
|
|
'name': 'EmployeeWithholdingTaxes',
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'company_id': cls.belgian_company.id,
|
|
})
|
|
|
|
cls.employee_withholding_taxes_contracts = first_contract_georges.copy({
|
|
'name': "EmployeeWithholdingTaxes' Contract",
|
|
'employee_id': cls.employee_withholding_taxes.id,
|
|
'resource_calendar_id': cls.resource_calendar.id,
|
|
'date_end': False,
|
|
'internet': False,
|
|
'mobile': False,
|
|
'meal_voucher_amount': 0,
|
|
'eco_checks': 0,
|
|
'wage': 2500,
|
|
})
|
|
if 'wage_on_signature' in cls.env['hr.contract']:
|
|
cls.employee_withholding_taxes_contracts['wage_on_signature'] = 2500
|
|
|
|
cls.employee_withholding_taxes_contracts.write({'state': 'open'}) # By default, the state is 'draft' when we create a new contract
|
|
cls.employee_withholding_taxes_contracts.generate_work_entries(cls.employee_withholding_taxes_contracts.date_start, today)
|
|
cls.employee_withholding_taxes_payslip = cls.env['hr.payslip'].create({
|
|
|
|
'name': "EmployeeWithholdingTaxes' Payslip",
|
|
'employee_id': cls.employee_withholding_taxes.id,
|
|
'contract_id': cls.employee_withholding_taxes_contracts.id,
|
|
})
|