# Remove view

* refactors remove view methods into classes
* introduced AbstractRemoveView
* disables final-delete actions from admin views
* extends error warnings on RemoveEcoAccountModalForm
* removes LoginRequiredMixin from AbstractPublicReportView to make it accessible for the public
* updates translations
This commit is contained in:
mpeltriaux 2025-12-14 17:37:01 +01:00
parent a2bda8d230
commit 1af807deae
19 changed files with 235 additions and 176 deletions

View File

@ -45,6 +45,14 @@ class AbstractCompensationAdmin(BaseObjectAdmin):
states = "\n".join(states)
return states
def get_actions(self, request):
DELETE_ACTION_IDENTIFIER = "delete_selected"
actions = super().get_actions(request)
if DELETE_ACTION_IDENTIFIER in actions:
del actions[DELETE_ACTION_IDENTIFIER]
return actions
class CompensationAdmin(AbstractCompensationAdmin):
autocomplete_fields = [

View File

@ -15,6 +15,7 @@ from compensation.models import EcoAccount
from intervention.models import Handler, Responsibility, Legal
from konova.forms import SimpleGeomForm
from konova.forms.modals import RemoveModalForm
from konova.settings import ETS_GROUP
from konova.utils import validators
from user.models import User, UserActionLogEntry
@ -246,4 +247,13 @@ class RemoveEcoAccountModalForm(RemoveModalForm):
"confirm",
_("The account can not be removed, since there are still deductions.")
)
# If there are deductions but the performing user is not part of an ETS group, we assume this poor
# fella does not know what he/she does -> give a hint that they should contact someone in charge...
user_is_ets_user = self.user.in_group(ETS_GROUP)
if not user_is_ets_user:
self.add_error(
"confirm",
_("Please contact the responsible conservation office to find a solution!")
)
return super_valid and not has_deductions

View File

