From c74aceba660f587086f932240ec69932b62b44e0 Mon Sep 17 00:00:00 2001
From: Helge Jung <hej@c3pb.de>
Date: Tue, 24 Dec 2024 23:53:48 +0100
Subject: [PATCH] c3nav API export: use location_state and add 'is_preview'
 attribute

---
 src/api/tests/map.py  |  3 ++-
 src/api/views/maps.py | 21 +++++++++++++++------
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/src/api/tests/map.py b/src/api/tests/map.py
index 41bf4fe15..173260088 100644
--- a/src/api/tests/map.py
+++ b/src/api/tests/map.py
@@ -49,6 +49,7 @@ class MapTest(TestCase):
 
         # set POI on assembly and accept it
         self.assembly.location_point = Point(8.9, 52.9)
+        self.assembly.location_state = Assembly.LocationState.ROUGH
         self.assembly.state = Assembly.State.ACCEPTED
         self.assembly.save()
         ConferenceExportCache.objects.all().delete()
@@ -60,7 +61,7 @@ class MapTest(TestCase):
         self.assertEqual(0, len(content['features']))
 
         # change state to 'placed', now there should be a POI
-        self.assembly.state = Assembly.State.PLACED
+        self.assembly.location_state = Assembly.LocationState.FINAL
         self.assembly.save()
         ConferenceExportCache.objects.all().delete()
         resp = self.client.get(url)
diff --git a/src/api/views/maps.py b/src/api/views/maps.py
index 245e265d5..77b920960 100644
--- a/src/api/views/maps.py
+++ b/src/api/views/maps.py
@@ -5,9 +5,10 @@ from rest_framework.response import Response
 from rest_framework.views import APIView
 
 from django.contrib.gis.gdal import CoordTransform, SpatialReference
+from django.db.models import Q, QuerySet
 
 from core.models.assemblies import Assembly
-from core.models.conference import ConferenceExportCache
+from core.models.conference import Conference, ConferenceExportCache
 from core.models.map import MapPOI
 
 from api.permissions import IsConferenceService, IsSuperUser
@@ -16,6 +17,13 @@ from api.views.mixins import ConferenceSlugMixin
 _cts = {}  # cache of CoordTransforms (if needed)
 
 
+def get_exportable_assemblies(conference: Conference) -> QuerySet[Assembly]:
+    """Fetches all assemblies in the given conference with publish-able location."""
+    exportable_states = [*Assembly.PUBLIC_STATES, Assembly.State.HIDDEN]
+    q_placed_assemblies = Q(location_state__in=[Assembly.LocationState.PREVIEW, Assembly.LocationState.FINAL])
+    return Assembly.objects.filter(conference=conference, state__in=exportable_states).filter(q_placed_assemblies)
+
+
 def get_field_geojson(value, srid: int, ct_cache: dict | None = None):
     if value.srid != srid:
         if ct_cache is None:
@@ -70,8 +78,7 @@ class AssembliesExportView(ConferenceSlugMixin, APIView, metaclass=abc.ABCMeta):
     geometry_field = None
 
     def get_queryset(self):
-        exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN]
-        return Assembly.objects.filter(conference=self.conference, state__in=exportable_states)
+        return get_exportable_assemblies(conference=self.conference)
 
     def get_geometry_field(self, obj):
         return getattr(obj, self.geometry_field)
@@ -137,8 +144,7 @@ class C3NavExportView(ConferenceSlugMixin, APIView):
 
         data = []
 
-        exportable_states = [*Assembly.PLACED_STATES, Assembly.State.HIDDEN]
-        qs = self.conference.assemblies.filter(state__in=exportable_states)
+        qs = get_exportable_assemblies(self.conference)
         if request.GET.get('all') != '1':
             qs = qs.exclude(location_data__point=None, location_data__boundaries=None)
         for assembly in qs.all():  # type: Assembly
@@ -153,8 +159,11 @@ class C3NavExportView(ConferenceSlugMixin, APIView):
                     'description': {'de': assembly.description_de, 'en': assembly.description_en},
                     'public_url': hub_absolute('plainui:assembly', assembly_slug=assembly.slug),
                     'parent_id': assembly.parent_id,
-                    'children': assembly.children.filter(state__in=exportable_states).values_list('slug', flat=True) if assembly.is_cluster else None,
+                    'children': get_exportable_assemblies(conference=self.conference).filter(parent=assembly).values_list('slug', flat=True)
+                    if assembly.is_cluster
+                    else None,
                     'floor': assembly.get_location_floor_index(),
+                    'is_preview': assembly.location_state != Assembly.LocationState.FINAL,
                     'location': loc_data.get('point'),  # assembly.get_location_point_xy(),
                     'polygons': loc_data.get('boundaries'),  # assembly.get_location_boundaries_xy(),
                 }
-- 
GitLab