#26 Annual conservation reports

* adds index form for selecting timespan and office of interest
* adds timespan support for TimespanReport
* fixes naive datetime issues
* fixes missing error message css tag
* adds/updates translations
This commit is contained in:
mpeltriaux 2021-10-20 13:23:35 +02:00
parent 5907d46ab2
commit c45198e825
13 changed files with 247 additions and 91 deletions

80
analysis/forms.py Normal file
View File

@ -0,0 +1,80 @@
"""
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")
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

View File

@ -6,7 +6,7 @@ Created on: 19.10.21
""" """
import datetime
# Defines the date of the legal publishing of the LKompVzVo # Defines the date of the legal publishing of the LKompVzVo
LKOMPVZVO_PUBLISH_DATE = datetime.date.fromisoformat("2018-06-16") from django.utils import timezone
LKOMPVZVO_PUBLISH_DATE = timezone.make_aware(timezone.datetime.fromisoformat("2018-06-16"))

View File

@ -4,10 +4,11 @@
{% block body %} {% block body %}
<div class="row"> <div class="row">
<div class="col-sm-12 col-md-12 col-lg-12"> <div class="col-sm-12 col-md-12 col-lg-12">
<h3>{% trans 'Report' %}</h3> <h3>{% trans 'Evaluation report' %} {{office.long_name}}</h3>
<h5>{{office.long_name}}</h5> <h5>{% trans 'From' %} {{report.date_from.date}} {% trans 'to' %} {{report.date_to.date}}</h5>
</div> </div>
</div> </div>
<hr>
<div class="col-sm-12 col-md-12 col-lg-12"> <div class="col-sm-12 col-md-12 col-lg-12">
{% include 'analysis/reports/includes/intervention/card_intervention.html' %} {% include 'analysis/reports/includes/intervention/card_intervention.html' %}
{% include 'analysis/reports/includes/compensation/card_compensation.html' %} {% include 'analysis/reports/includes/compensation/card_compensation.html' %}

View File

@ -3,6 +3,8 @@
{% block body %} {% block body %}
<div class="row"> <div class="row">
<h3>{% trans 'Reports' %}</h3> <div class="col-sm-12 col-md-12 col-lg-12">
{% include 'form/table/generic_table_form.html' %}
</div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -7,7 +7,6 @@ Created on: 18.10.21
""" """
from django.contrib.gis.db.models import MultiPolygonField from django.contrib.gis.db.models import MultiPolygonField
from django.contrib.gis.db.models.functions import NumGeometries from django.contrib.gis.db.models.functions import NumGeometries
from django.contrib.gis.measure import Area
from django.db.models import Count, Sum, Q from django.db.models import Count, Sum, Q
from django.db.models.functions import Cast from django.db.models.functions import Cast
@ -20,14 +19,18 @@ from konova.models import Geometry
class TimespanReport: class TimespanReport:
""" Holds multiple report elements for a timespan report
"""
office_id = -1 office_id = -1
date_from = -1
date_to = -1
class InterventionReport: class InterventionReport:
queryset = Intervention.objects.none() queryset = Intervention.objects.none()
queryset_checked = Intervention.objects.none() queryset_checked = Intervention.objects.none()
queryset_recorded = Intervention.objects.none() queryset_recorded = Intervention.objects.none()
# Law related # Law related
law_sum = -1 law_sum = -1
law_sum_checked = -1 law_sum_checked = -1
@ -45,11 +48,13 @@ class TimespanReport:
deduction_sum_checked = -1 deduction_sum_checked = -1
deduction_sum_recorded = -1 deduction_sum_recorded = -1
def __init__(self, id: str): def __init__(self, id: str, date_from: str, date_to: str):
self.queryset = Intervention.objects.filter( self.queryset = Intervention.objects.filter(
responsible__conservation_office__id=id, responsible__conservation_office__id=id,
legal__registration_date__gt=LKOMPVZVO_PUBLISH_DATE, legal__registration_date__gt=LKOMPVZVO_PUBLISH_DATE,
deleted=None, deleted=None,
created__timestamp__gte=date_from,
created__timestamp__lte=date_to,
) )
self.queryset_checked = self.queryset.filter( self.queryset_checked = self.queryset.filter(
checked__isnull=False checked__isnull=False
@ -160,11 +165,13 @@ class TimespanReport:
# Code list id for 'obere Naturschutzbehörde' # Code list id for 'obere Naturschutzbehörde'
id_onb = 1943084 id_onb = 1943084
def __init__(self, id: str): def __init__(self, id: str, date_from: str, date_to: str):
self.queryset = Compensation.objects.filter( self.queryset = Compensation.objects.filter(
intervention__responsible__conservation_office__id=id, intervention__responsible__conservation_office__id=id,
intervention__legal__registration_date__gt=LKOMPVZVO_PUBLISH_DATE, intervention__legal__registration_date__gt=LKOMPVZVO_PUBLISH_DATE,
deleted=None, deleted=None,
intervention__created__timestamp__gte=date_from,
intervention__created__timestamp__lte=date_to,
) )
self.queryset_checked = self.queryset.filter( self.queryset_checked = self.queryset.filter(
intervention__checked__isnull=False intervention__checked__isnull=False
@ -282,11 +289,13 @@ class TimespanReport:
deductions_sq_m = -1 deductions_sq_m = -1
recorded_deductions_sq_m = -1 recorded_deductions_sq_m = -1
def __init__(self, id: str): def __init__(self, id: str, date_from: str, date_to: str):
# First fetch all eco account for this office # First fetch all eco account for this office
self.queryset_total = EcoAccount.objects.filter( self.queryset_total = EcoAccount.objects.filter(
responsible__conservation_office__id=id, responsible__conservation_office__id=id,
deleted=None, deleted=None,
created__timestamp__gte=date_from,
created__timestamp__lte=date_to,
) )
self.queryset_recorded = self.queryset_total.filter( self.queryset_recorded = self.queryset_total.filter(
recorded__isnull=False recorded__isnull=False
@ -320,21 +329,23 @@ class TimespanReport:
def _evaluate_deductions(self): def _evaluate_deductions(self):
self.deductions_sq_m = self.queryset_deductions.aggregate( self.deductions_sq_m = self.queryset_deductions.aggregate(
sum=Sum("surface") sum=Sum("surface")
)["sum"] )["sum"] or 0
self.recorded_deductions_sq_m = self.queryset_deductions_recorded.aggregate( self.recorded_deductions_sq_m = self.queryset_deductions_recorded.aggregate(
sum=Sum("surface") sum=Sum("surface")
)["sum"] )["sum"] or 0
class OldInterventionReport: class OldInterventionReport:
queryset = Compensation.objects.none() queryset = Compensation.objects.none()
queryset_checked = Compensation.objects.none() queryset_checked = Compensation.objects.none()
queryset_recorded = Compensation.objects.none() queryset_recorded = Compensation.objects.none()
def __init__(self, id: str): def __init__(self, id: str, date_from: str, date_to: str):
self.queryset = Intervention.objects.filter( self.queryset = Intervention.objects.filter(
legal__registration_date__lte=LKOMPVZVO_PUBLISH_DATE, legal__registration_date__lte=LKOMPVZVO_PUBLISH_DATE,
responsible__conservation_office__id=id, responsible__conservation_office__id=id,
deleted=None, deleted=None,
created__timestamp__gte=date_from,
created__timestamp__lte=date_to,
) )
self.queryset_checked = self.queryset.filter( self.queryset_checked = self.queryset.filter(
checked__isnull=False checked__isnull=False
@ -343,9 +354,12 @@ class TimespanReport:
recorded__isnull=False recorded__isnull=False
) )
def __init__(self, office_id: str): def __init__(self, office_id: str, date_from: str, date_to: str):
self.office_id = office_id self.office_id = office_id
self.intervention_report = self.InterventionReport(self.office_id) self.date_from = date_from
self.compensation_report = self.CompensationReport(self.office_id) self.date_to = date_to
self.eco_account_report = self.EcoAccountReport(self.office_id)
self.old_intervention_report = self.OldInterventionReport(self.office_id) 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_intervention_report = self.OldInterventionReport(self.office_id, date_from, date_to)

View File

@ -1,11 +1,16 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpRequest from django.http import HttpRequest
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, redirect
from django.utils import timezone
from analysis.forms import TimespanReportForm
from analysis.utils.report import TimespanReport from analysis.utils.report import TimespanReport
from codelist.models import KonovaCode from codelist.models import KonovaCode
from konova.contexts import BaseContext from konova.contexts import BaseContext
from konova.decorators import conservation_office_group_required from konova.decorators import conservation_office_group_required
from konova.utils.message_templates import FORM_INVALID, PARAMS_INVALID
@login_required @login_required
@ -20,11 +25,26 @@ def index_reports_view(request: HttpRequest):
""" """
template = "analysis/reports/index.html" template = "analysis/reports/index.html"
context = {} 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 context = BaseContext(request, context).context
return render(request, template, context) return render(request, template, context)
@login_required
@conservation_office_group_required
def detail_report_view(request: HttpRequest, id: str): def detail_report_view(request: HttpRequest, id: str):
""" Renders the detailed report for a conservation office """ Renders the detailed report for a conservation office
@ -35,12 +55,27 @@ def detail_report_view(request: HttpRequest, id: str):
Returns: Returns:
""" """
cons_office = get_object_or_404( try:
KonovaCode, cons_office = KonovaCode.objects.get(id=id)
id=id, except (ObjectDoesNotExist, ValueError) as e:
messages.error(
request,
PARAMS_INVALID,
extra_tags="danger",
) )
report = TimespanReport(id) return redirect("analysis:reports")
try:
date_from = timezone.make_aware(timezone.datetime.fromisoformat(request.GET.get("df", None)))
date_to = timezone.make_aware(timezone.datetime.fromisoformat(request.GET.get("dt", None)))
except ValueError:
messages.error(
request,
PARAMS_INVALID,
extra_tags="danger",
)
return redirect("analysis:reports")
report = TimespanReport(id, date_from, date_to)
template = "analysis/reports/detail.html" template = "analysis/reports/detail.html"
context = { context = {
"office": cons_office, "office": cons_office,

View File

@ -77,7 +77,7 @@ def new_view(request: HttpRequest, intervention_id: str = None):
messages.success(request, _("Compensation {} added").format(comp.identifier)) messages.success(request, _("Compensation {} added").format(comp.identifier))
return redirect("compensation:detail", id=comp.id) return redirect("compensation:detail", id=comp.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass
@ -132,7 +132,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("Compensation {} edited").format(comp.identifier)) messages.success(request, _("Compensation {} edited").format(comp.identifier))
return redirect("compensation:detail", id=comp.id) return redirect("compensation:detail", id=comp.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass

View File

@ -86,7 +86,7 @@ def new_view(request: HttpRequest):
messages.success(request, _("Eco-Account {} added").format(acc.identifier)) messages.success(request, _("Eco-Account {} added").format(acc.identifier))
return redirect("compensation:acc-detail", id=acc.id) return redirect("compensation:acc-detail", id=acc.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass
@ -141,7 +141,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("Eco-Account {} edited").format(acc.identifier)) messages.success(request, _("Eco-Account {} edited").format(acc.identifier))
return redirect("compensation:acc-detail", id=acc.id) return redirect("compensation:acc-detail", id=acc.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass

View File

@ -78,7 +78,7 @@ def new_view(request: HttpRequest):
messages.success(request, _("EMA {} added").format(ema.identifier)) messages.success(request, _("EMA {} added").format(ema.identifier))
return redirect("ema:detail", id=ema.id) return redirect("ema:detail", id=ema.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass
@ -202,7 +202,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("EMA {} edited").format(ema.identifier)) messages.success(request, _("EMA {} edited").format(ema.identifier))
return redirect("ema:detail", id=ema.id) return redirect("ema:detail", id=ema.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass

View File

@ -79,7 +79,7 @@ def new_view(request: HttpRequest):
messages.success(request, _("Intervention {} added").format(intervention.identifier)) messages.success(request, _("Intervention {} added").format(intervention.identifier))
return redirect("intervention:detail", id=intervention.id) return redirect("intervention:detail", id=intervention.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass
@ -264,7 +264,7 @@ def edit_view(request: HttpRequest, id: str):
messages.success(request, _("Intervention {} edited").format(intervention.identifier)) messages.success(request, _("Intervention {} edited").format(intervention.identifier))
return redirect("intervention:detail", id=intervention.id) return redirect("intervention:detail", id=intervention.id)
else: else:
messages.error(request, FORM_INVALID) messages.error(request, FORM_INVALID, extra_tags="danger",)
else: else:
# For clarification: nothing in this case # For clarification: nothing in this case
pass pass

View File

@ -9,6 +9,7 @@ from django.utils.translation import gettext_lazy as _
FORM_INVALID = _("There was an error on this form.") FORM_INVALID = _("There was an error on this form.")
PARAMS_INVALID = _("Invalid parameters")
INTERVENTION_INVALID = _("There are errors in this intervention.") 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") 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") DATA_UNSHARED = _("This data is not shared with you")

Binary file not shown.

View File

@ -19,7 +19,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-10-19 16:04+0200\n" "POT-Creation-Date: 2021-10-20 13:19+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -29,13 +29,50 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: analysis/forms.py:26 analysis/templates/analysis/reports/detail.html:8
msgid "From"
msgstr "Vom"
#: analysis/forms.py:38
msgid "To"
msgstr "Bis"
#: analysis/forms.py:49 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"
#: analysis/forms.py:51 compensation/forms/forms.py:95
msgid "Select the responsible office"
msgstr "Verantwortliche Stelle"
#: analysis/forms.py:60 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..."
#: analysis/forms.py:67
msgid "Generate report"
msgstr "Bericht generieren"
#: analysis/forms.py:68
msgid "Select a timespan and the desired conservation office"
msgstr "Wählen Sie die Zeitspanne und die gewünschte Eintragungsstelle"
#: analysis/templates/analysis/reports/detail.html:7 #: analysis/templates/analysis/reports/detail.html:7
#: compensation/templates/compensation/report/compensation/report.html:7 msgid "Evaluation report"
#: compensation/templates/compensation/report/eco_account/report.html:7 msgstr "Auswertungsbericht"
#: ema/templates/ema/report/report.html:7
#: intervention/templates/intervention/report/report.html:7 #: analysis/templates/analysis/reports/detail.html:8
msgid "Report" msgid "to"
msgstr "Bericht" msgstr "bis"
#: analysis/templates/analysis/reports/includes/compensation/amount.html:3 #: analysis/templates/analysis/reports/includes/compensation/amount.html:3
#: analysis/templates/analysis/reports/includes/eco_account/amount.html:3 #: analysis/templates/analysis/reports/includes/eco_account/amount.html:3
@ -232,11 +269,6 @@ msgstr "Gesetz"
msgid "Old interventions" msgid "Old interventions"
msgstr "Altfälle" msgstr "Altfälle"
#: analysis/templates/analysis/reports/index.html:6
#: templates/navbars/navbar.html:46
msgid "Reports"
msgstr "Berichte"
#: compensation/filters.py:70 #: compensation/filters.py:70
msgid "Show only unrecorded" msgid "Show only unrecorded"
msgstr "Nur unverzeichnete anzeigen" msgstr "Nur unverzeichnete anzeigen"
@ -288,13 +320,6 @@ msgstr "Förderungen"
msgid "Select fundings for this compensation" msgid "Select fundings for this compensation"
msgstr "Wählen Sie ggf. Fördermittelprojekte" 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:73 compensation/forms/modalForms.py:61
#: compensation/forms/modalForms.py:272 compensation/forms/modalForms.py:367 #: 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/actions.html:34
@ -318,20 +343,6 @@ msgstr "Kommentar"
msgid "Additional comment" msgid "Additional comment"
msgstr "Zusätzlicher Kommentar" 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:109
#: compensation/templates/compensation/detail/eco_account/view.html:62 #: compensation/templates/compensation/detail/eco_account/view.html:62
#: compensation/templates/compensation/report/eco_account/report.html:20 #: compensation/templates/compensation/report/eco_account/report.html:20
@ -376,23 +387,23 @@ msgstr "Neue Kompensation"
msgid "Edit compensation" msgid "Edit compensation"
msgstr "Bearbeite Kompensation" msgstr "Bearbeite Kompensation"
#: compensation/forms/forms.py:299 #: compensation/forms/forms.py:290
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
msgid "Available Surface" msgid "Available Surface"
msgstr "Verfügbare Fläche" msgstr "Verfügbare Fläche"
#: compensation/forms/forms.py:363 #: compensation/forms/forms.py:293
msgid "The amount that can be used for deductions" msgid "The amount that can be used for deductions"
msgstr "Die für Abbuchungen zur Verfügung stehende Menge" msgstr "Die für Abbuchungen zur Verfügung stehende Menge"
#: compensation/forms/forms.py:384 #: compensation/forms/forms.py:315
msgid "New Eco-Account"
msgstr "Neues Ökokonto"
#: compensation/forms/forms.py:324
msgid "Eco-Account XY; Location ABC"
msgstr "Ökokonto XY; Flur ABC"
#: compensation/forms/forms.py:377
msgid "Edit Eco-Account" msgid "Edit Eco-Account"
msgstr "Ökokonto bearbeiten" msgstr "Ökokonto bearbeiten"
@ -953,6 +964,13 @@ msgstr "Fehlt"
msgid "Action handler" msgid "Action handler"
msgstr "Maßnahmenträger" msgstr "Maßnahmenträger"
#: compensation/templates/compensation/report/compensation/report.html:7
#: compensation/templates/compensation/report/eco_account/report.html:7
#: ema/templates/ema/report/report.html:7
#: intervention/templates/intervention/report/report.html:7
msgid "Report"
msgstr "Bericht"
#: compensation/templates/compensation/report/compensation/report.html:55 #: compensation/templates/compensation/report/compensation/report.html:55
#: compensation/templates/compensation/report/eco_account/report.html:72 #: compensation/templates/compensation/report/eco_account/report.html:72
#: ema/templates/ema/report/report.html:59 #: ema/templates/ema/report/report.html:59
@ -1271,31 +1289,31 @@ msgstr ""
"Das Ökokonto {} hat für eine Abbuchung von {} m² nicht ausreichend " "Das Ökokonto {} hat für eine Abbuchung von {} m² nicht ausreichend "
"Restfläche. Es stehen noch {} m² zur Verfügung." "Restfläche. Es stehen noch {} m² zur Verfügung."
#: intervention/models.py:329 #: intervention/models.py:326
msgid "Registration office file number missing" msgid "Registration office file number missing"
msgstr "Aktenzeichen Zulassungsbehörde fehlt" msgstr "Aktenzeichen Zulassungsbehörde fehlt"
#: intervention/models.py:332 #: intervention/models.py:329
msgid "Conservation office file number missing" msgid "Conservation office file number missing"
msgstr "Aktenzeichen Naturschutzbehörde fehlt" msgstr "Aktenzeichen Naturschutzbehörde fehlt"
#: intervention/models.py:335 #: intervention/models.py:332
msgid "Responsible data missing" msgid "Responsible data missing"
msgstr "Daten zu Verantwortlichen fehlen" msgstr "Daten zu Verantwortlichen fehlen"
#: intervention/models.py:349 #: intervention/models.py:346
msgid "Revocation exists" msgid "Revocation exists"
msgstr "Widerspruch liegt vor" msgstr "Widerspruch liegt vor"
#: intervention/models.py:352 #: intervention/models.py:349
msgid "Registration date missing" msgid "Registration date missing"
msgstr "Datum Zulassung bzw. Satzungsbeschluss fehlt" msgstr "Datum Zulassung bzw. Satzungsbeschluss fehlt"
#: intervention/models.py:355 #: intervention/models.py:352
msgid "Binding on missing" msgid "Binding on missing"
msgstr "Datum Bestandskraft fehlt" msgstr "Datum Bestandskraft fehlt"
#: intervention/models.py:357 #: intervention/models.py:354
msgid "Legal data missing" msgid "Legal data missing"
msgstr "Rechtliche Daten fehlen" msgstr "Rechtliche Daten fehlen"
@ -1598,10 +1616,14 @@ msgid "There was an error on this form."
msgstr "Es gab einen Fehler im Formular." msgstr "Es gab einen Fehler im Formular."
#: konova/utils/message_templates.py:12 #: 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." msgid "There are errors in this intervention."
msgstr "Es liegen Fehler in diesem Eingriff vor:" msgstr "Es liegen Fehler in diesem Eingriff vor:"
#: konova/utils/message_templates.py:13 #: konova/utils/message_templates.py:14
msgid "" msgid ""
"The identifier '{}' had to be changed to '{}' since another entry has been " "The identifier '{}' had to be changed to '{}' since another entry has been "
"added in the meanwhile, which uses this identifier" "added in the meanwhile, which uses this identifier"
@ -1609,11 +1631,11 @@ msgstr ""
"Die Kennung '{}' musste zu '{}' geändert werden, da ein anderer Eintrag in " "Die Kennung '{}' musste zu '{}' geändert werden, da ein anderer Eintrag in "
"der Zwischenzeit angelegt wurde, welcher diese Kennung nun bereits verwendet" "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" msgid "This data is not shared with you"
msgstr "Diese Daten sind für Sie nicht freigegeben" 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." msgid "You need to be part of another user group."
msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!" msgstr "Hierfür müssen Sie einer anderen Nutzergruppe angehören!"
@ -1784,6 +1806,10 @@ msgstr ""
msgid "Export..." msgid "Export..."
msgstr "" msgstr ""
#: templates/navbars/navbar.html:46
msgid "Reports"
msgstr "Berichte"
#: templates/navbars/navbar.html:58 user/templates/user/index.html:31 #: templates/navbars/navbar.html:58 user/templates/user/index.html:31
msgid "Settings" msgid "Settings"
msgstr "Einstellungen" msgstr "Einstellungen"
@ -3214,9 +3240,6 @@ msgstr ""
#~ msgid "Role changed" #~ msgid "Role changed"
#~ msgstr "Rolle geändert" #~ msgstr "Rolle geändert"
#~ msgid "Invalid role"
#~ msgstr "Rolle ungültig"
#~ msgid "Official" #~ msgid "Official"
#~ msgstr "Amtlich" #~ msgstr "Amtlich"