{% if is_default_member and has_access %}
-
+
+ {% fa5_icon 'edit' %}
+
+
{% fa5_icon 'trash' %}
{% endif %}
diff --git a/intervention/tests/test_views.py b/intervention/tests/test_views.py
index 23da913a..f12ee7a3 100644
--- a/intervention/tests/test_views.py
+++ b/intervention/tests/test_views.py
@@ -10,6 +10,7 @@ from django.test import Client
from django.contrib.auth.models import Group
from django.urls import reverse
+from intervention.models import Revocation
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.tests.test_views import BaseViewTestCase
@@ -20,19 +21,34 @@ class InterventionViewTestCase(BaseViewTestCase):
def setUpTestData(cls) -> None:
super().setUpTestData()
+ def setUp(self) -> None:
+ super().setUp()
# Prepare urls
- cls.index_url = reverse("intervention:index", args=())
- cls.new_url = reverse("intervention:new", args=())
- cls.new_id_url = reverse("intervention:new-id", args=())
- cls.detail_url = reverse("intervention:detail", args=(cls.intervention.id,))
- cls.log_url = reverse("intervention:log", args=(cls.intervention.id,))
- cls.edit_url = reverse("intervention:edit", args=(cls.intervention.id,))
- cls.remove_url = reverse("intervention:remove", args=(cls.intervention.id,))
- cls.share_url = reverse("intervention:share", args=(cls.intervention.id, cls.intervention.access_token,))
- cls.share_create_url = reverse("intervention:share-create", args=(cls.intervention.id,))
- cls.run_check_url = reverse("intervention:check", args=(cls.intervention.id,))
- cls.record_url = reverse("intervention:record", args=(cls.intervention.id,))
- cls.report_url = reverse("intervention:report", args=(cls.intervention.id,))
+ self.index_url = reverse("intervention:index", args=())
+ self.new_url = reverse("intervention:new", args=())
+ self.new_id_url = reverse("intervention:new-id", args=())
+ self.detail_url = reverse("intervention:detail", args=(self.intervention.id,))
+ self.log_url = reverse("intervention:log", args=(self.intervention.id,))
+ self.edit_url = reverse("intervention:edit", args=(self.intervention.id,))
+ self.remove_url = reverse("intervention:remove", args=(self.intervention.id,))
+ self.share_url = reverse("intervention:share", args=(self.intervention.id, self.intervention.access_token,))
+ self.share_create_url = reverse("intervention:share-create", args=(self.intervention.id,))
+ self.run_check_url = reverse("intervention:check", args=(self.intervention.id,))
+ self.record_url = reverse("intervention:record", args=(self.intervention.id,))
+ self.report_url = reverse("intervention:report", args=(self.intervention.id,))
+
+ self.deduction.intervention = self.intervention
+ self.deduction.save()
+ self.deduction_new_url = reverse("intervention:new-deduction", args=(self.intervention.id,))
+ self.deduction_edit_url = reverse("intervention:edit-deduction", args=(self.intervention.id, self.deduction.id,))
+ self.deduction_remove_url = reverse("intervention:remove-deduction", args=(self.intervention.id, self.deduction.id))
+
+ self.revocation = Revocation.objects.create(
+ legal=self.intervention.legal
+ )
+ self.revocation_new_url = reverse("intervention:new-revocation", args=(self.intervention.id,))
+ self.revocation_edit_url = reverse("intervention:edit-revocation", args=(self.intervention.id, self.revocation.id))
+ self.revocation_remove_url = reverse("intervention:remove-revocation", args=(self.intervention.id, self.revocation.id))
def test_views_anonymous_user(self):
""" Check correct status code for all requests
@@ -61,6 +77,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.share_create_url: f"{login_redirect_base}{self.share_create_url}",
self.run_check_url: f"{login_redirect_base}{self.run_check_url}",
self.record_url: f"{login_redirect_base}{self.record_url}",
+ self.deduction_new_url: f"{login_redirect_base}{self.deduction_new_url}",
+ self.deduction_edit_url: f"{login_redirect_base}{self.deduction_edit_url}",
+ self.deduction_remove_url: f"{login_redirect_base}{self.deduction_remove_url}",
+ self.revocation_new_url: f"{login_redirect_base}{self.revocation_new_url}",
+ self.revocation_edit_url: f"{login_redirect_base}{self.revocation_edit_url}",
+ self.revocation_remove_url: f"{login_redirect_base}{self.revocation_remove_url}",
}
self.assert_url_success(client, success_urls)
@@ -96,6 +118,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.share_create_url,
self.run_check_url,
self.record_url,
+ self.revocation_new_url,
+ self.revocation_edit_url,
+ self.revocation_remove_url,
+ self.deduction_new_url,
+ self.deduction_edit_url,
+ self.deduction_remove_url,
]
self.assert_url_success(client, success_urls)
@@ -128,6 +156,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.edit_url,
self.remove_url,
self.share_create_url,
+ self.revocation_new_url,
+ self.revocation_edit_url,
+ self.revocation_remove_url,
+ self.deduction_new_url,
+ self.deduction_edit_url,
+ self.deduction_remove_url,
]
fail_urls = [
self.run_check_url,
@@ -172,6 +206,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.remove_url,
self.share_create_url,
self.log_url,
+ self.revocation_new_url,
+ self.revocation_edit_url,
+ self.revocation_remove_url,
+ self.deduction_new_url,
+ self.deduction_edit_url,
+ self.deduction_remove_url,
]
success_urls_redirect = {
self.share_url: self.detail_url
@@ -212,6 +252,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.remove_url,
self.share_create_url,
self.record_url,
+ self.revocation_new_url,
+ self.revocation_edit_url,
+ self.revocation_remove_url,
+ self.deduction_new_url,
+ self.deduction_edit_url,
+ self.deduction_remove_url,
]
success_urls_redirect = {
self.share_url: self.detail_url
@@ -252,6 +298,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.share_create_url,
self.record_url,
self.run_check_url,
+ self.revocation_new_url,
+ self.revocation_edit_url,
+ self.revocation_remove_url,
+ self.deduction_new_url,
+ self.deduction_edit_url,
+ self.deduction_remove_url,
]
success_urls_redirect = {
self.share_url: self.detail_url
@@ -292,6 +344,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.remove_url,
self.share_create_url,
self.run_check_url,
+ self.revocation_new_url,
+ self.revocation_edit_url,
+ self.revocation_remove_url,
+ self.deduction_new_url,
+ self.deduction_edit_url,
+ self.deduction_remove_url,
]
success_urls_redirect = {
self.share_url: self.detail_url
@@ -332,6 +390,12 @@ class InterventionViewTestCase(BaseViewTestCase):
self.remove_url,
self.share_create_url,
self.run_check_url,
+ self.revocation_new_url,
+ self.revocation_edit_url,
+ self.revocation_remove_url,
+ self.deduction_new_url,
+ self.deduction_edit_url,
+ self.deduction_remove_url,
]
# Define urls where a redirect to a specific location is the proper response
success_urls_redirect = {
diff --git a/intervention/tests/test_workflow.py b/intervention/tests/test_workflow.py
index fbc2f81f..69f606f0 100644
--- a/intervention/tests/test_workflow.py
+++ b/intervention/tests/test_workflow.py
@@ -74,6 +74,9 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
self.assertEqual(obj.identifier, test_id)
self.assertEqual(obj.title, test_title)
self.assert_equal_geometries(obj.geometry.geom, test_geom)
+ self.assertEqual(1, obj.log.count())
+ self.assertEqual(obj.log.first().action, UserAction.CREATED)
+ self.assertEqual(obj.log.first().user, self.superuser)
except ObjectDoesNotExist:
# Fail if there is no such object
self.fail()
@@ -215,6 +218,8 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
# Make sure there are no payments on the intervention, yet
self.assertEqual(0, self.intervention.payments.count())
+ pre_payment_logs_count = self.intervention.log.count()
+
# Create form data to be sent to the url
test_amount = 10.00
test_due = "2021-01-01"
@@ -239,6 +244,10 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
self.assertEqual(payment.amount, test_amount)
self.assertEqual(payment.due_on, datetime.date.fromisoformat(test_due))
self.assertEqual(payment.comment, test_comment)
+
+ # Make sure a log entry has been created
+ self.assertEqual(self.intervention.log.first().action, UserAction.EDITED)
+ self.assertEqual(pre_payment_logs_count + 1, self.intervention.log.count())
return payment
def subtest_delete_payment(self, payment: Payment):
@@ -250,8 +259,10 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
Returns:
"""
+ pre_payment_logs_count = self.intervention.log.count()
+
# Create removing url for the payment
- remove_url = reverse("compensation:pay:remove", args=(payment.id,))
+ remove_url = reverse("compensation:pay:remove", args=(self.intervention.id, payment.id,))
post_data = {
"confirm": True,
}
@@ -266,6 +277,11 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
# Now make sure the intervention has no payments anymore
self.assertEqual(0, self.intervention.payments.count())
+ # Make sure a log entry has been created
+ self.assertEqual(self.intervention.log.first().action, UserAction.EDITED)
+ self.assertEqual(self.intervention.log.first().user, self.superuser)
+ self.assertEqual(pre_payment_logs_count + 1, self.intervention.log.count())
+
def test_payments(self):
"""
Checks a 'normal' case of adding a payment.
@@ -353,6 +369,8 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
Returns:
"""
+ pre_deduction_logs_count = self.intervention.log.count()
+
# Prepare the account for a working situation (enough deductable surface, recorded and shared)
self.eco_account.deductable_surface = 10000.00
if self.eco_account.recorded is None:
@@ -376,6 +394,11 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
)
self.assertEqual(deduction.surface, test_surface)
+ # Make sure a log entry has been created
+ self.assertEqual(self.intervention.log.first().action, UserAction.EDITED)
+ self.assertEqual(self.intervention.log.first().user, self.superuser)
+ self.assertEqual(pre_deduction_logs_count + 1, self.intervention.log.count())
+
# Return deduction for further usage in tests
return deduction
@@ -414,6 +437,8 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
Returns:
"""
+ pre_delete_logs_count = self.intervention.log.count()
+
# Prepare url for deleting of this deduction
delete_url = reverse("compensation:acc:remove-deduction", args=(self.eco_account.id, deduction.id,))
post_data = {
@@ -433,6 +458,11 @@ class InterventionWorkflowTestCase(BaseWorkflowTestCase):
# Expect the deduction to be totally gone
self.assert_object_is_deleted(deduction)
+ # Make sure a log entry has been created
+ self.assertEqual(self.intervention.log.first().action, UserAction.EDITED)
+ self.assertEqual(self.intervention.log.first().user, self.superuser)
+ self.assertEqual(pre_delete_logs_count + 1, self.intervention.log.count())
+
def test_deduction(self):
"""
Checks a 'normal case of adding a deduction.
diff --git a/intervention/urls.py b/intervention/urls.py
index 1c663124..2a5e6d38 100644
--- a/intervention/urls.py
+++ b/intervention/urls.py
@@ -10,7 +10,7 @@ from django.urls import path
from intervention.views import index_view, new_view, detail_view, edit_view, remove_view, new_document_view, share_view, \
create_share_view, remove_revocation_view, new_revocation_view, check_view, log_view, new_deduction_view, \
record_view, remove_document_view, get_document_view, get_revocation_view, new_id_view, report_view, \
- remove_deduction_view, remove_compensation_view
+ remove_deduction_view, remove_compensation_view, edit_deduction_view, edit_revocation_view, edit_document_view
app_name = "intervention"
urlpatterns = [
@@ -28,19 +28,22 @@ urlpatterns = [
path('/report', report_view, name='report'),
# Compensations
- path('/remove/', remove_compensation_view, name='remove-compensation'),
+ path('/compensation//remove', remove_compensation_view, name='remove-compensation'),
# Documents
path('/document/new/', new_document_view, name='new-doc'),
- path('document/', get_document_view, name='get-doc'),
- path('document//remove/', remove_document_view, name='remove-doc'),
+ path('/document/', get_document_view, name='get-doc'),
+ path('/document//remove/', remove_document_view, name='remove-doc'),
+ path('/document//edit/', edit_document_view, name='edit-doc'),
# Deductions
path('/deduction/new', new_deduction_view, name='new-deduction'),
- path('/remove/', remove_deduction_view, name='remove-deduction'),
+ path('/deduction//edit', edit_deduction_view, name='edit-deduction'),
+ path('/deduction//remove', remove_deduction_view, name='remove-deduction'),
# Revocation routes
path('/revocation/new', new_revocation_view, name='new-revocation'),
- path('revocation//remove', remove_revocation_view, name='remove-revocation'),
+ path('/revocation//edit', edit_revocation_view, name='edit-revocation'),
+ path('/revocation//remove', remove_revocation_view, name='remove-revocation'),
path('revocation/', get_revocation_view, name='get-doc-revocation'),
]
\ No newline at end of file
diff --git a/intervention/utils/quality.py b/intervention/utils/quality.py
index e15b4ca4..6135b403 100644
--- a/intervention/utils/quality.py
+++ b/intervention/utils/quality.py
@@ -89,7 +89,10 @@ class InterventionQualityChecker(AbstractQualityChecker):
Returns:
"""
- c_comps = self.obj.compensations.count()
+ comps = self.obj.compensations.filter(
+ deleted=None
+ )
+ c_comps = comps.count()
c_pays = self.obj.payments.count()
c_deducs = self.obj.deductions.count()
c_all = c_comps + c_pays + c_deducs
diff --git a/intervention/views.py b/intervention/views.py
index a518a9da..00440bb8 100644
--- a/intervention/views.py
+++ b/intervention/views.py
@@ -6,18 +6,19 @@ from django.shortcuts import render
from intervention.forms.forms import NewInterventionForm, EditInterventionForm
from intervention.forms.modalForms import ShareModalForm, NewRevocationModalForm, \
- CheckModalForm, NewDeductionModalForm, NewInterventionDocumentForm
+ CheckModalForm, NewDeductionModalForm, NewInterventionDocumentModalForm, RemoveEcoAccountDeductionModalForm, \
+ RemoveRevocationModalForm, EditEcoAccountDeductionModalForm, EditRevocationModalForm
from intervention.models import Intervention, Revocation, InterventionDocument, RevocationDocument
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
from konova.decorators import *
-from konova.forms import SimpleGeomForm, RemoveModalForm, RecordModalForm
+from konova.forms import SimpleGeomForm, RemoveModalForm, RecordModalForm, EditDocumentModalForm
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
from konova.utils.documents import remove_document, get_document
from konova.utils.generators import generate_qr_code
from konova.utils.message_templates import INTERVENTION_INVALID, FORM_INVALID, IDENTIFIER_REPLACED, \
CHECKED_RECORDED_RESET, DEDUCTION_REMOVED, DEDUCTION_ADDED, REVOCATION_ADDED, REVOCATION_REMOVED, \
- COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED
+ COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED, DEDUCTION_EDITED, REVOCATION_EDITED, DOCUMENT_EDITED
from konova.utils.user_checks import in_group
@@ -128,7 +129,7 @@ def new_document_view(request: HttpRequest, id: str):
"""
intervention = get_object_or_404(Intervention, id=id)
- form = NewInterventionDocumentForm(request.POST or None, request.FILES or None, instance=intervention, request=request)
+ form = NewInterventionDocumentModalForm(request.POST or None, request.FILES or None, instance=intervention, request=request)
return form.process_request(
request,
msg_success=DOCUMENT_ADDED,
@@ -160,48 +161,44 @@ def get_revocation_view(request: HttpRequest, doc_id: str):
return redirect("intervention:detail", id=doc.instance.id)
return get_document(doc)
-
@login_required
@default_group_required
-def get_document_view(request: HttpRequest, doc_id: str):
+@shared_access_required(Intervention, "id")
+def get_document_view(request: HttpRequest, id: str, doc_id: str):
""" Returns the document as downloadable file
Wraps the generic document fetcher function from konova.utils.
Args:
request (HttpRequest): The incoming request
+ id (str): The intervention id
doc_id (str): The document id
Returns:
"""
+ intervention = get_object_or_404(Intervention, id=id)
doc = get_object_or_404(InterventionDocument, id=doc_id)
- user = request.user
- instance = doc.instance
- # File download only possible if related instance is shared with user
- if not instance.users.filter(id=user.id):
- messages.info(
- request,
- DATA_UNSHARED
- )
- return redirect("intervention:detail", id=instance.id)
return get_document(doc)
@login_required
@default_group_required
-def remove_document_view(request: HttpRequest, doc_id: str):
+@shared_access_required(Intervention, "id")
+def remove_document_view(request: HttpRequest, id: str, doc_id: str):
""" Removes the document from the database and file system
Wraps the generic functionality from konova.utils.
Args:
request (HttpRequest): The incoming request
+ id (str): The intervention id
doc_id (str): The document id
Returns:
"""
+ intervention = get_object_or_404(Intervention, id=id)
doc = get_object_or_404(InterventionDocument, id=doc_id)
return remove_document(
request,
@@ -209,6 +206,32 @@ def remove_document_view(request: HttpRequest, doc_id: str):
)
+@login_required
+@default_group_required
+@shared_access_required(Intervention, "id")
+def edit_document_view(request: HttpRequest, id: str, doc_id: str):
+ """ Removes the document from the database and file system
+
+ Wraps the generic functionality from konova.utils.
+
+ Args:
+ request (HttpRequest): The incoming request
+ id (str): The intervention id
+ doc_id (str): The document id
+
+ Returns:
+
+ """
+ intervention = get_object_or_404(Intervention, id=id)
+ doc = get_object_or_404(InterventionDocument, id=doc_id)
+ form = EditDocumentModalForm(request.POST or None, request.FILES or None, instance=intervention, document=doc, request=request)
+ return form.process_request(
+ request,
+ DOCUMENT_EDITED,
+ redirect_url=reverse("intervention:detail", args=(intervention.id,)) + "#related_data"
+ )
+
+
@login_required
@any_group_check
def detail_view(request: HttpRequest, id: str):
@@ -244,14 +267,6 @@ def detail_view(request: HttpRequest, id: str):
parcels = intervention.get_underlying_parcels()
- # Inform user about revocation
- if intervention.legal.revocations.exists():
- messages.error(
- request,
- _("This intervention has {} revocations").format(intervention.legal.revocations.count()),
- extra_tags="danger",
- )
-
context = {
"obj": intervention,
"compensations": compensations,
@@ -340,23 +355,51 @@ def remove_view(request: HttpRequest, id: str):
@login_required
@default_group_required
-def remove_revocation_view(request: HttpRequest, id: str):
- """ Renders a remove view for a revocation
+@shared_access_required(Intervention, "id")
+def edit_revocation_view(request: HttpRequest, id: str, revocation_id: str):
+ """ Renders a edit view for a revocation
Args:
request (HttpRequest): The incoming request
- id (str): The revocation's id as string
+ id (str): The intervention's id as string
+ revocation_id (str): The revocation's id as string
Returns:
"""
- obj = Revocation.objects.get(id=id)
+ intervention = get_object_or_404(Intervention, id=id)
+ revocation = get_object_or_404(Revocation, id=revocation_id)
- form = RemoveModalForm(request.POST or None, instance=obj, request=request)
+ form = EditRevocationModalForm(request.POST or None, request.FILES or None, instance=intervention, revocation=revocation, request=request)
+ return form.process_request(
+ request,
+ REVOCATION_EDITED,
+ redirect_url=reverse("intervention:detail", args=(intervention.id,)) + "#related_data"
+ )
+
+
+@login_required
+@default_group_required
+@shared_access_required(Intervention, "id")
+def remove_revocation_view(request: HttpRequest, id: str, revocation_id: str):
+ """ Renders a remove view for a revocation
+
+ Args:
+ request (HttpRequest): The incoming request
+ id (str): The intervention's id as string
+ revocation_id (str): The revocation's id as string
+
+ Returns:
+
+ """
+ intervention = get_object_or_404(Intervention, id=id)
+ revocation = get_object_or_404(Revocation, id=revocation_id)
+
+ form = RemoveRevocationModalForm(request.POST or None, instance=intervention, revocation=revocation, request=request)
return form.process_request(
request,
REVOCATION_REMOVED,
- redirect_url=reverse("intervention:detail", args=(obj.intervention.id,)) + "#related_data"
+ redirect_url=reverse("intervention:detail", args=(intervention.id,)) + "#related_data"
)
@@ -533,7 +576,7 @@ def remove_deduction_view(request: HttpRequest, id: str, deduction_id: str):
except ObjectDoesNotExist:
raise Http404("Unknown deduction")
- form = RemoveModalForm(request.POST or None, instance=eco_deduction, request=request)
+ form = RemoveEcoAccountDeductionModalForm(request.POST or None, instance=intervention, deduction=eco_deduction, request=request)
return form.process_request(
request=request,
msg_success=DEDUCTION_REMOVED,
@@ -541,6 +584,34 @@ def remove_deduction_view(request: HttpRequest, id: str, deduction_id: str):
)
+@login_required
+@default_group_required
+@shared_access_required(Intervention, "id")
+def edit_deduction_view(request: HttpRequest, id: str, deduction_id: str):
+ """ Renders a modal view for removing deductions
+
+ Args:
+ request (HttpRequest): The incoming request
+ id (str): The intervention's id
+ deduction_id (str): The deduction's id
+
+ Returns:
+
+ """
+ intervention = get_object_or_404(Intervention, id=id)
+ try:
+ eco_deduction = intervention.deductions.get(id=deduction_id)
+ except ObjectDoesNotExist:
+ raise Http404("Unknown deduction")
+
+ form = EditEcoAccountDeductionModalForm(request.POST or None, instance=intervention, deduction=eco_deduction, request=request)
+ return form.process_request(
+ request=request,
+ msg_success=DEDUCTION_EDITED,
+ redirect_url=reverse("intervention:detail", args=(id,)) + "#related_data"
+ )
+
+
@login_required
@conservation_office_group_required
@shared_access_required(Intervention, "id")
diff --git a/konova/autocompletes.py b/konova/autocompletes.py
index 3c12b36d..3a79ab68 100644
--- a/konova/autocompletes.py
+++ b/konova/autocompletes.py
@@ -35,8 +35,9 @@ class EcoAccountAutocomplete(Select2QuerySetView):
)
if self.q:
qs = qs.filter(
- identifier__icontains=self.q
- )
+ Q(identifier__icontains=self.q) |
+ Q(title__icontains=self.q)
+ ).distinct()
return qs
@@ -57,8 +58,9 @@ class InterventionAutocomplete(Select2QuerySetView):
)
if self.q:
qs = qs.filter(
- identifier__icontains=self.q
- )
+ Q(identifier__icontains=self.q) |
+ Q(title__icontains=self.q)
+ ).distinct()
return qs
@@ -81,8 +83,9 @@ class ShareUserAutocomplete(Select2QuerySetView):
if self.q:
# Due to privacy concerns only a full username match will return the proper user entry
qs = qs.filter(
- username=self.q
- )
+ Q(username=self.q) |
+ Q(email=self.q)
+ ).distinct()
return qs
diff --git a/konova/forms.py b/konova/forms.py
index 030599c3..57562f71 100644
--- a/konova/forms.py
+++ b/konova/forms.py
@@ -12,6 +12,8 @@ from bootstrap_modal_forms.forms import BSModalForm
from bootstrap_modal_forms.utils import is_ajax
from django import forms
from django.contrib import messages
+from django.db.models.fields.files import FieldFile
+
from user.models import User
from django.contrib.gis.forms import OSMWidget, MultiPolygonField
from django.contrib.gis.geos import MultiPolygon
@@ -21,10 +23,10 @@ from django.shortcuts import render
from django.utils.translation import gettext_lazy as _
from konova.contexts import BaseContext
-from konova.models import BaseObject, Geometry, RecordableObjectMixin
+from konova.models import BaseObject, Geometry, RecordableObjectMixin, AbstractDocument
from konova.settings import DEFAULT_SRID
from konova.tasks import celery_update_parcels
-from konova.utils.message_templates import FORM_INVALID
+from konova.utils.message_templates import FORM_INVALID, FILE_TYPE_UNSUPPORTED, FILE_SIZE_TOO_LARGE, DOCUMENT_EDITED
from user.models import UserActionLogEntry
@@ -87,7 +89,7 @@ class BaseForm(forms.Form):
"""
self.fields[field].widget.attrs["placeholder"] = val
- def load_initial_data(self, form_data: dict, disabled_fields: list):
+ def load_initial_data(self, form_data: dict, disabled_fields: list = None):
""" Initializes form data from instance
Inserts instance data into form and disables form fields
@@ -99,8 +101,9 @@ class BaseForm(forms.Form):
return
for k, v in form_data.items():
self.initialize_form_field(k, v)
- for field in disabled_fields:
- self.disable_form_field(field)
+ if disabled_fields:
+ for field in disabled_fields:
+ self.disable_form_field(field)
def add_widget_html_class(self, field: str, cls: str):
""" Adds a HTML class string to the widget of a field
@@ -327,10 +330,27 @@ class RemoveModalForm(BaseModalForm):
self.instance.mark_as_deleted(self.user)
else:
# If the class does not provide restorable delete functionality, we must delete the entry finally
- self.instance.delete(self.user)
+ self.instance.delete()
-class NewDocumentForm(BaseModalForm):
+class RemoveDeadlineModalForm(RemoveModalForm):
+ """ Removing modal form for deadlines
+
+ Can be used for anything, where removing shall be confirmed by the user a second time.
+
+ """
+ deadline = None
+
+ def __init__(self, *args, **kwargs):
+ deadline = kwargs.pop("deadline", None)
+ self.deadline = deadline
+ super().__init__(*args, **kwargs)
+
+ def save(self):
+ self.instance.remove_deadline(self)
+
+
+class NewDocumentModalForm(BaseModalForm):
""" Modal form for new documents
"""
@@ -402,18 +422,22 @@ class NewDocumentForm(BaseModalForm):
_file = self.cleaned_data.get("file", None)
+ if _file is None or isinstance(_file, FieldFile):
+ # FieldFile declares that no new file has been uploaded and we do not need to check on the file again
+ return super_valid
+
mime_type_valid = self.document_model.is_mime_type_valid(_file)
if not mime_type_valid:
self.add_error(
"file",
- _("Unsupported file type")
+ FILE_TYPE_UNSUPPORTED
)
file_size_valid = self.document_model.is_file_size_valid(_file)
if not file_size_valid:
self.add_error(
"file",
- _("File too large")
+ FILE_SIZE_TOO_LARGE
)
file_valid = mime_type_valid and file_size_valid
@@ -440,6 +464,39 @@ class NewDocumentForm(BaseModalForm):
return doc
+class EditDocumentModalForm(NewDocumentModalForm):
+ document = None
+ document_model = AbstractDocument
+
+ def __init__(self, *args, **kwargs):
+ self.document = kwargs.pop("document", None)
+ super().__init__(*args, **kwargs)
+ form_data = {
+ "title": self.document.title,
+ "comment": self.document.comment,
+ "creation_date": str(self.document.date_of_creation),
+ "file": self.document.file,
+ }
+ self.load_initial_data(form_data)
+
+
+ def save(self):
+ with transaction.atomic():
+ document = self.document
+ file = self.cleaned_data.get("file", None)
+
+ document.title = self.cleaned_data.get("title", None)
+ document.comment = self.cleaned_data.get("comment", None)
+ document.date_of_creation = self.cleaned_data.get("creation_date", None)
+ if not isinstance(file, FieldFile):
+ document.replace_file(file)
+ document.save()
+
+ self.instance.mark_as_edited(self.user, self.request, edit_comment=DOCUMENT_EDITED)
+
+ return document
+
+
class RecordModalForm(BaseModalForm):
""" Modal form for recording data
@@ -515,7 +572,9 @@ class RecordModalForm(BaseModalForm):
Returns:
"""
- comps = self.instance.compensations.all()
+ comps = self.instance.compensations.filter(
+ deleted=None,
+ )
comps_valid = True
for comp in comps:
checker = comp.quality_check()
diff --git a/konova/migrations/0003_auto_20220208_1801.py b/konova/migrations/0003_auto_20220208_1801.py
new file mode 100644
index 00000000..d1d9b5a0
--- /dev/null
+++ b/konova/migrations/0003_auto_20220208_1801.py
@@ -0,0 +1,54 @@
+# Generated by Django 3.1.3 on 2022-02-08 17:01
+
+from django.db import migrations, models
+import django.db.models.deletion
+import uuid
+
+
+def migrate_parcels(apps, schema_editor):
+ Geometry = apps.get_model('konova', 'Geometry')
+ SpatialIntersection = apps.get_model('konova', 'SpatialIntersection')
+
+ all_geoms = Geometry.objects.all()
+ for geom in all_geoms:
+ SpatialIntersection.objects.bulk_create([
+ SpatialIntersection(geometry=geom, parcel=parcel)
+ for parcel in geom.parcels.all()
+ ])
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('konova', '0002_auto_20220114_0936'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SpatialIntersection',
+ fields=[
+ ('id', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False)),
+ ('calculated_on', models.DateTimeField(auto_now_add=True, null=True)),
+ ('geometry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='konova.geometry')),
+ ('parcel', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='konova.parcel')),
+ ],
+ options={
+ 'abstract': False,
+ },
+ ),
+ migrations.RunPython(migrate_parcels),
+ migrations.AddField(
+ model_name='parcel',
+ name='geometries_tmp',
+ field=models.ManyToManyField(blank=True, related_name='parcels', through='konova.SpatialIntersection', to='konova.Geometry'),
+ ),
+ migrations.RemoveField(
+ model_name='parcel',
+ name='geometries',
+ ),
+ migrations.RenameField(
+ model_name='parcel',
+ old_name='geometries_tmp',
+ new_name='geometries',
+ ),
+ ]
diff --git a/konova/migrations/0004_auto_20220209_0839.py b/konova/migrations/0004_auto_20220209_0839.py
new file mode 100644
index 00000000..fe41eada
--- /dev/null
+++ b/konova/migrations/0004_auto_20220209_0839.py
@@ -0,0 +1,17 @@
+# Generated by Django 3.1.3 on 2022-02-09 07:39
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('konova', '0003_auto_20220208_1801'),
+ ]
+
+ operations = [
+ migrations.RenameModel(
+ old_name='SpatialIntersection',
+ new_name='ParcelIntersection',
+ ),
+ ]
diff --git a/konova/models/document.py b/konova/models/document.py
index 72b124d3..b465d70c 100644
--- a/konova/models/document.py
+++ b/konova/models/document.py
@@ -101,3 +101,19 @@ class AbstractDocument(BaseResource):
def is_file_size_valid(cls, _file):
max_size = cls._maximum_file_size * pow(1000, 2)
return _file.size <= max_size
+
+ def replace_file(self, new_file):
+ """ Replaces the old file on the hard drive with the new one
+
+ Args:
+ new_file (File): The new file
+
+ Returns:
+
+ """
+ try:
+ os.remove(self.file.file.name)
+ except FileNotFoundError:
+ pass
+ self.file = new_file
+ self.save()
\ No newline at end of file
diff --git a/konova/models/geometry.py b/konova/models/geometry.py
index 0a380b48..bec89c39 100644
--- a/konova/models/geometry.py
+++ b/konova/models/geometry.py
@@ -99,7 +99,7 @@ class Geometry(BaseResource):
Returns:
"""
- from konova.models import Parcel, District
+ from konova.models import Parcel, District, ParcelIntersection
parcel_fetcher = ParcelWFSFetcher(
geometry_id=self.id,
)
@@ -107,6 +107,7 @@ class Geometry(BaseResource):
fetched_parcels = parcel_fetcher.get_features(
typename
)
+ _now = timezone.now()
underlying_parcels = []
for result in fetched_parcels:
fetched_parcel = result[typename]
@@ -125,19 +126,35 @@ class Geometry(BaseResource):
krs=fetched_parcel["ave:kreis"],
)[0]
parcel_obj.district = district
- parcel_obj.updated_on = timezone.now()
+ parcel_obj.updated_on = _now
parcel_obj.save()
underlying_parcels.append(parcel_obj)
+ # Update the linked parcels
self.parcels.set(underlying_parcels)
+ # Set the calculated_on intermediate field, so this related data will be found on lookups
+ intersections_without_ts = self.parcelintersection_set.filter(
+ parcel__in=self.parcels.all(),
+ calculated_on__isnull=True,
+ )
+ for entry in intersections_without_ts:
+ entry.calculated_on = _now
+ ParcelIntersection.objects.bulk_update(
+ intersections_without_ts,
+ ["calculated_on"]
+ )
+
def get_underlying_parcels(self):
""" Getter for related parcels and their districts
Returns:
parcels (QuerySet): The related parcels as queryset
"""
- parcels = self.parcels.all().prefetch_related(
+
+ parcels = self.parcels.filter(
+ parcelintersection__calculated_on__isnull=False,
+ ).prefetch_related(
"district"
).order_by(
"gmrkng",
diff --git a/konova/models/object.py b/konova/models/object.py
index 9eba8c1d..a6164f5a 100644
--- a/konova/models/object.py
+++ b/konova/models/object.py
@@ -12,6 +12,7 @@ from abc import abstractmethod
from django.contrib import messages
from django.db.models import QuerySet
+from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP, LANIS_ZOOM_LUT, LANIS_LINK_TEMPLATE
from konova.tasks import celery_send_mail_shared_access_removed, celery_send_mail_shared_access_given, \
celery_send_mail_shared_data_recorded, celery_send_mail_shared_data_unrecorded, \
celery_send_mail_shared_data_deleted, celery_send_mail_shared_data_checked
@@ -128,10 +129,27 @@ class BaseObject(BaseResource):
# Send mail
shared_users = self.shared_users.values_list("id", flat=True)
for user_id in shared_users:
- celery_send_mail_shared_data_deleted.delay(self.identifier, user_id)
+ celery_send_mail_shared_data_deleted.delay(self.identifier, self.title, user_id)
self.save()
+ def mark_as_edited(self, performing_user: User, request: HttpRequest = None, edit_comment: str = None):
+ """ In case the object or a related object changed the log history needs to be updated
+
+ Args:
+ performing_user (User): The user which performed the editing action
+ request (HttpRequest): The used request for this action
+ edit_comment (str): Additional comment for the log entry
+
+ Returns:
+
+ """
+ edit_action = UserActionLogEntry.get_edited_action(performing_user, edit_comment)
+ self.modified = edit_action
+ self.log.add(edit_action)
+ self.save()
+ return edit_action
+
def add_log_entry(self, action: UserAction, user: User, comment: str):
""" Wraps adding of UserActionLogEntry to log
@@ -200,6 +218,10 @@ class BaseObject(BaseResource):
_str = "{}{}-{}".format(curr_month, curr_year, rand_str)
return definitions[self.__class__]["template"].format(_str)
+ @abstractmethod
+ def get_detail_url(self):
+ raise NotImplementedError()
+
class RecordableObjectMixin(models.Model):
""" Wraps record related fields and functionality
@@ -236,7 +258,7 @@ class RecordableObjectMixin(models.Model):
shared_users = self.users.all().values_list("id", flat=True)
for user_id in shared_users:
- celery_send_mail_shared_data_unrecorded.delay(self.identifier, user_id)
+ celery_send_mail_shared_data_unrecorded.delay(self.identifier, self.title, user_id)
return action
@@ -258,29 +280,22 @@ class RecordableObjectMixin(models.Model):
shared_users = self.users.all().values_list("id", flat=True)
for user_id in shared_users:
- celery_send_mail_shared_data_recorded.delay(self.identifier, user_id)
+ celery_send_mail_shared_data_recorded.delay(self.identifier, self.title, user_id)
return action
- def mark_as_edited(self, performing_user: User, request: HttpRequest = None, edit_comment: str = None, reset_recorded: bool = True):
- """ In case the object or a related object changed, internal processes need to be started, such as
- unrecord and uncheck
+ def unrecord(self, performing_user: User, request: HttpRequest = None):
+ """ Unrecords a dataset
Args:
performing_user (User): The user which performed the editing action
request (HttpRequest): The used request for this action
- edit_comment (str): Additional comment for the log entry
- reset_recorded (bool): Whether the record-state of the object should be reset
Returns:
"""
- edit_action = UserActionLogEntry.get_edited_action(performing_user, edit_comment)
- self.modified = edit_action
- self.log.add(edit_action)
- self.save()
-
- if self.recorded and reset_recorded:
+ action = None
+ if self.recorded:
action = self.set_unrecorded(performing_user)
self.log.add(action)
if request:
@@ -288,7 +303,7 @@ class RecordableObjectMixin(models.Model):
request,
CHECKED_RECORDED_RESET
)
- return edit_action
+ return action
@abstractmethod
def is_ready_for_publish(self) -> bool:
@@ -350,7 +365,7 @@ class CheckableObjectMixin(models.Model):
# Send mail
shared_users = self.users.all().values_list("id", flat=True)
for user_id in shared_users:
- celery_send_mail_shared_data_checked.delay(self.identifier, user_id)
+ celery_send_mail_shared_data_checked.delay(self.identifier, self.title, user_id)
self.log.add(action)
return action
@@ -464,9 +479,9 @@ class ShareableObjectMixin(models.Model):
# Send mails
for user in removed_users:
- celery_send_mail_shared_access_removed.delay(self.identifier, user["id"])
+ celery_send_mail_shared_access_removed.delay(self.identifier, self.title, user["id"])
for user in new_accessing_users:
- celery_send_mail_shared_access_given.delay(self.identifier, user)
+ celery_send_mail_shared_access_given.delay(self.identifier, self.title, user)
# Set new shared users
self.share_with_list(users)
@@ -530,3 +545,31 @@ class GeoReferencedMixin(models.Model):
message_str = GEOMETRY_CONFLICT_WITH_TEMPLATE.format(instance_identifiers)
messages.info(request, message_str)
return request
+
+ def get_LANIS_link(self) -> str:
+ """ Generates a link for LANIS depending on the geometry
+
+ Returns:
+
+ """
+ try:
+ geom = self.geometry.geom.transform(DEFAULT_SRID_RLP, clone=True)
+ x = geom.centroid.x
+ y = geom.centroid.y
+ area = int(geom.envelope.area)
+ z_l = 16
+ for k_area, v_zoom in LANIS_ZOOM_LUT.items():
+ if k_area < area:
+ z_l = v_zoom
+ break
+ zoom_lvl = z_l
+ except (AttributeError, IndexError) as e:
+ # If no geometry has been added, yet.
+ x = 1
+ y = 1
+ zoom_lvl = 6
+ return LANIS_LINK_TEMPLATE.format(
+ zoom_lvl,
+ x,
+ y,
+ )
\ No newline at end of file
diff --git a/konova/models/parcel.py b/konova/models/parcel.py
index 487225e6..9c887f1a 100644
--- a/konova/models/parcel.py
+++ b/konova/models/parcel.py
@@ -22,7 +22,7 @@ class Parcel(UuidModel):
To avoid conflicts due to german Umlaute, the field names are shortened and vocals are dropped.
"""
- geometries = models.ManyToManyField("konova.Geometry", related_name="parcels", blank=True)
+ geometries = models.ManyToManyField("konova.Geometry", blank=True, related_name="parcels", through='ParcelIntersection')
district = models.ForeignKey("konova.District", on_delete=models.SET_NULL, null=True, blank=True, related_name="parcels")
gmrkng = models.CharField(
max_length=1000,
@@ -77,3 +77,22 @@ class District(UuidModel):
def __str__(self):
return f"{self.gmnd} | {self.krs}"
+
+
+class ParcelIntersection(UuidModel):
+ """ ParcelIntersection is an intermediary model, which is used to configure the
+ M2M relation between Parcel and Geometry.
+
+ Based on uuids, we will not have (practically) any problems on outrunning primary keys
+ and extending the model with calculated_on timestamp, we can 'hide' entries while they
+ are being recalculated and keep track on the last time they have been calculated this
+ way.
+
+ Please note: The calculated_on describes when the relation between the Parcel and the Geometry
+ has been established. The updated_on field of Parcel describes when this Parcel has been
+ changed the last time.
+
+ """
+ parcel = models.ForeignKey(Parcel, on_delete=models.CASCADE)
+ geometry = models.ForeignKey("konova.Geometry", on_delete=models.CASCADE)
+ calculated_on = models.DateTimeField(auto_now_add=True, null=True, blank=True)
diff --git a/konova/static/css/konova.css b/konova/static/css/konova.css
index a10e124b..709d3eb3 100644
--- a/konova/static/css/konova.css
+++ b/konova/static/css/konova.css
@@ -219,6 +219,13 @@ Overwrites bootstrap .btn:focus box shadow color
overflow: auto;
}
+.w-20{
+ width: 20%;
+}
+.w-10{
+ width: 20%;
+}
+
/*
Extends css for django autocomplete light (dal)
No other approach worked to get the autocomplete fields to full width of parent containers
diff --git a/konova/tasks.py b/konova/tasks.py
index a463374c..c74a2bd7 100644
--- a/konova/tasks.py
+++ b/konova/tasks.py
@@ -4,13 +4,19 @@ from celery import shared_task
from django.core.exceptions import ObjectDoesNotExist
-
@shared_task
def celery_update_parcels(geometry_id: str, recheck: bool = True):
- from konova.models import Geometry
+ from konova.models import Geometry, ParcelIntersection
try:
geom = Geometry.objects.get(id=geometry_id)
- geom.parcels.clear()
+ objs = geom.parcelintersection_set.all()
+ for obj in objs:
+ obj.calculated_on = None
+ ParcelIntersection.objects.bulk_update(
+ objs,
+ ["calculated_on"]
+ )
+
geom.update_parcels()
except ObjectDoesNotExist:
if recheck:
@@ -19,42 +25,42 @@ def celery_update_parcels(geometry_id: str, recheck: bool = True):
@shared_task
-def celery_send_mail_shared_access_removed(obj_identifier, user_id):
+def celery_send_mail_shared_access_removed(obj_identifier, obj_title=None, user_id=None):
from user.models import User
user = User.objects.get(id=user_id)
- user.send_mail_shared_access_removed(obj_identifier)
+ user.send_mail_shared_access_removed(obj_identifier, obj_title)
@shared_task
-def celery_send_mail_shared_access_given(obj_identifier, user_id):
+def celery_send_mail_shared_access_given(obj_identifier, obj_title=None, user_id=None):
from user.models import User
user = User.objects.get(id=user_id)
- user.send_mail_shared_access_given(obj_identifier)
+ user.send_mail_shared_access_given(obj_identifier, obj_title)
@shared_task
-def celery_send_mail_shared_data_recorded(obj_identifier, user_id):
+def celery_send_mail_shared_data_recorded(obj_identifier, obj_title=None, user_id=None):
from user.models import User
user = User.objects.get(id=user_id)
- user.send_mail_shared_data_recorded(obj_identifier)
+ user.send_mail_shared_data_recorded(obj_identifier, obj_title)
@shared_task
-def celery_send_mail_shared_data_unrecorded(obj_identifier, user_id):
+def celery_send_mail_shared_data_unrecorded(obj_identifier, obj_title=None, user_id=None):
from user.models import User
user = User.objects.get(id=user_id)
- user.send_mail_shared_data_unrecorded(obj_identifier)
+ user.send_mail_shared_data_unrecorded(obj_identifier, obj_title)
@shared_task
-def celery_send_mail_shared_data_deleted(obj_identifier, user_id):
+def celery_send_mail_shared_data_deleted(obj_identifier, obj_title=None, user_id=None):
from user.models import User
user = User.objects.get(id=user_id)
- user.send_mail_shared_data_deleted(obj_identifier)
+ user.send_mail_shared_data_deleted(obj_identifier, obj_title)
@shared_task
-def celery_send_mail_shared_data_checked(obj_identifier, user_id):
+def celery_send_mail_shared_data_checked(obj_identifier, obj_title=None, user_id=None):
from user.models import User
user = User.objects.get(id=user_id)
- user.send_mail_shared_data_checked(obj_identifier)
+ user.send_mail_shared_data_checked(obj_identifier, obj_title)
diff --git a/konova/tests/test_views.py b/konova/tests/test_views.py
index 1bf33325..6218a6c0 100644
--- a/konova/tests/test_views.py
+++ b/konova/tests/test_views.py
@@ -7,6 +7,7 @@ Created on: 26.10.21
"""
import datetime
+from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID
from ema.models import Ema
from user.models import User
from django.contrib.auth.models import Group
@@ -15,7 +16,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.test import TestCase, Client
from django.urls import reverse
-from codelist.models import KonovaCode
+from codelist.models import KonovaCode, KonovaCodeList
from compensation.models import Compensation, CompensationState, CompensationAction, EcoAccount, EcoAccountDeduction
from intervention.models import Legal, Responsibility, Intervention
from konova.management.commands.setup_data import GROUPS_DATA
@@ -46,43 +47,58 @@ class BaseTestCase(TestCase):
class Meta:
abstract = True
- @classmethod
- def setUpTestData(cls):
- cls.create_users()
- cls.create_groups()
- cls.intervention = cls.create_dummy_intervention()
- cls.compensation = cls.create_dummy_compensation()
- cls.eco_account = cls.create_dummy_eco_account()
- cls.ema = cls.create_dummy_ema()
- cls.deduction = cls.create_dummy_deduction()
- cls.create_dummy_states()
- cls.create_dummy_action()
- cls.codes = cls.create_dummy_codes()
+ def setUp(self) -> None:
+ """ Setup data before each test run
- @classmethod
- def create_users(cls):
+ Returns:
+
+ """
+ super().setUp()
+
+ self.create_users()
+ self.create_groups()
+ self.intervention = self.create_dummy_intervention()
+ self.compensation = self.create_dummy_compensation()
+ self.eco_account = self.create_dummy_eco_account()
+ self.ema = self.create_dummy_ema()
+ self.deduction = self.create_dummy_deduction()
+ self.create_dummy_states()
+ self.create_dummy_action()
+ self.codes = self.create_dummy_codes()
+
+ # Set the default group as only group for the user
+ default_group = self.groups.get(name=DEFAULT_GROUP)
+ self.superuser.groups.set([default_group])
+
+ # Create fresh logged in client and a non-logged in client (anon) for each test
+ self.client_user = Client()
+ self.client_user.login(username=self.superuser.username, password=self.superuser_pw)
+ self.client_anon = Client()
+
+
+ def create_users(self):
# Create superuser and regular user
- cls.superuser = User.objects.create_superuser(
+ self.superuser = User.objects.create_superuser(
username="root",
email="root@root.com",
- password=cls.superuser_pw,
+ password=self.superuser_pw,
)
- cls.user = User.objects.create_user(
+ self.user = User.objects.create_user(
username="user1",
email="user@root.com",
- password=cls.user_pw
+ password=self.user_pw
)
- cls.users = User.objects.all()
+ self.users = User.objects.all()
- @classmethod
- def create_groups(cls):
+
+ def create_groups(self):
# Create groups
for group_data in GROUPS_DATA:
name = group_data.get("name")
Group.objects.get_or_create(
name=name,
)
- cls.groups = Group.objects.all()
+ self.groups = Group.objects.all()
@staticmethod
def create_dummy_string(prefix: str = ""):
@@ -93,8 +109,7 @@ class BaseTestCase(TestCase):
"""
return f"{prefix}{generate_random_string(3, True)}"
- @classmethod
- def create_dummy_intervention(cls):
+ def create_dummy_intervention(self):
""" Creates an intervention which can be used for tests
Returns:
@@ -102,7 +117,7 @@ class BaseTestCase(TestCase):
"""
# Create dummy data
# Create log entry
- action = UserActionLogEntry.get_created_action(cls.superuser)
+ action = UserActionLogEntry.get_created_action(self.superuser)
# Create legal data object (without M2M laws first)
legal_data = Legal.objects.create()
# Create responsible data object
@@ -121,32 +136,30 @@ class BaseTestCase(TestCase):
intervention.generate_access_token(make_unique=True)
return intervention
- @classmethod
- def create_dummy_compensation(cls):
+ def create_dummy_compensation(self):
""" Creates a compensation which can be used for tests
Returns:
"""
- if cls.intervention is None:
- cls.intervention = cls.create_dummy_intervention()
+ if self.intervention is None:
+ self.intervention = self.create_dummy_intervention()
# Create dummy data
# Create log entry
- action = UserActionLogEntry.get_created_action(cls.superuser)
+ action = UserActionLogEntry.get_created_action(self.superuser)
geometry = Geometry.objects.create()
# Finally create main object, holding the other objects
compensation = Compensation.objects.create(
identifier="TEST",
title="Test_title",
- intervention=cls.intervention,
+ intervention=self.intervention,
created=action,
geometry=geometry,
comment="Test",
)
return compensation
- @classmethod
- def create_dummy_eco_account(cls):
+ def create_dummy_eco_account(self):
""" Creates an eco account which can be used for tests
Returns:
@@ -154,7 +167,7 @@ class BaseTestCase(TestCase):
"""
# Create dummy data
# Create log entry
- action = UserActionLogEntry.get_created_action(cls.superuser)
+ action = UserActionLogEntry.get_created_action(self.superuser)
geometry = Geometry.objects.create()
# Create responsible data object
lega_data = Legal.objects.create()
@@ -171,8 +184,7 @@ class BaseTestCase(TestCase):
)
return eco_account
- @classmethod
- def create_dummy_ema(cls):
+ def create_dummy_ema(self):
""" Creates an ema which can be used for tests
Returns:
@@ -180,7 +192,7 @@ class BaseTestCase(TestCase):
"""
# Create dummy data
# Create log entry
- action = UserActionLogEntry.get_created_action(cls.superuser)
+ action = UserActionLogEntry.get_created_action(self.superuser)
geometry = Geometry.objects.create()
# Create responsible data object
responsible_data = Responsibility.objects.create()
@@ -195,51 +207,47 @@ class BaseTestCase(TestCase):
)
return ema
- @classmethod
- def create_dummy_deduction(cls):
+ def create_dummy_deduction(self):
return EcoAccountDeduction.objects.create(
- account=cls.create_dummy_eco_account(),
- intervention=cls.create_dummy_intervention(),
+ account=self.create_dummy_eco_account(),
+ intervention=self.create_dummy_intervention(),
surface=100,
)
- @classmethod
- def create_dummy_states(cls):
+ def create_dummy_states(self):
""" Creates an intervention which can be used for tests
Returns:
"""
- cls.comp_state = CompensationState.objects.create(
+ self.comp_state = CompensationState.objects.create(
surface=10.00,
biotope_type=None,
)
- return cls.comp_state
+ return self.comp_state
- @classmethod
- def create_dummy_action(cls):
+ def create_dummy_action(self):
""" Creates an intervention which can be used for tests
Returns:
"""
- cls.comp_action = CompensationAction.objects.create(
+ self.comp_action = CompensationAction.objects.create(
amount=10
)
- return cls.comp_action
+ return self.comp_action
- @classmethod
- def create_dummy_codes(cls):
+ def create_dummy_codes(self):
""" Creates some dummy KonovaCodes which can be used for testing
Returns:
"""
codes = KonovaCode.objects.bulk_create([
- KonovaCode(id=1, is_selectable=True, long_name="Test1"),
- KonovaCode(id=2, is_selectable=True, long_name="Test2"),
- KonovaCode(id=3, is_selectable=True, long_name="Test3"),
- KonovaCode(id=4, is_selectable=True, long_name="Test4"),
+ KonovaCode(id=1, is_selectable=True, is_archived=False, is_leaf=True, long_name="Test1"),
+ KonovaCode(id=2, is_selectable=True, is_archived=False, is_leaf=True, long_name="Test2"),
+ KonovaCode(id=3, is_selectable=True, is_archived=False, is_leaf=True, long_name="Test3"),
+ KonovaCode(id=4, is_selectable=True, is_archived=False, is_leaf=True, long_name="Test4"),
])
return codes
@@ -255,8 +263,7 @@ class BaseTestCase(TestCase):
polygon = polygon.transform(3857, clone=True)
return MultiPolygon(polygon, srid=3857) # 3857 is the default srid used for MultiPolygonField in the form
- @classmethod
- def fill_out_intervention(cls, intervention: Intervention) -> Intervention:
+ def fill_out_intervention(self, intervention: Intervention) -> Intervention:
""" Adds all required (dummy) data to an intervention
Args:
@@ -276,13 +283,12 @@ class BaseTestCase(TestCase):
intervention.legal.process_type = KonovaCode.objects.get(id=3)
intervention.legal.save()
intervention.legal.laws.set([KonovaCode.objects.get(id=(4))])
- intervention.geometry.geom = cls.create_dummy_geometry()
+ intervention.geometry.geom = self.create_dummy_geometry()
intervention.geometry.save()
intervention.save()
return intervention
- @classmethod
- def fill_out_compensation(cls, compensation: Compensation) -> Compensation:
+ def fill_out_compensation(self, compensation: Compensation) -> Compensation:
""" Adds all required (dummy) data to a compensation
Args:
@@ -291,13 +297,62 @@ class BaseTestCase(TestCase):
Returns:
compensation (Compensation): The modified compensation
"""
- compensation.after_states.add(cls.comp_state)
- compensation.before_states.add(cls.comp_state)
- compensation.actions.add(cls.comp_action)
- compensation.geometry.geom = cls.create_dummy_geometry()
+ compensation.after_states.add(self.comp_state)
+ compensation.before_states.add(self.comp_state)
+ compensation.actions.add(self.comp_action)
+ compensation.geometry.geom = self.create_dummy_geometry()
compensation.geometry.save()
return compensation
+ def get_conservation_office_code(self):
+ """ Returns a dummy KonovaCode as conservation office code
+
+ Returns:
+
+ """
+ codelist = KonovaCodeList.objects.get_or_create(
+ id=CODELIST_CONSERVATION_OFFICE_ID
+ )[0]
+ code = KonovaCode.objects.get(id=2)
+ codelist.codes.add(code)
+ return code
+
+ def fill_out_ema(self, ema):
+ """ Adds all required (dummy) data to an Ema
+
+ Returns:
+ """
+ ema.responsible.conservation_office = self.get_conservation_office_code()
+ ema.responsible.conservation_file_number = "test"
+ ema.responsible.handler = "handler"
+ ema.responsible.save()
+ ema.after_states.add(self.comp_state)
+ ema.before_states.add(self.comp_state)
+ ema.actions.add(self.comp_action)
+ ema.geometry.geom = self.create_dummy_geometry()
+ ema.geometry.save()
+ return ema
+
+ def fill_out_eco_account(self, eco_account):
+ """ Adds all required (dummy) data to an EcoAccount
+
+ Returns:
+ """
+ eco_account.legal.registration_date = "2022-01-01"
+ eco_account.legal.save()
+ eco_account.responsible.conservation_office = self.get_conservation_office_code()
+ eco_account.responsible.conservation_file_number = "test"
+ eco_account.responsible.handler = "handler"
+ eco_account.responsible.save()
+ eco_account.after_states.add(self.comp_state)
+ eco_account.before_states.add(self.comp_state)
+ eco_account.actions.add(self.comp_action)
+ eco_account.geometry.geom = self.create_dummy_geometry()
+ eco_account.geometry.save()
+ eco_account.deductable_surface = eco_account.get_state_after_surface_sum()
+ eco_account.save()
+ return eco_account
+
def assert_equal_geometries(self, geom1: MultiPolygon, geom2: MultiPolygon):
""" Assert for geometries to be equal
@@ -337,7 +392,10 @@ class BaseViewTestCase(BaseTestCase):
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
- cls.login_url = reverse("simple-sso-login")
+
+ def setUp(self) -> None:
+ super().setUp()
+ self.login_url = reverse("simple-sso-login")
def assert_url_success(self, client: Client, urls: list):
""" Assert for all given urls a direct 200 response
@@ -496,21 +554,6 @@ class BaseWorkflowTestCase(BaseTestCase):
def setUpTestData(cls):
super().setUpTestData()
- def setUp(self) -> None:
- """ Setup data before each test run
-
- Returns:
-
- """
- # Set the default group as only group for the user
- default_group = self.groups.get(name=DEFAULT_GROUP)
- self.superuser.groups.set([default_group])
-
- # Create fresh logged in client and a non-logged in client (anon) for each test
- self.client_user = Client()
- self.client_user.login(username=self.superuser.username, password=self.superuser_pw)
- self.client_anon = Client()
-
def assert_object_is_deleted(self, obj):
""" Provides a quick check whether an object has been removed from the database or not
diff --git a/konova/utils/documents.py b/konova/utils/documents.py
index 63a7d328..f9b15160 100644
--- a/konova/utils/documents.py
+++ b/konova/utils/documents.py
@@ -50,5 +50,5 @@ def remove_document(request: HttpRequest, doc: AbstractDocument):
form = RemoveModalForm(request.POST or None, instance=doc, request=request)
return form.process_request(
request=request,
- msg_success=DOCUMENT_REMOVED_TEMPLATE.format(title)
+ msg_success=DOCUMENT_REMOVED_TEMPLATE.format(title),
)
\ No newline at end of file
diff --git a/konova/utils/mailer.py b/konova/utils/mailer.py
index e174ae56..33907f3c 100644
--- a/konova/utils/mailer.py
+++ b/konova/utils/mailer.py
@@ -45,11 +45,12 @@ class Mailer:
auth_password=self.auth_password
)
- def send_mail_shared_access_removed(self, obj_identifier, user):
+ def send_mail_shared_access_removed(self, obj_identifier, obj_title, user):
""" Send a mail if user has no access to the object anymore
Args:
obj_identifier (str): The object identifier
+ obj_title (str): The object title
Returns:
@@ -57,6 +58,7 @@ class Mailer:
context = {
"user": user,
"obj_identifier": obj_identifier,
+ "obj_title": obj_title,
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
}
msg = render_to_string("email/sharing/shared_access_removed.html", context)
@@ -67,7 +69,7 @@ class Mailer:
msg
)
- def send_mail_shared_access_given(self, obj_identifier, user):
+ def send_mail_shared_access_given(self, obj_identifier, obj_title, user):
""" Send a mail if user just got access to the object
Args:
@@ -79,6 +81,7 @@ class Mailer:
context = {
"user": user,
"obj_identifier": obj_identifier,
+ "obj_title": obj_title,
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
}
msg = render_to_string("email/sharing/shared_access_given.html", context)
@@ -89,7 +92,7 @@ class Mailer:
msg
)
- def send_mail_shared_data_recorded(self, obj_identifier, user):
+ def send_mail_shared_data_recorded(self, obj_identifier, obj_title, user):
""" Send a mail if the user's shared data has just been unrecorded
Args:
@@ -101,6 +104,7 @@ class Mailer:
context = {
"user": user,
"obj_identifier": obj_identifier,
+ "obj_title": obj_title,
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
}
msg = render_to_string("email/recording/shared_data_recorded.html", context)
@@ -111,7 +115,7 @@ class Mailer:
msg
)
- def send_mail_shared_data_unrecorded(self, obj_identifier, user):
+ def send_mail_shared_data_unrecorded(self, obj_identifier, obj_title, user):
""" Send a mail if the user's shared data has just been unrecorded
Args:
@@ -123,6 +127,7 @@ class Mailer:
context = {
"user": user,
"obj_identifier": obj_identifier,
+ "obj_title": obj_title,
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
}
msg = render_to_string("email/recording/shared_data_unrecorded.html", context)
@@ -133,7 +138,7 @@ class Mailer:
msg
)
- def send_mail_shared_data_deleted(self, obj_identifier, user):
+ def send_mail_shared_data_deleted(self, obj_identifier, obj_title, user):
""" Send a mail if shared data has just been deleted
Args:
@@ -145,6 +150,7 @@ class Mailer:
context = {
"user": user,
"obj_identifier": obj_identifier,
+ "obj_title": obj_title,
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
}
msg = render_to_string("email/deleting/shared_data_deleted.html", context)
@@ -155,7 +161,7 @@ class Mailer:
msg
)
- def send_mail_shared_data_checked(self, obj_identifier, user):
+ def send_mail_shared_data_checked(self, obj_identifier, obj_title, user):
""" Send a mail if shared data just has been checked
Args:
@@ -167,6 +173,7 @@ class Mailer:
context = {
"user": user,
"obj_identifier": obj_identifier,
+ "obj_title": obj_title,
"EMAIL_REPLY_TO": EMAIL_REPLY_TO,
}
msg = render_to_string("email/checking/shared_data_checked.html", context)
diff --git a/konova/utils/message_templates.py b/konova/utils/message_templates.py
index 79a190ca..c7a2be00 100644
--- a/konova/utils/message_templates.py
+++ b/konova/utils/message_templates.py
@@ -18,34 +18,61 @@ MISSING_GROUP_PERMISSION = _("You need to be part of another user group.")
CHECKED_RECORDED_RESET = _("Status of Checked and Recorded reseted")
+# FILES
+FILE_TYPE_UNSUPPORTED = _("Unsupported file type")
+FILE_SIZE_TOO_LARGE = _("File too large")
+
# ECO ACCOUNT
CANCEL_ACC_RECORDED_OR_DEDUCTED = _("Action canceled. Eco account is recorded or deductions exist. Only conservation office member can perform this action.")
# COMPENSATION
COMPENSATION_ADDED_TEMPLATE = _("Compensation {} added")
COMPENSATION_REMOVED_TEMPLATE = _("Compensation {} removed")
+COMPENSATION_EDITED_TEMPLATE = _("Compensation {} edited")
+ADDED_COMPENSATION_ACTION = _("Added compensation action")
+ADDED_COMPENSATION_STATE = _("Added compensation state")
+
+# COMPENSATION STATE
+COMPENSATION_STATE_REMOVED = _("State removed")
+COMPENSATION_STATE_EDITED = _("State edited")
+COMPENSATION_STATE_ADDED = _("State added")
+
+# COMPENSATION ACTION
+COMPENSATION_ACTION_ADDED = _("Action added")
+COMPENSATION_ACTION_EDITED = _("Action edited")
+COMPENSATION_ACTION_REMOVED = _("Action removed")
# DEDUCTIONS
DEDUCTION_ADDED = _("Deduction added")
+DEDUCTION_EDITED = _("Deduction edited")
DEDUCTION_REMOVED = _("Deduction removed")
+# DEADLINE
+DEADLINE_ADDED = _("Deadline added")
+DEADLINE_EDITED = _("Deadline edited")
+DEADLINE_REMOVED = _("Deadline removed")
+
# PAYMENTS
PAYMENT_ADDED = _("Payment added")
+PAYMENT_EDITED = _("Payment edited")
PAYMENT_REMOVED = _("Payment removed")
# REVOCATIONS
REVOCATION_ADDED = _("Revocation added")
+REVOCATION_EDITED = _("Revocation edited")
REVOCATION_REMOVED = _("Revocation removed")
# DOCUMENTS
DOCUMENT_REMOVED_TEMPLATE = _("Document '{}' deleted")
DOCUMENT_ADDED = _("Document added")
+DOCUMENT_EDITED = _("Document edited")
# Edited
EDITED_GENERAL_DATA = _("Edited general data")
-ADDED_COMPENSATION_STATE = _("Added compensation state")
ADDED_DEADLINE = _("Added deadline")
-ADDED_COMPENSATION_ACTION = _("Added compensation action")
# Geometry conflicts
GEOMETRY_CONFLICT_WITH_TEMPLATE = _("Geometry conflict detected with {}")
+
+# INTERVENTION
+INTERVENTION_HAS_REVOCATIONS_TEMPLATE = _("This intervention has {} revocations")
diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo
index 23892cf8..99058358 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 65808d43..cd7cd88f 100644
--- a/locale/de/LC_MESSAGES/django.po
+++ b/locale/de/LC_MESSAGES/django.po
@@ -5,10 +5,10 @@
#
#: compensation/filters.py:122 compensation/forms/modalForms.py:35
#: compensation/forms/modalForms.py:46 compensation/forms/modalForms.py:62
-#: compensation/forms/modalForms.py:256 compensation/forms/modalForms.py:350
+#: compensation/forms/modalForms.py:355 compensation/forms/modalForms.py:471
#: intervention/forms/forms.py:54 intervention/forms/forms.py:156
-#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:124
-#: intervention/forms/modalForms.py:137 intervention/forms/modalForms.py:150
+#: intervention/forms/forms.py:168 intervention/forms/modalForms.py:127
+#: intervention/forms/modalForms.py:140 intervention/forms/modalForms.py:153
#: konova/filters/mixins.py:53 konova/filters/mixins.py:54
#: konova/filters/mixins.py:81 konova/filters/mixins.py:82
#: konova/filters/mixins.py:94 konova/filters/mixins.py:95
@@ -18,15 +18,15 @@
#: konova/filters/mixins.py:270 konova/filters/mixins.py:315
#: konova/filters/mixins.py:353 konova/filters/mixins.py:354
#: konova/filters/mixins.py:385 konova/filters/mixins.py:386
-#: konova/forms.py:140 konova/forms.py:241 konova/forms.py:312
-#: konova/forms.py:339 konova/forms.py:349 konova/forms.py:362
-#: konova/forms.py:374 konova/forms.py:392 user/forms.py:42
+#: konova/forms.py:143 konova/forms.py:244 konova/forms.py:315
+#: konova/forms.py:359 konova/forms.py:369 konova/forms.py:382
+#: konova/forms.py:394 konova/forms.py:412 user/forms.py:42
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2022-02-03 13:37+0100\n"
+"POT-Creation-Date: 2022-02-10 13:31+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -63,7 +63,7 @@ msgstr "Verantwortliche Stelle"
#: analysis/forms.py:58 compensation/forms/forms.py:88
#: compensation/forms/forms.py:165 intervention/forms/forms.py:64
#: intervention/forms/forms.py:81 intervention/forms/forms.py:97
-#: intervention/forms/forms.py:113 intervention/forms/modalForms.py:46
+#: intervention/forms/forms.py:113 intervention/forms/modalForms.py:49
msgid "Click for selection"
msgstr "Auswählen..."
@@ -75,7 +75,7 @@ msgstr "Bericht generieren"
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:188
+#: analysis/forms.py:69 konova/forms.py:191
msgid "Continue"
msgstr "Weiter"
@@ -95,7 +95,7 @@ msgstr ""
#: 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:334
+#: compensation/forms/modalForms.py:455
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
#: intervention/templates/intervention/detail/includes/deductions.html:31
msgid "Amount"
@@ -136,9 +136,9 @@ msgstr "Zuständigkeitsbereich"
#: 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/tables.py:40
#: compensation/templates/compensation/detail/compensation/view.html:63
-#: intervention/tables.py:33
+#: intervention/tables.py:39
#: intervention/templates/intervention/detail/view.html:68
#: user/models/user_action.py:20
msgid "Checked"
@@ -152,12 +152,12 @@ msgstr "Geprüft"
#: 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:182
+#: compensation/tables.py:46 compensation/tables.py:222
#: compensation/templates/compensation/detail/compensation/view.html:77
#: 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:35
-#: intervention/tables.py:39
+#: ema/tables.py:44 ema/templates/ema/detail/view.html:35
+#: intervention/tables.py:45
#: intervention/templates/intervention/detail/view.html:82
#: user/models/user_action.py:21
msgid "Recorded"
@@ -196,7 +196,7 @@ msgid "Other registration office"
msgstr "Andere Zulassungsbehörden"
#: analysis/templates/analysis/reports/includes/compensation/card_compensation.html:11
-#: compensation/tables.py:62
+#: compensation/tables.py:67
#: intervention/templates/intervention/detail/includes/compensations.html:8
#: intervention/templates/intervention/report/report.html:49
msgid "Compensations"
@@ -213,14 +213,14 @@ 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:151
+#: compensation/forms/modalForms.py:193
#: 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:294
+#: intervention/forms/modalForms.py:338
msgid "Surface"
msgstr "Fläche"
@@ -239,7 +239,6 @@ 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:85
#: compensation/templates/compensation/detail/compensation/view.html:19
#: konova/templates/konova/includes/quickstart/compensations.html:4
#: templates/navbars/navbar.html:28
@@ -284,8 +283,8 @@ msgid "Type"
msgstr "Typ"
#: analysis/templates/analysis/reports/includes/old_data/amount.html:24
-#: intervention/forms/modalForms.py:305 intervention/forms/modalForms.py:312
-#: intervention/tables.py:89
+#: compensation/tables.py:89 intervention/forms/modalForms.py:349
+#: intervention/forms/modalForms.py:356 intervention/tables.py:88
#: intervention/templates/intervention/detail/view.html:19
#: konova/templates/konova/includes/quickstart/interventions.html:4
#: templates/navbars/navbar.html:22
@@ -293,9 +292,9 @@ msgid "Intervention"
msgstr "Eingriff"
#: analysis/templates/analysis/reports/includes/old_data/amount.html:34
-#: compensation/tables.py:226
+#: compensation/tables.py:266
#: compensation/templates/compensation/detail/eco_account/view.html:19
-#: intervention/forms/modalForms.py:278 intervention/forms/modalForms.py:285
+#: intervention/forms/modalForms.py:322 intervention/forms/modalForms.py:329
#: konova/templates/konova/includes/quickstart/ecoaccounts.html:4
#: templates/navbars/navbar.html:34
msgid "Eco-account"
@@ -314,8 +313,8 @@ msgid "Show only unrecorded"
msgstr "Nur unverzeichnete anzeigen"
#: compensation/forms/forms.py:32 compensation/tables.py:25
-#: compensation/tables.py:167 ema/tables.py:28 intervention/forms/forms.py:28
-#: intervention/tables.py:23
+#: compensation/tables.py:197 ema/tables.py:29 intervention/forms/forms.py:28
+#: intervention/tables.py:24
#: intervention/templates/intervention/detail/includes/compensations.html:30
msgid "Identifier"
msgstr "Kennung"
@@ -326,22 +325,22 @@ msgid "Generated automatically"
msgstr "Automatisch generiert"
#: compensation/forms/forms.py:44 compensation/tables.py:30
-#: compensation/tables.py:172
+#: compensation/tables.py:202
#: 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
#: compensation/templates/compensation/detail/eco_account/view.html:31
#: compensation/templates/compensation/report/compensation/report.html:12
#: compensation/templates/compensation/report/eco_account/report.html:12
-#: ema/tables.py:33 ema/templates/ema/detail/includes/documents.html:28
+#: ema/tables.py:34 ema/templates/ema/detail/includes/documents.html:28
#: ema/templates/ema/detail/view.html:31
#: ema/templates/ema/report/report.html:12 intervention/forms/forms.py:40
-#: intervention/tables.py:28
+#: intervention/tables.py:29
#: intervention/templates/intervention/detail/includes/compensations.html:33
#: 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:338
+#: konova/forms.py:358
msgid "Title"
msgstr "Bezeichnung"
@@ -354,25 +353,25 @@ msgid "Compensation XY; Location ABC"
msgstr "Kompensation XY; Flur ABC"
#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:61
-#: compensation/forms/modalForms.py:255 compensation/forms/modalForms.py:349
+#: compensation/forms/modalForms.py:354 compensation/forms/modalForms.py:470
#: compensation/templates/compensation/detail/compensation/includes/actions.html:35
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:34
-#: compensation/templates/compensation/detail/compensation/includes/documents.html:31
+#: compensation/templates/compensation/detail/compensation/includes/documents.html:34
#: compensation/templates/compensation/detail/eco_account/includes/actions.html:34
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:34
-#: compensation/templates/compensation/detail/eco_account/includes/documents.html:31
+#: compensation/templates/compensation/detail/eco_account/includes/documents.html:34
#: ema/templates/ema/detail/includes/actions.html:34
#: ema/templates/ema/detail/includes/deadlines.html:34
-#: ema/templates/ema/detail/includes/documents.html:31
-#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:149
-#: intervention/templates/intervention/detail/includes/documents.html:31
+#: ema/templates/ema/detail/includes/documents.html:34
+#: intervention/forms/forms.py:180 intervention/forms/modalForms.py:152
+#: intervention/templates/intervention/detail/includes/documents.html:34
#: intervention/templates/intervention/detail/includes/payments.html:34
#: intervention/templates/intervention/detail/includes/revocation.html:38
-#: konova/forms.py:373 konova/templates/konova/includes/comment_card.html:16
+#: konova/forms.py:393 konova/templates/konova/includes/comment_card.html:16
msgid "Comment"
msgstr "Kommentar"
-#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:351
+#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:472
#: intervention/forms/forms.py:182
msgid "Additional comment"
msgstr "Zusätzlicher Kommentar"
@@ -432,7 +431,7 @@ msgstr "kompensiert Eingriff"
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:184 compensation/views/compensation.py:92
+#: compensation/forms/forms.py:184 compensation/views/compensation.py:96
msgid "New compensation"
msgstr "Neue Kompensation"
@@ -458,7 +457,7 @@ msgstr "Vereinbarungsdatum"
msgid "When did the parties agree on this?"
msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
-#: compensation/forms/forms.py:354 compensation/views/eco_account.py:102
+#: compensation/forms/forms.py:354 compensation/views/eco_account.py:107
msgid "New Eco-Account"
msgstr "Neues Ökokonto"
@@ -483,8 +482,8 @@ msgstr "Fällig am"
msgid "Due on which date"
msgstr "Zahlung wird an diesem Datum erwartet"
-#: compensation/forms/modalForms.py:63 compensation/forms/modalForms.py:257
-#: intervention/forms/modalForms.py:151 konova/forms.py:375
+#: compensation/forms/modalForms.py:63 compensation/forms/modalForms.py:356
+#: intervention/forms/modalForms.py:154 konova/forms.py:395
msgid "Additional comment, maximum {} letters"
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
@@ -496,156 +495,152 @@ msgstr "Neue Ersatzzahlung zu Eingriff '{}' hinzufügen"
msgid "If there is no date you can enter, please explain why."
msgstr "Falls Sie kein Datum angeben können, erklären Sie bitte weshalb."
-#: compensation/forms/modalForms.py:115 compensation/forms/modalForms.py:127
+#: compensation/forms/modalForms.py:157 compensation/forms/modalForms.py:169
msgid "Biotope Type"
msgstr "Biotoptyp"
-#: compensation/forms/modalForms.py:118
+#: compensation/forms/modalForms.py:160
msgid "Select the biotope type"
msgstr "Biotoptyp wählen"
-#: compensation/forms/modalForms.py:132 compensation/forms/modalForms.py:144
+#: compensation/forms/modalForms.py:174 compensation/forms/modalForms.py:186
msgid "Biotope additional type"
msgstr "Zusatzbezeichnung"
-#: compensation/forms/modalForms.py:135
+#: compensation/forms/modalForms.py:177
msgid "Select an additional biotope type"
msgstr "Zusatzbezeichnung wählen"
-#: compensation/forms/modalForms.py:154 intervention/forms/modalForms.py:296
+#: compensation/forms/modalForms.py:196 intervention/forms/modalForms.py:340
msgid "in m²"
msgstr ""
-#: compensation/forms/modalForms.py:165
+#: compensation/forms/modalForms.py:207
msgid "New state"
msgstr "Neuer Zustand"
-#: compensation/forms/modalForms.py:166
+#: compensation/forms/modalForms.py:208
msgid "Insert data for the new state"
msgstr "Geben Sie die Daten des neuen Zustandes ein"
-#: compensation/forms/modalForms.py:173 konova/forms.py:190
+#: compensation/forms/modalForms.py:215 konova/forms.py:193
msgid "Object removed"
msgstr "Objekt entfernt"
-#: compensation/forms/modalForms.py:227
+#: compensation/forms/modalForms.py:326
msgid "Deadline Type"
msgstr "Fristart"
-#: compensation/forms/modalForms.py:230
+#: compensation/forms/modalForms.py:329
msgid "Select the deadline type"
msgstr "Fristart wählen"
-#: compensation/forms/modalForms.py:239
+#: compensation/forms/modalForms.py:338
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:31
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:31
#: ema/templates/ema/detail/includes/deadlines.html:31
-#: intervention/forms/modalForms.py:123
+#: intervention/forms/modalForms.py:126
msgid "Date"
msgstr "Datum"
-#: compensation/forms/modalForms.py:242
+#: compensation/forms/modalForms.py:341
msgid "Select date"
msgstr "Datum wählen"
-#: compensation/forms/modalForms.py:269
+#: compensation/forms/modalForms.py:368
msgid "New deadline"
msgstr "Neue Frist"
-#: compensation/forms/modalForms.py:270
+#: compensation/forms/modalForms.py:369
msgid "Insert data for the new deadline"
msgstr "Geben Sie die Daten der neuen Frist ein"
-#: compensation/forms/modalForms.py:288
+#: compensation/forms/modalForms.py:409
msgid "Action Type"
msgstr "Maßnahmentyp"
-#: compensation/forms/modalForms.py:291
+#: compensation/forms/modalForms.py:412
msgid "Select the action type"
msgstr "Maßnahmentyp wählen"
-#: compensation/forms/modalForms.py:300
+#: compensation/forms/modalForms.py:421
#: compensation/templates/compensation/detail/compensation/includes/actions.html:40
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:39
-#: compensation/templates/compensation/detail/compensation/includes/documents.html:36
+#: compensation/templates/compensation/detail/compensation/includes/documents.html:39
#: compensation/templates/compensation/detail/compensation/includes/states-after.html:41
#: compensation/templates/compensation/detail/compensation/includes/states-before.html:41
#: compensation/templates/compensation/detail/eco_account/includes/actions.html:39
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:38
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:41
-#: compensation/templates/compensation/detail/eco_account/includes/documents.html:35
+#: compensation/templates/compensation/detail/eco_account/includes/documents.html:38
#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:41
#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:41
#: ema/templates/ema/detail/includes/actions.html:38
#: ema/templates/ema/detail/includes/deadlines.html:38
-#: ema/templates/ema/detail/includes/documents.html:35
+#: ema/templates/ema/detail/includes/documents.html:38
#: ema/templates/ema/detail/includes/states-after.html:40
#: ema/templates/ema/detail/includes/states-before.html:40
#: intervention/templates/intervention/detail/includes/compensations.html:38
#: intervention/templates/intervention/detail/includes/deductions.html:39
-#: intervention/templates/intervention/detail/includes/documents.html:36
+#: intervention/templates/intervention/detail/includes/documents.html:39
#: intervention/templates/intervention/detail/includes/payments.html:39
#: intervention/templates/intervention/detail/includes/revocation.html:43
#: templates/log.html:10
msgid "Action"
msgstr "Aktionen"
-#: compensation/forms/modalForms.py:305 compensation/forms/modalForms.py:317
+#: compensation/forms/modalForms.py:426 compensation/forms/modalForms.py:438
msgid "Action Type detail"
msgstr "Zusatzmerkmal"
-#: compensation/forms/modalForms.py:308
+#: compensation/forms/modalForms.py:429
msgid "Select the action type detail"
msgstr "Zusatzmerkmal wählen"
-#: compensation/forms/modalForms.py:322
+#: compensation/forms/modalForms.py:443
msgid "Unit"
msgstr "Einheit"
-#: compensation/forms/modalForms.py:325
+#: compensation/forms/modalForms.py:446
msgid "Select the unit"
msgstr "Einheit wählen"
-#: compensation/forms/modalForms.py:337
+#: compensation/forms/modalForms.py:458
msgid "Insert the amount"
msgstr "Menge eingeben"
-#: compensation/forms/modalForms.py:362
+#: compensation/forms/modalForms.py:483
msgid "New action"
msgstr "Neue Maßnahme"
-#: compensation/forms/modalForms.py:363
+#: compensation/forms/modalForms.py:484
msgid "Insert data for the new action"
msgstr "Geben Sie die Daten der neuen Maßnahme ein"
-#: compensation/models/action.py:21
+#: compensation/models/action.py:22
msgid "cm"
msgstr ""
-#: compensation/models/action.py:22
+#: compensation/models/action.py:23
msgid "m"
msgstr ""
-#: compensation/models/action.py:23
+#: compensation/models/action.py:24
msgid "km"
msgstr ""
-#: compensation/models/action.py:24
+#: compensation/models/action.py:25
msgid "m²"
msgstr ""
-#: compensation/models/action.py:25
+#: compensation/models/action.py:26
msgid "ha"
msgstr ""
-#: compensation/models/action.py:26
+#: compensation/models/action.py:27
msgid "Pieces"
msgstr "Stück"
-#: compensation/models/compensation.py:63 konova/utils/message_templates.py:43
-msgid "Added deadline"
-msgstr "Frist/Termin hinzugefügt"
-
#: compensation/models/eco_account.py:56
msgid ""
"Deductable surface can not be larger than existing surfaces in after states"
@@ -661,65 +656,70 @@ 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:47 compensation/tables.py:188 ema/tables.py:44
+#: compensation/tables.py:35 compensation/tables.py:207 ema/tables.py:39
+#: intervention/tables.py:34 konova/filters/mixins.py:98
+msgid "Parcel gmrkng"
+msgstr "Gemarkung"
+
+#: compensation/tables.py:52 compensation/tables.py:228 ema/tables.py:50
#: intervention/tables.py:51
msgid "Editable"
msgstr "Freigegeben"
-#: compensation/tables.py:53 compensation/tables.py:194 ema/tables.py:50
+#: compensation/tables.py:58 compensation/tables.py:234 ema/tables.py:56
#: intervention/tables.py:57
msgid "Last edit"
msgstr "Zuletzt bearbeitet"
-#: compensation/tables.py:85 compensation/tables.py:226 ema/tables.py:83
-#: intervention/tables.py:89
+#: compensation/tables.py:89 compensation/tables.py:266 ema/tables.py:89
+#: intervention/tables.py:88
msgid "Open {}"
msgstr "Öffne {}"
-#: compensation/tables.py:106 intervention/tables.py:108
+#: compensation/tables.py:114 intervention/tables.py:111
msgid "Not checked yet"
msgstr "Noch nicht geprüft"
-#: compensation/tables.py:111 intervention/tables.py:113
+#: compensation/tables.py:119 intervention/tables.py:116
msgid "Checked on {} by {}"
msgstr "Am {} von {} geprüft worden"
-#: compensation/tables.py:130
+#: compensation/tables.py:160
#: compensation/templates/compensation/detail/compensation/view.html:80
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:58
#: compensation/templates/compensation/detail/eco_account/view.html:47
-#: ema/tables.py:102 ema/templates/ema/detail/view.html:38
-#: intervention/tables.py:132
+#: ema/tables.py:131 ema/templates/ema/detail/view.html:38
+#: intervention/tables.py:157
#: intervention/templates/intervention/detail/view.html:85
msgid "Not recorded yet"
msgstr "Noch nicht verzeichnet"
-#: compensation/tables.py:135 compensation/tables.py:264 ema/tables.py:107
-#: intervention/tables.py:137
+#: compensation/tables.py:165 compensation/tables.py:326 ema/tables.py:136
+#: intervention/tables.py:162
msgid "Recorded on {} by {}"
msgstr "Am {} von {} verzeichnet worden"
-#: compensation/tables.py:159 compensation/tables.py:286 ema/tables.py:130
-#: intervention/tables.py:160
+#: compensation/tables.py:189 compensation/tables.py:348 ema/tables.py:159
+#: intervention/tables.py:185
msgid "Full access granted"
msgstr "Für Sie freigegeben - Datensatz kann bearbeitet werden"
-#: compensation/tables.py:159 compensation/tables.py:286 ema/tables.py:130
-#: intervention/tables.py:160
+#: compensation/tables.py:189 compensation/tables.py:348 ema/tables.py:159
+#: intervention/tables.py:185
msgid "Access not granted"
msgstr "Nicht freigegeben - Datensatz nur lesbar"
-#: compensation/tables.py:177
+#: compensation/tables.py:212
#: 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:243
msgid "Eco Accounts"
msgstr "Ökokonten"
-#: compensation/tables.py:259
+#: compensation/tables.py:321
msgid "Not recorded yet. Can not be used for deductions, yet."
msgstr ""
"Noch nicht verzeichnet. Kann noch nicht für Abbuchungen genutzt werden."
@@ -753,6 +753,12 @@ msgstr "Menge"
#: compensation/templates/compensation/detail/compensation/includes/actions.html:66
#: compensation/templates/compensation/detail/eco_account/includes/actions.html:65
#: ema/templates/ema/detail/includes/actions.html:63
+msgid "Edit action"
+msgstr "Maßnahme bearbeiten"
+
+#: compensation/templates/compensation/detail/compensation/includes/actions.html:69
+#: compensation/templates/compensation/detail/eco_account/includes/actions.html:68
+#: ema/templates/ema/detail/includes/actions.html:66
msgid "Remove action"
msgstr "Maßnahme entfernen"
@@ -807,6 +813,12 @@ msgstr "Frist/Termin hinzufügen"
#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:59
#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:57
#: ema/templates/ema/detail/includes/deadlines.html:57
+msgid "Edit deadline"
+msgstr "Frist/Termin bearbeiten"
+
+#: compensation/templates/compensation/detail/compensation/includes/deadlines.html:62
+#: compensation/templates/compensation/detail/eco_account/includes/deadlines.html:60
+#: ema/templates/ema/detail/includes/deadlines.html:60
msgid "Remove deadline"
msgstr "Frist löschen"
@@ -821,14 +833,29 @@ 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:391
+#: konova/forms.py:411
msgid "Add new document"
msgstr "Neues Dokument hinzufügen"
-#: compensation/templates/compensation/detail/compensation/includes/documents.html:57
-#: compensation/templates/compensation/detail/eco_account/includes/documents.html:55
-#: ema/templates/ema/detail/includes/documents.html:55
-#: intervention/templates/intervention/detail/includes/documents.html:57
+#: compensation/templates/compensation/detail/compensation/includes/documents.html:31
+#: compensation/templates/compensation/detail/eco_account/includes/documents.html:31
+#: ema/templates/ema/detail/includes/documents.html:31
+#: intervention/templates/intervention/detail/includes/documents.html:31
+#: konova/forms.py:368
+msgid "Created on"
+msgstr "Erstellt"
+
+#: compensation/templates/compensation/detail/compensation/includes/documents.html:63
+#: compensation/templates/compensation/detail/eco_account/includes/documents.html:61
+#: ema/templates/ema/detail/includes/documents.html:61
+#: intervention/templates/intervention/detail/includes/documents.html:65
+msgid "Edit document"
+msgstr "Dokument bearbeitet"
+
+#: compensation/templates/compensation/detail/compensation/includes/documents.html:66
+#: compensation/templates/compensation/detail/eco_account/includes/documents.html:64
+#: ema/templates/ema/detail/includes/documents.html:64
+#: intervention/templates/intervention/detail/includes/documents.html:68
msgid "Remove document"
msgstr "Dokument löschen"
@@ -866,6 +893,15 @@ msgstr "Biotoptyp"
#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:62
#: ema/templates/ema/detail/includes/states-after.html:60
#: ema/templates/ema/detail/includes/states-before.html:60
+msgid "Edit state"
+msgstr "Zustand bearbeiten"
+
+#: compensation/templates/compensation/detail/compensation/includes/states-after.html:65
+#: compensation/templates/compensation/detail/compensation/includes/states-before.html:65
+#: compensation/templates/compensation/detail/eco_account/includes/states-after.html:65
+#: compensation/templates/compensation/detail/eco_account/includes/states-before.html:65
+#: ema/templates/ema/detail/includes/states-after.html:63
+#: ema/templates/ema/detail/includes/states-before.html:63
msgid "Remove state"
msgstr "Zustand entfernen"
@@ -943,14 +979,14 @@ msgstr "Zuletzt bearbeitet"
#: compensation/templates/compensation/detail/compensation/view.html:99
#: compensation/templates/compensation/detail/eco_account/view.html:82
-#: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:53
+#: ema/templates/ema/detail/view.html:76 intervention/forms/modalForms.py:56
#: intervention/templates/intervention/detail/view.html:116
msgid "Shared with"
msgstr "Freigegeben für"
#: compensation/templates/compensation/detail/eco_account/includes/controls.html:15
#: ema/templates/ema/detail/includes/controls.html:15
-#: intervention/forms/modalForms.py:67
+#: intervention/forms/modalForms.py:70
#: intervention/templates/intervention/detail/includes/controls.html:15
msgid "Share"
msgstr "Freigabe"
@@ -993,6 +1029,11 @@ msgstr "Verzeichnet am"
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:65
#: intervention/templates/intervention/detail/includes/deductions.html:60
+msgid "Edit Deduction"
+msgstr "Abbuchung bearbeiten"
+
+#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:68
+#: intervention/templates/intervention/detail/includes/deductions.html:63
msgid "Remove Deduction"
msgstr "Abbuchung entfernen"
@@ -1076,111 +1117,76 @@ msgstr ""
msgid "Responsible data"
msgstr "Daten zu den verantwortlichen Stellen"
-#: compensation/views/compensation.py:48
+#: compensation/views/compensation.py:52
msgid "Compensations - Overview"
msgstr "Kompensationen - Übersicht"
-#: compensation/views/compensation.py:147
+#: compensation/views/compensation.py:151 konova/utils/message_templates.py:31
msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet"
-#: compensation/views/compensation.py:157 compensation/views/eco_account.py:160
-#: ema/views.py:227 intervention/views.py:311
+#: compensation/views/compensation.py:161 compensation/views/eco_account.py:165
+#: ema/views.py:233 intervention/views.py:327
msgid "Edit {}"
msgstr "Bearbeite {}"
-#: compensation/views/compensation.py:236 compensation/views/eco_account.py:316
-#: ema/views.py:188 intervention/views.py:487
+#: compensation/views/compensation.py:240 compensation/views/eco_account.py:349
+#: ema/views.py:194 intervention/views.py:531
msgid "Log"
msgstr "Log"
-#: compensation/views/compensation.py:280 compensation/views/eco_account.py:496
-#: ema/views.py:359 intervention/views.py:133
-msgid "Document added"
-msgstr "Dokument hinzugefügt"
-
-#: compensation/views/compensation.py:350 compensation/views/eco_account.py:362
-#: ema/views.py:294
-msgid "State added"
-msgstr "Zustand hinzugefügt"
-
-#: compensation/views/compensation.py:372 compensation/views/eco_account.py:384
-#: ema/views.py:316
-msgid "Action added"
-msgstr "Maßnahme hinzugefügt"
-
-#: compensation/views/compensation.py:394 compensation/views/eco_account.py:475
-#: ema/views.py:338
-msgid "Deadline added"
-msgstr "Frist/Termin hinzugefügt"
-
-#: compensation/views/compensation.py:417 compensation/views/eco_account.py:453
-#: ema/views.py:595
-msgid "Deadline removed"
-msgstr "Frist gelöscht"
-
-#: compensation/views/compensation.py:440 compensation/views/eco_account.py:407
-#: ema/views.py:430
-msgid "State removed"
-msgstr "Zustand gelöscht"
-
-#: compensation/views/compensation.py:463 compensation/views/eco_account.py:430
-#: ema/views.py:453
-msgid "Action removed"
-msgstr "Maßnahme entfernt"
-
-#: compensation/views/compensation.py:482 compensation/views/eco_account.py:586
-#: ema/views.py:472 intervention/views.py:580
+#: compensation/views/compensation.py:584 compensation/views/eco_account.py:716
+#: ema/views.py:551 intervention/views.py:677
msgid "Report {}"
msgstr "Bericht {}"
-#: compensation/views/eco_account.py:59
+#: compensation/views/eco_account.py:64
msgid "Eco-account - Overview"
msgstr "Ökokonten - Übersicht"
-#: compensation/views/eco_account.py:92
+#: compensation/views/eco_account.py:97
msgid "Eco-Account {} added"
msgstr "Ökokonto {} hinzugefügt"
-#: compensation/views/eco_account.py:150
+#: compensation/views/eco_account.py:155
msgid "Eco-Account {} edited"
msgstr "Ökokonto {} bearbeitet"
-#: compensation/views/eco_account.py:263
+#: compensation/views/eco_account.py:268
msgid "Eco-account removed"
msgstr "Ökokonto entfernt"
-#: compensation/views/eco_account.py:337 ema/views.py:269
-#: intervention/views.py:558
+#: compensation/views/eco_account.py:370 ema/views.py:275
+#: intervention/views.py:630
msgid "{} unrecorded"
msgstr "{} entzeichnet"
-#: compensation/views/eco_account.py:337 ema/views.py:269
-#: intervention/views.py:558
+#: compensation/views/eco_account.py:370 ema/views.py:275
+#: intervention/views.py:630
msgid "{} recorded"
msgstr "{} verzeichnet"
-#: compensation/views/eco_account.py:659 ema/views.py:538
-#: intervention/views.py:384
+#: compensation/views/eco_account.py:789 ema/views.py:617
+#: intervention/views.py:428
msgid "{} has already been shared with you"
msgstr "{} wurde bereits für Sie freigegeben"
-#: compensation/views/eco_account.py:664 ema/views.py:543
-#: intervention/views.py:389
+#: compensation/views/eco_account.py:794 ema/views.py:622
+#: intervention/views.py:433
msgid "{} has been shared with you"
msgstr "{} ist nun für Sie freigegeben"
-#: compensation/views/eco_account.py:671 ema/views.py:550
-#: intervention/views.py:396
+#: compensation/views/eco_account.py:801 ema/views.py:629
+#: intervention/views.py:440
msgid "Share link invalid"
msgstr "Freigabelink ungültig"
-#: compensation/views/eco_account.py:694 ema/views.py:573
-#: intervention/views.py:419
+#: compensation/views/eco_account.py:824 ema/views.py:652
+#: intervention/views.py:463
msgid "Share settings updated"
msgstr "Freigabe Einstellungen aktualisiert"
-#: ema/forms.py:40 ema/views.py:92
+#: ema/forms.py:40 ema/views.py:98
msgid "New EMA"
msgstr "Neue EMA hinzufügen"
@@ -1188,11 +1194,11 @@ msgstr "Neue EMA hinzufügen"
msgid "Edit EMA"
msgstr "Bearbeite EMA"
-#: ema/tables.py:59 templates/navbars/navbar.html:43
+#: ema/tables.py:65 templates/navbars/navbar.html:43
msgid "Payment funded compensations"
msgstr "Ersatzzahlungsmaßnahmen (EMA)"
-#: ema/tables.py:60
+#: ema/tables.py:66
msgid "EMA explanation"
msgstr ""
"EMA sind Kompensationen, die durch Ersatzzahlungen finanziert wurden. "
@@ -1200,7 +1206,7 @@ msgstr ""
"Maßnahmen aus Ersatzzahlungen, die nach 2015 rechtskräftig wurden, werden "
"durch die Stiftung Natur und Umwelt verwaltet."
-#: ema/tables.py:83 templates/navbars/navbar.html:43
+#: ema/tables.py:89 templates/navbars/navbar.html:43
msgid "EMA"
msgstr ""
@@ -1208,19 +1214,19 @@ msgstr ""
msgid "Payment funded compensation"
msgstr "Ersatzzahlungsmaßnahme"
-#: ema/views.py:49
+#: ema/views.py:55
msgid "EMAs - Overview"
msgstr "EMAs - Übersicht"
-#: ema/views.py:82
+#: ema/views.py:88
msgid "EMA {} added"
msgstr "EMA {} hinzugefügt"
-#: ema/views.py:217
+#: ema/views.py:223
msgid "EMA {} edited"
msgstr "EMA {} bearbeitet"
-#: ema/views.py:250
+#: ema/views.py:256
msgid "EMA removed"
msgstr "EMA entfernt"
@@ -1281,7 +1287,7 @@ msgstr "Datum Zulassung bzw. Satzungsbeschluss"
msgid "Binding on"
msgstr "Datum Bestandskraft"
-#: intervention/forms/forms.py:193 intervention/views.py:92
+#: intervention/forms/forms.py:193 intervention/views.py:94
msgid "New intervention"
msgstr "Neuer Eingriff"
@@ -1289,19 +1295,19 @@ msgstr "Neuer Eingriff"
msgid "Edit intervention"
msgstr "Eingriff bearbeiten"
-#: intervention/forms/modalForms.py:26
+#: intervention/forms/modalForms.py:29
msgid "Share link"
msgstr "Freigabelink"
-#: intervention/forms/modalForms.py:28
+#: intervention/forms/modalForms.py:31
msgid "Send this link to users who you want to have writing access on the data"
msgstr "Andere Nutzer erhalten über diesen Link Zugriff auf die Daten"
-#: intervention/forms/modalForms.py:38
+#: intervention/forms/modalForms.py:41
msgid "Add user to share with"
msgstr "Nutzer direkt hinzufügen"
-#: intervention/forms/modalForms.py:40
+#: intervention/forms/modalForms.py:43
msgid ""
"Multiple selection possible - You can only select users which do not already "
"have access. Enter the full username."
@@ -1309,46 +1315,46 @@ msgstr ""
"Mehrfachauswahl möglich - Sie können nur Nutzer wählen, für die der Eintrag "
"noch nicht freigegeben wurde. Geben Sie den ganzen Nutzernamen an."
-#: intervention/forms/modalForms.py:56
+#: intervention/forms/modalForms.py:59
msgid "Remove check to remove access for this user"
msgstr "Wählen Sie die Nutzer ab, die keinen Zugriff mehr haben sollen"
-#: intervention/forms/modalForms.py:68
+#: intervention/forms/modalForms.py:71
msgid "Share settings for {}"
msgstr "Freigabe Einstellungen für {}"
-#: intervention/forms/modalForms.py:125
+#: intervention/forms/modalForms.py:128
msgid "Date of revocation"
msgstr "Datum des Widerspruchs"
-#: intervention/forms/modalForms.py:136
+#: intervention/forms/modalForms.py:139
#: intervention/templates/intervention/detail/includes/revocation.html:35
msgid "Document"
msgstr "Dokument"
-#: intervention/forms/modalForms.py:139
+#: intervention/forms/modalForms.py:142
msgid "Must be smaller than 15 Mb"
msgstr "Muss kleiner als 15 Mb sein"
-#: intervention/forms/modalForms.py:163
+#: intervention/forms/modalForms.py:167
#: intervention/templates/intervention/detail/includes/revocation.html:18
msgid "Add revocation"
msgstr "Widerspruch hinzufügen"
-#: intervention/forms/modalForms.py:180
+#: intervention/forms/modalForms.py:224
msgid "Checked intervention data"
msgstr "Eingriffsdaten geprüft"
-#: intervention/forms/modalForms.py:186
+#: intervention/forms/modalForms.py:230
msgid "Checked compensations data and payments"
msgstr "Kompensationen und Zahlungen geprüft"
-#: intervention/forms/modalForms.py:195
+#: intervention/forms/modalForms.py:239
#: intervention/templates/intervention/detail/includes/controls.html:19
msgid "Run check"
msgstr "Prüfung vornehmen"
-#: intervention/forms/modalForms.py:196 konova/forms.py:457
+#: intervention/forms/modalForms.py:240 konova/forms.py:514
msgid ""
"I, {} {}, confirm that all necessary control steps have been performed by "
"myself."
@@ -1356,23 +1362,23 @@ msgstr ""
"Ich, {} {}, bestätige, dass die notwendigen Kontrollschritte durchgeführt "
"wurden:"
-#: intervention/forms/modalForms.py:280
+#: intervention/forms/modalForms.py:324
msgid "Only recorded accounts can be selected for deductions"
msgstr "Nur verzeichnete Ökokonten können für Abbuchungen verwendet werden."
-#: intervention/forms/modalForms.py:307
+#: intervention/forms/modalForms.py:351
msgid "Only shared interventions can be selected"
msgstr "Nur freigegebene Eingriffe können gewählt werden"
-#: intervention/forms/modalForms.py:320
+#: intervention/forms/modalForms.py:364
msgid "New Deduction"
msgstr "Neue Abbuchung"
-#: intervention/forms/modalForms.py:321
+#: intervention/forms/modalForms.py:365
msgid "Enter the information for a new deduction from a chosen eco-account"
msgstr "Geben Sie die Informationen für eine neue Abbuchung ein."
-#: intervention/forms/modalForms.py:349
+#: intervention/forms/modalForms.py:408
msgid ""
"Eco-account {} is not recorded yet. You can only deduct from recorded "
"accounts."
@@ -1380,7 +1386,7 @@ msgstr ""
"Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von "
"verzeichneten Ökokonten erfolgen."
-#: intervention/forms/modalForms.py:362
+#: intervention/forms/modalForms.py:418
msgid ""
"The account {} has not enough surface for a deduction of {} m². There are "
"only {} m² left"
@@ -1388,19 +1394,6 @@ msgstr ""
"Das Ökokonto {} hat für eine Abbuchung von {} m² nicht ausreichend "
"Restfläche. Es stehen noch {} m² zur Verfügung."
-#: intervention/tables.py:45
-#: intervention/templates/intervention/detail/includes/revocation.html:58
-msgid "Revocation"
-msgstr "Widerspruch"
-
-#: intervention/tables.py:177
-msgid "No revocation"
-msgstr "Kein Widerspruch"
-
-#: intervention/tables.py:183
-msgid "Revocation from {}, added on {} by {}"
-msgstr "Widerspruch vom {}, am {} von {} hinzugefügt"
-
#: intervention/templates/intervention/detail/includes/compensations.html:14
msgid "Add new compensation"
msgstr "Neue Kompensation hinzufügen"
@@ -1436,6 +1429,10 @@ msgid "Amount"
msgstr "Betrag"
#: intervention/templates/intervention/detail/includes/payments.html:59
+msgid "Edit payment"
+msgstr "Zahlung bearbeitet"
+
+#: intervention/templates/intervention/detail/includes/payments.html:62
msgid "Remove payment"
msgstr "Zahlung entfernen"
@@ -1449,7 +1446,15 @@ msgctxt "Revocation"
msgid "From"
msgstr "Vom"
+#: intervention/templates/intervention/detail/includes/revocation.html:58
+msgid "Revocation"
+msgstr "Widerspruch"
+
#: intervention/templates/intervention/detail/includes/revocation.html:69
+msgid "Edit revocation"
+msgstr "Widerspruch bearbeiten"
+
+#: intervention/templates/intervention/detail/includes/revocation.html:72
msgid "Remove revocation"
msgstr "Widerspruch entfernen"
@@ -1466,6 +1471,7 @@ msgid "Exist"
msgstr "Vorhanden"
#: intervention/utils/quality.py:70
+#: templates/table/revocation_warning_col.html:5
msgid "Revocations exists"
msgstr "Widersprüche liegen vor"
@@ -1477,37 +1483,33 @@ msgstr "Datum Bestandskraft"
msgid "Laws"
msgstr "Gesetze"
-#: intervention/utils/quality.py:98
+#: intervention/utils/quality.py:101
msgid "No compensation of any type found (Compensation, Payment, Deduction)"
msgstr ""
"Kein Ausgleich jeglicher Art gefunden (Kompensation, Ersatzzahlung, "
"Abbuchung)"
-#: intervention/views.py:49
+#: intervention/views.py:51
msgid "Interventions - Overview"
msgstr "Eingriffe - Übersicht"
-#: intervention/views.py:82
+#: intervention/views.py:84
msgid "Intervention {} added"
msgstr "Eingriff {} hinzugefügt"
-#: intervention/views.py:250
-msgid "This intervention has {} revocations"
-msgstr "Dem Eingriff liegen {} Widersprüche vor"
-
-#: intervention/views.py:299
+#: intervention/views.py:315
msgid "Intervention {} edited"
msgstr "Eingriff {} bearbeitet"
-#: intervention/views.py:335
+#: intervention/views.py:351
msgid "{} removed"
msgstr "{} entfernt"
-#: intervention/views.py:440
+#: intervention/views.py:484
msgid "Check performed"
msgstr "Prüfung durchgeführt"
-#: intervention/views.py:563
+#: intervention/views.py:635
msgid "There are errors on this intervention:"
msgstr "Es liegen Fehler in diesem Eingriff vor:"
@@ -1544,10 +1546,6 @@ msgstr "Kreis"
msgid "Search for district"
msgstr "Nach Kreis suchen"
-#: konova/filters/mixins.py:98
-msgid "Parcel gmrkng"
-msgstr "Gemarkung"
-
#: konova/filters/mixins.py:99
msgid "Search for parcel gmrkng"
msgstr "Nach Gemarkung suchen"
@@ -1595,81 +1593,69 @@ msgstr "Nach Zulassungsbehörde suchen"
msgid "Search for conservation office"
msgstr "Nch Eintragungsstelle suchen"
-#: konova/forms.py:37 templates/form/collapsable/form.html:62
+#: konova/forms.py:39 templates/form/collapsable/form.html:62
msgid "Save"
msgstr "Speichern"
-#: konova/forms.py:69
+#: konova/forms.py:71
msgid "Not editable"
msgstr "Nicht editierbar"
-#: konova/forms.py:139 konova/forms.py:311
+#: konova/forms.py:142 konova/forms.py:314
msgid "Confirm"
msgstr "Bestätige"
-#: konova/forms.py:151 konova/forms.py:320
+#: konova/forms.py:154 konova/forms.py:323
msgid "Remove"
msgstr "Löschen"
-#: konova/forms.py:153
+#: konova/forms.py:156
msgid "You are about to remove {} {}"
msgstr "Sie sind dabei {} {} zu löschen"
-#: konova/forms.py:240 konova/utils/quality.py:44 konova/utils/quality.py:46
+#: konova/forms.py:243 konova/utils/quality.py:44 konova/utils/quality.py:46
#: templates/form/collapsable/form.html:45
msgid "Geometry"
msgstr "Geometrie"
-#: konova/forms.py:321
+#: konova/forms.py:324
msgid "Are you sure?"
msgstr "Sind Sie sicher?"
-#: konova/forms.py:348
-msgid "Created on"
-msgstr "Erstellt"
-
-#: konova/forms.py:350
+#: konova/forms.py:370
msgid "When has this file been created? Important for photos."
msgstr "Wann wurde diese Datei erstellt oder das Foto aufgenommen?"
-#: konova/forms.py:361
+#: konova/forms.py:381
#: venv/lib/python3.7/site-packages/django/db/models/fields/files.py:231
msgid "File"
msgstr "Datei"
-#: konova/forms.py:363
+#: konova/forms.py:383
msgid "Allowed formats: pdf, jpg, png. Max size 15 MB."
msgstr "Formate: pdf, jpg, png. Maximal 15 MB."
-#: konova/forms.py:409
-msgid "Unsupported file type"
-msgstr "Dateiformat nicht unterstützt"
-
-#: konova/forms.py:416
-msgid "File too large"
-msgstr "Datei zu groß"
-
-#: konova/forms.py:425
+#: konova/forms.py:449
msgid "Added document"
msgstr "Dokument hinzugefügt"
-#: konova/forms.py:448
+#: konova/forms.py:505
msgid "Confirm record"
msgstr "Verzeichnen bestätigen"
-#: konova/forms.py:456
+#: konova/forms.py:513
msgid "Record data"
msgstr "Daten verzeichnen"
-#: konova/forms.py:463
+#: konova/forms.py:520
msgid "Confirm unrecord"
msgstr "Entzeichnen bestätigen"
-#: konova/forms.py:464
+#: konova/forms.py:521
msgid "Unrecord data"
msgstr "Daten entzeichnen"
-#: konova/forms.py:465
+#: konova/forms.py:522
msgid "I, {} {}, confirm that this data must be unrecorded."
msgstr ""
"Ich, {} {}, bestätige, dass diese Daten wieder entzeichnet werden müssen."
@@ -1772,35 +1758,31 @@ msgstr "In Zwischenablage kopieren"
msgid "Copied to clipboard"
msgstr "In Zwischenablage kopiert"
-#: konova/utils/documents.py:52
-msgid "Document '{}' deleted"
-msgstr "Dokument '{}' gelöscht"
-
-#: konova/utils/mailer.py:66
+#: konova/utils/mailer.py:68
msgid "{} - Shared access removed"
msgstr "{} - Zugriff entzogen"
-#: konova/utils/mailer.py:88
+#: konova/utils/mailer.py:91
msgid "{} - Shared access given"
msgstr "{} - Zugriff freigegeben"
-#: konova/utils/mailer.py:110
+#: konova/utils/mailer.py:114
msgid "{} - Shared data recorded"
msgstr "{} - Freigegebene Daten verzeichnet"
-#: konova/utils/mailer.py:132
+#: konova/utils/mailer.py:137
msgid "{} - Shared data unrecorded"
msgstr "{} - Freigegebene Daten entzeichnet"
-#: konova/utils/mailer.py:154
+#: konova/utils/mailer.py:160
msgid "{} - Shared data deleted"
msgstr "{} - Freigegebene Daten gelöscht"
-#: konova/utils/mailer.py:176
+#: konova/utils/mailer.py:183
msgid "{} - Shared data checked"
msgstr "{} - Freigegebene Daten geprüft"
-#: konova/utils/mailer.py:197 templates/email/api/verify_token.html:4
+#: konova/utils/mailer.py:204 templates/email/api/verify_token.html:4
msgid "Request for new API token"
msgstr "Anfrage für neuen API Token"
@@ -1847,6 +1829,14 @@ msgid "Status of Checked and Recorded reseted"
msgstr "'Geprüft'/'Verzeichnet' wurde zurückgesetzt"
#: konova/utils/message_templates.py:22
+msgid "Unsupported file type"
+msgstr "Dateiformat nicht unterstützt"
+
+#: konova/utils/message_templates.py:23
+msgid "File too large"
+msgstr "Datei zu groß"
+
+#: konova/utils/message_templates.py:26
msgid ""
"Action canceled. Eco account is recorded or deductions exist. Only "
"conservation office member can perform this action."
@@ -1854,54 +1844,122 @@ msgstr ""
"Aktion abgebrochen. Ökokonto ist bereits verzeichnet oder Abbuchungen liegen "
"vor. Nur Eintragungsstellennutzer können diese Aktion jetzt durchführen."
-#: konova/utils/message_templates.py:25
+#: konova/utils/message_templates.py:29
msgid "Compensation {} added"
msgstr "Kompensation {} hinzugefügt"
-#: konova/utils/message_templates.py:26
+#: konova/utils/message_templates.py:30
msgid "Compensation {} removed"
msgstr "Kompensation {} entfernt"
-#: konova/utils/message_templates.py:29
-msgid "Deduction added"
-msgstr "Abbuchung hinzugefügt"
-
-#: konova/utils/message_templates.py:30
-msgid "Deduction removed"
-msgstr "Abbuchung entfernt"
+#: konova/utils/message_templates.py:32
+msgid "Added compensation action"
+msgstr "Maßnahme hinzugefügt"
#: konova/utils/message_templates.py:33
-msgid "Payment added"
-msgstr "Zahlung hinzugefügt"
-
-#: konova/utils/message_templates.py:34
-msgid "Payment removed"
-msgstr "Zahlung gelöscht"
-
-#: konova/utils/message_templates.py:37
-msgid "Revocation added"
-msgstr "Widerspruch hinzugefügt"
-
-#: konova/utils/message_templates.py:38
-msgid "Revocation removed"
-msgstr "Widerspruch entfernt"
-
-#: konova/utils/message_templates.py:41
-msgid "Edited general data"
-msgstr "Allgemeine Daten bearbeitet"
-
-#: konova/utils/message_templates.py:42
msgid "Added compensation state"
msgstr "Zustand hinzugefügt"
-#: konova/utils/message_templates.py:44
-msgid "Added compensation action"
-msgstr "Maßnahme hinzufügen"
+#: konova/utils/message_templates.py:36
+msgid "State removed"
+msgstr "Zustand gelöscht"
+
+#: konova/utils/message_templates.py:37
+msgid "State edited"
+msgstr "Zustand bearbeitet"
+
+#: konova/utils/message_templates.py:38
+msgid "State added"
+msgstr "Zustand hinzugefügt"
+
+#: konova/utils/message_templates.py:41
+msgid "Action added"
+msgstr "Maßnahme hinzugefügt"
+
+#: konova/utils/message_templates.py:42
+msgid "Action edited"
+msgstr "Maßnahme bearbeitet"
+
+#: konova/utils/message_templates.py:43
+msgid "Action removed"
+msgstr "Maßnahme entfernt"
+
+#: konova/utils/message_templates.py:46
+msgid "Deduction added"
+msgstr "Abbuchung hinzugefügt"
#: konova/utils/message_templates.py:47
+msgid "Deduction edited"
+msgstr "Abbuchung bearbeitet"
+
+#: konova/utils/message_templates.py:48
+msgid "Deduction removed"
+msgstr "Abbuchung entfernt"
+
+#: konova/utils/message_templates.py:51
+msgid "Deadline added"
+msgstr "Frist/Termin hinzugefügt"
+
+#: konova/utils/message_templates.py:52
+msgid "Deadline edited"
+msgstr "Frist/Termin bearbeitet"
+
+#: konova/utils/message_templates.py:53
+msgid "Deadline removed"
+msgstr "Frist/Termin gelöscht"
+
+#: konova/utils/message_templates.py:56
+msgid "Payment added"
+msgstr "Zahlung hinzugefügt"
+
+#: konova/utils/message_templates.py:57
+msgid "Payment edited"
+msgstr "Zahlung bearbeitet"
+
+#: konova/utils/message_templates.py:58
+msgid "Payment removed"
+msgstr "Zahlung gelöscht"
+
+#: konova/utils/message_templates.py:61
+msgid "Revocation added"
+msgstr "Widerspruch hinzugefügt"
+
+#: konova/utils/message_templates.py:62
+msgid "Revocation edited"
+msgstr "Widerspruch bearbeitet"
+
+#: konova/utils/message_templates.py:63
+msgid "Revocation removed"
+msgstr "Widerspruch entfernt"
+
+#: konova/utils/message_templates.py:66
+msgid "Document '{}' deleted"
+msgstr "Dokument '{}' gelöscht"
+
+#: konova/utils/message_templates.py:67
+msgid "Document added"
+msgstr "Dokument hinzugefügt"
+
+#: konova/utils/message_templates.py:68
+msgid "Document edited"
+msgstr "Dokument bearbeitet"
+
+#: konova/utils/message_templates.py:71
+msgid "Edited general data"
+msgstr "Allgemeine Daten bearbeitet"
+
+#: konova/utils/message_templates.py:72
+msgid "Added deadline"
+msgstr "Frist/Termin hinzugefügt"
+
+#: konova/utils/message_templates.py:75
msgid "Geometry conflict detected with {}"
msgstr "Geometriekonflikt mit folgenden Einträgen erkannt: {}"
+#: konova/utils/message_templates.py:78
+msgid "This intervention has {} revocations"
+msgstr "Dem Eingriff liegen {} Widersprüche vor"
+
#: konova/utils/messenger.py:70
msgid "{} checked"
msgstr "{} geprüft"
@@ -1984,12 +2042,12 @@ msgstr ""
"Admin Backend aktiviert worden ist."
#: templates/email/api/verify_token.html:18
-#: templates/email/checking/shared_data_checked.html:17
-#: templates/email/deleting/shared_data_deleted.html:17
-#: templates/email/recording/shared_data_recorded.html:17
-#: templates/email/recording/shared_data_unrecorded.html:17
-#: templates/email/sharing/shared_access_given.html:18
-#: templates/email/sharing/shared_access_removed.html:18
+#: templates/email/checking/shared_data_checked.html:19
+#: templates/email/deleting/shared_data_deleted.html:19
+#: templates/email/recording/shared_data_recorded.html:19
+#: templates/email/recording/shared_data_unrecorded.html:19
+#: templates/email/sharing/shared_access_given.html:20
+#: templates/email/sharing/shared_access_removed.html:20
msgid "Best regards"
msgstr "Beste Grüße"
@@ -2010,7 +2068,7 @@ msgstr "Hallo "
msgid "the following dataset has just been checked"
msgstr "der folgende Datensatz wurde soeben geprüft "
-#: templates/email/checking/shared_data_checked.html:14
+#: templates/email/checking/shared_data_checked.html:16
msgid ""
"This means, the responsible registration office just confirmed the "
"correctness of this dataset."
@@ -2026,7 +2084,7 @@ msgstr "Freigegebene Daten gelöscht"
msgid "the following dataset has just been deleted"
msgstr "der folgende Datensatz wurde soeben gelöscht "
-#: templates/email/deleting/shared_data_deleted.html:14
+#: templates/email/deleting/shared_data_deleted.html:16
msgid ""
"If this should not have been happened, please contact us. See the signature "
"for details."
@@ -2042,12 +2100,12 @@ msgstr "Freigegebene Daten verzeichnet"
msgid "the following dataset has just been recorded"
msgstr "der folgende Datensatz wurde soeben verzeichnet "
-#: templates/email/recording/shared_data_recorded.html:14
+#: templates/email/recording/shared_data_recorded.html:16
msgid "This means the data is now publicly available, e.g. in LANIS"
msgstr ""
"Das bedeutet, dass die Daten nun öffentlich verfügbar sind, z.B. im LANIS."
-#: templates/email/recording/shared_data_recorded.html:24
+#: templates/email/recording/shared_data_recorded.html:26
msgid ""
"Please note: Recorded intervention means the compensations are recorded as "
"well."
@@ -2063,11 +2121,11 @@ msgstr "Freigegebene Daten entzeichnet"
msgid "the following dataset has just been unrecorded"
msgstr "der folgende Datensatz wurde soeben entzeichnet "
-#: templates/email/recording/shared_data_unrecorded.html:14
+#: templates/email/recording/shared_data_unrecorded.html:16
msgid "This means the data is no longer publicly available."
msgstr "Das bedeutet, dass die Daten nicht länger öffentlich verfügbar sind."
-#: templates/email/recording/shared_data_unrecorded.html:24
+#: templates/email/recording/shared_data_unrecorded.html:26
msgid ""
"Please note: Unrecorded intervention means the compensations are unrecorded "
"as well."
@@ -2083,11 +2141,11 @@ msgstr "Zugriff freigegeben"
msgid "the following dataset has just been shared with you"
msgstr "der folgende Datensatz wurde soeben für Sie freigegeben "
-#: templates/email/sharing/shared_access_given.html:14
+#: templates/email/sharing/shared_access_given.html:16
msgid "This means you can now edit this dataset."
msgstr "Das bedeutet, dass Sie diesen Datensatz nun auch bearbeiten können."
-#: templates/email/sharing/shared_access_given.html:15
+#: templates/email/sharing/shared_access_given.html:17
msgid ""
"The shared dataset appears now by default on your overview for this dataset "
"type."
@@ -2095,7 +2153,7 @@ msgstr ""
"Der freigegebene Datensatz ist nun standardmäßig in Ihrer Übersicht für den "
"Datensatztyp im KSP gelistet."
-#: templates/email/sharing/shared_access_given.html:25
+#: templates/email/sharing/shared_access_given.html:27
msgid ""
"Please note: Shared access on an intervention means you automatically have "
"editing access to related compensations."
@@ -2115,11 +2173,11 @@ msgstr ""
"Ihnen wurde soeben der bearbeitende Zugriff auf den folgenden Datensatz "
"entzogen: "
-#: templates/email/sharing/shared_access_removed.html:14
+#: templates/email/sharing/shared_access_removed.html:16
msgid "However, you are still able to view the dataset content."
msgstr "Sie können den Datensatz aber immer noch im KSP einsehen."
-#: templates/email/sharing/shared_access_removed.html:15
+#: templates/email/sharing/shared_access_removed.html:17
msgid ""
"Please use the provided search filter on the dataset`s overview pages to "
"find them."
@@ -2270,6 +2328,14 @@ msgstr ""
"wieder vorbei. \n"
" "
+#: templates/table/gmrkng_col.html:6
+msgid ""
+"If the geometry is not empty, the parcels are currently recalculated. Please "
+"refresh this page in a few moments."
+msgstr ""
+"Falls die Geometrie nicht leer ist, werden die Flurstücke aktuell berechnet. "
+"Bitte laden Sie diese Seite in ein paar Augenblicken erneut..."
+
#: user/forms.py:27
msgid "Notifications"
msgstr "Benachrichtigungen"
@@ -3918,6 +3984,12 @@ msgstr ""
msgid "Unable to connect to qpid with SASL mechanism %s"
msgstr ""
+#~ msgid "No revocation"
+#~ msgstr "Kein Widerspruch"
+
+#~ msgid "Revocation from {}, added on {} by {}"
+#~ msgstr "Widerspruch vom {}, am {} von {} hinzugefügt"
+
#~ msgid "General data edited"
#~ msgstr "Allgemeine Daten bearbeitet"
@@ -3942,12 +4014,6 @@ msgstr ""
#~ msgid "No file given!"
#~ msgstr "Keine Datei angegeben!"
-#~ msgid "Added payment"
-#~ msgstr "Zahlung hinzufügen"
-
-#~ msgid "Added state"
-#~ msgstr "Zustand hinzugefügt"
-
#~ msgid "Added action"
#~ msgstr "Maßnahme hinzugefügt"
diff --git a/templates/email/checking/shared_data_checked.html b/templates/email/checking/shared_data_checked.html
index 0707cfbc..0b67ecc7 100644
--- a/templates/email/checking/shared_data_checked.html
+++ b/templates/email/checking/shared_data_checked.html
@@ -11,6 +11,8 @@
{{obj_identifier}}
+ {{obj_title}}
+
{% trans 'This means, the responsible registration office just confirmed the correctness of this dataset.' %}
diff --git a/templates/email/deleting/shared_data_deleted.html b/templates/email/deleting/shared_data_deleted.html
index b920f1ec..272b0fde 100644
--- a/templates/email/deleting/shared_data_deleted.html
+++ b/templates/email/deleting/shared_data_deleted.html
@@ -11,6 +11,8 @@
{{obj_identifier}}
+ "{{obj_title}}"
+
{% trans 'If this should not have been happened, please contact us. See the signature for details.' %}
diff --git a/templates/email/recording/shared_data_recorded.html b/templates/email/recording/shared_data_recorded.html
index f8db9182..6805c928 100644
--- a/templates/email/recording/shared_data_recorded.html
+++ b/templates/email/recording/shared_data_recorded.html
@@ -11,6 +11,8 @@
{{obj_identifier}}
+ "{{obj_title}}"
+
{% trans 'This means the data is now publicly available, e.g. in LANIS' %}
diff --git a/templates/email/recording/shared_data_unrecorded.html b/templates/email/recording/shared_data_unrecorded.html
index d4639c9e..1e0310ae 100644
--- a/templates/email/recording/shared_data_unrecorded.html
+++ b/templates/email/recording/shared_data_unrecorded.html
@@ -11,6 +11,8 @@
{{obj_identifier}}
+ "{{obj_title}}"
+
{% trans 'This means the data is no longer publicly available.' %}
diff --git a/templates/email/sharing/shared_access_given.html b/templates/email/sharing/shared_access_given.html
index b8b26b7a..140e7a88 100644
--- a/templates/email/sharing/shared_access_given.html
+++ b/templates/email/sharing/shared_access_given.html
@@ -11,6 +11,8 @@
{{obj_identifier}}
+ "{{obj_title}}"
+
{% trans 'This means you can now edit this dataset.' %}
{% trans 'The shared dataset appears now by default on your overview for this dataset type.' %}
diff --git a/templates/email/sharing/shared_access_removed.html b/templates/email/sharing/shared_access_removed.html
index 86d4fddd..d1cbc5bf 100644
--- a/templates/email/sharing/shared_access_removed.html
+++ b/templates/email/sharing/shared_access_removed.html
@@ -11,6 +11,8 @@
{{obj_identifier}}
+ "{{obj_title}}"
+
{% trans 'However, you are still able to view the dataset content.' %}
{% trans 'Please use the provided search filter on the dataset`s overview pages to find them.' %}
diff --git a/templates/table/gmrkng_col.html b/templates/table/gmrkng_col.html
new file mode 100644
index 00000000..bd8878de
--- /dev/null
+++ b/templates/table/gmrkng_col.html
@@ -0,0 +1,9 @@
+{% load i18n fontawesome_5 %}
+
+{% for entry in entries %}
+ {{entry}}
+{% empty %}
+
+ {% fa5_icon 'hourglass-half' %}
+
+{% endfor %}
\ No newline at end of file
diff --git a/templates/table/revocation_warning_col.html b/templates/table/revocation_warning_col.html
new file mode 100644
index 00000000..2ed0922a
--- /dev/null
+++ b/templates/table/revocation_warning_col.html
@@ -0,0 +1,14 @@
+{% load i18n fontawesome_5 %}
+
+{% if has_revocations %}
+
+
+ {% fa5_icon 'ban' %}
+ {{content}}
+
+
+{% else %}
+
+ {{content}}
+
+{% endif %}
\ No newline at end of file
diff --git a/user/models/user.py b/user/models/user.py
index 6370f2d5..df63dd76 100644
--- a/user/models/user.py
+++ b/user/models/user.py
@@ -60,11 +60,12 @@ class User(AbstractUser):
name=ETS_GROUP
).exists()
- def send_mail_shared_access_removed(self, obj_identifier):
+ def send_mail_shared_access_removed(self, obj_identifier, obj_title):
""" Sends a mail to the user in case of removed shared access
Args:
obj_identifier ():
+ obj_title ():
Returns:
@@ -72,9 +73,9 @@ class User(AbstractUser):
notification_set = self.is_notification_setting_set(UserNotificationEnum.NOTIFY_ON_SHARED_ACCESS_REMOVED)
if notification_set:
mailer = Mailer()
- mailer.send_mail_shared_access_removed(obj_identifier, self)
+ mailer.send_mail_shared_access_removed(obj_identifier, obj_title, self)
- def send_mail_shared_access_given(self, obj_identifier):
+ def send_mail_shared_access_given(self, obj_identifier, obj_title):
""" Sends a mail to the user in case of given shared access
Args:
@@ -86,9 +87,9 @@ class User(AbstractUser):
notification_set = self.is_notification_setting_set(UserNotificationEnum.NOTIFY_ON_SHARED_ACCESS_GAINED)
if notification_set:
mailer = Mailer()
- mailer.send_mail_shared_access_given(obj_identifier, self)
+ mailer.send_mail_shared_access_given(obj_identifier, obj_title, self)
- def send_mail_shared_data_recorded(self, obj_identifier):
+ def send_mail_shared_data_recorded(self, obj_identifier, obj_title):
""" Sends a mail to the user in case of shared data has been recorded
Args:
@@ -100,9 +101,9 @@ class User(AbstractUser):
notification_set = self.is_notification_setting_set(UserNotificationEnum.NOTIFY_ON_SHARED_DATA_RECORDED)
if notification_set:
mailer = Mailer()
- mailer.send_mail_shared_data_recorded(obj_identifier, self)
+ mailer.send_mail_shared_data_recorded(obj_identifier, obj_title, self)
- def send_mail_shared_data_unrecorded(self, obj_identifier):
+ def send_mail_shared_data_unrecorded(self, obj_identifier, obj_title):
""" Sends a mail to the user in case of shared data has been unrecorded
Args:
@@ -114,9 +115,9 @@ class User(AbstractUser):
notification_set = self.is_notification_setting_set(UserNotificationEnum.NOTIFY_ON_SHARED_DATA_RECORDED)
if notification_set:
mailer = Mailer()
- mailer.send_mail_shared_data_unrecorded(obj_identifier, self)
+ mailer.send_mail_shared_data_unrecorded(obj_identifier, obj_title, self)
- def send_mail_shared_data_deleted(self, obj_identifier):
+ def send_mail_shared_data_deleted(self, obj_identifier, obj_title):
""" Sends a mail to the user in case of shared data has been deleted
Args:
@@ -128,9 +129,9 @@ class User(AbstractUser):
notification_set = self.is_notification_setting_set(UserNotificationEnum.NOTIFY_ON_SHARED_DATA_DELETED)
if notification_set:
mailer = Mailer()
- mailer.send_mail_shared_data_deleted(obj_identifier, self)
+ mailer.send_mail_shared_data_deleted(obj_identifier, obj_title, self)
- def send_mail_shared_data_checked(self, obj_identifier):
+ def send_mail_shared_data_checked(self, obj_identifier, obj_title):
""" Sends a mail to the user in case of shared data has been deleted
Args:
@@ -142,7 +143,7 @@ class User(AbstractUser):
notification_set = self.is_notification_setting_set(UserNotificationEnum.NOTIFY_ON_SHARED_DATA_CHECKED)
if notification_set:
mailer = Mailer()
- mailer.send_mail_shared_data_checked(obj_identifier, self)
+ mailer.send_mail_shared_data_checked(obj_identifier, obj_title, self)
def get_API_token(self):
""" Getter for an API token