@ -10,6 +10,7 @@ from django.urls import path
from compensation.views.compensation.detail import DetailCompensationView
from compensation.views.compensation.document import EditCompensationDocumentView, NewCompensationDocumentView, \
GetCompensationDocumentView, RemoveCompensationDocumentView
from compensation.views.compensation.remove import RemoveCompensationView
from compensation.views.compensation.resubmission import CompensationResubmissionView
from compensation.views.compensation.report import CompensationPublicReportView
from compensation.views.compensation.deadline import NewCompensationDeadlineView, EditCompensationDeadlineView, \
@ -19,7 +20,7 @@ from compensation.views.compensation.action import NewCompensationActionView, Ed
from compensation.views.compensation.state import NewCompensationStateView, EditCompensationStateView, \
RemoveCompensationStateView
from compensation.views.compensation.compensation import new_view, edit_view, \
remove_view, IndexCompensationView, CompensationIdentifierGeneratorView
IndexCompensationView, CompensationIdentifierGeneratorView
from compensation.views.compensation.log import CompensationLogView
urlpatterns = [
@ -31,7 +32,7 @@ urlpatterns = [
path('<id>', DetailCompensationView.as_view(), name='detail'),
path('<id>/log', CompensationLogView.as_view(), name='log'),
path('<id>/edit', edit_view, name='edit'),
path('<id>/remove', remove_view, name='remove'),
path('<id>/remove', RemoveCompensationView.as_view(), name='remove'),
path('<id>/state/new', NewCompensationStateView.as_view(), name='new-state'),
path('<id>/state/<state_id>/edit', EditCompensationStateView.as_view(), name='state-edit'),

View File

@ -9,10 +9,11 @@ from django.urls import path
from compensation.autocomplete.eco_account import EcoAccountAutocomplete
from compensation.views.eco_account.detail import DetailEcoAccountView
from compensation.views.eco_account.eco_account import new_view, edit_view, remove_view, \
from compensation.views.eco_account.eco_account import new_view, edit_view, \
IndexEcoAccountView, EcoAccountIdentifierGeneratorView
from compensation.views.eco_account.log import EcoAccountLogView
from compensation.views.eco_account.record import EcoAccountRecordView
from compensation.views.eco_account.remove import RemoveEcoAccountView
from compensation.views.eco_account.report import EcoAccountPublicReportView
from compensation.views.eco_account.resubmission import EcoAccountResubmissionView
from compensation.views.eco_account.state import NewEcoAccountStateView, EditEcoAccountStateView, \
@ -37,7 +38,7 @@ urlpatterns = [
path('<id>/record', EcoAccountRecordView.as_view(), name='record'),
path('<id>/report', EcoAccountPublicReportView.as_view(), name='report'),
path('<id>/edit', edit_view, name='edit'),
path('<id>/remove', remove_view, name='remove'),
path('<id>/remove', RemoveEcoAccountView.as_view(), name='remove'),
path('<id>/resub', EcoAccountResubmissionView.as_view(), name='resubmission-create'),
path('<id>/state/new', NewEcoAccountStateView.as_view(), name='new-state'),

View File

@ -10,7 +10,6 @@ from django.contrib.auth.decorators import login_required
from django.core.exceptions import ObjectDoesNotExist
from django.http import HttpRequest, HttpResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from compensation.forms.compensation import EditCompensationForm, NewCompensationForm
@ -18,13 +17,11 @@ from compensation.models import Compensation
from compensation.tables.compensation import CompensationTable
from intervention.models import Intervention
from konova.contexts import BaseContext
from konova.decorators import shared_access_required, default_group_required, login_required_modal
from konova.decorators import shared_access_required, default_group_required
from konova.forms import SimpleGeomForm
from konova.forms.modals import RemoveModalForm
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE, \
RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, IDENTIFIER_REPLACED, \
COMPENSATION_ADDED_TEMPLATE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, \
IDENTIFIER_REPLACED, COMPENSATION_ADDED_TEMPLATE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
from konova.views.identifier import AbstractIdentifierGeneratorView
from konova.views.index import AbstractIndexView
@ -194,26 +191,3 @@ def edit_view(request: HttpRequest, id: str):
}
context = BaseContext(request, context).context
return render(request, template, context)
@login_required_modal
@login_required
@default_group_required
@shared_access_required(Compensation, "id")
def remove_view(request: HttpRequest, id: str):
""" Renders a modal view for removing the compensation
Args:
request (HttpRequest): The incoming request
id (str): The compensation's id
Returns:
"""
comp = get_object_or_404(Compensation, id=id)
form = RemoveModalForm(request.POST or None, instance=comp, request=request)
return form.process_request(
request=request,
msg_success=COMPENSATION_REMOVED_TEMPLATE.format(comp.identifier),
redirect_url=reverse("compensation:index"),
)

View File

@ -0,0 +1,20 @@
"""
Author: Michel Peltriaux
Created on: 14.12.25
"""
from django.http import HttpRequest
from django.utils.decorators import method_decorator
from compensation.models import Compensation
from konova.decorators import shared_access_required
from konova.views.remove import AbstractRemoveView
class RemoveCompensationView(AbstractRemoveView):
_MODEL = Compensation
_REDIRECT_URL = "compensation:index"
@method_decorator(shared_access_required(Compensation, "id"))
def dispatch(self, request: HttpRequest, id: str, *args, **kwargs):
return super().dispatch(request, id, *args, **kwargs)

View File

@ -9,18 +9,16 @@ from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpRequest, HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from compensation.forms.eco_account import EditEcoAccountForm, NewEcoAccountForm, RemoveEcoAccountModalForm
from compensation.forms.eco_account import EditEcoAccountForm, NewEcoAccountForm
from compensation.models import EcoAccount
from compensation.tables.eco_account import EcoAccountTable
from konova.contexts import BaseContext
from konova.decorators import shared_access_required, default_group_required, login_required_modal
from konova.decorators import shared_access_required, default_group_required
from konova.forms import SimpleGeomForm
from konova.settings import ETS_GROUP
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import CANCEL_ACC_RECORDED_OR_DEDUCTED, RECORDED_BLOCKS_EDIT, FORM_INVALID, \
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, FORM_INVALID, \
IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
from konova.views.identifier import AbstractIdentifierGeneratorView
from konova.views.index import AbstractIndexView
@ -171,36 +169,3 @@ def edit_view(request: HttpRequest, id: str):
}
context = BaseContext(request, context).context
return render(request, template, context)
@login_required_modal
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def remove_view(request: HttpRequest, id: str):
""" Renders a modal view for removing the eco account
Args:
request (HttpRequest): The incoming request
id (str): The account's id
Returns:
"""
acc = get_object_or_404(EcoAccount, id=id)
# If the eco account has already been recorded OR there are already deductions, it can not be deleted by a regular
# default group user
if acc.recorded is not None or acc.deductions.exists():
user = request.user
if not user.in_group(ETS_GROUP):
messages.info(request, CANCEL_ACC_RECORDED_OR_DEDUCTED)
return redirect("compensation:acc:detail", id=id)
form = RemoveEcoAccountModalForm(request.POST or None, instance=acc, request=request)
return form.process_request(
request=request,
msg_success=_("Eco-account removed"),
redirect_url=reverse("compensation:acc:index"),
)

View File

@ -0,0 +1,22 @@
"""
Author: Michel Peltriaux
Created on: 14.12.25
"""
from django.http import HttpRequest
from django.utils.decorators import method_decorator
from compensation.forms.eco_account import RemoveEcoAccountModalForm
from compensation.models import EcoAccount
from konova.decorators import shared_access_required
from konova.views.remove import AbstractRemoveView
class RemoveEcoAccountView(AbstractRemoveView):
_MODEL = EcoAccount
_REDIRECT_URL = "compensation:acc:index"
_FORM = RemoveEcoAccountModalForm
@method_decorator(shared_access_required(EcoAccount, "id"))
def dispatch(self, request: HttpRequest, id: str, *args, **kwargs):
return super().dispatch(request, id, *args, **kwargs)

View File

@ -11,9 +11,10 @@ from ema.views.action import NewEmaActionView, EditEmaActionView, RemoveEmaActio
from ema.views.deadline import NewEmaDeadlineView, EditEmaDeadlineView, RemoveEmaDeadlineView
from ema.views.detail import DetailEmaView
from ema.views.document import NewEmaDocumentView, EditEmaDocumentView, RemoveEmaDocumentView, GetEmaDocumentView
from ema.views.ema import new_view, edit_view, remove_view, IndexEmaView, EmaIdentifierGeneratorView
from ema.views.ema import new_view, edit_view, IndexEmaView, EmaIdentifierGeneratorView
from ema.views.log import EmaLogView
from ema.views.record import EmaRecordView
from ema.views.remove import RemoveEmaView
from ema.views.report import EmaPublicReportView
from ema.views.resubmission import EmaResubmissionView
from ema.views.share import EmaShareFormView, EmaShareByTokenView
@ -27,7 +28,7 @@ urlpatterns = [
path("<id>", DetailEmaView.as_view(), name="detail"),
path('<id>/log', EmaLogView.as_view(), name='log'),
path('<id>/edit', edit_view, name='edit'),
path('<id>/remove', remove_view, name='remove'),
path('<id>/remove', RemoveEmaView.as_view(), name='remove'),
path('<id>/record', EmaRecordView.as_view(), name='record'),
path('<id>/report', EmaPublicReportView.as_view(), name='report'),
path('<id>/resub', EmaResubmissionView.as_view(), name='resubmission-create'),

View File

@ -174,27 +174,3 @@ def edit_view(request: HttpRequest, id: str):
}
context = BaseContext(request, context).context
return render(request, template, context)
@login_required_modal
@login_required
@conservation_office_group_required
@shared_access_required(Ema, "id")
def remove_view(request: HttpRequest, id: str):
""" Renders a modal view for removing the EMA
Args:
request (HttpRequest): The incoming request
id (str): The EMA's id
Returns:
"""
ema = get_object_or_404(Ema, id=id)
form = RemoveModalForm(request.POST or None, instance=ema, request=request)
return form.process_request(
request=request,
msg_success=_("EMA removed"),
redirect_url=reverse("ema:index"),
)

20
ema/views/remove.py Normal file
View File

@ -0,0 +1,20 @@
"""
Author: Michel Peltriaux
Created on: 14.12.25
"""
from django.utils.decorators import method_decorator
from ema.models import Ema
from konova.decorators import shared_access_required, conservation_office_group_required
from konova.views.remove import AbstractRemoveView
class RemoveEmaView(AbstractRemoveView):
_MODEL = Ema
_REDIRECT_URL = "ema:index"
@method_decorator(conservation_office_group_required)
@method_decorator(shared_access_required(Ema, "id"))
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)

