diff --git a/api/utils/serializer/v1/compensation.py b/api/utils/serializer/v1/compensation.py index 6bddadbf..fbdbba62 100644 --- a/api/utils/serializer/v1/compensation.py +++ b/api/utils/serializer/v1/compensation.py @@ -11,7 +11,7 @@ from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, Abs from compensation.models import Compensation from intervention.models import Intervention from konova.models import Geometry -from konova.tasks import celery_update_parcels +from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts from konova.utils.message_templates import DATA_UNSHARED from user.models import UserActionLogEntry @@ -128,6 +128,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa obj.log.add(obj.created) celery_update_parcels.delay(obj.geometry.id) + celery_check_for_geometry_conflicts.delay(obj.geometry.id) return obj.id diff --git a/api/utils/serializer/v1/ecoaccount.py b/api/utils/serializer/v1/ecoaccount.py index d466c34f..c3d27867 100644 --- a/api/utils/serializer/v1/ecoaccount.py +++ b/api/utils/serializer/v1/ecoaccount.py @@ -13,7 +13,7 @@ from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_HANDLER_ from compensation.models import EcoAccount from intervention.models import Legal, Responsibility, Handler from konova.models import Geometry -from konova.tasks import celery_update_parcels +from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts from user.models import UserActionLogEntry @@ -150,6 +150,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1, obj.users.add(user) celery_update_parcels.delay(obj.geometry.id) + celery_check_for_geometry_conflicts.delay(obj.geometry.id) return obj.id diff --git a/api/utils/serializer/v1/ema.py b/api/utils/serializer/v1/ema.py index 2f5c596e..4bbb6d9e 100644 --- a/api/utils/serializer/v1/ema.py +++ b/api/utils/serializer/v1/ema.py @@ -13,7 +13,7 @@ from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_HANDLER_ from ema.models import Ema from intervention.models import Responsibility, Handler from konova.models import Geometry -from konova.tasks import celery_update_parcels +from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts from user.models import UserActionLogEntry @@ -122,6 +122,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe obj.users.add(user) celery_update_parcels.delay(obj.geometry.id) + celery_check_for_geometry_conflicts.delay(obj.geometry.id) return obj.id diff --git a/api/utils/serializer/v1/intervention.py b/api/utils/serializer/v1/intervention.py index a6d5084c..dca53d72 100644 --- a/api/utils/serializer/v1/intervention.py +++ b/api/utils/serializer/v1/intervention.py @@ -13,7 +13,7 @@ from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, \ from compensation.models import Payment from intervention.models import Intervention, Responsibility, Legal, Handler from konova.models import Geometry -from konova.tasks import celery_update_parcels +from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts from user.models import UserActionLogEntry @@ -165,6 +165,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1, obj.log.add(obj.created) celery_update_parcels.delay(obj.geometry.id) + celery_check_for_geometry_conflicts.delay(obj.geometry.id) return obj.id diff --git a/api/utils/serializer/v1/serializer.py b/api/utils/serializer/v1/serializer.py index fe979775..78f8d1f6 100644 --- a/api/utils/serializer/v1/serializer.py +++ b/api/utils/serializer/v1/serializer.py @@ -392,7 +392,8 @@ class AbstractCompensationAPISerializerV1Mixin: self._konova_code_from_json(e, CODELIST_COMPENSATION_ACTION_DETAIL_ID) for e in entry["action_details"] ] amount = float(entry["amount"]) - unit = entry["unit"] + # Mapping of old "qm" into "m²" + unit = UnitChoices.m2.value if entry["unit"] == "qm" else entry["unit"] comment = entry["comment"] # Check on validity diff --git a/konova/forms/geometry_form.py b/konova/forms/geometry_form.py index f76b907f..95e0a7db 100644 --- a/konova/forms/geometry_form.py +++ b/konova/forms/geometry_form.py @@ -15,7 +15,7 @@ from django.utils.translation import gettext_lazy as _ from konova.forms.base_form import BaseForm from konova.models import Geometry -from konova.tasks import celery_update_parcels +from konova.tasks import celery_update_parcels, celery_check_for_geometry_conflicts from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP from user.models import UserActionLogEntry @@ -82,7 +82,12 @@ class SimpleGeomForm(BaseForm): "MultiPolygon25D", ] for feature in features_json: - feature_geom = json.dumps(feature.get("geometry", feature)) + feature_geom = feature.get("geometry", feature) + if feature_geom is None: + # Fallback for rare cases where a feature does not contain any geometry + continue + + feature_geom = json.dumps(feature_geom) g = gdal.OGRGeometry(feature_geom, srs=DEFAULT_SRID_RLP) flatten_geometry = g.coord_dim > 2 @@ -141,8 +146,9 @@ class SimpleGeomForm(BaseForm): geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP)), created=action, ) - # Start the parcel update procedure in a background process + # Start parcel update and geometry conflict checking procedure in a background process celery_update_parcels.delay(geometry.id) + celery_check_for_geometry_conflicts.delay(geometry.id) return geometry def __flatten_geom_to_2D(self, geom): diff --git a/konova/models/geometry.py b/konova/models/geometry.py index f8c272f9..492ba439 100644 --- a/konova/models/geometry.py +++ b/konova/models/geometry.py @@ -8,13 +8,11 @@ Created on: 15.11.21 import json from django.contrib.gis.db.models import MultiPolygonField -from django.contrib.gis.geos import Polygon from django.db import models, transaction from django.utils import timezone from konova.models import BaseResource, UuidModel from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP -from konova.tasks import celery_check_for_geometry_conflicts from konova.utils.wfs.spatial import ParcelWFSFetcher @@ -29,7 +27,18 @@ class Geometry(BaseResource): def save(self, *args, **kwargs): super().save(*args, **kwargs) - celery_check_for_geometry_conflicts.delay(self.id) + + @property + def geom_small_buffered(self): + """ + Returns a smaller buffered version of the geometry. + Can be used to shrink the geometry used for intersection purposes to avoid intersection detection on + neighbouring geometries. + + Returns: + + """ + return self.geom.buffer(-0.001) def check_for_conflicts(self): """ Checks for new geometry overlaps @@ -44,9 +53,8 @@ class Geometry(BaseResource): return None self.recheck_existing_conflicts() - overlapping_geoms = Geometry.objects.filter( - geom__intersects=self.geom, + geom__intersects=self.geom_small_buffered, ).exclude( id=self.id ).distinct() @@ -68,14 +76,14 @@ class Geometry(BaseResource): """ all_conflicts_as_conflicting = self.conflicts_geometries.all() still_conflicting_conflicts = all_conflicts_as_conflicting.filter( - affected_geometry__geom__intersects=self.geom + affected_geometry__geom__intersects=self.geom_small_buffered ) resolved_conflicts = all_conflicts_as_conflicting.exclude(id__in=still_conflicting_conflicts) resolved_conflicts.delete() all_conflicted_by_conflicts = self.conflicted_by_geometries.all() still_conflicting_conflicts = all_conflicted_by_conflicts.filter( - conflicting_geometry__geom__intersects=self.geom + conflicting_geometry__geom__intersects=self.geom_small_buffered ) resolved_conflicts = all_conflicted_by_conflicts.exclude(id__in=still_conflicting_conflicts) resolved_conflicts.delete() diff --git a/konova/utils/wfs/spatial.py b/konova/utils/wfs/spatial.py index 5578c35a..a3d4bd62 100644 --- a/konova/utils/wfs/spatial.py +++ b/konova/utils/wfs/spatial.py @@ -91,7 +91,7 @@ class ParcelWFSFetcher(AbstractWFSFetcher): geom = Geometry.objects.filter( id=self.geometry_id ).annotate( - smaller=Func(F('geom'), -0.001, function="ST_Buffer") + smaller=Func(F('geom'), -0.001, function="ST_Buffer") # same as geometry.geom_small_buffered but for QuerySet ).annotate( gml=AsGML(MakeValid('smaller')) ).first() diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo index 422ac7b6..b87493bc 100644 Binary files a/locale/de/LC_MESSAGES/django.mo and b/locale/de/LC_MESSAGES/django.mo differ diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po index 96bfa072..fb261034 100644 --- a/locale/de/LC_MESSAGES/django.po +++ b/locale/de/LC_MESSAGES/django.po @@ -2307,8 +2307,8 @@ msgid "Server Error" msgstr "" #: templates/500.html:10 -msgid "Something happened. We are working on it!" -msgstr "Irgendetwas ist passiert. Wir arbeiten daran!" +msgid "Something happened. Admins have been informed. We are working on it!" +msgstr "Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir arbeiten daran!" #: templates/email/api/verify_token.html:7 msgid "Hello support" diff --git a/templates/500.html b/templates/500.html index 5299a693..f3839716 100644 --- a/templates/500.html +++ b/templates/500.html @@ -7,7 +7,7 @@

{% trans 'Server Error' %}


- {% trans 'Something happened. We are working on it!' %} + {% trans 'Something happened. Admins have been informed. We are working on it!' %}

{% endblock %} \ No newline at end of file