diff --git a/analysis/__init__.py b/analysis/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/analysis/admin.py b/analysis/admin.py
new file mode 100644
index 00000000..8c38f3f3
--- /dev/null
+++ b/analysis/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/analysis/apps.py b/analysis/apps.py
new file mode 100644
index 00000000..126ab0e5
--- /dev/null
+++ b/analysis/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class AnalysisConfig(AppConfig):
+ name = 'analysis'
diff --git a/analysis/forms.py b/analysis/forms.py
new file mode 100644
index 00000000..11d2f98b
--- /dev/null
+++ b/analysis/forms.py
@@ -0,0 +1,82 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: michel.peltriaux@sgdnord.rlp.de
+Created on: 20.10.21
+
+"""
+from dal import autocomplete
+from django import forms
+from django.urls import reverse
+from django.utils.translation import gettext_lazy as _
+
+from codelist.models import KonovaCode
+from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID
+from konova.forms import BaseForm
+
+
+class TimespanReportForm(BaseForm):
+ """ TimespanReporForm is used for allowing simple creation of an e.g. annual report for conservation offices
+
+ """
+ date_from = forms.DateField(
+ label_suffix="",
+ label=_("From"),
+ widget=forms.DateInput(
+ attrs={
+ "type": "date",
+ "data-provide": "datepicker",
+ "class": "form-control",
+ },
+ format="%d.%m.%Y"
+ )
+ )
+ date_to = forms.DateField(
+ label_suffix="",
+ label=_("To"),
+ widget=forms.DateInput(
+ attrs={
+ "type": "date",
+ "data-provide": "datepicker",
+ "class": "form-control",
+ },
+ format="%d.%m.%Y"
+ )
+ )
+ conservation_office = forms.ModelChoiceField(
+ label=_("Conservation office"),
+ label_suffix="",
+ help_text=_("Select the responsible office"),
+ queryset=KonovaCode.objects.filter(
+ is_archived=False,
+ is_leaf=True,
+ code_lists__in=[CODELIST_CONSERVATION_OFFICE_ID],
+ ),
+ widget=autocomplete.ModelSelect2(
+ url="codes-conservation-office-autocomplete",
+ attrs={
+ "data-placeholder": _("Click for selection")
+ }
+ ),
+ )
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.form_title = _("Generate report")
+ self.form_caption = _("Select a timespan and the desired conservation office")
+ self.action_url = reverse("analysis:reports")
+ self.show_cancel_btn = False
+ self.action_btn_label = _("Continue")
+
+ def save(self) -> str:
+ """ Generates a redirect url for the detail report
+
+ Returns:
+ detail_report_url (str): The constructed detail report url
+
+ """
+ date_from = self.cleaned_data.get("date_from", None)
+ date_to = self.cleaned_data.get("date_to", None)
+ office = self.cleaned_data.get("conservation_office", None)
+ detail_report_url = reverse("analysis:report-detail", args=(office.id,)) + f"?df={date_from}&dt={date_to}"
+ return detail_report_url
diff --git a/analysis/models.py b/analysis/models.py
new file mode 100644
index 00000000..71a83623
--- /dev/null
+++ b/analysis/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/analysis/settings.py b/analysis/settings.py
new file mode 100644
index 00000000..74978d13
--- /dev/null
+++ b/analysis/settings.py
@@ -0,0 +1,12 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: michel.peltriaux@sgdnord.rlp.de
+Created on: 19.10.21
+
+"""
+
+# Defines the date of the legal publishing of the LKompVzVo
+from django.utils import timezone
+
+LKOMPVZVO_PUBLISH_DATE = timezone.make_aware(timezone.datetime.fromisoformat("2018-06-16"))
diff --git a/analysis/templates/analysis/reports/detail.html b/analysis/templates/analysis/reports/detail.html
new file mode 100644
index 00000000..ac4f08e2
--- /dev/null
+++ b/analysis/templates/analysis/reports/detail.html
@@ -0,0 +1,36 @@
+{% extends 'base.html' %}
+{% load i18n fontawesome_5 %}
+
+{% block body %}
+
+
+
{% trans 'Evaluation report' %} {{office.long_name}}
+ {% trans 'From' %} {{report.date_from.date}} {% trans 'to' %} {{report.date_to.date}}
+
+
+
+
+
+
+ {% fa5_icon 'download' %}
+
+
+
+
+
+
+
+
+
+ {% include 'analysis/reports/includes/intervention/card_intervention.html' %}
+ {% include 'analysis/reports/includes/compensation/card_compensation.html' %}
+ {% include 'analysis/reports/includes/eco_account/card_eco_account.html' %}
+ {% include 'analysis/reports/includes/old_data/card_old_interventions.html' %}
+
+{% endblock %}
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/compensation/amount.html b/analysis/templates/analysis/reports/includes/compensation/amount.html
new file mode 100644
index 00000000..86383b69
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/compensation/amount.html
@@ -0,0 +1,55 @@
+{% load i18n fontawesome_5 ksp_filters %}
+
+{% trans 'Amount' %}
+
+ {% blocktrans %}
+ Checked = Has been checked by the registration office according to LKompVzVo
+ {% endblocktrans %}
+
+ {% blocktrans %}
+ Recorded = Has been checked and published by the conservation office
+ {% endblocktrans %}
+
+
+
+
+
+ {% trans 'Area of responsibility' %}
+ {% fa5_icon 'star' %} {% trans 'Checked' %}
+ {% fa5_icon 'bookmark' %} {% trans 'Recorded' %}
+ {% trans 'Number single areas' %}
+ {% trans 'Total' %}
+
+
+
+
+ {% trans 'Conservation office by law' %}
+ {{report.compensation_report.queryset_registration_office_unb_checked_count|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_registration_office_unb_recorded_count|default_if_zero:"-"}}
+ {{report.compensation_report.num_single_surfaces_total_unb|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_registration_office_unb_count|default_if_zero:"-"}}
+
+
+ {% trans 'Land-use planning' %}
+ {{report.compensation_report.queryset_registration_office_tbp_checked_count|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_registration_office_tbp_recorded_count|default_if_zero:"-"}}
+ {{report.compensation_report.num_single_surfaces_total_tbp|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_registration_office_tbp_count|default_if_zero:"-"}}
+
+
+ {% trans 'Other registration office' %}
+ {{report.compensation_report.queryset_registration_office_other_checked_count|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_registration_office_other_recorded_count|default_if_zero:"-"}}
+ {{report.compensation_report.num_single_surfaces_total_other|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_registration_office_other_count|default_if_zero:"-"}}
+
+
+ {% trans 'Total' %}
+ {{report.compensation_report.queryset_checked_count|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_recorded_count|default_if_zero:"-"}}
+ {{report.compensation_report.num_single_surfaces_total|default_if_zero:"-"}}
+ {{report.compensation_report.queryset_count|default_if_zero:"-"}}
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/compensation/card_compensation.html b/analysis/templates/analysis/reports/includes/compensation/card_compensation.html
new file mode 100644
index 00000000..8fe2eec4
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/compensation/card_compensation.html
@@ -0,0 +1,23 @@
+{% load i18n fontawesome_5 %}
+
+
+
+
+
+
+
+ {% include 'analysis/reports/includes/compensation/amount.html' %}
+
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/eco_account/amount.html b/analysis/templates/analysis/reports/includes/eco_account/amount.html
new file mode 100644
index 00000000..668250e6
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/eco_account/amount.html
@@ -0,0 +1,24 @@
+{% load i18n fontawesome_5 ksp_filters %}
+
+{% trans 'Amount' %}
+
+ {% blocktrans %}
+ Recorded = Has been checked and published by the conservation office
+ {% endblocktrans %}
+
+
+
+
+
+ {% fa5_icon 'bookmark' %} {% trans 'Recorded' %}
+ {% trans 'Total' %}
+
+
+
+
+ {{report.eco_account_report.queryset_recorded_count|default_if_zero:"-"}}
+ {{report.eco_account_report.queryset_count|default_if_zero:"-"}}
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/eco_account/card_eco_account.html b/analysis/templates/analysis/reports/includes/eco_account/card_eco_account.html
new file mode 100644
index 00000000..850ac60a
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/eco_account/card_eco_account.html
@@ -0,0 +1,25 @@
+{% load i18n fontawesome_5 %}
+
+
+
+
+
+
+
+ {% include 'analysis/reports/includes/eco_account/amount.html' %}
+
+ {% include 'analysis/reports/includes/eco_account/deductions.html' %}
+
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/eco_account/deductions.html b/analysis/templates/analysis/reports/includes/eco_account/deductions.html
new file mode 100644
index 00000000..c9a0e8d5
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/eco_account/deductions.html
@@ -0,0 +1,23 @@
+{% load i18n fontawesome_5 ksp_filters %}
+
+{% trans 'Deductions' %}
+
+
+
+
+ {% fa5_icon 'bookmark' %} {% trans 'Recorded' %}
+ {% fa5_icon 'bookmark' %} {% trans 'Recorded' %} {% trans 'Surface' %}
+ {% trans 'Total' %}
+ {% trans 'Total' %} {% trans 'Surface' %}
+
+
+
+
+ {{report.eco_account_report.queryset_deductions_recorded_count|default_if_zero:"-"}}
+ {{report.eco_account_report.recorded_deductions_sq_m|default_if_zero:"-"}}m²
+ {{report.eco_account_report.queryset_deductions_count|default_if_zero:"-"}}
+ {{report.eco_account_report.deductions_sq_m|default_if_zero:"-"}}m²
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/intervention/amount.html b/analysis/templates/analysis/reports/includes/intervention/amount.html
new file mode 100644
index 00000000..0c934483
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/intervention/amount.html
@@ -0,0 +1,30 @@
+{% load i18n fontawesome_5 ksp_filters %}
+
+{% trans 'Amount' %}
+
+ {% blocktrans %}
+ Checked = Has been checked by the registration office according to LKompVzVo
+ {% endblocktrans %}
+
+ {% blocktrans %}
+ Recorded = Has been checked and published by the conservation office
+ {% endblocktrans %}
+
+
+
+
+
+ {% fa5_icon 'star' %} {% trans 'Checked' %}
+ {% fa5_icon 'bookmark' %} {% trans 'Recorded' %}
+ {% trans 'Total' %}
+
+
+
+
+ {{report.intervention_report.queryset_checked_count|default_if_zero:"-"}}
+ {{report.intervention_report.queryset_recorded_count|default_if_zero:"-"}}
+ {{report.intervention_report.queryset_count|default_if_zero:"-"}}
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/intervention/card_intervention.html b/analysis/templates/analysis/reports/includes/intervention/card_intervention.html
new file mode 100644
index 00000000..6a9993a3
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/intervention/card_intervention.html
@@ -0,0 +1,26 @@
+{% load i18n fontawesome_5 %}
+
+
+
+
+
+
+ {% include 'analysis/reports/includes/intervention/amount.html' %}
+
+ {% include 'analysis/reports/includes/intervention/compensated_by.html' %}
+
+ {% include 'analysis/reports/includes/intervention/laws.html' %}
+
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/intervention/compensated_by.html b/analysis/templates/analysis/reports/includes/intervention/compensated_by.html
new file mode 100644
index 00000000..c6be40cc
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/intervention/compensated_by.html
@@ -0,0 +1,34 @@
+{% load i18n fontawesome_5 ksp_filters %}
+{% trans 'Compensated by' %}
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/intervention/laws.html b/analysis/templates/analysis/reports/includes/intervention/laws.html
new file mode 100644
index 00000000..e310197f
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/intervention/laws.html
@@ -0,0 +1,50 @@
+{% load i18n fontawesome_5 ksp_filters %}
+{% trans 'Law usage' %}
+
+ {% blocktrans %}
+ Please note: One intervention can be based on multiple laws. This table therefore does not
+ count
+ {% endblocktrans %}
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/old_data/amount.html b/analysis/templates/analysis/reports/includes/old_data/amount.html
new file mode 100644
index 00000000..cd79cb6f
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/old_data/amount.html
@@ -0,0 +1,40 @@
+{% load i18n fontawesome_5 ksp_filters %}
+
+{% trans 'Amount' %}
+
+ {% blocktrans %}
+ Checked = Has been checked by the registration office according to LKompVzVo
+ {% endblocktrans %}
+
+ {% blocktrans %}
+ Recorded = Has been checked and published by the conservation office
+ {% endblocktrans %}
+
+
+
+
+
+ {% fa5_icon 'star' %} {% trans 'Type' %}
+ {% fa5_icon 'bookmark' %} {% trans 'Recorded' %}
+ {% trans 'Total' %}
+
+
+
+
+ {% trans 'Intervention' %}
+ {{report.old_data_report.queryset_intervention_recorded_count|default_if_zero:"-"}}
+ {{report.old_data_report.queryset_intervention_count|default_if_zero:"-"}}
+
+
+ {% trans 'Compensation' %}
+ {{report.old_data_report.queryset_comps_recorded_count|default_if_zero:"-"}}
+ {{report.old_data_report.queryset_comps_count|default_if_zero:"-"}}
+
+
+ {% trans 'Eco-account' %}
+ {{report.old_data_report.queryset_acc_recorded_count|default_if_zero:"-"}}
+ {{report.old_data_report.queryset_acc_count|default_if_zero:"-"}}
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html b/analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html
new file mode 100644
index 00000000..a25a5712
--- /dev/null
+++ b/analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html
@@ -0,0 +1,24 @@
+{% load i18n fontawesome_5 %}
+
+
+
+
+
+
+
+ {% include 'analysis/reports/includes/old_data/amount.html' %}
+
+
+
+
+
\ No newline at end of file
diff --git a/analysis/templates/analysis/reports/index.html b/analysis/templates/analysis/reports/index.html
new file mode 100644
index 00000000..9c35d057
--- /dev/null
+++ b/analysis/templates/analysis/reports/index.html
@@ -0,0 +1,10 @@
+{% extends 'base.html' %}
+{% load i18n fontawesome_5 %}
+
+{% block body %}
+
+
+ {% include 'form/table/generic_table_form.html' %}
+
+
+{% endblock %}
\ No newline at end of file
diff --git a/analysis/tests.py b/analysis/tests.py
new file mode 100644
index 00000000..7ce503c2
--- /dev/null
+++ b/analysis/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/analysis/urls.py b/analysis/urls.py
new file mode 100644
index 00000000..71eb6665
--- /dev/null
+++ b/analysis/urls.py
@@ -0,0 +1,15 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: michel.peltriaux@sgdnord.rlp.de
+Created on: 15.10.21
+
+"""
+from django.urls import path
+from analysis.views import *
+
+app_name = "analysis"
+urlpatterns = [
+ path("reports/", index_reports_view, name="reports"),
+ path("reports/", detail_report_view, name="report-detail"),
+]
\ No newline at end of file
diff --git a/analysis/utils/excel/excel.py b/analysis/utils/excel/excel.py
new file mode 100644
index 00000000..611f6a0c
--- /dev/null
+++ b/analysis/utils/excel/excel.py
@@ -0,0 +1,114 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: michel.peltriaux@sgdnord.rlp.de
+Created on: 21.10.21
+
+"""
+from django.core.files.temp import NamedTemporaryFile
+from openpyxl import load_workbook
+
+
+class TempExcelFile:
+ """ A temporary excel sheet which will not be saved on the hard drive permanently.
+
+ Using a template file and a template_map dictionary, this class can be used to fill in automatically
+ predefined values into certain cells.
+
+ Can be used to create excel files from data and sending it as a response like
+ _file = TempExcelFile()
+ response = HttpResponse(
+ content=file.stream,
+ content_type="application/ms-excel",
+ )
+ response['Content-Disposition'] = 'attachment; filename=my_file.xlsx'
+ return response
+
+ """
+ stream = None
+ _template_file_path = None
+ _template_map = {}
+ _data_obj = None
+
+ def __init__(self, template_file_path: str = None, template_map: dict = None):
+ self._template_map = template_map or {}
+ self._template_file_path = template_file_path
+ self._workbook = load_workbook(template_file_path)
+ self._file = NamedTemporaryFile()
+
+ self._replace_template_placeholders()
+
+ def _replace_template_placeholders(self, start_row: int = 0):
+ """ Replaces all placeholder inside the template according to _template_map
+
+ Args:
+ start_row (int): Defines where to start
+
+ Returns:
+
+ """
+ sheets = self._workbook.worksheets
+ for sheet in sheets:
+ ws = sheet
+ # Always activate sheet protection
+ ws.protection.sheet = True
+ ws.protection.enable()
+ _rows = ws.iter_rows(start_row)
+ for row in _rows:
+ for cell in row:
+ val = cell.value
+ if val in self._template_map:
+ attr = self._template_map[val]
+ # If keyword '_iter' can be found inside the placeholder value it's an iterable and we
+ # need to process it differently
+ if isinstance(attr, dict):
+ # Read the iterable object and related attributes from the dict
+ _iter_obj = attr.get("iterable", None)
+ _attrs = attr.get("attrs", [])
+ self._add_cells_from_iterable(ws, cell, _iter_obj, _attrs)
+ # Since the sheet length did change now, we need to rerun this function starting with the new
+ # row counter
+ self._replace_template_placeholders(start_row=cell.row + len(_iter_obj))
+ else:
+ cell.value = attr
+ self._workbook.save(self._file.name)
+ self._file.seek(0)
+ self.stream = self._file.read()
+
+ def _add_cells_from_iterable(self, ws, start_cell, _iter_obj: iter, _attrs: list):
+ """
+ Adds iterable data defined by _template_map like
+ ...
+ "some_placeholder_iter": {
+ "iterable": iterable_object,
+ "attrs": [
+ "attr1",
+ "attr2",
+ "attr3",
+ ...
+ ]
+ },
+ ...
+
+ Args:
+ ws (Workbook): The active workbook
+ _iter_obj (dict): Iterable definitions from template_map
+
+ Returns:
+
+ """
+ # Save border style
+ border_style = start_cell.border.copy()
+ # Drop current row, since it is just placeholder
+ ws.delete_rows(start_cell.row)
+ # Add enoug empty rows for the data
+ ws.insert_rows(start_cell.row, len(_iter_obj))
+
+ i = 0
+ for _iter_entry in _iter_obj:
+ j = 0
+ for _iter_attr in _attrs:
+ _new_cell = ws.cell(start_cell.row + i, start_cell.column + j, getattr(_iter_entry, _iter_attr))
+ _new_cell.border = border_style
+ j += 1
+ i += 1
diff --git a/analysis/utils/excel/excel_report.xlsx b/analysis/utils/excel/excel_report.xlsx
new file mode 100644
index 00000000..72cf1295
Binary files /dev/null and b/analysis/utils/excel/excel_report.xlsx differ
diff --git a/analysis/utils/report.py b/analysis/utils/report.py
new file mode 100644
index 00000000..3bfd6370
--- /dev/null
+++ b/analysis/utils/report.py
@@ -0,0 +1,547 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: michel.peltriaux@sgdnord.rlp.de
+Created on: 18.10.21
+
+"""
+from django.contrib.gis.db.models import MultiPolygonField
+from django.contrib.gis.db.models.functions import NumGeometries
+from django.db.models import Count, Sum, Q
+from django.db.models.functions import Cast
+
+from analysis.settings import LKOMPVZVO_PUBLISH_DATE
+from codelist.models import KonovaCode
+from codelist.settings import CODELIST_LAW_ID
+from compensation.models import Compensation, Payment, EcoAccountDeduction, EcoAccount
+from intervention.models import Intervention
+from konova.models import Geometry
+from konova.sub_settings.django_settings import BASE_DIR, DEFAULT_DATE_FORMAT
+
+
+class TimespanReport:
+ """ Holds multiple report elements for a timespan report
+
+ """
+ office_id = -1
+ date_from = -1
+ date_to = -1
+
+ # Excel map is used to map a cell value ("A1") to an attribute
+ excel_map = {}
+ excel_template_path = f"{BASE_DIR}/analysis/utils/excel/excel_report.xlsx"
+
+ class InterventionReport:
+ queryset = Intervention.objects.none()
+ queryset_checked = Intervention.objects.none()
+ queryset_recorded = Intervention.objects.none()
+
+ queryset_count = -1
+ queryset_checked_count = -1
+ queryset_recorded_count = -1
+
+ # Law related
+ law_sum = -1
+ law_sum_checked = -1
+ law_sum_recorded = -1
+ evaluated_laws = None
+
+ # Compensations related
+ compensation_sum = -1
+ compensation_sum_checked = -1
+ compensation_sum_recorded = -1
+ payment_sum = -1
+ payment_sum_checked = -1
+ payment_sum_recorded = -1
+ deduction_sum = -1
+ deduction_sum_checked = -1
+ deduction_sum_recorded = -1
+
+ excel_map = {}
+
+ def __init__(self, id: str, date_from: str, date_to: str):
+ self.queryset = Intervention.objects.filter(
+ responsible__conservation_office__id=id,
+ legal__registration_date__gt=LKOMPVZVO_PUBLISH_DATE,
+ deleted=None,
+ created__timestamp__gte=date_from,
+ created__timestamp__lte=date_to,
+ )
+ self.queryset_checked = self.queryset.filter(
+ checked__isnull=False
+ )
+ self.queryset_recorded = self.queryset.filter(
+ recorded__isnull=False
+ )
+ self.queryset_count = self.queryset.count()
+ self.queryset_checked_count = self.queryset_checked.count()
+ self.queryset_recorded_count = self.queryset_recorded.count()
+
+ self._create_report()
+ self._define_excel_map()
+
+ def _define_excel_map(self):
+ """ Define the excel map, which holds values for each placeholder used in the template
+
+ Returns:
+
+ """
+ self.excel_map = {
+ "i_checked": self.queryset_checked_count,
+ "i_recorded": self.queryset_recorded_count,
+ "i_total": self.queryset_count,
+ "i_compensations_checked": self.compensation_sum_checked,
+ "i_compensations_recorded": self.compensation_sum_recorded,
+ "i_compensations_total": self.compensation_sum,
+ "i_payments_recorded": self.payment_sum_recorded,
+ "i_payments_checked": self.payment_sum_checked,
+ "i_payments_total": self.payment_sum,
+ "i_deductions_recorded": self.deduction_sum_recorded,
+ "i_deductions_checked": self.deduction_sum_checked,
+ "i_deductions_total": self.deduction_sum,
+ "i_laws_iter": {
+ "iterable": self.evaluated_laws,
+ "attrs": [
+ "short_name",
+ "num_checked",
+ "num_recorded",
+ "num",
+ ]
+ },
+ "i_laws_checked": self.law_sum_checked,
+ "i_laws_recorded": self.law_sum_recorded,
+ "i_laws_total": self.law_sum,
+ }
+
+ def _create_report(self):
+ """ Creates all report information
+
+ Returns:
+
+ """
+ self._evaluate_laws()
+ self._evaluate_compensations()
+
+ def _evaluate_laws(self):
+ """ Analyzes the intervention-law distribution
+
+ Returns:
+
+ """
+ # Count interventions based on law
+ # Fetch all KonovaCodes for laws, sorted alphabetically
+ laws = KonovaCode.objects.filter(
+ is_archived=False,
+ is_leaf=True,
+ code_lists__in=[CODELIST_LAW_ID],
+ ).order_by(
+ "long_name"
+ )
+ # Fetch all law ids which are used by any .legal object of an intervention object
+ intervention_laws_total = self.queryset.values_list("legal__laws__id")
+ intervention_laws_checked = self.queryset.filter(checked__isnull=False).values_list("legal__laws__id")
+ intervention_laws_recorded = self.queryset.filter(recorded__isnull=False).values_list(
+ "legal__laws__id")
+ # Count how often which law id appears in the above list, return only the long_name of the law and the resulting
+ # count (here 'num'). This is for keeping the db fetch as small as possible
+ # Compute the sum for total, checked and recorded
+ self.evaluated_laws = laws.annotate(
+ num=Count("id", filter=Q(id__in=intervention_laws_total)),
+ num_checked=Count("id", filter=Q(id__in=intervention_laws_checked)),
+ num_recorded=Count("id", filter=Q(id__in=intervention_laws_recorded)),
+ ).values_list("short_name", "long_name", "num_checked", "num_recorded", "num", named=True)
+ self.law_sum = self.evaluated_laws.aggregate(sum_num=Sum("num"))["sum_num"]
+ self.law_sum_checked = self.evaluated_laws.aggregate(sum_num_checked=Sum("num_checked"))["sum_num_checked"]
+ self.law_sum_recorded = self.evaluated_laws.aggregate(sum_num_recorded=Sum("num_recorded"))["sum_num_recorded"]
+
+ def _evaluate_compensations(self):
+ """ Analyzes the types of compensation distribution
+
+ Returns:
+
+ """
+ # Count all compensations
+ comps = Compensation.objects.filter(
+ intervention__in=self.queryset
+ )
+ self.compensation_sum = comps.count()
+ self.compensation_sum_checked = comps.filter(intervention__checked__isnull=False).count()
+ self.compensation_sum_recorded = comps.filter(intervention__recorded__isnull=False).count()
+
+ # Count all payments
+ payments = Payment.objects.filter(
+ intervention__in=self.queryset
+ )
+ self.payment_sum = payments.count()
+ self.payment_sum_checked = payments.filter(intervention__checked__isnull=False).count()
+ self.payment_sum_recorded = payments.filter(intervention__recorded__isnull=False).count()
+
+ # Count all deductions
+ deductions = EcoAccountDeduction.objects.filter(
+ intervention__in=self.queryset
+ )
+ self.deduction_sum = deductions.count()
+ self.deduction_sum_checked = deductions.filter(intervention__checked__isnull=False).count()
+ self.deduction_sum_recorded = deductions.filter(intervention__recorded__isnull=False).count()
+
+ class CompensationReport:
+ queryset = Compensation.objects.none()
+ queryset_checked = Compensation.objects.none()
+ queryset_recorded = Compensation.objects.none()
+ queryset_count = -1
+ queryset_checked_count = -1
+ queryset_recorded_count = -1
+
+ queryset_registration_office_unb = Compensation.objects.none()
+ queryset_registration_office_unb_checked = Compensation.objects.none()
+ queryset_registration_office_unb_recorded = Compensation.objects.none()
+ queryset_registration_office_unb_count = -1
+ queryset_registration_office_unb_checked_count = -1
+ queryset_registration_office_unb_recorded_count = -1
+ num_single_surfaces_total_unb = -1
+
+ queryset_registration_office_tbp = Compensation.objects.none()
+ queryset_registration_office_tbp_checked = Compensation.objects.none()
+ queryset_registration_office_tbp_recorded = Compensation.objects.none()
+ queryset_registration_office_tbp_count = -1
+ queryset_registration_office_tbp_checked_count = -1
+ queryset_registration_office_tbp_recorded_count = -1
+ num_single_surfaces_total_tbp = -1
+
+ queryset_registration_office_other = Compensation.objects.none()
+ queryset_registration_office_other_checked = Compensation.objects.none()
+ queryset_registration_office_other_recorded = Compensation.objects.none()
+ queryset_registration_office_other_count = -1
+ queryset_registration_office_other_checked_count = -1
+ queryset_registration_office_other_recorded_count = -1
+ num_single_surfaces_total_other = -1
+
+ num_single_surfaces_total = -1
+ num_single_surfaces_recorded = -1
+
+ # Code list id for 'Träger der Bauleitplanung' parent
+ id_tbp = 1943695
+ # Code list id for 'untere Naturschutzbehörde'
+ id_unb = 1943087
+ # Code list id for 'obere Naturschutzbehörde'
+ id_onb = 1943084
+
+ def __init__(self, id: str, date_from: str, date_to: str):
+ self.queryset = Compensation.objects.filter(
+ intervention__responsible__conservation_office__id=id,
+ intervention__legal__registration_date__gt=LKOMPVZVO_PUBLISH_DATE,
+ deleted=None,
+ intervention__created__timestamp__gte=date_from,
+ intervention__created__timestamp__lte=date_to,
+ )
+ self.queryset_checked = self.queryset.filter(
+ intervention__checked__isnull=False
+ )
+ self.queryset_recorded = self.queryset.filter(
+ intervention__recorded__isnull=False
+ )
+
+ self.queryset_count = self.queryset.count()
+ self.queryset_checked_count = self.queryset_checked.count()
+ self.queryset_recorded_count = self.queryset_recorded.count()
+
+ self._create_report()
+ self._define_excel_map()
+
+ def _define_excel_map(self):
+ """ Define the excel map, which holds values for each placeholder used in the template
+
+ Returns:
+
+ """
+ self.excel_map = {
+ "c_unb_checked": self.queryset_registration_office_unb_checked_count,
+ "c_unb_recorded": self.queryset_registration_office_unb_recorded_count,
+ "c_unb": self.queryset_registration_office_unb_count,
+ "c_surfaces_unb": self.num_single_surfaces_total_unb,
+ "c_tbp_checked": self.queryset_registration_office_tbp_checked_count,
+ "c_tbp_recorded": self.queryset_registration_office_tbp_recorded_count,
+ "c_tbp": self.queryset_registration_office_tbp_count,
+ "c_surfaces_tbp": self.num_single_surfaces_total_tbp,
+ "c_other_checked": self.queryset_registration_office_other_checked_count,
+ "c_other_recorded": self.queryset_registration_office_other_recorded_count,
+ "c_other": self.queryset_registration_office_other_count,
+ "c_surfaces_other": self.num_single_surfaces_total_other,
+ "c_checked": self.queryset_checked_count,
+ "c_recorded": self.queryset_recorded_count,
+ "c_total": self.queryset_count,
+ "c_surfaces": self.num_single_surfaces_total,
+ }
+
+ def _create_report(self):
+ """ Creates all report information
+
+ Returns:
+
+ """
+ self._evaluate_compensation_responsibility()
+ self._evaluate_surfaces()
+
+ def _evaluate_surfaces(self):
+ """ Evaluates the surfaces of compensation Multipolygon fields
+
+ Returns:
+
+ """
+ # Evaluate all surfaces
+ ids = self.queryset.values_list("geometry_id")
+ self.num_single_surfaces_total = self._count_geometry_surfaces(ids)
+
+ # Evaluate surfaces where the conservation office is the registration office as well
+ ids = self.queryset_registration_office_unb.values_list("geometry_id")
+ self.num_single_surfaces_total_unb = self._count_geometry_surfaces(ids)
+
+ # Evaluates surfaces where the registration office is a Träger Bauleitplanung
+ ids = self.queryset_registration_office_tbp.values_list("geometry_id")
+ self.num_single_surfaces_total_tbp = self._count_geometry_surfaces(ids)
+
+ # Evaluates surfaces where any other registration office is responsible
+ ids = self.queryset_registration_office_other.values_list("geometry_id")
+ self.num_single_surfaces_total_other = self._count_geometry_surfaces(ids)
+
+ def _count_geometry_surfaces(self, ids: list):
+ """ Wraps counting of geometry surfaces from a given list of ids
+
+ Args:
+ ids (list): List of geometry ids
+
+ Returns:
+
+ """
+ # Now select all geometries matching the ids
+ # Then perform a ST_NumGeometries variant over all geometries
+ # Then sum up all of the calculated surface numbers
+ return Geometry.objects.filter(
+ id__in=ids
+ ).annotate(
+ geom_cast=Cast("geom", MultiPolygonField())
+ ).annotate(
+ num=NumGeometries("geom_cast")
+ ).aggregate(
+ num_geoms=Sum("num")
+ )["num_geoms"] or 0
+
+ def _evaluate_compensation_responsibility(self):
+ """ Evaluates compensations based on different responsibility areas
+
+ unb -> Untere Naturschutzbehörde
+ Holds entries where conservation_office and registration_office basically are the same
+ tbp -> Träger Bauleitplanung
+ Holds entries where registration_office is a Träger der Bauleitplanung
+ other -> Other registration offices
+ Holds all other entries
+
+ Returns:
+
+ """
+ self.queryset_registration_office_unb = self.queryset.filter(
+ intervention__responsible__registration_office__parent__id=self.id_unb
+ )
+ self.queryset_registration_office_unb_recorded = self.queryset_registration_office_unb.filter(
+ intervention__recorded__isnull=False,
+ )
+ self.queryset_registration_office_unb_checked = self.queryset_registration_office_unb.filter(
+ intervention__checked__isnull=False,
+ )
+ self.queryset_registration_office_unb_count = self.queryset_registration_office_unb.count()
+ self.queryset_registration_office_unb_checked_count = self.queryset_registration_office_unb_checked.count()
+ self.queryset_registration_office_unb_recorded_count = self.queryset_registration_office_unb_recorded.count()
+
+ self.queryset_registration_office_tbp = self.queryset.filter(
+ intervention__responsible__registration_office__parent__id=self.id_tbp
+ )
+ self.queryset_registration_office_tbp_recorded = self.queryset_registration_office_tbp.filter(
+ intervention__recorded__isnull=False,
+ )
+ self.queryset_registration_office_tbp_checked = self.queryset_registration_office_tbp.filter(
+ intervention__checked__isnull=False,
+ )
+ self.queryset_registration_office_tbp_count = self.queryset_registration_office_tbp.count()
+ self.queryset_registration_office_tbp_checked_count = self.queryset_registration_office_tbp_checked.count()
+ self.queryset_registration_office_tbp_recorded_count = self.queryset_registration_office_tbp_recorded.count()
+
+ self.queryset_registration_office_other = self.queryset.exclude(
+ Q(id__in=self.queryset_registration_office_tbp) | Q(id__in=self.queryset_registration_office_unb)
+ )
+ self.queryset_registration_office_other_recorded = self.queryset_registration_office_other.filter(
+ intervention__recorded__isnull=False,
+ )
+ self.queryset_registration_office_other_checked = self.queryset_registration_office_other.filter(
+ intervention__checked__isnull=False,
+ )
+ self.queryset_registration_office_other_count = self.queryset_registration_office_other.count()
+ self.queryset_registration_office_other_checked_count = self.queryset_registration_office_other_checked.count()
+ self.queryset_registration_office_other_recorded_count = self.queryset_registration_office_other_recorded.count()
+
+ class EcoAccountReport:
+ queryset = EcoAccount.objects.none()
+ queryset_recorded = EcoAccount.objects.none()
+ queryset_count = -1
+ queryset_recorded_count = -1
+
+ queryset_deductions = EcoAccountDeduction.objects.none()
+ queryset_deductions_recorded = EcoAccountDeduction.objects.none()
+ queryset_has_deductions = EcoAccountDeduction.objects.none()
+ queryset_deductions_count = -1
+ queryset_deductions_recorded_count = -1
+ queryset_has_deductions_count = -1
+
+ # Total size of deductions
+ deductions_sq_m = -1
+ recorded_deductions_sq_m = -1
+
+ def __init__(self, id: str, date_from: str, date_to: str):
+ # First fetch all eco account for this office
+ self.queryset = EcoAccount.objects.filter(
+ responsible__conservation_office__id=id,
+ deleted=None,
+ created__timestamp__gte=date_from,
+ created__timestamp__lte=date_to,
+ )
+ self.queryset_recorded = self.queryset.filter(
+ recorded__isnull=False
+ )
+ # Fetch all related deductions
+ self.queryset_deductions = EcoAccountDeduction.objects.filter(
+ account__id__in=self.queryset.values_list("id")
+ )
+ # Fetch deductions for interventions which are already recorded
+ self.queryset_deductions_recorded = self.queryset_deductions.filter(
+ intervention__recorded__isnull=False
+ )
+
+ self.queryset_count = self.queryset.count()
+ self.queryset_recorded_count = self.queryset_recorded.count()
+ self.queryset_deductions_count = self.queryset_deductions.count()
+ self.queryset_deductions_recorded_count = self.queryset_deductions_recorded.count()
+ self.queryset_has_deductions_count = self.queryset_has_deductions.count()
+
+ self._create_report()
+ self._define_excel_map()
+
+ def _define_excel_map(self):
+ """ Define the excel map, which holds values for each placeholder used in the template
+
+ Returns:
+
+ """
+ self.excel_map = {
+ "acc_total": self.queryset_count,
+ "acc_recorded": self.queryset_recorded_count,
+ "acc_deduc_recorded": self.queryset_deductions_recorded_count,
+ "acc_deduc_surface_recorded": self.recorded_deductions_sq_m,
+ "acc_deduc_total": self.queryset_deductions_count,
+ "acc_deduc_surface_total": self.deductions_sq_m,
+ }
+
+ def _create_report(self):
+ """ Creates all report information
+
+ Returns:
+
+ """
+ self._evaluate_deductions()
+
+ def _evaluate_deductions(self):
+ self.deductions_sq_m = self.queryset_deductions.aggregate(
+ sum=Sum("surface")
+ )["sum"] or 0
+ self.recorded_deductions_sq_m = self.queryset_deductions_recorded.aggregate(
+ sum=Sum("surface")
+ )["sum"] or 0
+
+ class OldDataReport:
+ """
+ Evaluates 'old data' (registered (zugelassen) before 16.06.2018)
+ """
+ queryset_intervention = Intervention.objects.none()
+ queryset_intervention_recorded = Intervention.objects.none()
+ queryset_intervention_count = -1
+ queryset_intervention_recorded_count = -1
+
+ queryset_comps = Compensation.objects.none()
+ queryset_comps_recorded = Compensation.objects.none()
+ queryset_comps_count = -1
+ queryset_comps_recorded_count = -1
+
+ queryset_acc = EcoAccount.objects.none()
+ queryset_acc_recorded = EcoAccount.objects.none()
+ queryset_acc_count = -1
+ queryset_acc_recorded_count = -1
+
+ def __init__(self, id: str, date_from: str, date_to: str):
+ self.queryset_intervention = Intervention.objects.filter(
+ legal__registration_date__lte=LKOMPVZVO_PUBLISH_DATE,
+ responsible__conservation_office__id=id,
+ deleted=None,
+ created__timestamp__gte=date_from,
+ created__timestamp__lte=date_to,
+ )
+ self.queryset_intervention_recorded = self.queryset_intervention.filter(
+ recorded__isnull=False
+ )
+ self.queryset_intervention_count = self.queryset_intervention.count()
+ self.queryset_intervention_recorded_count = self.queryset_intervention_recorded.count()
+
+ self.queryset_comps = Compensation.objects.filter(
+ intervention__in=self.queryset_intervention
+ )
+ self.queryset_comps_recorded = Compensation.objects.filter(
+ intervention__in=self.queryset_intervention_recorded,
+ )
+ self.queryset_comps_count = self.queryset_comps.count()
+ self.queryset_comps_recorded_count = self.queryset_comps_recorded.count()
+
+ self.queryset_acc = EcoAccount.objects.filter(
+ legal__registration_date__lte=LKOMPVZVO_PUBLISH_DATE,
+ responsible__conservation_office__id=id,
+ deleted=None,
+ created__timestamp__gte=date_from,
+ created__timestamp__lte=date_to,
+ )
+ self.queryset_acc_recorded = self.queryset_acc.filter(
+ recorded__isnull=False,
+ )
+ self.queryset_acc_count = self.queryset_acc.count()
+ self.queryset_acc_recorded_count = self.queryset_acc_recorded.count()
+ self._define_excel_map()
+
+ def _define_excel_map(self):
+ """ Define the excel map, which holds values for each placeholder used in the template
+
+ Returns:
+
+ """
+ self.excel_map = {
+ "old_i_recorded": self.queryset_intervention_recorded_count,
+ "old_i_total": self.queryset_intervention_count,
+ "old_c_recorded": self.queryset_comps_recorded_count,
+ "old_c_total": self.queryset_comps_count,
+ "old_ea_recorded": self.queryset_acc_recorded_count,
+ "old_ea_total": self.queryset_acc_count,
+ }
+
+ def __init__(self, office_id: str, date_from: str, date_to: str):
+ self.office_id = office_id
+ self.date_from = date_from
+ self.date_to = date_to
+
+ self.intervention_report = self.InterventionReport(self.office_id, date_from, date_to)
+ self.compensation_report = self.CompensationReport(self.office_id, date_from, date_to)
+ self.eco_account_report = self.EcoAccountReport(self.office_id, date_from, date_to)
+ self.old_data_report = self.OldDataReport(self.office_id, date_from, date_to)
+
+ # Build excel map
+ self.excel_map = {
+ "date_from": date_from.strftime(DEFAULT_DATE_FORMAT),
+ "date_to": date_to.strftime(DEFAULT_DATE_FORMAT),
+ }
+ self.excel_map.update(self.intervention_report.excel_map)
+ self.excel_map.update(self.compensation_report.excel_map)
+ self.excel_map.update(self.eco_account_report.excel_map)
+ self.excel_map.update(self.old_data_report.excel_map)
diff --git a/analysis/views.py b/analysis/views.py
new file mode 100644
index 00000000..6da4a586
--- /dev/null
+++ b/analysis/views.py
@@ -0,0 +1,98 @@
+from django.contrib import messages
+from django.contrib.auth.decorators import login_required
+from django.http import HttpRequest, HttpResponse
+from django.shortcuts import render, redirect, get_object_or_404
+from django.utils import timezone
+
+from analysis.forms import TimespanReportForm
+from analysis.utils.excel.excel import TempExcelFile
+from analysis.utils.report import TimespanReport
+from codelist.models import KonovaCode
+from konova.contexts import BaseContext
+from konova.decorators import conservation_office_group_required
+from konova.utils.message_templates import FORM_INVALID, PARAMS_INVALID
+
+
+@login_required
+@conservation_office_group_required
+def index_reports_view(request: HttpRequest):
+ """
+
+ Args:
+ request (HttpRequest): The incoming request
+
+ Returns:
+
+ """
+ template = "analysis/reports/index.html"
+ form = TimespanReportForm(request.POST or None)
+ if request.method == "POST":
+ if form.is_valid():
+ redirect_url = form.save()
+ return redirect(redirect_url)
+ else:
+ messages.error(
+ request,
+ FORM_INVALID,
+ extra_tags="danger",
+ )
+ context = {
+ "form": form
+ }
+ context = BaseContext(request, context).context
+ return render(request, template, context)
+
+
+@login_required
+@conservation_office_group_required
+def detail_report_view(request: HttpRequest, id: str):
+ """ Renders the detailed report for a conservation office
+
+ Args:
+ request (HttpRequest): The incoming request
+ id (str): The conservation_office KonovaCode id
+
+ Returns:
+
+ """
+ # Try to resolve the requested office id
+ cons_office = get_object_or_404(
+ KonovaCode,
+ id=id
+ )
+ # Try to resolve the date parameters into Date objects -> redirect if this fails
+ try:
+ df = request.GET.get("df", None)
+ dt = request.GET.get("dt", None)
+ date_from = timezone.make_aware(timezone.datetime.fromisoformat(df))
+ date_to = timezone.make_aware(timezone.datetime.fromisoformat(dt))
+ except ValueError:
+ messages.error(
+ request,
+ PARAMS_INVALID,
+ extra_tags="danger",
+ )
+ return redirect("analysis:reports")
+
+ # Check whether the html default rendering is requested or an alternative
+ format_param = request.GET.get("format", "html")
+ report = TimespanReport(id, date_from, date_to)
+
+ if format_param == "html":
+ template = "analysis/reports/detail.html"
+ context = {
+ "office": cons_office,
+ "report": report,
+ }
+ context = BaseContext(request, context).context
+ return render(request, template, context)
+ elif format_param == "excel":
+ file = TempExcelFile(report.excel_template_path, report.excel_map)
+ response = HttpResponse(
+ content=file.stream,
+ content_type="application/ms-excel",
+ )
+ response['Content-Disposition'] = f'attachment; filename={cons_office.long_name}_{df}_{dt}.xlsx'
+ return response
+ else:
+ raise NotImplementedError
diff --git a/compensation/forms/forms.py b/compensation/forms/forms.py
index fd747ef5..eadee2f4 100644
--- a/compensation/forms/forms.py
+++ b/compensation/forms/forms.py
@@ -16,7 +16,7 @@ from codelist.models import KonovaCode
from codelist.settings import CODELIST_COMPENSATION_FUNDING_ID, CODELIST_CONSERVATION_OFFICE_ID
from compensation.models import Compensation, EcoAccount
from intervention.inputs import GenerateInput
-from intervention.models import Intervention, ResponsibilityData
+from intervention.models import Intervention, ResponsibilityData, LegalData
from konova.forms import BaseForm, SimpleGeomForm
from user.models import UserActionLogEntry, UserAction
@@ -284,10 +284,40 @@ class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMix
Inherits from basic AbstractCompensationForm and further form fields from CompensationResponsibleFormMixin
"""
+ surface = forms.DecimalField(
+ min_value=0.00,
+ decimal_places=2,
+ label=_("Available Surface"),
+ label_suffix="",
+ required=False,
+ help_text=_("The amount that can be used for deductions"),
+ widget=forms.NumberInput(
+ attrs={
+ "class": "form-control",
+ "placeholder": "0,00"
+ }
+ )
+ )
+ registration_date = forms.DateField(
+ label=_("Agreement date"),
+ label_suffix="",
+ help_text=_("When did the parties agree on this?"),
+ required=False,
+ widget=forms.DateInput(
+ attrs={
+ "type": "date",
+ "class": "form-control",
+ },
+ format="%d.%m.%Y"
+ )
+ )
+
field_order = [
"identifier",
"title",
"conservation_office",
+ "registration_date",
+ "surface",
"conservation_file_number",
"handler",
"fundings",
@@ -313,7 +343,9 @@ class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMix
identifier = self.cleaned_data.get("identifier", None)
title = self.cleaned_data.get("title", None)
fundings = self.cleaned_data.get("fundings", None)
+ registration_date = self.cleaned_data.get("registration_date", None)
handler = self.cleaned_data.get("handler", None)
+ surface = self.cleaned_data.get("surface", None)
conservation_office = self.cleaned_data.get("conservation_office", None)
conservation_file_number = self.cleaned_data.get("conservation_file_number", None)
comment = self.cleaned_data.get("comment", None)
@@ -332,15 +364,20 @@ class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMix
conservation_office=conservation_office,
)
+ legal = LegalData.objects.create(
+ registration_date=registration_date
+ )
+
# Finally create main object
acc = EcoAccount.objects.create(
identifier=identifier,
title=title,
responsible=responsible,
- deductable_surface=0.00,
+ deductable_surface=surface,
created=action,
geometry=geometry,
comment=comment,
+ legal=legal
)
acc.fundings.set(fundings)
acc.users.add(user)
@@ -354,30 +391,6 @@ class EditEcoAccountForm(NewEcoAccountForm):
""" Form for editing eco accounts
"""
- surface = forms.DecimalField(
- min_value=0.00,
- decimal_places=2,
- label=_("Available Surface"),
- label_suffix="",
- required=False,
- help_text=_("The amount that can be used for deductions"),
- widget=forms.NumberInput(
- attrs={
- "class": "form-control",
- "placeholder": "0,00"
- }
- )
- )
- field_order = [
- "identifier",
- "title",
- "conservation_office",
- "surface",
- "conservation_file_number",
- "handler",
- "fundings",
- "comment",
- ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
@@ -387,11 +400,15 @@ class EditEcoAccountForm(NewEcoAccountForm):
self.cancel_redirect = reverse("compensation:acc-detail", args=(self.instance.id,))
# Initialize form data
+ reg_date = self.instance.legal.registration_date
+ if reg_date is not None:
+ reg_date = reg_date.isoformat()
form_data = {
"identifier": self.instance.identifier,
"title": self.instance.title,
"surface": self.instance.deductable_surface,
"handler": self.instance.responsible.handler,
+ "registration_date": reg_date,
"conservation_office": self.instance.responsible.conservation_office,
"conservation_file_number": self.instance.responsible.conservation_file_number,
"fundings": self.instance.fundings.all(),
@@ -409,6 +426,7 @@ class EditEcoAccountForm(NewEcoAccountForm):
identifier = self.cleaned_data.get("identifier", None)
title = self.cleaned_data.get("title", None)
fundings = self.cleaned_data.get("fundings", None)
+ registration_date = self.cleaned_data.get("registration_date", None)
handler = self.cleaned_data.get("handler", None)
surface = self.cleaned_data.get("surface", None)
conservation_office = self.cleaned_data.get("conservation_office", None)
@@ -429,6 +447,10 @@ class EditEcoAccountForm(NewEcoAccountForm):
self.instance.responsible.conservation_file_number = conservation_file_number
self.instance.responsible.save()
+ # Update legal data
+ self.instance.legal.registration_date = registration_date
+ self.instance.legal.save()
+
# Update main oject data
self.instance.identifier = identifier
self.instance.title = title
diff --git a/compensation/models.py b/compensation/models.py
index 4f9cc919..d2d18be5 100644
--- a/compensation/models.py
+++ b/compensation/models.py
@@ -19,7 +19,7 @@ from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES
CODELIST_COMPENSATION_FUNDING_ID
from compensation.managers import CompensationStateManager, EcoAccountDeductionManager, CompensationActionManager, \
EcoAccountManager, CompensationManager
-from intervention.models import Intervention, ResponsibilityData
+from intervention.models import Intervention, ResponsibilityData, LegalData
from konova.models import BaseObject, BaseResource, Geometry, UuidModel, AbstractDocument, \
generate_document_file_upload_path
from konova.settings import DEFAULT_SRID_RLP, LANIS_LINK_TEMPLATE
@@ -309,6 +309,14 @@ class EcoAccount(AbstractCompensation):
default=0,
)
+ legal = models.OneToOneField(
+ LegalData,
+ on_delete=models.SET_NULL,
+ null=True,
+ blank=True,
+ help_text="Holds data on legal dates or law"
+ )
+
objects = EcoAccountManager()
def __str__(self):
diff --git a/compensation/templates/compensation/detail/eco_account/view.html b/compensation/templates/compensation/detail/eco_account/view.html
index e839e6e9..6f7eca99 100644
--- a/compensation/templates/compensation/detail/eco_account/view.html
+++ b/compensation/templates/compensation/detail/eco_account/view.html
@@ -61,6 +61,10 @@
{% trans 'Conservation office file number' %}
{{obj.responsible.conservation_file_number|default_if_none:""}}
+
+ {% trans 'Agreement date' %}
+ {{obj.legal.registration_date|default_if_none:""}}
+
{% trans 'Action handler' %}
{{obj.responsible.handler|default_if_none:""}}
diff --git a/compensation/views/compensation_views.py b/compensation/views/compensation_views.py
index 994e9647..5b187501 100644
--- a/compensation/views/compensation_views.py
+++ b/compensation/views/compensation_views.py
@@ -77,7 +77,7 @@ def new_view(request: HttpRequest, intervention_id: str = None):
messages.success(request, _("Compensation {} added").format(comp.identifier))
return redirect("compensation:detail", id=comp.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
@@ -132,7 +132,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("Compensation {} edited").format(comp.identifier))
return redirect("compensation:detail", id=comp.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
diff --git a/compensation/views/eco_account_views.py b/compensation/views/eco_account_views.py
index dadac7e6..bb04facb 100644
--- a/compensation/views/eco_account_views.py
+++ b/compensation/views/eco_account_views.py
@@ -86,7 +86,7 @@ def new_view(request: HttpRequest):
messages.success(request, _("Eco-Account {} added").format(acc.identifier))
return redirect("compensation:acc-detail", id=acc.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
@@ -141,7 +141,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
return redirect("compensation:acc-detail", id=acc.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
diff --git a/ema/views.py b/ema/views.py
index ead1a899..a9ad2bdb 100644
--- a/ema/views.py
+++ b/ema/views.py
@@ -78,7 +78,7 @@ def new_view(request: HttpRequest):
messages.success(request, _("EMA {} added").format(ema.identifier))
return redirect("ema:detail", id=ema.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
@@ -202,7 +202,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("EMA {} edited").format(ema.identifier))
return redirect("ema:detail", id=ema.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
diff --git a/intervention/managers.py b/intervention/managers.py
index 213e8659..a0fb28ae 100644
--- a/intervention/managers.py
+++ b/intervention/managers.py
@@ -23,26 +23,3 @@ class InterventionManager(models.Manager):
).prefetch_related(
"users",
)
-
-
-class LegalDataManager(models.Manager):
- """ Holds default db fetch setting for this model type
-
- """
- def get_queryset(self):
- return super().get_querset().select_related(
- "process_type",
- ).prefetch_related(
- "laws"
- )
-
-
-class ResponsibilityDataManager(models.Manager):
- """ Holds default db fetch setting for this model type
-
- """
- def get_queryset(self):
- return super().get_querset().select_related(
- "registration_office",
- "conservation_office",
- )
diff --git a/intervention/models.py b/intervention/models.py
index 2bdf1eff..9d0c8816 100644
--- a/intervention/models.py
+++ b/intervention/models.py
@@ -15,7 +15,7 @@ from django.utils.translation import gettext_lazy as _
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, LegalDataManager, ResponsibilityDataManager
+from intervention.managers import InterventionManager
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 +56,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'")
- objects = ResponsibilityDataManager()
def __str__(self):
return "ZB: {} | ETS: {} | Handler: {}".format(
@@ -172,8 +171,6 @@ class LegalData(UuidModel):
revocation = models.OneToOneField(Revocation, null=True, blank=True, help_text="Refers to 'Widerspruch am'", on_delete=models.SET_NULL)
- objects = LegalDataManager()
-
class Intervention(BaseObject):
"""
diff --git a/intervention/views.py b/intervention/views.py
index 6853197f..bd770ce2 100644
--- a/intervention/views.py
+++ b/intervention/views.py
@@ -79,7 +79,7 @@ def new_view(request: HttpRequest):
messages.success(request, _("Intervention {} added").format(intervention.identifier))
return redirect("intervention:detail", id=intervention.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
@@ -264,7 +264,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("Intervention {} edited").format(intervention.identifier))
return redirect("intervention:detail", id=intervention.id)
else:
- messages.error(request, FORM_INVALID)
+ messages.error(request, FORM_INVALID, extra_tags="danger",)
else:
# For clarification: nothing in this case
pass
diff --git a/konova/forms.py b/konova/forms.py
index 26914d27..74e53896 100644
--- a/konova/forms.py
+++ b/konova/forms.py
@@ -37,12 +37,14 @@ class BaseForm(forms.Form):
"""
template = None
action_url = None
+ action_btn_label = _("Save")
form_title = None
cancel_redirect = None
form_caption = None
instance = None # The data holding model object
form_attrs = {} # Holds additional attributes, that can be used in the template
has_required_fields = False # Automatically set. Triggers hint rendering in templates
+ show_cancel_btn = True
def __init__(self, *args, **kwargs):
self.instance = kwargs.pop("instance", None)
@@ -189,6 +191,7 @@ class BaseModalForm(BaseForm, BSModalForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
+ self.action_btn_label = _("Continue")
def process_request(self, request: HttpRequest, msg_success: str = _("Object removed"), msg_error: str = FORM_INVALID, redirect_url: str = None):
""" Generic processing of request
diff --git a/konova/sub_settings/django_settings.py b/konova/sub_settings/django_settings.py
index 29540d4b..df875a81 100644
--- a/konova/sub_settings/django_settings.py
+++ b/konova/sub_settings/django_settings.py
@@ -69,6 +69,7 @@ INSTALLED_APPS = [
'user',
'ema',
'codelist',
+ 'analysis',
]
if DEBUG:
INSTALLED_APPS += [
diff --git a/konova/templatetags/ksp_filters.py b/konova/templatetags/ksp_filters.py
index 95fc7ea0..1472d503 100644
--- a/konova/templatetags/ksp_filters.py
+++ b/konova/templatetags/ksp_filters.py
@@ -34,3 +34,19 @@ def bootstrap_cls(value):
"""
return SVI_BOOTSTRAP_CLS_MAP.get(value, "")
+
+
+@register.filter("default_if_zero")
+def default_if_zero(val1, val2):
+ """ Returns val2 if val1 is 0
+
+ Similar to default_if_none
+
+ Args:
+ val1 (int): The numerical value
+ val2 (str): The alternative
+
+ Returns:
+
+ """
+ return val1 if val1 > 0 else val2
diff --git a/konova/urls.py b/konova/urls.py
index 8448cb4e..1aebcbcc 100644
--- a/konova/urls.py
+++ b/konova/urls.py
@@ -36,7 +36,8 @@ urlpatterns = [
path('ema/', include("ema.urls")),
path('user/', include("user.urls")),
path('news/', include("news.urls")),
- path('news/', include("codelist.urls")),
+ path('cl/', include("codelist.urls")),
+ path('analysis/', include("analysis.urls")),
# Generic deadline routes
path('deadline//remove', remove_deadline_view, name="deadline-remove"),
diff --git a/konova/utils/message_templates.py b/konova/utils/message_templates.py
index f9c8e2b9..e28f39de 100644
--- a/konova/utils/message_templates.py
+++ b/konova/utils/message_templates.py
@@ -9,6 +9,7 @@ from django.utils.translation import gettext_lazy as _
FORM_INVALID = _("There was an error on this form.")
+PARAMS_INVALID = _("Invalid parameters")
INTERVENTION_INVALID = _("There are errors in this intervention.")
IDENTIFIER_REPLACED = _("The identifier '{}' had to be changed to '{}' since another entry has been added in the meanwhile, which uses this identifier")
DATA_UNSHARED = _("This data is not shared with you")
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index b9d3ebde..8a1e11b3 100644
Binary files a/locale/de/LC_MESSAGES/django.mo and b/locale/de/LC_MESSAGES/django.mo differ
diff --git a/locale/de/LC_MESSAGES/django.po b/locale/de/LC_MESSAGES/django.po
index aebd7445..2ac3f918 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -11,15 +11,15 @@
#: intervention/forms/forms.py:53 intervention/forms/forms.py:155
#: intervention/forms/forms.py:167 intervention/forms/modalForms.py:107
#: intervention/forms/modalForms.py:120 intervention/forms/modalForms.py:133
-#: konova/forms.py:140 konova/forms.py:244 konova/forms.py:310
-#: konova/forms.py:337 konova/forms.py:347 konova/forms.py:360
-#: konova/forms.py:372 konova/forms.py:393 user/forms.py:38
+#: konova/forms.py:142 konova/forms.py:247 konova/forms.py:313
+#: konova/forms.py:340 konova/forms.py:350 konova/forms.py:363
+#: konova/forms.py:375 konova/forms.py:396 user/forms.py:38
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2021-10-14 09:12+0200\n"
+"POT-Creation-Date: 2021-10-22 13:14+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -29,23 +29,288 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+#: analysis/forms.py:24 analysis/templates/analysis/reports/detail.html:8
+msgid "From"
+msgstr "Vom"
+
+#: analysis/forms.py:36
+msgid "To"
+msgstr "Bis"
+
+#: analysis/forms.py:47 compensation/forms/forms.py:94
+#: compensation/templates/compensation/detail/eco_account/view.html:58
+#: compensation/templates/compensation/report/eco_account/report.html:16
+#: ema/templates/ema/detail/view.html:42
+#: ema/templates/ema/report/report.html:16 intervention/forms/forms.py:101
+#: intervention/templates/intervention/detail/view.html:56
+#: intervention/templates/intervention/report/report.html:37
+msgid "Conservation office"
+msgstr "Eintragungsstelle"
+
+#: analysis/forms.py:49 compensation/forms/forms.py:96
+msgid "Select the responsible office"
+msgstr "Verantwortliche Stelle"
+
+#: analysis/forms.py:58 compensation/forms/forms.py:68
+#: compensation/forms/forms.py:105 compensation/forms/forms.py:156
+#: intervention/forms/forms.py:63 intervention/forms/forms.py:80
+#: intervention/forms/forms.py:96 intervention/forms/forms.py:112
+msgid "Click for selection"
+msgstr "Auswählen..."
+
+#: analysis/forms.py:65
+msgid "Generate report"
+msgstr "Bericht generieren"
+
+#: analysis/forms.py:66
+msgid "Select a timespan and the desired conservation office"
+msgstr "Wählen Sie die Zeitspanne und die gewünschte Eintragungsstelle"
+
+#: analysis/forms.py:69 konova/forms.py:194
+msgid "Continue"
+msgstr "Weiter"
+
+#: analysis/templates/analysis/reports/detail.html:7
+msgid "Evaluation report"
+msgstr "Auswertungsbericht"
+
+#: analysis/templates/analysis/reports/detail.html:8
+msgid "to"
+msgstr "bis"
+
+#: analysis/templates/analysis/reports/detail.html:14
+msgid "Download"
+msgstr ""
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:3
+#: analysis/templates/analysis/reports/includes/eco_account/amount.html:3
+#: analysis/templates/analysis/reports/includes/intervention/amount.html:3
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:3
+#: compensation/forms/modalForms.py:351
+#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
+#: intervention/templates/intervention/detail/includes/deductions.html:31
+msgid "Amount"
+msgstr "Menge"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:5
+#: analysis/templates/analysis/reports/includes/intervention/amount.html:5
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:5
+msgid ""
+"\n"
+" Checked = Has been checked by the registration office according to "
+"LKompVzVo\n"
+" "
+msgstr ""
+"\n"
+" Geprüft = Wurde von der zuständigen Zulassungsbehörde überprüft\n"
+" "
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:9
+#: analysis/templates/analysis/reports/includes/eco_account/amount.html:5
+#: analysis/templates/analysis/reports/includes/intervention/amount.html:9
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:9
+msgid ""
+"\n"
+" Recorded = Has been checked and published by the conservation office\n"
+" "
+msgstr ""
+"\n"
+" Verzeichnet = Wurde von der Eintragungsstelle überprüft und "
+"veröffentlicht\n"
+" "
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:17
+msgid "Area of responsibility"
+msgstr "Zuständigkeitsbereich"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:18
+#: analysis/templates/analysis/reports/includes/intervention/amount.html:17
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:8
+#: analysis/templates/analysis/reports/includes/intervention/laws.html:17
+#: compensation/tables.py:35
+#: compensation/templates/compensation/detail/compensation/view.html:43
+#: intervention/tables.py:33
+#: intervention/templates/intervention/detail/view.html:68 user/models.py:48
+msgid "Checked"
+msgstr "Geprüft"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:19
+#: analysis/templates/analysis/reports/includes/eco_account/amount.html:13
+#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:8
+#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:9
+#: analysis/templates/analysis/reports/includes/intervention/amount.html:18
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:9
+#: analysis/templates/analysis/reports/includes/intervention/laws.html:20
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:18
+#: compensation/tables.py:41 compensation/tables.py:181
+#: compensation/templates/compensation/detail/compensation/view.html:57
+#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:31
+#: compensation/templates/compensation/detail/eco_account/view.html:44
+#: ema/tables.py:38 ema/templates/ema/detail/view.html:28
+#: intervention/tables.py:39
+#: intervention/templates/intervention/detail/view.html:82 user/models.py:49
+msgid "Recorded"
+msgstr "Verzeichnet"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:20
+msgid "Number single areas"
+msgstr "Einzelflächen"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:21
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:47
+#: analysis/templates/analysis/reports/includes/eco_account/amount.html:14
+#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:10
+#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:11
+#: analysis/templates/analysis/reports/includes/intervention/amount.html:19
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:10
+#: analysis/templates/analysis/reports/includes/intervention/laws.html:23
+#: analysis/templates/analysis/reports/includes/intervention/laws.html:43
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:19
+#: konova/templates/konova/home.html:23 konova/templates/konova/home.html:61
+#: konova/templates/konova/home.html:100
+msgid "Total"
+msgstr "Insgesamt"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:26
+msgid "Conservation office by law"
+msgstr "Naturschutzbehörde (§17 Abs.3 BNatSchG)"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:33
+msgid "Land-use planning"
+msgstr "Träger Bauleitplanung"
+
+#: analysis/templates/analysis/reports/includes/compensation/amount.html:40
+msgid "Other registration office"
+msgstr "Andere Zulassungsbehörden"
+
+#: analysis/templates/analysis/reports/includes/compensation/card_compensation.html:11
+#: compensation/tables.py:62
+#: intervention/templates/intervention/detail/includes/compensations.html:8
+#: intervention/templates/intervention/report/report.html:49
+msgid "Compensations"
+msgstr "Kompensationen"
+
+#: analysis/templates/analysis/reports/includes/eco_account/card_eco_account.html:11
+msgid "Eco-Accounts"
+msgstr "Ökokonten"
+
+#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:3
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:27
+msgid "Deductions"
+msgstr "Abbuchungen"
+
+#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:9
+#: analysis/templates/analysis/reports/includes/eco_account/deductions.html:11
+#: compensation/forms/modalForms.py:152
+#: compensation/templates/compensation/detail/compensation/includes/states-after.html:36
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:36
+#: compensation/templates/compensation/detail/eco_account/includes/states-after.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-before.html:36
+#: intervention/forms/modalForms.py:274
+msgid "Surface"
+msgstr "Fläche"
+
+#: analysis/templates/analysis/reports/includes/intervention/card_intervention.html:10
+#: intervention/tables.py:66
+msgid "Interventions"
+msgstr "Eingriffe"
+
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:2
+msgid "Compensated by"
+msgstr "Kompensiert durch"
+
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:7
+msgid "Compensation type"
+msgstr "Kompensationsart"
+
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:15
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:29
+#: compensation/tables.py:84
+#: compensation/templates/compensation/detail/compensation/view.html:19
+#: konova/templates/konova/home.html:49 templates/navbars/navbar.html:28
+msgid "Compensation"
+msgstr "Kompensation"
+
+#: analysis/templates/analysis/reports/includes/intervention/compensated_by.html:21
+#: compensation/forms/modalForms.py:75
+msgid "Payment"
+msgstr "Zahlung"
+
+#: analysis/templates/analysis/reports/includes/intervention/laws.html:2
+msgid "Law usage"
+msgstr "Gesetzesanwendungen"
+
+#: analysis/templates/analysis/reports/includes/intervention/laws.html:4
+msgid ""
+"\n"
+" Please note: One intervention can be based on multiple laws. This table "
+"therefore does not\n"
+" count\n"
+" "
+msgstr ""
+"\n"
+" Beachten Sie: Ein Eingriff kann mehreren Gesetzen zugeordnet worden "
+"sein. Diese Tabelle zählt daher nicht die Eingriffe selbst , sondern wie oft "
+"ein Gesetz Anwendung fand.\n"
+" "
+
+#: analysis/templates/analysis/reports/includes/intervention/laws.html:14
+#: intervention/forms/forms.py:68
+#: intervention/templates/intervention/detail/view.html:39
+#: intervention/templates/intervention/report/report.html:20
+msgid "Law"
+msgstr "Gesetz"
+
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:17
+#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:28
+#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:28
+#: ema/templates/ema/detail/includes/deadlines.html:28
+msgid "Type"
+msgstr "Typ"
+
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:24
+#: intervention/forms/modalForms.py:285 intervention/forms/modalForms.py:292
+#: intervention/tables.py:88
+#: intervention/templates/intervention/detail/view.html:19
+#: konova/templates/konova/home.html:11 templates/navbars/navbar.html:22
+msgid "Intervention"
+msgstr "Eingriff"
+
+#: analysis/templates/analysis/reports/includes/old_data/amount.html:34
+#: compensation/tables.py:224
+#: compensation/templates/compensation/detail/eco_account/view.html:19
+#: intervention/forms/modalForms.py:258 intervention/forms/modalForms.py:265
+#: konova/templates/konova/home.html:88 templates/navbars/navbar.html:34
+msgid "Eco-account"
+msgstr "Ökokonto"
+
+#: analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html:11
+msgid "Old interventions"
+msgstr "Altfälle"
+
+#: analysis/templates/analysis/reports/includes/old_data/card_old_interventions.html:13
+msgid "Before"
+msgstr "Vor"
+
#: compensation/filters.py:70
msgid "Show only unrecorded"
msgstr "Nur unverzeichnete anzeigen"
-#: compensation/forms/forms.py:31 compensation/tables.py:25
-#: compensation/tables.py:167 ema/tables.py:28 intervention/forms/forms.py:27
+#: compensation/forms/forms.py:32 compensation/tables.py:25
+#: compensation/tables.py:166 ema/tables.py:28 intervention/forms/forms.py:27
#: intervention/tables.py:23
#: intervention/templates/intervention/detail/includes/compensations.html:30
msgid "Identifier"
msgstr "Kennung"
-#: compensation/forms/forms.py:34 intervention/forms/forms.py:30
+#: compensation/forms/forms.py:35 intervention/forms/forms.py:30
msgid "Generated automatically"
msgstr "Automatisch generiert"
-#: compensation/forms/forms.py:43 compensation/tables.py:30
-#: compensation/tables.py:172
+#: compensation/forms/forms.py:44 compensation/tables.py:30
+#: compensation/tables.py:171
#: compensation/templates/compensation/detail/compensation/includes/documents.html:28
#: compensation/templates/compensation/detail/compensation/view.html:31
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:28
@@ -60,34 +325,27 @@ msgstr "Automatisch generiert"
#: intervention/templates/intervention/detail/includes/documents.html:28
#: intervention/templates/intervention/detail/view.html:31
#: intervention/templates/intervention/report/report.html:12
-#: konova/forms.py:336
+#: konova/forms.py:339
msgid "Title"
msgstr "Bezeichnung"
-#: compensation/forms/forms.py:45 intervention/forms/forms.py:41
+#: compensation/forms/forms.py:46 intervention/forms/forms.py:41
msgid "An explanatory name"
msgstr "Aussagekräftiger Titel"
-#: compensation/forms/forms.py:49 ema/forms.py:47 ema/forms.py:105
+#: compensation/forms/forms.py:50 ema/forms.py:47 ema/forms.py:105
msgid "Compensation XY; Location ABC"
msgstr "Kompensation XY; Flur ABC"
-#: compensation/forms/forms.py:55
+#: compensation/forms/forms.py:56
msgid "Fundings"
msgstr "Förderungen"
-#: compensation/forms/forms.py:58
+#: compensation/forms/forms.py:59
msgid "Select fundings for this compensation"
msgstr "Wählen Sie ggf. Fördermittelprojekte"
-#: compensation/forms/forms.py:67 compensation/forms/forms.py:104
-#: compensation/forms/forms.py:155 intervention/forms/forms.py:63
-#: intervention/forms/forms.py:80 intervention/forms/forms.py:96
-#: intervention/forms/forms.py:112
-msgid "Click for selection"
-msgstr "Auswählen..."
-
-#: compensation/forms/forms.py:73 compensation/forms/modalForms.py:61
+#: compensation/forms/forms.py:74 compensation/forms/modalForms.py:61
#: compensation/forms/modalForms.py:272 compensation/forms/modalForms.py:367
#: compensation/templates/compensation/detail/compensation/includes/actions.html:34
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:34
@@ -102,29 +360,15 @@ msgstr "Auswählen..."
#: intervention/templates/intervention/detail/includes/documents.html:31
#: intervention/templates/intervention/detail/includes/payments.html:34
#: intervention/templates/intervention/detail/includes/revocation.html:38
-#: konova/forms.py:371 konova/templates/konova/comment_card.html:16
+#: konova/forms.py:374 konova/templates/konova/comment_card.html:16
msgid "Comment"
msgstr "Kommentar"
-#: compensation/forms/forms.py:75 intervention/forms/forms.py:181
+#: compensation/forms/forms.py:76 intervention/forms/forms.py:181
msgid "Additional comment"
msgstr "Zusätzlicher Kommentar"
-#: compensation/forms/forms.py:93
-#: compensation/templates/compensation/detail/eco_account/view.html:58
-#: compensation/templates/compensation/report/eco_account/report.html:16
-#: ema/templates/ema/detail/view.html:42
-#: ema/templates/ema/report/report.html:16 intervention/forms/forms.py:101
-#: intervention/templates/intervention/detail/view.html:56
-#: intervention/templates/intervention/report/report.html:37
-msgid "Conservation office"
-msgstr "Eintragungsstelle"
-
-#: compensation/forms/forms.py:95
-msgid "Select the responsible office"
-msgstr "Verantwortliche Stelle"
-
-#: compensation/forms/forms.py:109
+#: compensation/forms/forms.py:110
#: compensation/templates/compensation/detail/eco_account/view.html:62
#: compensation/templates/compensation/report/eco_account/report.html:20
#: ema/templates/ema/detail/view.html:46
@@ -134,57 +378,65 @@ msgstr "Verantwortliche Stelle"
msgid "Conservation office file number"
msgstr "Aktenzeichen Eintragungsstelle"
-#: compensation/forms/forms.py:115 intervention/forms/forms.py:135
+#: compensation/forms/forms.py:116 intervention/forms/forms.py:135
msgid "ETS-123/ABC.456"
msgstr ""
-#: compensation/forms/forms.py:121
+#: compensation/forms/forms.py:122
msgid "Eco-account handler"
msgstr "Maßnahmenträger"
-#: compensation/forms/forms.py:125
+#: compensation/forms/forms.py:126
msgid "Who handles the eco-account"
msgstr "Wer für die Herrichtung des Ökokontos verantwortlich ist"
-#: compensation/forms/forms.py:128 intervention/forms/forms.py:148
+#: compensation/forms/forms.py:129 intervention/forms/forms.py:148
msgid "Company Mustermann"
msgstr "Firma Mustermann"
-#: compensation/forms/forms.py:146
+#: compensation/forms/forms.py:147
#: compensation/templates/compensation/detail/compensation/view.html:35
#: compensation/templates/compensation/report/compensation/report.html:16
msgid "compensates intervention"
msgstr "kompensiert Eingriff"
-#: compensation/forms/forms.py:148
+#: compensation/forms/forms.py:149
msgid "Select the intervention for which this compensation compensates"
msgstr "Wählen Sie den Eingriff, für den diese Kompensation bestimmt ist"
-#: compensation/forms/forms.py:173
+#: compensation/forms/forms.py:174
msgid "New compensation"
msgstr "Neue Kompensation"
-#: compensation/forms/forms.py:231
+#: compensation/forms/forms.py:232
msgid "Edit compensation"
msgstr "Bearbeite Kompensation"
-#: compensation/forms/forms.py:299
-msgid "New Eco-Account"
-msgstr "Neues Ökokonto"
-
-#: compensation/forms/forms.py:308
-msgid "Eco-Account XY; Location ABC"
-msgstr "Ökokonto XY; Flur ABC"
-
-#: compensation/forms/forms.py:360
+#: compensation/forms/forms.py:291
msgid "Available Surface"
msgstr "Verfügbare Fläche"
-#: compensation/forms/forms.py:363
+#: compensation/forms/forms.py:294
msgid "The amount that can be used for deductions"
msgstr "Die für Abbuchungen zur Verfügung stehende Menge"
-#: compensation/forms/forms.py:384
+#: compensation/forms/forms.py:303
+msgid "Agreement date"
+msgstr "Vereinbarungsdatum"
+
+#: compensation/forms/forms.py:304
+msgid "When did the parties agree on this?"
+msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
+
+#: compensation/forms/forms.py:329
+msgid "New Eco-Account"
+msgstr "Neues Ökokonto"
+
+#: compensation/forms/forms.py:338
+msgid "Eco-Account XY; Location ABC"
+msgstr "Ökokonto XY; Flur ABC"
+
+#: compensation/forms/forms.py:397
msgid "Edit Eco-Account"
msgstr "Ökokonto bearbeiten"
@@ -203,14 +455,10 @@ msgstr "Zahlung wird an diesem Datum erwartet"
#: compensation/forms/modalForms.py:63 compensation/forms/modalForms.py:274
#: compensation/forms/modalForms.py:369 intervention/forms/modalForms.py:134
-#: konova/forms.py:373
+#: konova/forms.py:376
msgid "Additional comment, maximum {} letters"
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
-#: compensation/forms/modalForms.py:75
-msgid "Payment"
-msgstr "Zahlung"
-
#: compensation/forms/modalForms.py:76
msgid "Add a payment for intervention '{}'"
msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen"
@@ -231,17 +479,6 @@ msgstr "Biotoptyp"
msgid "Select the biotope type"
msgstr "Biotoptyp wählen"
-#: compensation/forms/modalForms.py:152
-#: compensation/templates/compensation/detail/compensation/includes/states-after.html:36
-#: compensation/templates/compensation/detail/compensation/includes/states-before.html:36
-#: compensation/templates/compensation/detail/eco_account/includes/states-after.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-before.html:36
-#: intervention/forms/modalForms.py:274
-msgid "Surface"
-msgstr "Fläche"
-
#: compensation/forms/modalForms.py:155 intervention/forms/modalForms.py:276
msgid "in m²"
msgstr ""
@@ -258,7 +495,7 @@ msgstr "Geben Sie die Daten des neuen Zustandes ein"
msgid "Added state"
msgstr "Zustand hinzugefügt"
-#: compensation/forms/modalForms.py:190 konova/forms.py:193
+#: compensation/forms/modalForms.py:190 konova/forms.py:196
msgid "Object removed"
msgstr "Objekt entfernt"
@@ -308,12 +545,12 @@ msgstr "Maßnahmentyp wählen"
#: compensation/templates/compensation/detail/compensation/includes/documents.html:35
#: compensation/templates/compensation/detail/compensation/includes/states-after.html:40
#: compensation/templates/compensation/detail/compensation/includes/states-before.html:40
-#: compensation/templates/compensation/detail/eco_account/includes/actions.html:37
+#: compensation/templates/compensation/detail/eco_account/includes/actions.html:38
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:37
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:40
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:34
-#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:39
-#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:39
+#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:40
+#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:40
#: ema/templates/ema/detail/includes/actions.html:37
#: ema/templates/ema/detail/includes/deadlines.html:37
#: ema/templates/ema/detail/includes/documents.html:34
@@ -336,12 +573,6 @@ msgstr "Einheit"
msgid "Select the unit"
msgstr "Einheit wählen"
-#: compensation/forms/modalForms.py:351
-#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
-#: intervention/templates/intervention/detail/includes/deductions.html:31
-msgid "Amount"
-msgstr "Menge"
-
#: compensation/forms/modalForms.py:354
msgid "Insert the amount"
msgstr "Menge eingeben"
@@ -358,38 +589,38 @@ msgstr "Geben Sie die Daten der neuen Maßnahme ein"
msgid "Added action"
msgstr "Maßnahme hinzugefügt"
-#: compensation/models.py:78
+#: compensation/models.py:82
msgid "cm"
msgstr ""
-#: compensation/models.py:79
+#: compensation/models.py:83
msgid "m"
msgstr ""
-#: compensation/models.py:80
+#: compensation/models.py:84
msgid "km"
msgstr ""
-#: compensation/models.py:81
+#: compensation/models.py:85
msgid "m²"
msgstr ""
-#: compensation/models.py:82
+#: compensation/models.py:86
msgid "ha"
msgstr ""
-#: compensation/models.py:83
+#: compensation/models.py:87
msgid "Pieces"
msgstr "Stück"
-#: compensation/models.py:311
+#: compensation/models.py:329
msgid ""
"Deductable surface can not be larger than existing surfaces in after states"
msgstr ""
"Die abbuchbare Fläche darf die Gesamtfläche der Zielzustände nicht "
"überschreiten"
-#: compensation/models.py:318
+#: compensation/models.py:336
msgid ""
"Deductable surface can not be smaller than the sum of already existing "
"deductions. Please contact the responsible users for the deductions!"
@@ -397,50 +628,21 @@ msgstr ""
"Es wurde bereits mehr Fläche abgebucht, als Sie nun als abbuchbar einstellen "
"wollen. Kontaktieren Sie die für die Abbuchungen verantwortlichen Nutzer!"
-#: compensation/tables.py:35
-#: compensation/templates/compensation/detail/compensation/view.html:43
-#: intervention/tables.py:33
-#: intervention/templates/intervention/detail/view.html:68 user/models.py:48
-msgid "Checked"
-msgstr "Geprüft"
-
-#: compensation/tables.py:41 compensation/tables.py:182
-#: compensation/templates/compensation/detail/compensation/view.html:57
-#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:31
-#: compensation/templates/compensation/detail/eco_account/view.html:44
-#: ema/tables.py:38 ema/templates/ema/detail/view.html:28
-#: intervention/tables.py:39
-#: intervention/templates/intervention/detail/view.html:82 user/models.py:49
-msgid "Recorded"
-msgstr "Verzeichnet"
-
-#: compensation/tables.py:47 compensation/tables.py:188 ema/tables.py:44
+#: compensation/tables.py:47 compensation/tables.py:187 ema/tables.py:44
#: intervention/tables.py:51
msgid "Editable"
msgstr "Freigegeben"
-#: compensation/tables.py:53 compensation/tables.py:194 ema/tables.py:50
+#: compensation/tables.py:53 compensation/tables.py:193 ema/tables.py:50
#: intervention/tables.py:57
msgid "Last edit"
msgstr "Zuletzt bearbeitet"
-#: compensation/tables.py:62
-#: intervention/templates/intervention/detail/includes/compensations.html:8
-#: intervention/templates/intervention/report/report.html:49
-msgid "Compensations"
-msgstr "Kompensationen"
-
-#: compensation/tables.py:84 compensation/tables.py:225 ema/tables.py:82
+#: compensation/tables.py:84 compensation/tables.py:224 ema/tables.py:82
#: intervention/tables.py:88
msgid "Open {}"
msgstr "Öffne {}"
-#: compensation/tables.py:84
-#: compensation/templates/compensation/detail/compensation/view.html:19
-#: konova/templates/konova/home.html:49 templates/navbars/navbar.html:28
-msgid "Compensation"
-msgstr "Kompensation"
-
#: compensation/tables.py:105 intervention/tables.py:107
msgid "Not checked yet"
msgstr "Noch nicht geprüft"
@@ -451,46 +653,40 @@ msgstr "Am {} von {} geprüft worden"
#: compensation/tables.py:129
#: compensation/templates/compensation/detail/compensation/view.html:60
+#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:56
#: compensation/templates/compensation/detail/eco_account/view.html:47
#: ema/tables.py:101 ema/templates/ema/detail/view.html:31
-#: intervention/models.py:384 intervention/tables.py:131
+#: intervention/tables.py:131
#: intervention/templates/intervention/detail/view.html:85
msgid "Not recorded yet"
msgstr "Noch nicht verzeichnet"
-#: compensation/tables.py:134 compensation/tables.py:263 ema/tables.py:106
-#: intervention/models.py:389 intervention/tables.py:136
+#: compensation/tables.py:134 compensation/tables.py:262 ema/tables.py:106
+#: intervention/tables.py:136
msgid "Recorded on {} by {}"
msgstr "Am {} von {} verzeichnet worden"
-#: compensation/tables.py:159 compensation/tables.py:286 ema/tables.py:129
+#: compensation/tables.py:158 compensation/tables.py:284 ema/tables.py:129
#: intervention/tables.py:159
msgid "Full access granted"
msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden"
-#: compensation/tables.py:159 compensation/tables.py:286 ema/tables.py:129
+#: compensation/tables.py:158 compensation/tables.py:284 ema/tables.py:129
#: intervention/tables.py:159
msgid "Access not granted"
msgstr "Nicht freigegeben - Datensatz nur lesbar"
-#: compensation/tables.py:177
+#: compensation/tables.py:176
#: compensation/templates/compensation/detail/eco_account/view.html:35
#: konova/templates/konova/widgets/progressbar.html:3
msgid "Available"
msgstr "Verfügbar"
-#: compensation/tables.py:203
+#: compensation/tables.py:202
msgid "Eco Accounts"
msgstr "Ökokonten"
-#: compensation/tables.py:225
-#: compensation/templates/compensation/detail/eco_account/view.html:19
-#: intervention/forms/modalForms.py:258 intervention/forms/modalForms.py:265
-#: konova/templates/konova/home.html:88 templates/navbars/navbar.html:34
-msgid "Eco-account"
-msgstr "Ökokonto"
-
-#: compensation/tables.py:258
+#: compensation/tables.py:257
msgid "Not recorded yet. Can not be used for deductions, yet."
msgstr ""
"Noch nicht verzeichnet. Kann noch nicht für Abbuchungen genutzt werden."
@@ -522,7 +718,7 @@ msgid "Amount"
msgstr "Menge"
#: compensation/templates/compensation/detail/compensation/includes/actions.html:53
-#: compensation/templates/compensation/detail/eco_account/includes/actions.html:51
+#: compensation/templates/compensation/detail/eco_account/includes/actions.html:53
#: ema/templates/ema/detail/includes/actions.html:51
msgid "Remove action"
msgstr "Maßnahme entfernen"
@@ -575,12 +771,6 @@ msgstr "Termine und Fristen"
msgid "Add new deadline"
msgstr "Frist/Termin hinzufügen"
-#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:28
-#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:28
-#: ema/templates/ema/detail/includes/deadlines.html:28
-msgid "Type"
-msgstr "Typ"
-
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:53
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:51
#: ema/templates/ema/detail/includes/deadlines.html:51
@@ -598,7 +788,7 @@ msgstr "Dokumente"
#: compensation/templates/compensation/detail/eco_account/includes/documents.html:14
#: ema/templates/ema/detail/includes/documents.html:14
#: intervention/templates/intervention/detail/includes/documents.html:14
-#: konova/forms.py:392
+#: konova/forms.py:395
msgid "Add new document"
msgstr "Neues Dokument hinzufügen"
@@ -638,8 +828,8 @@ msgstr "Biotoptyp"
#: compensation/templates/compensation/detail/compensation/includes/states-after.html:54
#: compensation/templates/compensation/detail/compensation/includes/states-before.html:54
-#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:52
-#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:52
+#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:54
+#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:54
#: ema/templates/ema/detail/includes/states-after.html:52
#: ema/templates/ema/detail/includes/states-before.html:52
msgid "Remove state"
@@ -670,6 +860,7 @@ msgstr "Geprüft am "
#: compensation/templates/compensation/detail/compensation/view.html:50
#: compensation/templates/compensation/detail/compensation/view.html:64
+#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:54
#: compensation/templates/compensation/detail/eco_account/view.html:51
#: ema/templates/ema/detail/view.html:35
#: intervention/templates/intervention/detail/view.html:75
@@ -703,7 +894,7 @@ msgstr "Gefördert mit"
#: intervention/templates/intervention/report/report.html:57
#: intervention/templates/intervention/report/report.html:78
msgid "None"
-msgstr ""
+msgstr "-"
#: compensation/templates/compensation/detail/compensation/view.html:84
#: compensation/templates/compensation/detail/eco_account/view.html:83
@@ -755,6 +946,10 @@ msgstr "Eingriffskennung"
msgid "Created"
msgstr "Erstellt"
+#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:54
+msgid "Recorded on"
+msgstr "Verzeichnet am"
+
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:63
#: intervention/templates/intervention/detail/includes/deductions.html:58
msgid "Remove Deduction"
@@ -796,17 +991,17 @@ msgstr "Maßnahmenträger"
msgid "Report"
msgstr "Bericht"
-#: compensation/templates/compensation/report/compensation/report.html:58
-#: compensation/templates/compensation/report/eco_account/report.html:75
-#: ema/templates/ema/report/report.html:62
-#: intervention/templates/intervention/report/report.html:108
+#: compensation/templates/compensation/report/compensation/report.html:55
+#: compensation/templates/compensation/report/eco_account/report.html:72
+#: ema/templates/ema/report/report.html:59
+#: intervention/templates/intervention/report/report.html:105
msgid "Open in browser"
msgstr "Im Browser öffnen"
-#: compensation/templates/compensation/report/compensation/report.html:62
-#: compensation/templates/compensation/report/eco_account/report.html:79
-#: ema/templates/ema/report/report.html:66
-#: intervention/templates/intervention/report/report.html:112
+#: compensation/templates/compensation/report/compensation/report.html:59
+#: compensation/templates/compensation/report/eco_account/report.html:76
+#: ema/templates/ema/report/report.html:63
+#: intervention/templates/intervention/report/report.html:109
msgid "View in LANIS"
msgstr "In LANIS öffnen"
@@ -823,8 +1018,8 @@ msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet"
#: compensation/views/compensation_views.py:213
-#: compensation/views/eco_account_views.py:278 ema/views.py:175
-#: intervention/views.py:428
+#: compensation/views/eco_account_views.py:287 ema/views.py:175
+#: intervention/views.py:437
msgid "Log"
msgstr "Log"
@@ -833,23 +1028,23 @@ msgid "Compensation removed"
msgstr "Kompensation entfernt"
#: compensation/views/compensation_views.py:253
-#: compensation/views/eco_account_views.py:377 ema/views.py:328
-#: intervention/views.py:124
+#: compensation/views/eco_account_views.py:386 ema/views.py:328
+#: intervention/views.py:126
msgid "Document added"
msgstr "Dokument hinzugefügt"
#: compensation/views/compensation_views.py:309
-#: compensation/views/eco_account_views.py:321 ema/views.py:272
+#: compensation/views/eco_account_views.py:330 ema/views.py:272
msgid "State added"
msgstr "Zustand hinzugefügt"
#: compensation/views/compensation_views.py:328
-#: compensation/views/eco_account_views.py:340 ema/views.py:291
+#: compensation/views/eco_account_views.py:349 ema/views.py:291
msgid "Action added"
msgstr "Maßnahme hinzugefügt"
#: compensation/views/compensation_views.py:347
-#: compensation/views/eco_account_views.py:359 ema/views.py:310
+#: compensation/views/eco_account_views.py:368 ema/views.py:310
msgid "Deadline added"
msgstr "Frist/Termin hinzugefügt"
@@ -861,33 +1056,33 @@ msgstr "Zustand gelöscht"
msgid "Action removed"
msgstr "Maßnahme entfernt"
-#: compensation/views/eco_account_views.py:87
+#: compensation/views/eco_account_views.py:86
msgid "Eco-Account {} added"
msgstr "Ökokonto {} hinzugefügt"
-#: compensation/views/eco_account_views.py:142
+#: compensation/views/eco_account_views.py:141
msgid "Eco-Account {} edited"
msgstr "Ökokonto {} bearbeitet"
-#: compensation/views/eco_account_views.py:228
+#: compensation/views/eco_account_views.py:237
msgid "Eco-account removed"
msgstr "Ökokonto entfernt"
-#: compensation/views/eco_account_views.py:255
+#: compensation/views/eco_account_views.py:264
msgid "Deduction removed"
msgstr "Abbuchung entfernt"
-#: compensation/views/eco_account_views.py:298 ema/views.py:249
-#: intervention/views.py:468
+#: compensation/views/eco_account_views.py:307 ema/views.py:249
+#: intervention/views.py:477
msgid "{} unrecorded"
msgstr "{} entzeichnet"
-#: compensation/views/eco_account_views.py:298 ema/views.py:249
-#: intervention/views.py:468
+#: compensation/views/eco_account_views.py:307 ema/views.py:249
+#: intervention/views.py:477
msgid "{} recorded"
msgstr "{} verzeichnet"
-#: compensation/views/eco_account_views.py:434 intervention/views.py:450
+#: compensation/views/eco_account_views.py:443 intervention/views.py:459
msgid "Deduction added"
msgstr "Abbuchung hinzugefügt"
@@ -965,12 +1160,6 @@ msgstr "Bauvorhaben XY; Flur ABC"
msgid "Process type"
msgstr "Verfahrenstyp"
-#: intervention/forms/forms.py:68
-#: intervention/templates/intervention/detail/view.html:39
-#: intervention/templates/intervention/report/report.html:20
-msgid "Law"
-msgstr "Gesetz"
-
#: intervention/forms/forms.py:70
msgid "Multiple selection possible"
msgstr "Mehrfachauswahl möglich"
@@ -1051,7 +1240,7 @@ msgstr "Datum des Widerspruchs"
msgid "Document"
msgstr "Dokument"
-#: intervention/forms/modalForms.py:122 konova/forms.py:361
+#: intervention/forms/modalForms.py:122 konova/forms.py:364
msgid "Must be smaller than 15 Mb"
msgstr "Muss kleiner als 15 Mb sein"
@@ -1073,7 +1262,7 @@ msgstr "Kompensationen und Zahlungen geprüft"
msgid "Run check"
msgstr "Prüfung vornehmen"
-#: intervention/forms/modalForms.py:201 konova/forms.py:446
+#: intervention/forms/modalForms.py:201 konova/forms.py:449
msgid ""
"I, {} {}, confirm that all necessary control steps have been performed by "
"myself."
@@ -1085,13 +1274,6 @@ msgstr ""
msgid "Only recorded accounts can be selected for deductions"
msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden."
-#: intervention/forms/modalForms.py:285 intervention/forms/modalForms.py:292
-#: intervention/tables.py:88
-#: intervention/templates/intervention/detail/view.html:19
-#: konova/templates/konova/home.html:11 templates/navbars/navbar.html:22
-msgid "Intervention"
-msgstr "Eingriff"
-
#: intervention/forms/modalForms.py:287
msgid "Only shared interventions can be selected"
msgstr "Nur freigegebene Eingriffe können gewählt werden"
@@ -1120,31 +1302,31 @@ msgstr ""
"Das Ökokonto {} hat für eine Abbuchung von {} m² nicht ausreichend "
"Restfläche. Es stehen noch {} m² zur Verfügung."
-#: intervention/models.py:324
+#: intervention/models.py:326
msgid "Registration office file number missing"
msgstr "Aktenzeichen Zulassungsbehörde fehlt"
-#: intervention/models.py:327
+#: intervention/models.py:329
msgid "Conservation office file number missing"
msgstr "Aktenzeichen Naturschutzbehörde fehlt"
-#: intervention/models.py:330
+#: intervention/models.py:332
msgid "Responsible data missing"
msgstr "Daten zu Verantwortlichen fehlen"
-#: intervention/models.py:344
+#: intervention/models.py:346
msgid "Revocation exists"
msgstr "Widerspruch liegt vor"
-#: intervention/models.py:347
+#: intervention/models.py:349
msgid "Registration date missing"
msgstr "Datum Zulassung bzw. Satzungsbeschluss fehlt"
-#: intervention/models.py:350
+#: intervention/models.py:352
msgid "Binding on missing"
msgstr "Datum Bestandskraft fehlt"
-#: intervention/models.py:352
+#: intervention/models.py:354
msgid "Legal data missing"
msgstr "Rechtliche Daten fehlen"
@@ -1155,10 +1337,6 @@ msgstr "Rechtliche Daten fehlen"
msgid "Revocation"
msgstr "Widerspruch"
-#: intervention/tables.py:66
-msgid "Interventions"
-msgstr "Eingriffe"
-
#: intervention/tables.py:176
msgid "No revocation"
msgstr "Kein Widerspruch"
@@ -1226,15 +1404,15 @@ msgstr "Abbuchungen von Ökokonten"
msgid "Exist"
msgstr "Vorhanden"
-#: intervention/views.py:77
+#: intervention/views.py:79
msgid "Intervention {} added"
msgstr "Eingriff {} hinzugefügt"
-#: intervention/views.py:212
+#: intervention/views.py:221
msgid "This intervention has a revocation from {}"
msgstr "Es existiert ein Widerspruch vom {}"
-#: intervention/views.py:228
+#: intervention/views.py:237
msgid ""
"Remember: This data has not been shared with you, yet. This means you can "
"only read but can not edit or perform any actions like running a check or "
@@ -1244,43 +1422,43 @@ msgstr ""
"bedeutet, dass Sie nur lesenden Zugriff hierauf haben und weder bearbeiten, "
"noch Prüfungen durchführen oder verzeichnen können."
-#: intervention/views.py:255
+#: intervention/views.py:264
msgid "Intervention {} edited"
msgstr "Eingriff {} bearbeitet"
-#: intervention/views.py:287
+#: intervention/views.py:296
msgid "{} removed"
msgstr "{} entfernt"
-#: intervention/views.py:308
+#: intervention/views.py:317
msgid "Revocation removed"
msgstr "Widerspruch entfernt"
-#: intervention/views.py:334
+#: intervention/views.py:343
msgid "{} has already been shared with you"
msgstr "{} wurde bereits für Sie freigegeben"
-#: intervention/views.py:339
+#: intervention/views.py:348
msgid "{} has been shared with you"
msgstr "{} ist nun für Sie freigegeben"
-#: intervention/views.py:346
+#: intervention/views.py:355
msgid "Share link invalid"
msgstr "Freigabelink ungültig"
-#: intervention/views.py:367
+#: intervention/views.py:376
msgid "Share settings updated"
msgstr "Freigabe Einstellungen aktualisiert"
-#: intervention/views.py:386
+#: intervention/views.py:395
msgid "Check performed"
msgstr "Prüfung durchgeführt"
-#: intervention/views.py:406
+#: intervention/views.py:415
msgid "Revocation added"
msgstr "Widerspruch hinzugefügt"
-#: intervention/views.py:473
+#: intervention/views.py:482
msgid "There are errors on this intervention:"
msgstr "Es liegen Fehler in diesem Eingriff vor:"
@@ -1301,64 +1479,68 @@ msgstr ""
"somit nichts eingeben, bearbeiten oder sonstige Aktionen ausführen. "
"Kontaktieren Sie bitte einen Administrator. +++"
-#: konova/forms.py:69
+#: konova/forms.py:40 templates/form/collapsable/form.html:62
+msgid "Save"
+msgstr "Speichern"
+
+#: konova/forms.py:71
msgid "Not editable"
msgstr "Nicht editierbar"
-#: konova/forms.py:139 konova/forms.py:309
+#: konova/forms.py:141 konova/forms.py:312
msgid "Confirm"
msgstr "Bestätige"
-#: konova/forms.py:151 konova/forms.py:318
+#: konova/forms.py:153 konova/forms.py:321
msgid "Remove"
msgstr "Löschen"
-#: konova/forms.py:153
+#: konova/forms.py:155
msgid "You are about to remove {} {}"
msgstr "Sie sind dabei {} {} zu löschen"
-#: konova/forms.py:243 templates/form/collapsable/form.html:45
+#: konova/forms.py:246 templates/form/collapsable/form.html:45
msgid "Geometry"
msgstr "Geometrie"
-#: konova/forms.py:319
+#: konova/forms.py:322
msgid "Are you sure?"
msgstr "Sind Sie sicher?"
-#: konova/forms.py:346
+#: konova/forms.py:349
msgid "Created on"
msgstr "Erstellt"
-#: konova/forms.py:348
+#: konova/forms.py:351
msgid "When has this file been created? Important for photos."
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
-#: konova/forms.py:359
+#: konova/forms.py:362
#: venv/lib/python3.7/site-packages/django/db/models/fields/files.py:231
msgid "File"
msgstr "Datei"
-#: konova/forms.py:423
+#: konova/forms.py:426
msgid "Added document"
msgstr "Dokument hinzugefügt"
-#: konova/forms.py:437
+#: konova/forms.py:440
msgid "Confirm record"
msgstr "Verzeichnen bestätigen"
-#: konova/forms.py:445
+#: konova/forms.py:448
msgid "Record data"
msgstr "Daten verzeichnen"
-#: konova/forms.py:452
+#: konova/forms.py:455
msgid "Confirm unrecord"
msgstr "Entzeichnen bestätigen"
-#: konova/forms.py:453
+#: konova/forms.py:456
msgid "Unrecord data"
msgstr "Daten entzeichnen"
-#: konova/forms.py:454
+#: konova/forms.py:457
msgid "I, {} {}, confirm that this data must be unrecorded."
msgstr ""
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
@@ -1403,10 +1585,13 @@ msgstr "Kontrolle am"
msgid "Other"
msgstr "Sonstige"
-#: konova/templates/konova/home.html:23 konova/templates/konova/home.html:61
-#: konova/templates/konova/home.html:100
-msgid "Total"
-msgstr "Insgesamt"
+#: konova/sub_settings/django_settings.py:154
+msgid "German"
+msgstr ""
+
+#: konova/sub_settings/django_settings.py:155
+msgid "English"
+msgstr ""
#: konova/templates/konova/home.html:27 konova/templates/konova/home.html:65
#: konova/templates/konova/home.html:104
@@ -1448,10 +1633,14 @@ msgid "There was an error on this form."
msgstr "Es gab einen Fehler im Formular."
#: konova/utils/message_templates.py:12
+msgid "Invalid parameters"
+msgstr "Parameter ungültig"
+
+#: konova/utils/message_templates.py:13
msgid "There are errors in this intervention."
msgstr "Es liegen Fehler in diesem Eingriff vor:"
-#: konova/utils/message_templates.py:13
+#: konova/utils/message_templates.py:14
msgid ""
"The identifier '{}' had to be changed to '{}' since another entry has been "
"added in the meanwhile, which uses this identifier"
@@ -1459,11 +1648,11 @@ msgstr ""
"Die Kennung '{}' musste zu '{}' geändert werden, da ein anderer Eintrag in "
"der Zwischenzeit angelegt wurde, welcher diese Kennung nun bereits verwendet"
-#: konova/utils/message_templates.py:14
+#: konova/utils/message_templates.py:15
msgid "This data is not shared with you"
msgstr "Diese Daten sind für Sie nicht freigegeben"
-#: konova/utils/message_templates.py:15
+#: konova/utils/message_templates.py:16
msgid "You need to be part of another user group."
msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!"
@@ -1549,15 +1738,10 @@ msgid "General data"
msgstr "Allgemeine Daten"
#: templates/form/collapsable/form.html:58
-#: templates/form/table/generic_table_form.html:23
+#: templates/form/table/generic_table_form.html:24
msgid "Cancel"
msgstr "Abbrechen"
-#: templates/form/collapsable/form.html:62
-#: templates/form/table/generic_table_form.html:27
-msgid "Save"
-msgstr "Speichern"
-
#: templates/form/table/generic_table_form_body.html:24
msgid "Fields with * are required."
msgstr "* sind Pflichtfelder."
@@ -1606,10 +1790,6 @@ msgstr "Nutzer"
msgid "No geometry added, yet."
msgstr "Keine Geometrie vorhanden"
-#: templates/modal/modal_form.html:25
-msgid "Continue"
-msgstr "Weiter"
-
#: templates/navbars/navbar.html:4
msgid "Kompensationsverzeichnis Service Portal"
msgstr ""
@@ -2935,6 +3115,21 @@ msgstr ""
msgid "A fontawesome icon field"
msgstr ""
+#~ msgid "After"
+#~ msgstr "Nach"
+
+#~ msgid "Total interventions"
+#~ msgstr "Insgesamt"
+
+#~ msgid "Amount total"
+#~ msgstr "Anzahl insgesamt"
+
+#~ msgid "Amount checked"
+#~ msgstr "Anzahl geprüft"
+
+#~ msgid "Amount recorded"
+#~ msgstr "Anzahl verzeichnet"
+
#~ msgid "Funding by..."
#~ msgstr "Gefördert mit..."
@@ -2980,9 +3175,6 @@ msgstr ""
#~ msgid "Transfer comment"
#~ msgstr "Verwendungszweck"
-#~ msgid "EMA recorded"
-#~ msgstr "EMA verzeichnet"
-
#~ msgid "Edit {}"
#~ msgstr "Bearbeite {}"
@@ -3059,9 +3251,6 @@ msgstr ""
#~ msgid "Role changed"
#~ msgstr "Rolle geändert"
-#~ msgid "Invalid role"
-#~ msgstr "Rolle ungültig"
-
#~ msgid "Official"
#~ msgstr "Amtlich"
diff --git a/requirements.txt b/requirements.txt
index 360af590..ac893917 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -11,11 +11,14 @@ django-filter==2.4.0
django-fontawesome-5==1.0.18
django-simple-sso==1.1.0
django-tables2==2.3.4
+et-xmlfile==1.1.0
idna==2.10
importlib-metadata==2.1.1
-itsdangerous
-psycopg2-binary
+itsdangerous==0.24
+openpyxl==3.0.9
+psycopg2-binary==2.9.1
pytz==2020.4
+qrcode==7.3.1
requests==2.25.0
six==1.15.0
soupsieve==2.2.1
diff --git a/templates/form/table/generic_table_form.html b/templates/form/table/generic_table_form.html
index 7d321436..a89ee4bf 100644
--- a/templates/form/table/generic_table_form.html
+++ b/templates/form/table/generic_table_form.html
@@ -19,12 +19,14 @@
{% include 'form/table/generic_table_form_body.html' %}
- {% trans 'Save' %}
+ {{form.action_btn_label}}
diff --git a/templates/modal/modal_form.html b/templates/modal/modal_form.html
index eda17303..6f47b127 100644
--- a/templates/modal/modal_form.html
+++ b/templates/modal/modal_form.html
@@ -22,7 +22,7 @@
{% if form.render_submit %}
{% endif %}
\ No newline at end of file
diff --git a/templates/navbars/navbar.html b/templates/navbars/navbar.html
index 39b622e1..46a274ff 100644
--- a/templates/navbars/navbar.html
+++ b/templates/navbars/navbar.html
@@ -43,7 +43,7 @@
{% fa5_icon 'euro-sign' %} {% trans 'EMA' %}
{% fa5_icon 'file-import' %} {% trans 'Import...' %}
{% fa5_icon 'file-export' %} {% trans 'Export...' %}
- {% fa5_icon 'file-alt' %} {% trans 'Reports' %}
+ {% fa5_icon 'file-alt' %} {% trans 'Reports' %}