Files
enterprise-addons/hr_payroll/tests/test_payslip_empty_contract.py
T

111 lines
4.9 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.fields import Date, Datetime
from odoo.tests import tagged, freeze_time
from odoo.addons.hr_payroll.tests.common import TestPayslipContractBase
@tagged('post_install', '-at_install')
class TestPayslipNewEmployeeToday(TestPayslipContractBase):
def _month_bounds(self, base_date):
date_from = base_date.replace(day=1)
date_to = date_from + relativedelta(months=1, days=-1)
return date_from, date_to
def _assert_full_out_of_contract(self, slip, date_from, date_to, lines, expected_duration):
out_type = self.env.ref('hr_work_entry.hr_work_entry_type_out_of_contract', raise_if_not_found=False)
self.assertTrue(out_type, "Missing 'Out of Contract' type")
out_lines = [l for l in lines if l.get('work_entry_type_id') == out_type.id]
self.assertTrue(out_lines, "Missing 'Out of Contract' line in payslip")
self.assertEqual(len(out_lines), 1, f"Expected exactly one 'Out of Contract' line, got {len(out_lines)}")
out_line = out_lines[0]
self.assertAlmostEqual(out_line['number_of_days'], expected_duration['days'], places=2)
self.assertAlmostEqual(out_line['number_of_hours'], expected_duration['hours'], places=2)
other_lines = [l for l in lines if l is not out_line]
self.assertFalse(other_lines, "Expected only 'Out of Contract' line")
def _make_new_employee_no_contract(self):
emp = self.env['hr.employee'].create({
'name': 'Employee Without Contract',
'company_id': self.company_us.id,
'resource_calendar_id': self.calendar_richard.id,
})
version = emp.version_id
self.assertEqual(version.date_version, Date.today())
self.assertFalse(version.contract_date_start)
return emp, version
def _make_draft_payslip(self, emp, version, date_from, date_to):
return self.env['hr.payslip'].new({
'name': 'Draft',
'employee_id': emp.id,
'version_id': version.id,
'company_id': emp.company_id.id,
'date_from': date_from,
'date_to': date_to,
})
def _assert_no_work_entries(self, emp, date_from, date_to):
emp.version_id.generate_work_entries(date_from, date_to)
dt_from = Datetime.to_datetime(date_from)
dt_to = Datetime.to_datetime(date_to) + relativedelta(hour=23, minute=59, second=59)
work_entries = self.env['hr.work.entry'].search([
('employee_id', '=', emp.id),
('date', '>=', dt_from),
('date', '<=', dt_to),
], limit=1)
self.assertFalse(
work_entries,
f"Expected no work entries for {emp.name} between {date_from} and {date_to}, "
f"but found at least one."
)
def test_employee_without_contract_payslip_current_month(self):
with freeze_time(date(2025, 12, 20)):
emp, version = self._make_new_employee_no_contract()
date_from, date_to = self._month_bounds(Date.today())
slip = self._make_draft_payslip(emp, version, date_from, date_to)
lines = slip._get_worked_day_lines(domain=None, check_out_of_version=True)
expected_duration = {'days': 23.0, 'hours': 184.0}
self._assert_full_out_of_contract(slip, date_from, date_to, lines, expected_duration)
self._assert_no_work_entries(emp, date_from, date_to)
def test_employee_without_contract_payslip_previous_month(self):
with freeze_time(date(2025, 12, 20)):
emp, version = self._make_new_employee_no_contract()
prev_month_date = Date.today() + relativedelta(months=-1)
date_from, date_to = self._month_bounds(prev_month_date)
slip = self._make_draft_payslip(emp, version, date_from, date_to)
lines = slip._get_worked_day_lines(domain=None, check_out_of_version=True)
expected_duration = {'days': 20.0, 'hours': 160.0}
self._assert_full_out_of_contract(slip, date_from, date_to, lines, expected_duration)
self._assert_no_work_entries(emp, date_from, date_to)
def test_employee_without_contract_payslip_next_month(self):
with freeze_time(date(2025, 12, 20)):
emp, version = self._make_new_employee_no_contract()
next_month_date = Date.today() + relativedelta(months=1)
date_from, date_to = self._month_bounds(next_month_date)
slip = self._make_draft_payslip(emp, version, date_from, date_to)
lines = slip._get_worked_day_lines(domain=None, check_out_of_version=True)
expected_duration = {'days': 22.0, 'hours': 176.0}
self._assert_full_out_of_contract(slip, date_from, date_to, lines, expected_duration)
self._assert_no_work_entries(emp, date_from, date_to)