View File

@ -37,6 +37,14 @@ class InterventionAdmin(BaseObjectAdmin):
"geometry",
]
def get_actions(self, request):
DELETE_ACTION_IDENTIFIER = "delete_selected"
actions = super().get_actions(request)
if DELETE_ACTION_IDENTIFIER in actions:
del actions[DELETE_ACTION_IDENTIFIER]
return actions
class InterventionDocumentAdmin(AbstractDocumentAdmin):
pass

View File

@ -14,8 +14,9 @@ from intervention.views.deduction import NewInterventionDeductionView, EditInter
RemoveInterventionDeductionView
from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \
RemoveInterventionDocumentView, EditInterventionDocumentView
from intervention.views.intervention import new_view, edit_view, remove_view, \
from intervention.views.intervention import new_view, edit_view, \
IndexInterventionView, InterventionIdentifierGeneratorView
from intervention.views.remove import RemoveInterventionView
from intervention.views.detail import DetailInterventionView
from intervention.views.log import InterventionLogView
from intervention.views.record import InterventionRecordView
@ -33,7 +34,7 @@ urlpatterns = [
path('<id>', DetailInterventionView.as_view(), name='detail'),
path('<id>/log', InterventionLogView.as_view(), name='log'),
path('<id>/edit', edit_view, name='edit'),
path('<id>/remove', remove_view, name='remove'),
path('<id>/remove', RemoveInterventionView.as_view(), name='remove'),
path('<id>/share/<token>', InterventionShareByTokenView.as_view(), name='share-token'),
path('<id>/share', InterventionShareFormView.as_view(), name='share-form'),
path('<id>/check', check_view, name='check'),

View File

@ -9,16 +9,14 @@ from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import HttpRequest, HttpResponse
from django.shortcuts import get_object_or_404, render, redirect
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
from intervention.forms.intervention import EditInterventionForm, NewInterventionForm
from intervention.models import Intervention
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
from konova.decorators import default_group_required, shared_access_required, login_required_modal
from konova.decorators import default_group_required, shared_access_required
from konova.forms import SimpleGeomForm
from konova.forms.modals import RemoveModalForm
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, \
CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, \
@ -179,26 +177,3 @@ def edit_view(request: HttpRequest, id: str):
context = BaseContext(request, context).context
return render(request, template, context)
@login_required_modal
@login_required
@default_group_required
@shared_access_required(Intervention, "id")
def remove_view(request: HttpRequest, id: str):
""" Renders a remove view for this intervention
Args:
request (HttpRequest): The incoming request
id (str): The uuid id as string
Returns:
"""
obj = Intervention.objects.get(id=id)
identifier = obj.identifier
form = RemoveModalForm(request.POST or None, instance=obj, request=request)
return form.process_request(
request,
_("{} removed").format(identifier),
redirect_url=reverse("intervention:index")
)

View File

@ -0,0 +1,19 @@
"""
Author: Michel Peltriaux
Created on: 14.12.25
"""
from django.utils.decorators import method_decorator
from intervention.models import Intervention
from konova.decorators import shared_access_required
from konova.views.remove import AbstractRemoveView
class RemoveInterventionView(AbstractRemoveView):
_MODEL = Intervention
_REDIRECT_URL = "intervention:index"
@method_decorator(shared_access_required(Intervention, "id"))
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)

