# -*- coding: utf-8 -*- # Copyright 2026 Nexa Systems Inc. # License OPL-1 (Odoo Proprietary License v1.0) # # The per-day model now allows split shifts. The attendance contract # (_get_fclk_day_plan) MUST still hand the rest of the pipeline a single # work-window so penalties / overtime / absence stay correct. from datetime import date from odoo.tests import tagged from odoo.tests.common import TransactionCase @tagged('-at_install', 'post_install', 'fusion_clock') class TestMultiShiftWindow(TransactionCase): def setUp(self): super().setUp() self.S = self.env['fusion.clock.schedule'] self.emp = self.env['hr.employee'].create({'name': 'Sam Split'}) def test_split_shift_resolves_to_single_window(self): self.S.create({'employee_id': self.emp.id, 'schedule_date': date(2026, 6, 1), 'start_time': 8.0, 'end_time': 12.0, 'break_minutes': 0.0, 'state': 'posted'}) self.S.create({'employee_id': self.emp.id, 'schedule_date': date(2026, 6, 1), 'start_time': 13.0, 'end_time': 17.0, 'break_minutes': 0.0, 'state': 'posted'}) plan = self.emp._get_fclk_day_plan(date(2026, 6, 1)) self.assertTrue(plan['scheduled']) self.assertEqual(plan['start_time'], 8.0, "window starts at earliest shift") self.assertEqual(plan['end_time'], 17.0, "window ends at latest shift") self.assertAlmostEqual(plan['hours'], 8.0, places=2, msg="worked hours = sum of shifts") def test_draft_shift_excluded_from_window(self): self.S.create({'employee_id': self.emp.id, 'schedule_date': date(2026, 6, 1), 'start_time': 8.0, 'end_time': 12.0, 'break_minutes': 0.0, 'state': 'posted'}) self.S.create({'employee_id': self.emp.id, 'schedule_date': date(2026, 6, 1), 'start_time': 13.0, 'end_time': 17.0, 'break_minutes': 0.0, 'state': 'draft'}) plan = self.emp._get_fclk_day_plan(date(2026, 6, 1)) self.assertEqual(plan['end_time'], 12.0, "draft shift must not widen the window") def test_all_off_rows_resolve_to_off(self): self.S.create({'employee_id': self.emp.id, 'schedule_date': date(2026, 6, 1), 'is_off': True, 'state': 'posted'}) plan = self.emp._get_fclk_day_plan(date(2026, 6, 1)) self.assertTrue(plan['is_off']) self.assertFalse(plan['scheduled']) def test_open_shift_does_not_feed_employee_plan(self): # An open shift (no employee) on the same day must not affect anyone. self.S.create({'is_open': True, 'schedule_date': date(2026, 6, 1), 'start_time': 9.0, 'end_time': 17.0, 'state': 'posted'}) plan = self.emp._get_fclk_day_plan(date(2026, 6, 1)) self.assertFalse(plan['scheduled'], "open shift is not assigned to this employee")