diff --git a/addons/hr/models/hr_employee.py b/addons/hr/models/hr_employee.py
index 1b0eb784eba984..40a983b4793d01 100644
--- a/addons/hr/models/hr_employee.py
+++ b/addons/hr/models/hr_employee.py
@@ -216,7 +216,6 @@ def _lang_get(self):
}
"""
- permit_no = fields.Char('Work Permit No', groups="hr.group_hr_user", tracking=True)
visa_no = fields.Char('Visa No', groups="hr.group_hr_user", tracking=True)
visa_expire = fields.Date('Visa Expiration Date', groups="hr.group_hr_user", tracking=True)
work_permit_expiration_date = fields.Date('Work Permit Expiration Date', groups="hr.group_hr_user", tracking=True)
@@ -258,6 +257,8 @@ def _lang_get(self):
related='version_id.country_id.code',
groups="hr.group_hr_user"
)
+ permit_no = fields.Char('Work Permit No', readonly=False, related="version_id.permit_no", inherited=True, groups="hr.group_hr_user", tracking=True)
+
# Direct subordinates
parent_id = fields.Many2one('hr.employee', 'Manager', tracking=True, index=True,
domain="['|', ('company_id', '=', False), ('company_id', 'in', allowed_company_ids)]")
diff --git a/addons/hr/models/hr_version.py b/addons/hr/models/hr_version.py
index 1e0a2c9fd0f175..86a6fd7fd54a05 100644
--- a/addons/hr/models/hr_version.py
+++ b/addons/hr/models/hr_version.py
@@ -118,6 +118,7 @@ def _get_hr_responsible_domain(self):
spouse_complete_name = fields.Char(string="Spouse Legal Name", groups="hr.group_hr_user", tracking=1)
spouse_birthdate = fields.Date(string="Spouse Birthdate", groups="hr.group_hr_user", tracking=1)
children = fields.Integer(string='Dependent Children', groups="hr.group_hr_user", tracking=1)
+ permit_no = fields.Char('Work Permit No', groups="hr.group_hr_user", tracking=1)
# Work Information
department_id = fields.Many2one('hr.department', check_company=True, tracking=1, index=True)
diff --git a/addons/hr/views/hr_employee_views.xml b/addons/hr/views/hr_employee_views.xml
index 74f6252d3774b1..a6b0da8882114c 100644
--- a/addons/hr/views/hr_employee_views.xml
+++ b/addons/hr/views/hr_employee_views.xml
@@ -387,8 +387,8 @@
to
-
+ class="o_hr_narrow_field ms-3" invisible="not contract_date_start" required="fixed_term"/>
+
diff --git a/addons/hr_holidays/models/hr_work_entry_type.py b/addons/hr_holidays/models/hr_work_entry_type.py
index 0473b4b3e9514e..1fe00371990683 100644
--- a/addons/hr_holidays/models/hr_work_entry_type.py
+++ b/addons/hr_holidays/models/hr_work_entry_type.py
@@ -279,7 +279,7 @@ def _search_max_leaves(self, operator, value):
def _search_virtual_remaining_leaves(self, operator, value):
def is_valid(work_entry_type):
- return not work_entry_type.requires_allocation or op(work_entry_type.virtual_remaining_leaves)
+ return not work_entry_type.requires_allocation or op(work_entry_type.virtual_remaining_leaves, value)
op = PY_OPERATORS.get(operator)
if not op:
return NotImplemented
diff --git a/addons/hr_holidays/static/src/components/accrual_level/accrual_levels.scss b/addons/hr_holidays/static/src/components/accrual_level/accrual_levels.scss
index f6a930fd221024..93843403dfabfa 100644
--- a/addons/hr_holidays/static/src/components/accrual_level/accrual_levels.scss
+++ b/addons/hr_holidays/static/src/components/accrual_level/accrual_levels.scss
@@ -10,7 +10,7 @@
}
.o_accrual {
- .o_field_accrual, .o_field_selection, .o_field_filterable_selection {
+ .o_field_accrual, .o_field_selection, .o_field_day_selection, .o_field_filterable_selection {
width: fit-content !important;
&:not(.o_readonly_modifier) > *:first-child {
diff --git a/addons/hr_holidays/static/src/components/day_selection/day_selection.js b/addons/hr_holidays/static/src/components/day_selection/day_selection.js
new file mode 100644
index 00000000000000..2f459c64e2d145
--- /dev/null
+++ b/addons/hr_holidays/static/src/components/day_selection/day_selection.js
@@ -0,0 +1,34 @@
+import { registry } from "@web/core/registry";
+import { SelectionField, selectionField } from "@web/views/fields/selection/selection_field";
+
+export class DaySelection extends SelectionField {
+ static props = {
+ ...SelectionField.props,
+ month: { type: String, optional: true },
+ };
+
+ get options() {
+ const options = super.options;
+ const selectedMonth = this.props.record.data[this.props.month];
+ if (!selectedMonth) return options;
+
+ const maxDays = new Date(2024, parseInt(selectedMonth), 0).getDate();
+ return options.filter(option => parseInt(option[0]) <= maxDays);
+ }
+}
+
+export const daySelection = {
+ ...selectionField,
+ component: DaySelection,
+ extractProps({ attrs }) {
+ const props = selectionField.extractProps(...arguments);
+ props.month = attrs.month;
+ return props;
+ },
+ fieldDependencies: ({ attrs }) => [
+ { name: attrs.month, type: "selection" },
+ ],
+};
+
+
+registry.category("fields").add("day_selection", daySelection);
diff --git a/addons/hr_holidays/tests/__init__.py b/addons/hr_holidays/tests/__init__.py
index 2131051075109c..f17a7354a68cb4 100644
--- a/addons/hr_holidays/tests/__init__.py
+++ b/addons/hr_holidays/tests/__init__.py
@@ -38,3 +38,4 @@
from . import test_timeoff_overview_my_department_tour
from . import test_hr_leave_report
from . import test_member_of_department
+from . import test_time_off_type
diff --git a/addons/hr_holidays/tests/test_time_off_type.py b/addons/hr_holidays/tests/test_time_off_type.py
new file mode 100644
index 00000000000000..d5aa057bcc4610
--- /dev/null
+++ b/addons/hr_holidays/tests/test_time_off_type.py
@@ -0,0 +1,34 @@
+from odoo.addons.hr_holidays.tests.common import TestHrHolidaysCommon
+
+
+class TestTimeOffType(TestHrHolidaysCommon):
+
+ @classmethod
+ def setUpClass(cls):
+
+ super().setUpClass()
+
+ cls.work_entry_type_paid = cls.env['hr.work.entry.type'].create({
+ 'name': 'Paid Time Off',
+ 'code': 'Paid Time Off',
+ 'requires_allocation': True,
+ 'request_unit': 'day',
+ 'unit_of_measure': 'day',
+ 'allows_negative': False,
+ })
+
+ cls.allocation = cls.env['hr.leave.allocation'].create({
+ 'name': 'Regular allocation',
+ 'date_from': '2024-01-04',
+ 'work_entry_type_id': cls.work_entry_type_paid.id,
+ 'employee_id': cls.employee_emp.id,
+ 'number_of_days': 10,
+ })
+ cls.allocation.action_approve()
+
+ def test_time_off_type_selection_with_existing_allocations(self):
+ self.env['hr.work.entry.type'].with_context(
+ default_employee_id=self.employee_emp.id,
+ ).search([
+ ('virtual_remaining_leaves', '>', 0),
+ ])
diff --git a/addons/hr_holidays/views/hr_leave_accrual_views.xml b/addons/hr_holidays/views/hr_leave_accrual_views.xml
index 0630b086ad787e..12fe7b3836927c 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
@@ -204,8 +204,8 @@
options="{'links': {'other': 'carryover_custom_date'}, 'observe': 'carryover'}"/>
: the
-
+
of