diff --git a/addons/hr_holidays/static/src/components/day_month_selection/day_month_selection.js b/addons/hr_holidays/static/src/components/day_month_selection/day_month_selection.js new file mode 100644 index 0000000000000..f96120efaa895 --- /dev/null +++ b/addons/hr_holidays/static/src/components/day_month_selection/day_month_selection.js @@ -0,0 +1,32 @@ +import { registry } from "@web/core/registry"; +import { SelectionField, selectionField } from "@web/views/fields/selection/selection_field"; + +export class DayMonthSelectionField extends SelectionField { + static props = { + ...SelectionField.props, + selectedMonth: { type: String, optional: true }, + }; + + + get options() { + const selectedMonth = this.props.record.data[this.props.selectedMonth]; + // The year 2024 is used as a default year as it's a leap year so it will alow us to select the 29th of February (to be more generic) + const date = new Date(2024, selectedMonth, 0); + const days = date.getDate(); + let newChoicesList = Array.from({length: days}, (_, i) => [(i + 1).toString(), (i + 1).toString()]) + return newChoicesList; + } + +} + +export const dayMonthSelectionField = { + ...selectionField, + component: DayMonthSelectionField, + extractProps: (fieldInfo, dynamicInfo) => { + const props = selectionField.extractProps(fieldInfo, dynamicInfo); + props.selectedMonth = fieldInfo.attrs.selected_month; + return props; + }, +}; + +registry.category("fields").add("day_month_selection", dayMonthSelectionField); diff --git a/addons/hr_holidays/tests/test_expiring_leaves.py b/addons/hr_holidays/tests/test_expiring_leaves.py index 90d4232e33b94..d35c73d9d2909 100644 --- a/addons/hr_holidays/tests/test_expiring_leaves.py +++ b/addons/hr_holidays/tests/test_expiring_leaves.py @@ -809,3 +809,60 @@ def test_carried_over_days_expiration_date_2(self): # Assert the number of expiring leaves self.assertEqual(allocation_data[logged_in_emp][0][1]['closest_allocation_remaining'], 1) + + def test_leap_year_in_accrual_plan(self): + """ + This test case aims to assert that the system correctly handles recurring plan dates that are set on 29th of February + + - We create an accrual plan with a carryover date of 29/2 as well as first_month accrual cutoff set to 29/2 + - We create a new testing accrual plan on 1/8/2023 to be followed by a leap year + - We test the correct accrual on 29/2/2024 to check that the 10 days have been accrued correctly + - We test the correct accrual on 1/7/2024 to check that it doesn't affect the other cycle in a biyearly setup + - Finally, we test the correct accrual on 28/2/2025 to check the number of days was accrued correctly even though + it's a normal year with 1 day less than a leap one + """ + accrual_plan = self.env['hr.leave.accrual.plan'].with_context(tracking_disable=True).create({ + 'name': 'Accrual Plan For Test', + 'can_be_carryover': True, + 'carryover_date': 'other', + 'carryover_day': 29, + 'carryover_month': '2', + 'level_ids': [(0, 0, { + 'added_value_type': 'day', + 'milestone_date': 'creation', + 'start_type': 'day', + 'added_value': 10, + 'frequency': 'biyearly', + 'first_month': '2', + 'first_month_day': 29, + 'second_month': '7', + 'second_month_day': 1, + 'action_with_unused_accruals': 'all', + 'accrual_validity': True, + 'accrual_validity_type': 'month', + 'accrual_validity_count': 5, + })], + }) + with freeze_time('2023-07-01'): + allocation = self.env['hr.leave.allocation'].sudo().with_context(tracking_disable=True).create({ + 'name': 'Accrual allocation for employee', + 'accrual_plan_id': accrual_plan.id, + 'employee_id': self.employee_emp.id, + 'holiday_status_id': self.leave_type.id, + 'number_of_days': 0, + 'allocation_type': 'accrual', + }) + allocation.action_approve() + + with freeze_time('2023-07-01'): + allocation._update_accrual() + self.assertEqual(allocation.number_of_days, 0) + with freeze_time('2024-02-29'): + allocation._update_accrual() + self.assertEqual(allocation.number_of_days, 10) + with freeze_time('2025-01-01'): + allocation._update_accrual() + self.assertEqual(allocation.number_of_days, 20) + with freeze_time('2025-02-28'): + allocation._update_accrual() + self.assertEqual(allocation.number_of_days, 30) diff --git a/addons/hr_holidays/views/hr_leave_accrual_views.xml b/addons/hr_holidays/views/hr_leave_accrual_views.xml index 53e2df20c6ff2..ca117ceda936c 100644 --- a/addons/hr_holidays/views/hr_leave_accrual_views.xml +++ b/addons/hr_holidays/views/hr_leave_accrual_views.xml @@ -36,17 +36,17 @@ on the - + of and the - + of on the - + of @@ -192,7 +192,7 @@ options="{'links': {'other': 'carryover_custom_date'}, 'observe': 'carryover'}"/> : the - of