Skip to content

Commit fd32130

Browse files
committed
[FIX] hr_holidays: dynamic accrual days
Changed the {day} dropdown to adapt to the selected month. It was previously set to 31 for all months which allowed the user to select the 31st on a 28 or 30 day month for example. task-5392293
1 parent fdc2c51 commit fd32130

File tree

3 files changed

+96
-4
lines changed

3 files changed

+96
-4
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { registry } from "@web/core/registry";
2+
import { SelectionField, selectionField } from "@web/views/fields/selection/selection_field";
3+
4+
export class DayMonthSelectionField extends SelectionField {
5+
static props = {
6+
...SelectionField.props,
7+
selectedMonth: { type: String, optional: true },
8+
};
9+
10+
11+
get options() {
12+
const selectedMonth = this.props.record.data[this.props.selectedMonth];
13+
if (isNaN(selectedMonth) || selectedMonth < 1 || selectedMonth > 12){
14+
throw new Error("Please select a valid month.");
15+
}
16+
// 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)
17+
const date = new Date(2024, selectedMonth, 0);
18+
const days = date.getDate();
19+
let newChoicesList = Array.from({length: days}, (_, i) => [(i + 1).toString(), (i + 1).toString()])
20+
return newChoicesList;
21+
}
22+
23+
}
24+
25+
export const dayMonthSelectionField = {
26+
...selectionField,
27+
component: DayMonthSelectionField,
28+
extractProps: (fieldInfo, dynamicInfo) => {
29+
const props = selectionField.extractProps(fieldInfo, dynamicInfo);
30+
props.selectedMonth = fieldInfo.attrs.selected_month;
31+
return props;
32+
},
33+
};
34+
35+
registry.category("fields").add("day_month_selection", dayMonthSelectionField);

addons/hr_holidays/tests/test_expiring_leaves.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,3 +809,60 @@ def test_carried_over_days_expiration_date_2(self):
809809

810810
# Assert the number of expiring leaves
811811
self.assertEqual(allocation_data[logged_in_emp][0][1]['closest_allocation_remaining'], 1)
812+
813+
def test_leap_year_in_accrual_plan(self):
814+
"""
815+
This test case aims to assert that the system correctly handles recurring plan dates that are set on 29th of February
816+
817+
- We create an accrual plan with a carryover date of 29/2 as well as first_month accrual cutoff set to 29/2
818+
- We create a new testing accrual plan on 1/8/2023 to be followed by a leap year
819+
- We test the correct accrual on 29/2/2024 to check that the 10 days have been accrued correctly
820+
- We test the correct accrual on 1/7/2024 to check that it doesn't affect the other cycle in a biyearly setup
821+
- Finally, we test the correct accrual on 28/2/2025 to check the number of days was accrued correctly even though
822+
it's a normal year with 1 day less than a leap one
823+
"""
824+
accrual_plan = self.env['hr.leave.accrual.plan'].with_context(tracking_disable=True).create({
825+
'name': 'Accrual Plan For Test',
826+
'can_be_carryover': True,
827+
'carryover_date': 'other',
828+
'carryover_day': 29,
829+
'carryover_month': '2',
830+
'level_ids': [(0, 0, {
831+
'added_value_type': 'day',
832+
'milestone_date': 'creation',
833+
'start_type': 'day',
834+
'added_value': 10,
835+
'frequency': 'biyearly',
836+
'first_month': '2',
837+
'first_month_day': 29,
838+
'second_month': '7',
839+
'second_month_day': 1,
840+
'action_with_unused_accruals': 'all',
841+
'accrual_validity': True,
842+
'accrual_validity_type': 'month',
843+
'accrual_validity_count': 5,
844+
})],
845+
})
846+
with freeze_time('2023-07-01'):
847+
allocation = self.env['hr.leave.allocation'].sudo().with_context(tracking_disable=True).create({
848+
'name': 'Accrual allocation for employee',
849+
'accrual_plan_id': accrual_plan.id,
850+
'employee_id': self.employee_emp.id,
851+
'holiday_status_id': self.leave_type.id,
852+
'number_of_days': 0,
853+
'allocation_type': 'accrual',
854+
})
855+
allocation.action_approve()
856+
857+
with freeze_time('2023-07-01'):
858+
allocation._update_accrual()
859+
self.assertEqual(allocation.number_of_days, 0)
860+
with freeze_time('2024-02-29'):
861+
allocation._update_accrual()
862+
self.assertEqual(allocation.number_of_days, 10)
863+
with freeze_time('2025-01-01'):
864+
allocation._update_accrual()
865+
self.assertEqual(allocation.number_of_days, 20)
866+
with freeze_time('2025-02-28'):
867+
allocation._update_accrual()
868+
self.assertEqual(allocation.number_of_days, 30)

addons/hr_holidays/views/hr_leave_accrual_views.xml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,17 @@
3636
</span>
3737
<span name="biyearly" invisible="frequency != 'biyearly'">
3838
on the
39-
<field nolabel="1" name="first_month_day" class="o_field_accrual" placeholder="select a day" required="frequency == 'biyearly'"/>
39+
<field nolabel="1" name="first_month_day" class="o_field_accrual" widget="day_month_selection" selected_month="first_month" placeholder="select a day" required="frequency == 'biyearly'"/>
4040
of
4141
<field name="first_month" class="o_field_accrual" placeholder="select a month" required="frequency == 'biyearly'"/>
4242
and the
43-
<field nolabel="1" name="second_month_day" class="o_field_accrual" placeholder="select a day" required="frequency == 'biyearly'"/>
43+
<field nolabel="1" name="second_month_day" class="o_field_accrual" widget="day_month_selection" selected_month="second_month" placeholder="select a day" required="frequency == 'biyearly'"/>
4444
of
4545
<field nolabel="1" name="second_month" class="o_field_accrual" placeholder="select a month" required="frequency == 'biyearly'"/>
4646
</span>
4747
<span name="yearly" invisible="frequency != 'yearly'">
4848
on the
49-
<field nolabel="1" name="yearly_day" class="o_field_accrual" required="frequency == 'yearly'" placeholder="select a day"/>
49+
<field nolabel="1" name="yearly_day" class="o_field_accrual" widget="day_month_selection" selected_month="yearly_month" required="frequency == 'yearly'" placeholder="select a day"/>
5050
of
5151
<field nolabel="1" name="yearly_month" class="o_field_accrual" required="frequency == 'yearly'" placeholder="select a month"/>
5252
</span>
@@ -192,7 +192,7 @@
192192
options="{'links': {'other': 'carryover_custom_date'}, 'observe': 'carryover'}"/>
193193
<span id="carryover_custom_date">
194194
: the
195-
<field name="carryover_day" placeholder="select a day"
195+
<field name="carryover_day" placeholder="select a day" widget="day_month_selection" selected_month="carryover_month"
196196
required="carryover_date == 'other'"/>
197197
of
198198
<field name="carryover_month" placeholder="select a month"

0 commit comments

Comments
 (0)