# Parcel duplicate repair
* adds mechanic to repair parcels in case of unwanted parcel duplicates * optimizes filtering of geometries for parcel recalculation
This commit is contained in:
parent
8ef11c681e
commit
7820dec3d1
@ -8,11 +8,9 @@ Created on: 04.01.22
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.contrib.gis.db.models.functions import Area
|
from django.contrib.gis.db.models.functions import Area
|
||||||
from django.db.models import Q
|
|
||||||
from django.utils.timezone import now
|
|
||||||
|
|
||||||
from konova.management.commands.setup import BaseKonovaCommand
|
from konova.management.commands.setup import BaseKonovaCommand
|
||||||
from konova.models import Geometry
|
from konova.models import Geometry, ParcelIntersection
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseKonovaCommand):
|
class Command(BaseKonovaCommand):
|
||||||
@ -36,17 +34,21 @@ class Command(BaseKonovaCommand):
|
|||||||
def recalculate_parcels(self, options: dict):
|
def recalculate_parcels(self, options: dict):
|
||||||
force_all = options.get("force_all", False)
|
force_all = options.get("force_all", False)
|
||||||
|
|
||||||
if force_all:
|
|
||||||
geometry_objects = Geometry.objects.all()
|
geometry_objects = Geometry.objects.all()
|
||||||
else:
|
|
||||||
_today = now().date()
|
if not force_all:
|
||||||
_date_threshold = _today - datetime.timedelta(days=1)
|
# Fetch all intersections
|
||||||
geometry_objects = Geometry.objects.filter(
|
intersection_objs = ParcelIntersection.objects.filter(
|
||||||
Q(
|
geometry__in=geometry_objects
|
||||||
Q(parcel_update_start__date__lte=_date_threshold) |
|
)
|
||||||
Q(parcel_update_start__isnull=True)
|
# Just take the geometry ids, which seem to have intersections
|
||||||
),
|
geom_with_intersection_ids = intersection_objs.values_list(
|
||||||
parcel_update_end__isnull=True
|
"geometry__id",
|
||||||
|
flat=True
|
||||||
|
)
|
||||||
|
# Filter those geometries out (they have intersections and do not need to be processed)
|
||||||
|
geometry_objects = geometry_objects.exclude(
|
||||||
|
id__in=geom_with_intersection_ids
|
||||||
)
|
)
|
||||||
|
|
||||||
self._write_warning("=== Update parcels and districts ===")
|
self._write_warning("=== Update parcels and districts ===")
|
||||||
|
@ -8,7 +8,7 @@ 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.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
@ -223,6 +223,17 @@ class Geometry(BaseResource):
|
|||||||
)
|
)
|
||||||
parcel_obj.updated_on = _now
|
parcel_obj.updated_on = _now
|
||||||
parcels_to_update.append(parcel_obj)
|
parcels_to_update.append(parcel_obj)
|
||||||
|
except MultipleObjectsReturned:
|
||||||
|
parcel_obj = Parcel.make_unique(
|
||||||
|
district=district,
|
||||||
|
municipal=municipal,
|
||||||
|
parcel_group=parcel_group,
|
||||||
|
flr=flr_val,
|
||||||
|
flrstck_nnr=flrstck_nnr,
|
||||||
|
flrstck_zhlr=flrstck_zhlr,
|
||||||
|
)
|
||||||
|
parcel_obj.updated_on = _now
|
||||||
|
parcels_to_update.append(parcel_obj)
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
# If not existing, create object but do not commit, yet
|
# If not existing, create object but do not commit, yet
|
||||||
parcel_obj = Parcel(
|
parcel_obj = Parcel(
|
||||||
|
@ -5,7 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
|
|||||||
Created on: 16.12.21
|
Created on: 16.12.21
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from django.db import models
|
from django.db import models, transaction
|
||||||
|
|
||||||
from konova.models import UuidModel
|
from konova.models import UuidModel
|
||||||
|
|
||||||
@ -158,6 +158,46 @@ class Parcel(UuidModel):
|
|||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.parcel_group} | {self.flr} | {self.flrstck_zhlr} | {self.flrstck_nnr}"
|
return f"{self.parcel_group} | {self.flr} | {self.flrstck_zhlr} | {self.flrstck_nnr}"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
@transaction.atomic
|
||||||
|
def make_unique(cls, **kwargs):
|
||||||
|
""" Checks for duplicates of a Parcel, choose a (now) unique one,
|
||||||
|
repairs relations for ParcelIntersection and removes duplicates.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
**kwargs ():
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
unique_true (Parcel): The new unique 'true one'
|
||||||
|
"""
|
||||||
|
parcel_objs = Parcel.objects.filter(**kwargs)
|
||||||
|
|
||||||
|
if not parcel_objs.exists():
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Get one of the found parcels and use it as new 'true one'
|
||||||
|
unique_parcel = parcel_objs.first()
|
||||||
|
# separate it from the rest
|
||||||
|
parcel_objs = parcel_objs.exclude(id=unique_parcel.id)
|
||||||
|
|
||||||
|
if not parcel_objs.exists():
|
||||||
|
# There are no duplicates - all good, just return
|
||||||
|
return unique_parcel
|
||||||
|
|
||||||
|
# Fetch existing intersections, which still point on the duplicated parcels
|
||||||
|
intersection_objs = ParcelIntersection.objects.filter(
|
||||||
|
parcel__in=parcel_objs
|
||||||
|
)
|
||||||
|
# Change each intersection, so they point on the 'true one' parcel from now on
|
||||||
|
for intersection in intersection_objs:
|
||||||
|
intersection.parcel = unique_parcel
|
||||||
|
intersection.save()
|
||||||
|
|
||||||
|
# Remove the duplicated parcels
|
||||||
|
parcel_objs.delete()
|
||||||
|
|
||||||
|
return unique_parcel
|
||||||
|
|
||||||
|
|
||||||
class ParcelIntersection(UuidModel):
|
class ParcelIntersection(UuidModel):
|
||||||
"""
|
"""
|
||||||
|
Loading…
Reference in New Issue
Block a user