Further fixes
* fixes race condition on geometry conflict calculation if performed in background process * simplifies access to smaller buffered geometry * adds mapping of "qm"->"m2" for UnitChoice in API usage for backwards compatibility
This commit is contained in:
parent
5594250d59
commit
a6a5bd5450
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
@ -146,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):
|
||||||
|
@ -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()
|
||||||
|
@ -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()
|
||||||
|
Loading…
Reference in New Issue
Block a user