#36 Quality checks

* adds AbstractQualityChecker as base for all quality checker instances
* adds InterventionQualityChecker, inheriting from AbstractQualityChecker
* adds functionality to InterventionQualityChecker
* adds/updates translations
This commit is contained in:
2021-10-25 13:06:54 +02:00
parent e2409fdbde
commit a5b1f68f62
6 changed files with 272 additions and 382 deletions

View File

@@ -208,13 +208,13 @@ class RunCheckModalForm(BaseModalForm):
"""
super_result = super().is_valid()
# Perform check
msgs = self.instance.quality_check()
for msg in msgs:
checker = self.instance.quality_check()
for msg in checker.messages:
self.add_error(
"checked_intervention",
msg
)
return super_result and (len(msgs) == 0)
return super_result and checker.valid
def save(self):
""" Saving logic

View File

@@ -16,6 +16,7 @@ from codelist.models import KonovaCode
from codelist.settings import CODELIST_REGISTRATION_OFFICE_ID, CODELIST_CONSERVATION_OFFICE_ID, CODELIST_LAW_ID, \
CODELIST_PROCESS_TYPE_ID
from intervention.managers import InterventionManager
from intervention.utils.quality import InterventionQualityChecker
from konova.models import BaseObject, Geometry, UuidModel, BaseResource, AbstractDocument, \
generate_document_file_upload_path
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE, LANIS_ZOOM_LUT
@@ -56,7 +57,6 @@ class ResponsibilityData(UuidModel):
conservation_file_number = models.CharField(max_length=1000, blank=True, null=True)
handler = models.CharField(max_length=500, null=True, blank=True, help_text="Refers to 'Eingriffsverursacher' or 'Maßnahmenträger'")
def __str__(self):
return "ZB: {} | ETS: {} | Handler: {}".format(
self.registration_office,
@@ -296,62 +296,15 @@ class Intervention(BaseObject):
pass
super().delete(using, keep_parents)
def quality_check(self) -> list:
def quality_check(self) -> InterventionQualityChecker:
""" Quality check
Returns:
ret_msgs (list): Holds error messages
"""
ret_msgs = []
self._check_quality_responsible_data(ret_msgs)
self._check_quality_legal_data(ret_msgs)
# ToDo: Extend for more!
return ret_msgs
def _check_quality_responsible_data(self, ret_msgs: list):
""" Checks data quality of related ResponsibilityData
Args:
ret_msgs (dict): Holds error messages
Returns:
"""
try:
# Check for file numbers
if not self.responsible.registration_file_number or len(self.responsible.registration_file_number) == 0:
ret_msgs.append(_("Registration office file number missing"))
if not self.responsible.conservation_file_number or len(self.responsible.conservation_file_number) == 0:
ret_msgs.append(_("Conservation office file number missing"))
except AttributeError:
# responsible data not found
ret_msgs.append(_("Responsible data missing"))
def _check_quality_legal_data(self, ret_msgs: list):
""" Checks data quality of related LegalData
Args:
ret_msgs (dict): Holds error messages
Returns:
"""
try:
# Check for a revocation
if self.legal.revocation:
ret_msgs.append(_("Revocation exists"))
if self.legal.registration_date is None:
ret_msgs.append(_("Registration date missing"))
if self.legal.binding_date is None:
ret_msgs.append(_("Binding on missing"))
except AttributeError:
ret_msgs.append(_("Legal data missing"))
checker = InterventionQualityChecker(obj=self)
checker.run_check()
return checker
def get_LANIS_link(self) -> str:
""" Generates a link for LANIS depending on the geometry

View File

@@ -0,0 +1,112 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 25.10.21
"""
from django.utils.translation import gettext_lazy as _
from konova.utils.quality import AbstractQualityChecker
class InterventionQualityChecker(AbstractQualityChecker):
def run_check(self):
""" Perform all defined data checks
Returns:
"""
self._check_responsible_data()
self._check_legal_data()
self._check_compensations()
self._check_geometry()
self.valid = len(self.messages) == 0
def _check_responsible_data(self):
""" Checks data quality of related ResponsibilityData
Args:
self.messages (dict): Holds error messages
Returns:
"""
try:
resp = self.obj.responsible
# Check for file numbers
if not resp.registration_file_number or len(resp.registration_file_number) == 0:
self._add_missing_attr_name(_("Registration office file number"))
if not resp.conservation_file_number or len(resp.conservation_file_number) == 0:
self._add_missing_attr_name(_("Conservation office file number"))
# Check for selected offices
if resp.registration_office is None:
self._add_missing_attr_name(_("Registration office"))
if resp.conservation_office is None:
self._add_missing_attr_name(_("Conservation office"))
if resp.handler is None:
self._add_missing_attr_name(_("Intervention handler"))
except AttributeError:
# responsible data not found
self._add_missing_attr_name(_("Responsible data"))
def _check_legal_data(self):
""" Checks data quality of related LegalData
Args:
self.messages (dict): Holds error messages
Returns:
"""
try:
legal = self.obj.legal
# Check for a revocation
if legal.revocation:
self.messages.append(_("Revocation exists"))
if legal.registration_date is None:
self._add_missing_attr_name(_("Registration date"))
if legal.binding_date is None:
self._add_missing_attr_name(_("Binding date"))
if legal.laws.count() == 0:
self._add_missing_attr_name(_("Laws"))
if legal.process_type is None:
self._add_missing_attr_name(_("Process type"))
except AttributeError:
self._add_missing_attr_name(_("Legal data"))
def _check_compensations(self):
""" Checks for compensation, deduction or payment
Returns:
"""
c_comps = self.obj.compensations.count()
c_pays = self.obj.payments.count()
c_deducs = self.obj.deductions.count()
c_all = c_comps + c_pays + c_deducs
if c_all == 0:
self.messages.append(
_("No compensation of any type found (Compensation, Payment, Deduction)")
)
def _check_geometry(self):
""" Checks on the geometry
Returns:
"""
try:
geometry_obj = self.obj.geometry
if geometry_obj.geom.empty:
self._add_missing_attr_name(_("Geometry"))
except AttributeError:
self._add_missing_attr_name(_("Geometry"))