243_GDALException_on_null #244

Merged
mpeltriaux merged 2 commits from 243_GDALException_on_null into master 2022-11-23 07:13:18 +01:00
11 changed files with 38 additions and 19 deletions

View File

@ -11,7 +11,7 @@ from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, Abs
from compensation.models import Compensation from compensation.models import Compensation
from intervention.models import Intervention from intervention.models import Intervention
from konova.models import Geometry 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 konova.utils.message_templates import DATA_UNSHARED
from user.models import UserActionLogEntry from user.models import UserActionLogEntry
@ -128,6 +128,7 @@ class CompensationAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensa
obj.log.add(obj.created) obj.log.add(obj.created)
celery_update_parcels.delay(obj.geometry.id) celery_update_parcels.delay(obj.geometry.id)
celery_check_for_geometry_conflicts.delay(obj.geometry.id)
return obj.id return obj.id

View File

@ -13,7 +13,7 @@ from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_HANDLER_
from compensation.models import EcoAccount from compensation.models import EcoAccount
from intervention.models import Legal, Responsibility, Handler from intervention.models import Legal, Responsibility, Handler
from konova.models import Geometry 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 from user.models import UserActionLogEntry
@ -150,6 +150,7 @@ class EcoAccountAPISerializerV1(AbstractModelAPISerializerV1,
obj.users.add(user) obj.users.add(user)
celery_update_parcels.delay(obj.geometry.id) celery_update_parcels.delay(obj.geometry.id)
celery_check_for_geometry_conflicts.delay(obj.geometry.id)
return obj.id return obj.id

View File

@ -13,7 +13,7 @@ from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_HANDLER_
from ema.models import Ema from ema.models import Ema
from intervention.models import Responsibility, Handler from intervention.models import Responsibility, Handler
from konova.models import Geometry 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 from user.models import UserActionLogEntry
@ -122,6 +122,7 @@ class EmaAPISerializerV1(AbstractModelAPISerializerV1, AbstractCompensationAPISe
obj.users.add(user) obj.users.add(user)
celery_update_parcels.delay(obj.geometry.id) celery_update_parcels.delay(obj.geometry.id)
celery_check_for_geometry_conflicts.delay(obj.geometry.id)
return obj.id return obj.id

View File

@ -13,7 +13,7 @@ from api.utils.serializer.v1.serializer import AbstractModelAPISerializerV1, \
from compensation.models import Payment from compensation.models import Payment
from intervention.models import Intervention, Responsibility, Legal, Handler from intervention.models import Intervention, Responsibility, Legal, Handler
from konova.models import Geometry 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 from user.models import UserActionLogEntry
@ -165,6 +165,7 @@ class InterventionAPISerializerV1(AbstractModelAPISerializerV1,
obj.log.add(obj.created) obj.log.add(obj.created)
celery_update_parcels.delay(obj.geometry.id) celery_update_parcels.delay(obj.geometry.id)
celery_check_for_geometry_conflicts.delay(obj.geometry.id)
return obj.id return obj.id

View File

@ -392,7 +392,8 @@ class AbstractCompensationAPISerializerV1Mixin:
self._konova_code_from_json(e, CODELIST_COMPENSATION_ACTION_DETAIL_ID) for e in entry["action_details"] self._konova_code_from_json(e, CODELIST_COMPENSATION_ACTION_DETAIL_ID) for e in entry["action_details"]
] ]
amount = float(entry["amount"]) 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"] comment = entry["comment"]
# Check on validity # Check on validity

View File

@ -15,7 +15,7 @@ from django.utils.translation import gettext_lazy as _
from konova.forms.base_form import BaseForm from konova.forms.base_form import BaseForm
from konova.models import Geometry 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 konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
from user.models import UserActionLogEntry from user.models import UserActionLogEntry
@ -82,7 +82,12 @@ class SimpleGeomForm(BaseForm):
"MultiPolygon25D", "MultiPolygon25D",
] ]
for feature in features_json: 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) g = gdal.OGRGeometry(feature_geom, srs=DEFAULT_SRID_RLP)
flatten_geometry = g.coord_dim > 2 flatten_geometry = g.coord_dim > 2
@ -141,8 +146,9 @@ class SimpleGeomForm(BaseForm):
geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP)), geom=self.cleaned_data.get("geom", MultiPolygon(srid=DEFAULT_SRID_RLP)),
created=action, 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_update_parcels.delay(geometry.id)
celery_check_for_geometry_conflicts.delay(geometry.id)
return geometry return geometry
def __flatten_geom_to_2D(self, geom): def __flatten_geom_to_2D(self, geom):

