From 07bac26a5820beabbae1f63baa4696e58ea969ea Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Mon, 18 Aug 2025 08:46:21 +0200 Subject: [PATCH] # Hotfix #480 * (potentially) fixes a bug occuring on non multipolygon geometries processed in an api call * simplifies casting into multipolygon * simplifies casting into rlp srid (epsg:25832) --- api/tests/v1/update/test_api_update.py | 10 ++++----- api/utils/serializer/serializer.py | 6 ++--- konova/forms/geometry_form.py | 3 +-- konova/models/geometry.py | 31 ++++++++++++++++++++++++++ 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/api/tests/v1/update/test_api_update.py b/api/tests/v1/update/test_api_update.py index ffaa6870..faf6eadb 100644 --- a/api/tests/v1/update/test_api_update.py +++ b/api/tests/v1/update/test_api_update.py @@ -12,7 +12,7 @@ from django.contrib.gis import geos from django.urls import reverse from api.tests.v1.share.test_api_sharing import BaseAPIV1TestCase -from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP +from konova.models import Geometry class APIV1UpdateTestCase(BaseAPIV1TestCase): @@ -64,7 +64,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase): put_props = put_body["properties"] put_geom = geos.fromstr(json.dumps(put_body)) - put_geom.transform(DEFAULT_SRID_RLP) + put_geom = Geometry.cast_to_rlp_srid(put_geom) self.assertEqual(put_geom, self.intervention.geometry.geom) self.assertEqual(put_props["title"], self.intervention.title) self.assertNotEqual(modified_on, self.intervention.modified) @@ -94,7 +94,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase): put_props = put_body["properties"] put_geom = geos.fromstr(json.dumps(put_body)) - put_geom.transform(DEFAULT_SRID_RLP) + put_geom = Geometry.cast_to_rlp_srid(put_geom) self.assertEqual(put_geom, self.compensation.geometry.geom) self.assertEqual(put_props["title"], self.compensation.title) self.assertNotEqual(modified_on, self.compensation.modified) @@ -124,7 +124,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase): put_props = put_body["properties"] put_geom = geos.fromstr(json.dumps(put_body)) - put_geom.transform(DEFAULT_SRID_RLP) + put_geom = Geometry.cast_to_rlp_srid(put_geom) self.assertEqual(put_geom, self.eco_account.geometry.geom) self.assertEqual(put_props["title"], self.eco_account.title) self.assertNotEqual(modified_on, self.eco_account.modified) @@ -156,7 +156,7 @@ class APIV1UpdateTestCase(BaseAPIV1TestCase): put_props = put_body["properties"] put_geom = geos.fromstr(json.dumps(put_body)) - put_geom.transform(DEFAULT_SRID_RLP) + put_geom = Geometry.cast_to_rlp_srid(put_geom) self.assertEqual(put_geom, self.ema.geometry.geom) self.assertEqual(put_props["title"], self.ema.title) self.assertNotEqual(modified_on, self.ema.modified) diff --git a/api/utils/serializer/serializer.py b/api/utils/serializer/serializer.py index c3096cc1..f4a35bdc 100644 --- a/api/utils/serializer/serializer.py +++ b/api/utils/serializer/serializer.py @@ -13,7 +13,7 @@ from django.contrib.gis.geos import GEOSGeometry from django.core.paginator import Paginator from django.db.models import Q -from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP +from konova.models import Geometry from konova.utils.message_templates import DATA_UNSHARED @@ -145,8 +145,8 @@ class AbstractModelAPISerializer: if isinstance(geojson, dict): geojson = json.dumps(geojson) geometry = geos.fromstr(geojson) - if geometry.srid != DEFAULT_SRID_RLP: - geometry.transform(DEFAULT_SRID_RLP) + geometry = Geometry.cast_to_rlp_srid(geometry) + geometry = Geometry.cast_to_multipolygon(geometry) return geometry def _get_obj_from_db(self, id, user): diff --git a/konova/forms/geometry_form.py b/konova/forms/geometry_form.py index 75b6e97c..e6ef3998 100644 --- a/konova/forms/geometry_form.py +++ b/konova/forms/geometry_form.py @@ -117,8 +117,7 @@ class SimpleGeomForm(BaseForm): form_geom = form_geom.union(feature) # Make sure to convert into a MultiPolygon. Relevant if a single Polygon is provided. - if form_geom.geom_type != "MultiPolygon": - form_geom = MultiPolygon(form_geom, srid=DEFAULT_SRID_RLP) + form_geom = Geometry.cast_to_multipolygon(form_geom) # Write unioned Multipolygon into cleaned data if self.cleaned_data is None: diff --git a/konova/models/geometry.py b/konova/models/geometry.py index ffe93aa9..1839f103 100644 --- a/konova/models/geometry.py +++ b/konova/models/geometry.py @@ -11,6 +11,7 @@ from django.contrib.gis.db.models import MultiPolygonField from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned from django.db import models, transaction from django.utils import timezone +from django.contrib.gis.geos import MultiPolygon from konova.models import BaseResource, UuidModel from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP @@ -383,6 +384,36 @@ class Geometry(BaseResource): return complexity_factor + @staticmethod + def cast_to_multipolygon(input_geom): + """ If input_geom is not a MultiPolygon, cast to MultiPolygon + + Args: + input_geom (): + + Returns: + output_geom + """ + output_geom = input_geom + if input_geom.geom_type != "MultiPolygon": + output_geom = MultiPolygon(input_geom, srid=DEFAULT_SRID_RLP) + return output_geom + + @staticmethod + def cast_to_rlp_srid(input_geom): + """ If input_geom is not of RLP SRID (25832), cast to RLP SRID + + Args: + input_geom (): + + Returns: + output_geom + """ + output_geom = input_geom + if output_geom.srid != DEFAULT_SRID_RLP: + output_geom.transform(DEFAULT_SRID_RLP) + return output_geom + class GeometryConflict(UuidModel): """