Repository: ephios-dev/ephios

Issue:
Datatables sorts dates lexicographic order
The next event should be displayed in the first row of the table


Discussion:
Cannot reproduce. We don't use `order_by` in the List View's `get_queryset`, but an ascending by start time is the default datatables ordering at the moment.
Ok I have a guess on what's happening

Resolving patch:
diff --git a/ephios/event_management/urls.py b/ephios/event_management/urls.py
--- a/ephios/event_management/urls.py
+++ b/ephios/event_management/urls.py
@@ -17,6 +17,7 @@
     path("events/<int:pk>/copy", views.EventCopyView.as_view(), name="event_copy"),
     path("events/create/", views.EventCreateView.as_view(), name="event_create"),
     path("events/past/", views.EventArchiveView.as_view(), name="event_list_past"),
+    path("events/delete", views.EventBulkDeleteView.as_view(), name="event_bulk_delete"),
     path(
         "shifts/<int:pk>/signup-action/",
         views.ShiftSignupView.as_view(),
diff --git a/ephios/event_management/views.py b/ephios/event_management/views.py
--- a/ephios/event_management/views.py
+++ b/ephios/event_management/views.py
@@ -24,6 +24,7 @@
     UpdateView,
     View,
 )
+from django.views.generic.base import TemplateResponseMixin
 from django.views.generic.detail import SingleObjectMixin
 from django.views.generic.edit import FormView
 from guardian.shortcuts import assign_perm, get_objects_for_user
@@ -50,6 +51,7 @@ def get_queryset(self):
             )
             .filter(end_time__gte=timezone.now())
             .select_related("type")
+            .order_by("start_time")
         )
 
 
@@ -124,6 +126,22 @@ class EventDeleteView(CustomPermissionRequiredMixin, DeleteView):
     success_url = reverse_lazy("event_management:event_list")
 
 
+class EventBulkDeleteView(CustomPermissionRequiredMixin, TemplateResponseMixin, View):
+    permission_required = "event_management.delete_event"
+    template_name = "event_management/event_bulk_delete.html"
+
+    def post(self, request, *args, **kwargs):
+        events = Event.objects.filter(pk__in=request.POST.getlist("bulk_action"))
+        if not events:
+            messages.info(request, _("No events were selected for deletion."))
+            return redirect(reverse("event_management:event_list"))
+        if request.POST.get("confirm"):
+            events.delete()
+            messages.info(request, _("The selected events have been deleted."))
+            return redirect(reverse("event_management:event_list"))
+        return self.render_to_response({"events": events})
+
+
 class EventArchiveView(CustomPermissionRequiredMixin, ListView):
     permission_required = "event_management.view_past_event"
     model = Event


Test patch:
diff --git a/tests/event_management/test_event_bulk_actions.py b/tests/event_management/test_event_bulk_actions.py
new file mode 100644
--- /dev/null
+++ b/tests/event_management/test_event_bulk_actions.py
@@ -0,0 +1,28 @@
+import pytest
+from django.urls import reverse
+
+from ephios.event_management.models import Event
+
+
+@pytest.mark.django_db
+class TestEventBulkDelete:
+    def test_empty_list(self, django_app, planner, event, groups):
+        event_count = Event.objects.count()
+        form = django_app.get(reverse("event_management:event_list"), user=planner).form
+        form.action = reverse(
+            "event_management:event_bulk_delete"
+        )  # webtest cannot read the formaction from button
+        form.submit(name="delete")
+        assert event_count == Event.objects.count()
+
+    def test_delete_multiple_events(self, django_app, planner, event, multi_shift_event, groups):
+        event_count = Event.objects.count()
+        form = django_app.get(reverse("event_management:event_list"), user=planner).form
+        form.action = reverse(
+            "event_management:event_bulk_delete"
+        )  # webtest cannot read the formaction from button
+        form["bulk_action"] = [event.pk, multi_shift_event.pk]
+        confirm_page = form.submit(name="delete")
+        # assert confirm_page.html.findAll(string=[event.title, multi_shift_event])
+        confirm_page.form.submit()
+        assert Event.objects.count() == event_count - 2