#36 Quality checks

* adds quality check logic for Compensations with CompensationQUalityChecker
* adds compensation quality checking to checking routine of RunCheckModalForm.is_valid()
* adds/updates translations
This commit is contained in:
mpeltriaux 2021-10-25 13:44:54 +02:00
parent efd5b6bb98
commit ba04788064
6 changed files with 159 additions and 43 deletions

View File

@ -19,6 +19,7 @@ from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES
CODELIST_COMPENSATION_FUNDING_ID CODELIST_COMPENSATION_FUNDING_ID
from compensation.managers import CompensationStateManager, EcoAccountDeductionManager, CompensationActionManager, \ from compensation.managers import CompensationStateManager, EcoAccountDeductionManager, CompensationActionManager, \
EcoAccountManager, CompensationManager EcoAccountManager, CompensationManager
from compensation.utils.quality import CompensationQualityChecker
from intervention.models import Intervention, ResponsibilityData, LegalData from intervention.models import Intervention, ResponsibilityData, LegalData
from konova.models import BaseObject, BaseResource, Geometry, UuidModel, AbstractDocument, \ from konova.models import BaseObject, BaseResource, Geometry, UuidModel, AbstractDocument, \
generate_document_file_upload_path generate_document_file_upload_path
@ -163,13 +164,42 @@ class AbstractCompensation(BaseObject):
class Meta: class Meta:
abstract = True abstract = True
def get_surface(self) -> float: def get_surface_after_states(self) -> float:
""" Calculates the compensation's/account's surface """ Calculates the compensation's/account's surface
Returns: Returns:
sum_surface (float) sum_surface (float)
""" """
return self.after_states.all().aggregate(Sum("surface"))["surface__sum"] return self._calc_surface(self.after_states.all())
def get_surface_before_states(self) -> float:
""" Calculates the compensation's/account's surface
Returns:
sum_surface (float)
"""
return self._calc_surface(self.before_states.all())
def _calc_surface(self, qs: QuerySet):
""" Calculates the surface sum of a given queryset
Args:
qs (QuerySet): The queryset containing CompensationState entries
Returns:
"""
return qs.aggregate(Sum("surface"))["surface__sum"] or 0
def quality_check(self) -> CompensationQualityChecker:
""" Performs data quality check
Returns:
checker (CompensationQualityChecker): Holds validity data and error messages
"""
checker = CompensationQualityChecker(self)
checker.run_check()
return checker
class Compensation(AbstractCompensation): class Compensation(AbstractCompensation):

View File

