""" Author: Michel Peltriaux Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany Contact: michel.peltriaux@sgdnord.rlp.de Created on: 04.01.22 """ import datetime from django.contrib.gis.db.models.functions import Area from konova.management.commands.setup import BaseKonovaCommand from konova.models import Geometry, ParcelIntersection class Command(BaseKonovaCommand): help = "Recalculates parcels for entries with geometry but missing parcel information" def add_arguments(self, parser): parser.add_argument( "--force-all", action="store_true", default=False, help="If Attribute set, all entries parcels will be recalculated" ) def handle(self, *args, **options): try: self.recalculate_parcels(options) except KeyboardInterrupt: self._break_line() exit(-1) def recalculate_parcels(self, options: dict): force_all = options.get("force_all", False) 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 ===") # Order geometries by size to process smaller once at first geometries = geometry_objects.exclude( geom=None ).annotate(area=Area("geom")).order_by( 'area' ) self._write_warning(f"Process parcels for {geometries.count()} geometry entries now ...") i = 0 num_geoms = geometries.count() geoms_with_errors = {} for geometry in geometries: self._write_warning(f"--- {datetime.datetime.now()} Process {geometry.id} now ...") try: geometry.update_parcels() self._write_warning(f"--- Processed {geometry.get_underlying_parcels().count()} underlying parcels") except Exception as e: geoms_with_errors[geometry.id] = str(e) i += 1 self._write_warning(f"--- {i}/{num_geoms} processed") self._write_success("Updating parcels done!") for key, val in geoms_with_errors.items(): self._write_error(f" Error on {key}: {val}") self._write_success(f"{num_geoms - len(geoms_with_errors)} geometries successfuly recalculated!") self._break_line()