View File

@ -8,13 +8,11 @@ Created on: 15.11.21
import json import json
from django.contrib.gis.db.models import MultiPolygonField from django.contrib.gis.db.models import MultiPolygonField
from django.contrib.gis.geos import Polygon
from django.db import models, transaction from django.db import models, transaction
from django.utils import timezone from django.utils import timezone
from konova.models import BaseResource, UuidModel from konova.models import BaseResource, UuidModel
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP 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 from konova.utils.wfs.spatial import ParcelWFSFetcher
@ -29,7 +27,18 @@ class Geometry(BaseResource):
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super().save(*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): def check_for_conflicts(self):
""" Checks for new geometry overlaps """ Checks for new geometry overlaps
@ -44,9 +53,8 @@ class Geometry(BaseResource):
return None return None
self.recheck_existing_conflicts() self.recheck_existing_conflicts()
overlapping_geoms = Geometry.objects.filter( overlapping_geoms = Geometry.objects.filter(
geom__intersects=self.geom, geom__intersects=self.geom_small_buffered,
).exclude( ).exclude(
id=self.id id=self.id
).distinct() ).distinct()
@ -68,14 +76,14 @@ class Geometry(BaseResource):
""" """
all_conflicts_as_conflicting = self.conflicts_geometries.all() all_conflicts_as_conflicting = self.conflicts_geometries.all()
still_conflicting_conflicts = all_conflicts_as_conflicting.filter( 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 = all_conflicts_as_conflicting.exclude(id__in=still_conflicting_conflicts)
resolved_conflicts.delete() resolved_conflicts.delete()
all_conflicted_by_conflicts = self.conflicted_by_geometries.all() all_conflicted_by_conflicts = self.conflicted_by_geometries.all()
still_conflicting_conflicts = all_conflicted_by_conflicts.filter( 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 = all_conflicted_by_conflicts.exclude(id__in=still_conflicting_conflicts)
resolved_conflicts.delete() resolved_conflicts.delete()

View File

@ -91,7 +91,7 @@ class ParcelWFSFetcher(AbstractWFSFetcher):
geom = Geometry.objects.filter( geom = Geometry.objects.filter(
id=self.geometry_id id=self.geometry_id
).annotate( ).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( ).annotate(
gml=AsGML(MakeValid('smaller')) gml=AsGML(MakeValid('smaller'))
).first() ).first()

Binary file not shown.

View File

@ -2307,8 +2307,8 @@ msgid "Server Error"
msgstr "" msgstr ""
#: templates/500.html:10 #: templates/500.html:10
msgid "Something happened. We are working on it!" msgid "Something happened. Admins have been informed. We are working on it!"
msgstr "Irgendetwas ist passiert. Wir arbeiten daran!" msgstr "Irgendetwas ist passiert. Die Administratoren wurden informiert. Wir arbeiten daran!"
#: templates/email/api/verify_token.html:7 #: templates/email/api/verify_token.html:7
msgid "Hello support" msgid "Hello support"

View File

@ -7,7 +7,7 @@
<h1 class="display-4">{% trans 'Server Error' %}</h1> <h1 class="display-4">{% trans 'Server Error' %}</h1>
<hr> <hr>
<p class="lead"> <p class="lead">
{% trans 'Something happened. We are working on it!' %} {% trans 'Something happened. Admins have been informed. We are working on it!' %}
</p> </p>
</div> </div>
{% endblock %} {% endblock %}