@ -0,0 +1,48 @@
"""
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 _, pgettext_lazy as _con
from konova.utils.quality import AbstractQualityChecker
class CompensationQualityChecker(AbstractQualityChecker):
def run_check(self):
""" Perform all defined data checks
Returns:
"""
self._check_states()
self._check_actions()
self._check_geometry()
self.valid = len(self.messages) == 0
def _check_states(self):
""" Checks data quality for related CompensationState objects
Returns:
"""
after_states = self.obj.get_surface_after_states()
before_states = self.obj.get_surface_before_states()
if after_states != before_states:
self.messages.append(
_("States unequal")
)
if before_states == 0:
self._add_missing_attr_name(_("States before"))
if after_states == 0:
self._add_missing_attr_name(_("States after"))
def _check_actions(self):
""" Checks data quality for related CompensationState objects
Returns:
"""
if not self.obj.actions.all():
self._add_missing_attr_name(_con("Compensation", "Actions"))

20
ema/utils/quality.py Normal file
View File

@ -0,0 +1,20 @@
"""
Author: Michel Peltriaux
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
Contact: michel.peltriaux@sgdnord.rlp.de
Created on: 25.10.21
"""
from konova.utils.quality import AbstractQualityChecker
class EmaQualityChecker(AbstractQualityChecker):
def run_check(self):
""" Perform all defined data checks
Returns:
"""
self._check_geometry()
self.valid = len(self.messages) == 0

View File

@ -214,6 +214,14 @@ class RunCheckModalForm(BaseModalForm):
"checked_intervention", "checked_intervention",
msg msg
) )
comps = self.instance.compensations.all()
for comp in comps:
checker = comp.quality_check()
for msg in checker.messages:
self.add_error(
"checked_comps",
f"{comp.identifier}: {msg}"
)
return super_result and checker.valid return super_result and checker.valid
def save(self): def save(self):
@ -336,7 +344,7 @@ class NewDeductionModalForm(BaseModalForm):
return False return False
# Calculate valid surface # Calculate valid surface
sum_surface = acc.get_surface() sum_surface = acc.get_surface_after_states()
sum_surface_deductions = acc.get_deductions_surface() sum_surface_deductions = acc.get_deductions_surface()
rest_surface = sum_surface - sum_surface_deductions rest_surface = sum_surface - sum_surface_deductions
form_surface = float(self.cleaned_data["surface"]) form_surface = float(self.cleaned_data["surface"])

Binary file not shown.

View File

@ -19,7 +19,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-25 12:54+0200\n" "POT-Creation-Date: 2021-10-25 13:37+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -44,7 +44,7 @@ msgstr "Bis"
#: ema/templates/ema/report/report.html:16 intervention/forms/forms.py:101 #: ema/templates/ema/report/report.html:16 intervention/forms/forms.py:101
#: intervention/templates/intervention/detail/view.html:56 #: intervention/templates/intervention/detail/view.html:56
#: intervention/templates/intervention/report/report.html:37 #: intervention/templates/intervention/report/report.html:37
#: intervention/utils/quality.py:49 #: intervention/utils/quality.py:51
msgid "Conservation office" msgid "Conservation office"
msgstr "Eintragungsstelle" msgstr "Eintragungsstelle"
@ -209,7 +209,7 @@ msgstr "Abbuchungen"
#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:36 #: compensation/templates/compensation/detail/eco_account/includes/states-before.html:36
#: ema/templates/ema/detail/includes/states-after.html:36 #: ema/templates/ema/detail/includes/states-after.html:36
#: ema/templates/ema/detail/includes/states-before.html:36 #: ema/templates/ema/detail/includes/states-before.html:36
#: intervention/forms/modalForms.py:274 #: intervention/forms/modalForms.py:282
msgid "Surface" msgid "Surface"
msgstr "Fläche" msgstr "Fläche"
@ -272,7 +272,7 @@ msgid "Type"
msgstr "Typ" msgstr "Typ"
#: analysis/templates/analysis/reports/includes/old_data/amount.html:24 #: analysis/templates/analysis/reports/includes/old_data/amount.html:24
#: intervention/forms/modalForms.py:285 intervention/forms/modalForms.py:292 #: intervention/forms/modalForms.py:293 intervention/forms/modalForms.py:300
#: intervention/tables.py:88 #: intervention/tables.py:88
#: intervention/templates/intervention/detail/view.html:19 #: intervention/templates/intervention/detail/view.html:19
#: konova/templates/konova/home.html:11 templates/navbars/navbar.html:22 #: konova/templates/konova/home.html:11 templates/navbars/navbar.html:22
@ -282,7 +282,7 @@ msgstr "Eingriff"
#: analysis/templates/analysis/reports/includes/old_data/amount.html:34 #: analysis/templates/analysis/reports/includes/old_data/amount.html:34
#: compensation/tables.py:224 #: compensation/tables.py:224
#: compensation/templates/compensation/detail/eco_account/view.html:19 #: compensation/templates/compensation/detail/eco_account/view.html:19
#: intervention/forms/modalForms.py:258 intervention/forms/modalForms.py:265 #: intervention/forms/modalForms.py:266 intervention/forms/modalForms.py:273
#: konova/templates/konova/home.html:88 templates/navbars/navbar.html:34 #: konova/templates/konova/home.html:88 templates/navbars/navbar.html:34
msgid "Eco-account" msgid "Eco-account"
msgstr "Ökokonto" msgstr "Ökokonto"
@ -376,7 +376,7 @@ msgstr "Zusätzlicher Kommentar"
#: ema/templates/ema/report/report.html:20 intervention/forms/forms.py:129 #: ema/templates/ema/report/report.html:20 intervention/forms/forms.py:129
#: intervention/templates/intervention/detail/view.html:60 #: intervention/templates/intervention/detail/view.html:60
#: intervention/templates/intervention/report/report.html:41 #: intervention/templates/intervention/report/report.html:41
#: intervention/utils/quality.py:42 #: intervention/utils/quality.py:44
msgid "Conservation office file number" msgid "Conservation office file number"
msgstr "Aktenzeichen Eintragungsstelle" msgstr "Aktenzeichen Eintragungsstelle"
@ -482,7 +482,7 @@ msgstr "Biotoptyp"
msgid "Select the biotope type" msgid "Select the biotope type"
msgstr "Biotoptyp wählen" msgstr "Biotoptyp wählen"
#: compensation/forms/modalForms.py:155 intervention/forms/modalForms.py:276 #: compensation/forms/modalForms.py:155 intervention/forms/modalForms.py:284
msgid "in m²" msgid "in m²"
msgstr "" msgstr ""
@ -592,38 +592,38 @@ msgstr "Geben Sie die Daten der neuen Maßnahme ein"
msgid "Added action" msgid "Added action"
msgstr "Maßnahme hinzugefügt" msgstr "Maßnahme hinzugefügt"
#: compensation/models.py:82 #: compensation/models.py:83
msgid "cm" msgid "cm"
msgstr "" msgstr ""
#: compensation/models.py:83 #: compensation/models.py:84
msgid "m" msgid "m"
msgstr "" msgstr ""
#: compensation/models.py:84 #: compensation/models.py:85
msgid "km" msgid "km"
msgstr "" msgstr ""
#: compensation/models.py:85 #: compensation/models.py:86
msgid "m²" msgid "m²"
msgstr "" msgstr ""
#: compensation/models.py:86 #: compensation/models.py:87
msgid "ha" msgid "ha"
msgstr "" msgstr ""
#: compensation/models.py:87 #: compensation/models.py:88
msgid "Pieces" msgid "Pieces"
msgstr "Stück" msgstr "Stück"
#: compensation/models.py:329 #: compensation/models.py:359
msgid "" msgid ""
"Deductable surface can not be larger than existing surfaces in after states" "Deductable surface can not be larger than existing surfaces in after states"
msgstr "" msgstr ""
"Die abbuchbare Fläche darf die Gesamtfläche der Zielzustände nicht " "Die abbuchbare Fläche darf die Gesamtfläche der Zielzustände nicht "
"überschreiten" "überschreiten"
#: compensation/models.py:336 #: compensation/models.py:366
msgid "" msgid ""
"Deductable surface can not be smaller than the sum of already existing " "Deductable surface can not be smaller than the sum of already existing "
"deductions. Please contact the responsible users for the deductions!" "deductions. Please contact the responsible users for the deductions!"
@ -978,7 +978,7 @@ msgstr "Keine Flächenmenge für Abbuchungen eingegeben. Bitte bearbeiten."
#: intervention/templates/intervention/detail/view.html:63 #: intervention/templates/intervention/detail/view.html:63
#: intervention/templates/intervention/detail/view.html:95 #: intervention/templates/intervention/detail/view.html:95
#: intervention/templates/intervention/detail/view.html:99 #: intervention/templates/intervention/detail/view.html:99
msgid "missing" msgid "Missing"
msgstr "fehlt" msgstr "fehlt"
#: compensation/templates/compensation/detail/eco_account/view.html:70 #: compensation/templates/compensation/detail/eco_account/view.html:70
@ -1013,6 +1013,10 @@ msgstr "In LANIS öffnen"
msgid "Deductions for" msgid "Deductions for"
msgstr "Abbuchungen für" msgstr "Abbuchungen für"
#: compensation/utils/quality.py:35
msgid "States unequal"
msgstr "Ungleiche Zustandsflächenmengen"
#: compensation/views/compensation_views.py:77 #: compensation/views/compensation_views.py:77
msgid "Compensation {} added" msgid "Compensation {} added"
msgstr "Kompensation {} hinzugefügt" msgstr "Kompensation {} hinzugefügt"
@ -1161,7 +1165,7 @@ msgstr "Bauvorhaben XY; Flur ABC"
#: intervention/forms/forms.py:51 #: intervention/forms/forms.py:51
#: intervention/templates/intervention/detail/view.html:35 #: intervention/templates/intervention/detail/view.html:35
#: intervention/templates/intervention/report/report.html:16 #: intervention/templates/intervention/report/report.html:16
#: intervention/utils/quality.py:82 #: intervention/utils/quality.py:84
msgid "Process type" msgid "Process type"
msgstr "Verfahrenstyp" msgstr "Verfahrenstyp"
@ -1172,14 +1176,14 @@ msgstr "Mehrfachauswahl möglich"
#: intervention/forms/forms.py:85 #: intervention/forms/forms.py:85
#: intervention/templates/intervention/detail/view.html:48 #: intervention/templates/intervention/detail/view.html:48
#: intervention/templates/intervention/report/report.html:29 #: intervention/templates/intervention/report/report.html:29
#: intervention/utils/quality.py:46 #: intervention/utils/quality.py:48
msgid "Registration office" msgid "Registration office"
msgstr "Zulassungsbehörde" msgstr "Zulassungsbehörde"
#: intervention/forms/forms.py:117 #: intervention/forms/forms.py:117
#: intervention/templates/intervention/detail/view.html:52 #: intervention/templates/intervention/detail/view.html:52
#: intervention/templates/intervention/report/report.html:33 #: intervention/templates/intervention/report/report.html:33
#: intervention/utils/quality.py:39 #: intervention/utils/quality.py:41
msgid "Registration office file number" msgid "Registration office file number"
msgstr "Aktenzeichen Zulassungsbehörde" msgstr "Aktenzeichen Zulassungsbehörde"
@ -1190,7 +1194,7 @@ msgstr ""
#: intervention/forms/forms.py:141 #: intervention/forms/forms.py:141
#: intervention/templates/intervention/detail/view.html:64 #: intervention/templates/intervention/detail/view.html:64
#: intervention/templates/intervention/report/report.html:45 #: intervention/templates/intervention/report/report.html:45
#: intervention/utils/quality.py:52 #: intervention/utils/quality.py:54
msgid "Intervention handler" msgid "Intervention handler"
msgstr "Eingriffsverursacher" msgstr "Eingriffsverursacher"
@ -1201,7 +1205,7 @@ msgstr "Wer führt den Eingriff durch"
#: intervention/forms/forms.py:154 #: intervention/forms/forms.py:154
#: intervention/templates/intervention/detail/view.html:96 #: intervention/templates/intervention/detail/view.html:96
#: intervention/templates/intervention/report/report.html:83 #: intervention/templates/intervention/report/report.html:83
#: intervention/utils/quality.py:73 #: intervention/utils/quality.py:75
msgid "Registration date" msgid "Registration date"
msgstr "Datum Zulassung bzw. Satzungsbeschluss" msgstr "Datum Zulassung bzw. Satzungsbeschluss"
@ -1279,23 +1283,23 @@ msgstr ""
"Ich, {} {}, bestätige, dass die notwendigen Kontrollschritte durchgeführt " "Ich, {} {}, bestätige, dass die notwendigen Kontrollschritte durchgeführt "
"wurden:" "wurden:"
#: intervention/forms/modalForms.py:260 #: intervention/forms/modalForms.py:268
msgid "Only recorded accounts can be selected for deductions" msgid "Only recorded accounts can be selected for deductions"
msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden." msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden."
#: intervention/forms/modalForms.py:287 #: intervention/forms/modalForms.py:295
msgid "Only shared interventions can be selected" msgid "Only shared interventions can be selected"
msgstr "Nur freigegebene Eingriffe können gewählt werden" msgstr "Nur freigegebene Eingriffe können gewählt werden"
#: intervention/forms/modalForms.py:300 #: intervention/forms/modalForms.py:308
msgid "New Deduction" msgid "New Deduction"
msgstr "Neue Abbuchung" msgstr "Neue Abbuchung"
#: intervention/forms/modalForms.py:301 #: intervention/forms/modalForms.py:309
msgid "Enter the information for a new deduction from a chosen eco-account" msgid "Enter the information for a new deduction from a chosen eco-account"
msgstr "Geben Sie die Informationen für eine neue Abbuchung ein." msgstr "Geben Sie die Informationen für eine neue Abbuchung ein."
#: intervention/forms/modalForms.py:334 #: intervention/forms/modalForms.py:342
msgid "" msgid ""
"Eco-account {} is not recorded yet. You can only deduct from recorded " "Eco-account {} is not recorded yet. You can only deduct from recorded "
"accounts." "accounts."
@ -1303,7 +1307,7 @@ msgstr ""
"Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von " "Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von "
"verzeichneten Ökokonten erfolgen." "verzeichneten Ökokonten erfolgen."
#: intervention/forms/modalForms.py:347 #: intervention/forms/modalForms.py:355
msgid "" msgid ""
"The account {} has not enough surface for a deduction of {} m². There are " "The account {} has not enough surface for a deduction of {} m². There are "
"only {} m² left" "only {} m² left"
@ -1385,34 +1389,31 @@ msgstr "Abbuchungen von Ökokonten"
msgid "Exist" msgid "Exist"
msgstr "Vorhanden" msgstr "Vorhanden"
#: intervention/utils/quality.py:55 #: intervention/utils/quality.py:57
msgid "Responsible data" msgid "Responsible data"
msgstr "Daten zu den verantwortlichen Stellen" msgstr "Daten zu den verantwortlichen Stellen"
#: intervention/utils/quality.py:70 #: intervention/utils/quality.py:72
msgid "Revocation exists" msgid "Revocation exists"
msgstr "Widerspruch liegt vor" msgstr "Widerspruch liegt vor"
#: intervention/utils/quality.py:76 #: intervention/utils/quality.py:78
msgid "Binding date" msgid "Binding date"
msgstr "Datum Bestandskraft" msgstr "Datum Bestandskraft"
#: intervention/utils/quality.py:79 #: intervention/utils/quality.py:81
msgid "Laws" msgid "Laws"
msgstr "Gesetze" msgstr "Gesetze"
#: intervention/utils/quality.py:84 #: intervention/utils/quality.py:86
msgid "Legal data" msgid "Legal data"
msgstr "Rechtliche Daten" msgstr "Rechtliche Daten"
#: intervention/utils/quality.py:98 #: intervention/utils/quality.py:100
msgid "No compensation of any type found (Compensation, Payment, Deduction)" msgid "No compensation of any type found (Compensation, Payment, Deduction)"
msgstr "Kein Ausgleich jeglicher Art gefunden (Kompensation, Ersatzzahlung, Abbuchung)" msgstr ""
"Kein Ausgleich jeglicher Art gefunden (Kompensation, Ersatzzahlung, "
#: intervention/utils/quality.py:110 intervention/utils/quality.py:112 "Abbuchung)"
#: konova/forms.py:246 templates/form/collapsable/form.html:45
msgid "Geometry"
msgstr "Geometrie"
#: intervention/views.py:80 #: intervention/views.py:80
msgid "Intervention {} added" msgid "Intervention {} added"
@ -1499,6 +1500,11 @@ msgstr "Löschen"
msgid "You are about to remove {} {}" msgid "You are about to remove {} {}"
msgstr "Sie sind dabei {} {} zu löschen" msgstr "Sie sind dabei {} {} zu löschen"
#: konova/forms.py:246 konova/utils/quality.py:44 konova/utils/quality.py:46
#: templates/form/collapsable/form.html:45
msgid "Geometry"
msgstr "Geometrie"
#: konova/forms.py:322 #: konova/forms.py:322
msgid "Are you sure?" msgid "Are you sure?"
msgstr "Sind Sie sicher?" msgstr "Sind Sie sicher?"
@ -1674,6 +1680,10 @@ msgstr "<a href=\"{}\">Schauen Sie rein</a>"
msgid "{} has been checked successfully by user {}! {}" msgid "{} has been checked successfully by user {}! {}"
msgstr "{} wurde erfolgreich vom Nutzer {} geprüft! {}" msgstr "{} wurde erfolgreich vom Nutzer {} geprüft! {}"
#: konova/utils/quality.py:32
msgid "missing"
msgstr "fehlt"
#: konova/views.py:115 #: konova/views.py:115
msgid "Deadline removed" msgid "Deadline removed"
msgstr "Frist gelöscht" msgstr "Frist gelöscht"