111 lines
4.9 KiB
Python
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)
|