diff --git a/presente/tables.py b/presente/tables.py index 44dfa00..17f2b11 100644 --- a/presente/tables.py +++ b/presente/tables.py @@ -88,7 +88,7 @@ class ActivityAttendanceTable(django_tables2.Table): accessor="user", verbose_name=_("Nome"), orderable=True, - order_by=("user_name_collated", "user__full_name"), + order_by=("user__full_name_normalized", "user__full_name"), ) user_type = django_tables2.Column( accessor="user__type", diff --git a/presente/views.py b/presente/views.py index fe41910..0a874bf 100644 --- a/presente/views.py +++ b/presente/views.py @@ -322,20 +322,8 @@ def get_page_title(self): return _("Presenças - {}").format(activity.title) def get_queryset(self): - from django.db import connection - from django.db.models import F - activity = self.get_activity() qs = Attendance.objects.filter(activity=activity).select_related("user") - - if connection.vendor == "postgresql": - from django.db.models.functions import Collate - - qs = qs.annotate(user_name_collated=Collate("user__full_name", "pt_BR")) - else: - # SQLite: just alias the field for compatibility - qs = qs.annotate(user_name_collated=F("user__full_name")) - return qs.order_by("-checked_in_at") def get_context_data(self, **kwargs): @@ -415,6 +403,7 @@ class ActivityAttendancePDFView( template_name = "presente/attendance_pdf.html" context_object_name = "attendances" pdf_filename = "relatorio_presencas.pdf" + pdf_attachment = False # Display inline in browser instead of downloading def get_pdf_filename(self): activity = self.get_activity() @@ -434,8 +423,8 @@ def get_queryset(self): if sort_by: # Map sort fields to actual model fields sort_mapping = { - "name": "user__full_name", - "-name": "-user__full_name", + "name": "user__full_name_normalized", + "-name": "-user__full_name_normalized", "type": "user__type", "-type": "-user__type", "curso": "user__curso", @@ -445,10 +434,10 @@ def get_queryset(self): "checked_in_at": "checked_in_at", "-checked_in_at": "-checked_in_at", } - sort_field = sort_mapping.get(sort_by, "user__full_name") + sort_field = sort_mapping.get(sort_by, "user__full_name_normalized") qs = qs.order_by(sort_field) else: - qs = qs.order_by("user__full_name") + qs = qs.order_by("user__full_name_normalized") return qs @@ -457,8 +446,27 @@ def get_context_data(self, **kwargs): activity = self.get_activity() context["activity"] = activity - # Get the filtered queryset (after filters are applied) - filtered_qs = context["filter"].qs + # Get the filtered queryset (after filters are applied) and apply sorting + sort_by = self.request.GET.get("sort_by", "name") + sort_mapping = { + "name": "user__full_name_normalized", + "-name": "-user__full_name_normalized", + "type": "user__type", + "-type": "-user__type", + "curso": "user__curso", + "-curso": "-user__curso", + "periodo": "user__periodo_referencia", + "-periodo": "-user__periodo_referencia", + "checked_in_at": "checked_in_at", + "-checked_in_at": "-checked_in_at", + } + sort_field = sort_mapping.get(sort_by, "user__full_name_normalized") + + # Apply sorting to the filtered queryset + filtered_qs = context["filter"].qs.order_by(sort_field) + + # Store the sorted queryset for the template + context["sorted_qs"] = filtered_qs context["total_attendances"] = filtered_qs.count() # Get column configuration @@ -511,8 +519,8 @@ def get_queryset(self): # Apply sorting sort_by = self.request.GET.get("sort_by", "name") sort_mapping = { - "name": "user__full_name", - "-name": "-user__full_name", + "name": "user__full_name_normalized", + "-name": "-user__full_name_normalized", "type": "user__type", "-type": "-user__type", "curso": "user__curso", @@ -522,7 +530,7 @@ def get_queryset(self): "checked_in_at": "checked_in_at", "-checked_in_at": "-checked_in_at", } - sort_field = sort_mapping.get(sort_by, "user__full_name") + sort_field = sort_mapping.get(sort_by, "user__full_name_normalized") qs = qs.order_by(sort_field) return qs @@ -532,6 +540,23 @@ def get(self, request, *args, **kwargs): filterset = self.filterset_class(request.GET, queryset=self.get_queryset()) queryset = filterset.qs + # Reapply sorting to ensure it's maintained after filtering + sort_by = request.GET.get("sort_by", "name") + sort_mapping = { + "name": "user__full_name_normalized", + "-name": "-user__full_name_normalized", + "type": "user__type", + "-type": "-user__type", + "curso": "user__curso", + "-curso": "-user__curso", + "periodo": "user__periodo_referencia", + "-periodo": "-user__periodo_referencia", + "checked_in_at": "checked_in_at", + "-checked_in_at": "-checked_in_at", + } + sort_field = sort_mapping.get(sort_by, "user__full_name_normalized") + queryset = queryset.order_by(sort_field) + # Get column configuration columns = request.GET.getlist("columns") if not columns: @@ -578,7 +603,7 @@ def get(self, request, *args, **kwargs): if "number" in columns: row.append(idx) if "name" in columns: - row.append(attendance.user.get_full_name()) + row.append(attendance.user.get_full_name().upper()) if "email" in columns: row.append(attendance.user.email or "-") if "matricula" in columns: diff --git a/templates/core/list.html b/templates/core/list.html index e00751b..a5f74c6 100644 --- a/templates/core/list.html +++ b/templates/core/list.html @@ -41,7 +41,7 @@
-
+ {% for field in filter.form %} {% if field.name != 'csrfmiddlewaretoken' %}
diff --git a/templates/presente/activity_attendance_list.html b/templates/presente/activity_attendance_list.html index 182e79f..c370605 100644 --- a/templates/presente/activity_attendance_list.html +++ b/templates/presente/activity_attendance_list.html @@ -5,6 +5,7 @@ hx-get="{% url 'presente:activity_attendance_export_config' activity.pk %}?{{ request.GET.urlencode }}" hx-target="#modals-here .modal-content" hx-trigger="click" + hx-include="#filter-form" data-bs-toggle="modal" data-bs-target="#modals-here"> Exportar Relatório diff --git a/templates/presente/attendance_pdf.html b/templates/presente/attendance_pdf.html index 3489d7d..514861f 100644 --- a/templates/presente/attendance_pdf.html +++ b/templates/presente/attendance_pdf.html @@ -196,7 +196,7 @@

Filtros Aplicados:

Total de Presenças: {{ total_attendances }}
- {% if filter.qs %} + {% if sorted_qs %} @@ -212,10 +212,10 @@

Filtros Aplicados:

- {% for attendance in filter.qs %} + {% for attendance in sorted_qs %} {% if "number" in columns %}{% endif %} - {% if "name" in columns %}{% endif %} + {% if "name" in columns %}{% endif %} {% if "email" in columns %}{% endif %} {% if "matricula" in columns %}{% endif %} {% if "type" in columns %}{% endif %} diff --git a/templates/presente/includes/attendance_export_config_modal.html b/templates/presente/includes/attendance_export_config_modal.html index 6d10582..98312a6 100644 --- a/templates/presente/includes/attendance_export_config_modal.html +++ b/templates/presente/includes/attendance_export_config_modal.html @@ -11,9 +11,7 @@
{{ forloop.counter }}{{ attendance.user.get_full_name }}{{ attendance.user.get_full_name|upper }}{{ attendance.user.email|default:"-" }}{{ attendance.user.matricula|default:"-" }}{{ attendance.user.get_type_display }}