diff --git a/addons/hr/models/hr_employee.py b/addons/hr/models/hr_employee.py
index 1b0eb784eba984..417c84ef30b4da 100644
--- a/addons/hr/models/hr_employee.py
+++ b/addons/hr/models/hr_employee.py
@@ -216,7 +216,7 @@ def _lang_get(self):
}
"""
- permit_no = fields.Char('Work Permit No', groups="hr.group_hr_user", tracking=True)
+ permit_no = fields.Char(readonly=False, related='version_id.permit_no', inherited=True, groups="hr.group_hr_user")
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)
diff --git a/addons/hr/models/hr_version.py b/addons/hr/models/hr_version.py
index 1e0a2c9fd0f175..920e2d1735c520 100644
--- a/addons/hr/models/hr_version.py
+++ b/addons/hr/models/hr_version.py
@@ -154,6 +154,7 @@ def _get_hr_responsible_domain(self):
is_flexible = fields.Boolean(compute='_compute_is_flexible', store=True, groups="hr.group_hr_user")
is_fully_flexible = fields.Boolean(compute='_compute_is_flexible', store=True, groups="hr.group_hr_user")
tz = fields.Selection(_tz_get, string='Timezone', required=True, default=lambda self: self.env.context.get('tz') or self.env.user.tz or 'UTC')
+ permit_no = fields.Char(string='Work Permit No', tracking=True, groups="hr.group_hr_user")
# Contract Information
contract_date_start = fields.Date('Contract Start Date', tracking=1, groups="hr.group_hr_manager")
diff --git a/addons/hr/views/hr_employee_views.xml b/addons/hr/views/hr_employee_views.xml
index 74f6252d3774b1..35bec5651f0d0d 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..8e052ffe5bbf7d 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 {
@@ -20,7 +20,7 @@
field-sizing: content;
}
- &:not(.o_field_selection, .o_field_filterable_selection) > *:first-child {
+ &:not(.o_field_selection, .o_field_day_selection, .o_field_filterable_selection) > *:first-child {
max-width: 8ch;
}
}
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..a9a66c86e3b242
--- /dev/null
+++ b/addons/hr_holidays/static/src/components/day_selection/day_selection.js
@@ -0,0 +1,44 @@
+import { selectionField, SelectionField } from "@web/views/fields/selection/selection_field";
+import { registry } from "@web/core/registry";
+
+export class DaySelectionField extends SelectionField {
+ static props = {
+ ...SelectionField.props,
+ month_field: {
+ type: String,
+ optional: true
+ },
+ }
+
+ get options() {
+ let month = parseInt(this.props.record.data[this.props.month_field]);
+ if (month) {
+ let days_number = new Date(2024, month, 0).getDate()
+ let new_options = []
+ for (let i = 0 ; i < days_number ; i++) new_options[i] = [i + 1, i + 1]
+ return new_options
+ }
+ else {
+ return super.options
+ }
+ }
+}
+
+export const daySelection = {
+ ...selectionField,
+ component: DaySelectionField,
+ extractProps({ options }) {
+ const props = selectionField.extractProps(...arguments);
+ props.month_field = options["month_field"];
+ return props;
+ },
+ fieldDependencies({ options }){
+ if (options["month_field"]) {
+ return [{
+ "name": options["month_field"]
+ }]
+ }
+ },
+};
+
+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..37275ccf2cda50 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_work_entry_type_search
diff --git a/addons/hr_holidays/tests/test_work_entry_type_search.py b/addons/hr_holidays/tests/test_work_entry_type_search.py
new file mode 100644
index 00000000000000..165e64a2405ffd
--- /dev/null
+++ b/addons/hr_holidays/tests/test_work_entry_type_search.py
@@ -0,0 +1,40 @@
+from odoo.tests import tagged
+
+from odoo.addons.hr_holidays.tests.common import TestHrHolidaysCommon
+
+
+@tagged("work_entry_search")
+class TestWorkEntryTypeSearch(TestHrHolidaysCommon):
+ def test_work_entry_type_search(self):
+ employee_test = self.env["hr.employee"].create({"name": "Test Employee"})
+
+ work_entry_type_test = self.env["hr.work.entry.type"].create(
+ {
+ "name": "Paid Time Off",
+ "code": "Paid Time Off",
+ "requires_allocation": True,
+ "allocation_validation_type": "no_validation",
+ "request_unit": "day",
+ "unit_of_measure": "day",
+ }
+ )
+
+ self.env["hr.leave.allocation"].create(
+ {
+ "employee_id": employee_test.id,
+ "work_entry_type_id": work_entry_type_test.id,
+ "number_of_days": 1,
+ }
+ )
+
+ work_entry_type_search_test = (
+ self.env["hr.work.entry.type"]
+ .with_context(employee_id=employee_test.id)
+ .search([("virtual_remaining_leaves", ">", 0)])
+ )
+
+ self.assertIn(
+ work_entry_type_test,
+ work_entry_type_search_test,
+ "Should have found the work entry type that was created.",
+ )
diff --git a/addons/hr_holidays/views/hr_leave_accrual_views.xml b/addons/hr_holidays/views/hr_leave_accrual_views.xml
index 0630b086ad787e..272580bbe4cd85 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,7 +204,7 @@
options="{'links': {'other': 'carryover_custom_date'}, 'observe': 'carryover'}"/>
: the
-
of