Files
hrms/accessibility/filters.py
2026-01-16 12:45:14 +01:00

118 lines
3.8 KiB
Python

"""
accessibility/filters.py
"""
from functools import reduce
import django_filters
from django.db.models import Q
from django.template.loader import render_to_string
from django.utils.translation import gettext as _
from employee.models import Employee
from horilla.filters import HorillaFilterSet
from horilla.horilla_middlewares import _thread_locals
def _filter_form_structured(self):
"""
Render the form fields as HTML table rows with Bootstrap styling.
"""
request = getattr(_thread_locals, "request", None)
context = {
"form": self,
"request": request,
}
table_html = render_to_string("accessibility/filter_form_body.html", context)
return table_html
class AccessibilityFilter(HorillaFilterSet):
"""
Accessibility Filter with dynamic OR logic between fields
"""
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form.structured = _filter_form_structured(self.form)
pk = django_filters.ModelMultipleChoiceFilter(
queryset=Employee.objects.all(),
field_name="pk",
lookup_expr="in",
label=_("Employee"),
)
excluded_employees = django_filters.ModelMultipleChoiceFilter(
queryset=Employee.objects.all(),
label=_("Exclude Employees"),
)
verbose_name = {
"employee_work_info__job_position_id": _("Job Position"),
"employee_work_info__department_id": _("Department"),
"employee_work_info__work_type_id": _("Work Type"),
"employee_work_info__employee_type_id": _("Employee Type"),
"employee_work_info__job_role_id": _("Job Role"),
"employee_work_info__company_id": _("Company"),
"employee_work_info__shift_id": _("Shift"),
"employee_work_info__tags": _("Tags"),
"employee_user_id__groups": _("Groups"),
"employee_user_id__user_permissions": _("Permissions"),
}
class Meta:
"""
Meta class for additional options
"""
model = Employee
fields = [
"pk",
"employee_work_info__job_position_id",
"employee_work_info__department_id",
"employee_work_info__work_type_id",
"employee_work_info__employee_type_id",
"employee_work_info__job_role_id",
"employee_work_info__company_id",
"employee_work_info__shift_id",
"employee_work_info__tags",
"employee_user_id__groups",
"employee_user_id__user_permissions",
]
def filter_queryset(self, queryset):
"""
Dynamically apply OR condition between all specified fields
"""
or_conditions = []
for field in self.Meta.fields:
field_value = self.data.get(field)
if field_value:
# Ensure field_value is always a list of strings (IDs)
if not isinstance(field_value, (list, tuple)):
field_value = [field_value]
# Convert all to ints
try:
field_value = [int(v) for v in field_value if v]
except ValueError:
continue # skip invalid values
# For related fields, use __in
if "__" in field:
or_conditions.append(Q(**{f"{field}__id__in": field_value}))
else:
or_conditions.append(Q(**{f"{field}__in": field_value}))
if or_conditions:
queryset = queryset.filter(reduce(lambda x, y: x | y, or_conditions))
excluded_employees = self.data.get("excluded_employees")
if excluded_employees:
if not isinstance(excluded_employees, (list, tuple)):
excluded_employees = [excluded_employees]
queryset = queryset.exclude(pk__in=excluded_employees)
return queryset