65
konova/views/remove.py Normal file
View File

@ -0,0 +1,65 @@
"""
Author: Michel Peltriaux
Created on: 14.12.25
"""
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpRequest
from django.urls import reverse
from django.utils.decorators import method_decorator
from django.views import View
from django.utils.translation import gettext_lazy as _
from konova.decorators import default_group_required
from konova.forms.modals import RemoveModalForm
class AbstractRemoveView(LoginRequiredMixin, View):
_MODEL = None
_REDIRECT_URL = None
_FORM = RemoveModalForm
class Meta:
abstract = True
@method_decorator(default_group_required)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def __process_request(self, request: HttpRequest, id: str):
obj = self._MODEL.objects.get(id=id)
identifier = obj.identifier
form = self._FORM(request.POST or None, instance=obj, request=request)
return form.process_request(
request,
_("{} removed").format(identifier),
redirect_url=reverse(self._REDIRECT_URL)
)
def get(self, request: HttpRequest, id: str):
""" GET endpoint for removing via modal form
Due to the legacy logic of the form (which processes get and post requests directly), we simply need to pipe
the request from GET and POST endpoints directly into the same method.
Args:
request (HttpRequest): The incoming request
id (str): The uuid id as string
Returns:
"""
return self.__process_request(request, id)
def post(self, request: HttpRequest, id: str):
""" POST endpoint for removing via modal form
Due to the legacy logic of the form (which processes get and post requests directly), we simply need to pipe
the request from GET and POST endpoints directly into the same method.
Args:
request (HttpRequest): The incoming request
id (str): The uuid id as string
Returns:
"""
return self.__process_request(request, id)

View File

