Merge pull request '# Parcel duplicate repair' (#444) from 439_Wartungskommando_Nachverschneidung into master

Reviewed-on: #444
This commit is contained in:
mpeltriaux 2024-10-26 09:48:32 +02:00
commit 90e5cf5b36
3 changed files with 69 additions and 16 deletions

View File

@ -8,11 +8,9 @@ Created on: 04.01.22
import datetime
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.models import Geometry
from konova.models import Geometry, ParcelIntersection
class Command(BaseKonovaCommand):
@ -36,17 +34,21 @@ class Command(BaseKonovaCommand):
def recalculate_parcels(self, options: dict):
force_all = options.get("force_all", False)
if force_all:
geometry_objects = Geometry.objects.all()
else:
_today = now().date()
_date_threshold = _today - datetime.timedelta(days=1)
geometry_objects = Geometry.objects.filter(
Q(
Q(parcel_update_start__date__lte=_date_threshold) |
Q(parcel_update_start__isnull=True)
),
parcel_update_end__isnull=True
geometry_objects = Geometry.objects.all()
if not force_all:
# Fetch all intersections
intersection_objs = ParcelIntersection.objects.filter(
geometry__in=geometry_objects
)
# Just take the geometry ids, which seem to have intersections
geom_with_intersection_ids = intersection_objs.values_list(
"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 ===")

View File

@ -8,7 +8,7 @@ Created on: 15.11.21
import json
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.utils import timezone
@ -223,6 +223,17 @@ class Geometry(BaseResource):
)
parcel_obj.updated_on = _now
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:
# If not existing, create object but do not commit, yet
parcel_obj = Parcel(

View File

@ -5,7 +5,7 @@ Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 16.12.21
"""
from django.db import models
from django.db import models, transaction
from konova.models import UuidModel
@ -158,6 +158,46 @@ class Parcel(UuidModel):
def __str__(self):
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):
"""