@ -3,9 +3,8 @@ Author: Michel Peltriaux
Created on: 14.12.25
"""
from abc import abstractmethod
from abc import abstractmethod, ABC
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpRequest, HttpResponse
from django.utils.decorators import method_decorator
from django.views import View
@ -13,12 +12,9 @@ from django.views import View
from konova.decorators import uuid_required
class AbstractPublicReportView(LoginRequiredMixin, View):
class AbstractPublicReportView(View, ABC):
_TEMPLATE = None
class Meta:
abstract = True
@method_decorator(uuid_required)
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)

Binary file not shown.

View File

@ -45,7 +45,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-10-15 09:11+0200\n"
"POT-Creation-Date: 2025-12-14 17:23+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -448,7 +448,7 @@ msgid "Select the intervention for which this compensation compensates"
msgstr "Wählen Sie den Eingriff, für den diese Kompensation bestimmt ist"
#: compensation/forms/compensation.py:114
#: compensation/views/compensation/compensation.py:120
#: compensation/views/compensation/compensation.py:121
msgid "New compensation"
msgstr "Neue Kompensation"
@ -456,38 +456,38 @@ msgstr "Neue Kompensation"
msgid "Edit compensation"
msgstr "Bearbeite Kompensation"
#: compensation/forms/eco_account.py:31 compensation/utils/quality.py:97
#: compensation/forms/eco_account.py:32 compensation/utils/quality.py:97
msgid "Available Surface"
msgstr "Verfügbare Fläche"
#: compensation/forms/eco_account.py:34
#: compensation/forms/eco_account.py:35
msgid "The amount that can be used for deductions"
msgstr "Die für Abbuchungen zur Verfügung stehende Menge"
#: compensation/forms/eco_account.py:43
#: compensation/forms/eco_account.py:44
#: compensation/templates/compensation/detail/eco_account/view.html:67
#: compensation/utils/quality.py:84
msgid "Agreement date"
msgstr "Vereinbarungsdatum"
#: compensation/forms/eco_account.py:45
#: compensation/forms/eco_account.py:46
msgid "When did the parties agree on this?"
msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
#: compensation/forms/eco_account.py:72
#: compensation/views/eco_account/eco_account.py:101
#: compensation/forms/eco_account.py:73
#: compensation/views/eco_account/eco_account.py:105
msgid "New Eco-Account"
msgstr "Neues Ökokonto"
#: compensation/forms/eco_account.py:81
#: compensation/forms/eco_account.py:82
msgid "Eco-Account XY; Location ABC"
msgstr "Ökokonto XY; Flur ABC"
#: compensation/forms/eco_account.py:147
#: compensation/forms/eco_account.py:148
msgid "Edit Eco-Account"
msgstr "Ökokonto bearbeiten"
#: compensation/forms/eco_account.py:183
#: compensation/forms/eco_account.py:184
msgid ""
"{}m² have been deducted from this eco account so far. The given value of {} "
"would be too low."
@ -495,12 +495,16 @@ msgstr ""
"{}n² wurden bereits von diesem Ökokonto abgebucht. Der eingegebene Wert von "
"{} wäre daher zu klein."
#: compensation/forms/eco_account.py:247
#: compensation/forms/eco_account.py:248
msgid "The account can not be removed, since there are still deductions."
msgstr ""
"Das Ökokonto kann nicht entfernt werden, da hierzu noch Abbuchungen "
"vorliegen."
#: compensation/forms/eco_account.py:257
msgid "Please contact the responsible conservation office to find a solution!"
msgstr "Kontaktieren Sie die zuständige Naturschutzbehörde um eine Lösung zu finden!"
#: compensation/forms/mixins.py:37
#: compensation/templates/compensation/detail/eco_account/view.html:63
#: compensation/templates/compensation/report/eco_account/report.html:20
@ -1288,44 +1292,40 @@ msgstr ""
msgid "Responsible data"
msgstr "Daten zu den verantwortlichen Stellen"
#: compensation/views/compensation/compensation.py:58
#: compensation/views/compensation/compensation.py:52
msgid "Compensations - Overview"
msgstr "Kompensationen - Übersicht"
#: compensation/views/compensation/compensation.py:181
#: compensation/views/compensation/compensation.py:167
#: konova/utils/message_templates.py:40
msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet"
#: compensation/views/compensation/compensation.py:196
#: compensation/views/eco_account/eco_account.py:173 ema/views/ema.py:238
#: intervention/views/intervention.py:253
#: compensation/views/compensation/compensation.py:190
#: compensation/views/eco_account/eco_account.py:168 ema/views/ema.py:173
#: intervention/views/intervention.py:175
msgid "Edit {}"
msgstr "Bearbeite {}"
#: compensation/views/compensation/report.py:35
#: compensation/views/eco_account/report.py:36 ema/views/report.py:35
#: intervention/views/report.py:35
#: compensation/views/eco_account/report.py:35 ema/views/report.py:35
#: intervention/views/report.py:36
msgid "Report {}"
msgstr "Bericht {}"
#: compensation/views/eco_account/eco_account.py:53
#: compensation/views/eco_account/eco_account.py:49
msgid "Eco-account - Overview"
msgstr "Ökokonten - Übersicht"
#: compensation/views/eco_account/eco_account.py:86
#: compensation/views/eco_account/eco_account.py:82
msgid "Eco-Account {} added"
msgstr "Ökokonto {} hinzugefügt"
#: compensation/views/eco_account/eco_account.py:158
#: compensation/views/eco_account/eco_account.py:145
msgid "Eco-Account {} edited"
msgstr "Ökokonto {} bearbeitet"
#: compensation/views/eco_account/eco_account.py:288
msgid "Eco-account removed"
msgstr "Ökokonto entfernt"
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:108
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:107
msgid "New EMA"
msgstr "Neue EMA hinzufügen"
@ -1353,22 +1353,18 @@ msgstr ""
msgid "Payment funded compensation"
msgstr "Ersatzzahlungsmaßnahme"
#: ema/views/ema.py:53
#: ema/views/ema.py:52
msgid "EMAs - Overview"
msgstr "EMAs - Übersicht"
#: ema/views/ema.py:86
#: ema/views/ema.py:85
msgid "EMA {} added"
msgstr "EMA {} hinzugefügt"
#: ema/views/ema.py:223
#: ema/views/ema.py:150
msgid "EMA {} edited"
msgstr "EMA {} bearbeitet"
#: ema/views/ema.py:262
msgid "EMA removed"
msgstr "EMA entfernt"
#: intervention/forms/intervention.py:49
msgid "Construction XY; Location ABC"
msgstr "Bauvorhaben XY; Flur ABC"
@ -1429,7 +1425,7 @@ msgstr "Datum Bestandskraft bzw. Rechtskraft"
#: intervention/forms/intervention.py:216
#: intervention/tests/unit/test_forms.py:36
#: intervention/views/intervention.py:105
#: intervention/views/intervention.py:109
msgid "New intervention"
msgstr "Neuer Eingriff"
@ -1665,22 +1661,18 @@ msgstr ""
msgid "Check performed"
msgstr "Prüfung durchgeführt"
#: intervention/views/intervention.py:57
#: intervention/views/intervention.py:53
msgid "Interventions - Overview"
msgstr "Eingriffe - Übersicht"
#: intervention/views/intervention.py:90
#: intervention/views/intervention.py:86
msgid "Intervention {} added"
msgstr "Eingriff {} hinzugefügt"
#: intervention/views/intervention.py:236
#: intervention/views/intervention.py:150
msgid "Intervention {} edited"
msgstr "Eingriff {} bearbeitet"
#: intervention/views/intervention.py:278
msgid "{} removed"
msgstr "{} entfernt"
#: konova/decorators.py:32
msgid "You need to be staff to perform this action!"
msgstr "Hierfür müssen Sie Mitarbeiter sein!"
@ -1810,7 +1802,7 @@ msgstr "Nicht editierbar"
msgid "Geometry"
msgstr "Geometrie"
#: konova/forms/geometry_form.py:100
#: konova/forms/geometry_form.py:105
msgid "Only surfaces allowed. Points or lines must be buffered."
msgstr ""
"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
@ -2268,8 +2260,9 @@ msgid ""
"too small to be valid). These parts have been removed. Please check the "
"stored geometry."
msgstr ""
"Die Geometrie enthielt {} invalide Bestandteile (z.B. unaussagekräftige Kleinstflächen)."
"Diese Bestandteile wurden automatisch entfernt. Bitte überprüfen Sie die angepasste Geometrie."
"Die Geometrie enthielt {} invalide Bestandteile (z.B. unaussagekräftige "
"Kleinstflächen).Diese Bestandteile wurden automatisch entfernt. Bitte "
"überprüfen Sie die angepasste Geometrie."
#: konova/utils/message_templates.py:89
msgid "This intervention has {} revocations"
@ -2330,6 +2323,10 @@ msgstr "{} verzeichnet"
msgid "Errors found:"
msgstr "Fehler gefunden:"
#: konova/views/remove.py:35
msgid "{} removed"
msgstr "{} entfernt"
#: konova/views/resubmission.py:39
msgid "Resubmission set"
msgstr "Wiedervorlage gesetzt"