#86 Edit deductions

* adds support for editing deductions
* adds tests
* improves major base test logic
pull/111/head
mpeltriaux 3 years ago
parent ce9143e4b2
commit d106977c34

@ -12,15 +12,17 @@ class BaseAPIV1TestCase(BaseTestCase):
def setUpTestData(cls):
super().setUpTestData()
cls.superuser.get_API_token()
cls.superuser.api_token.is_active = True
cls.superuser.api_token.save()
default_group = cls.groups.get(name=DEFAULT_GROUP)
cls.superuser.groups.add(default_group)
cls.header_data = {
"HTTP_ksptoken": cls.superuser.api_token.token,
"HTTP_kspuser": cls.superuser.username,
def setUp(self) -> None:
super().setUp()
self.superuser.get_API_token()
self.superuser.api_token.is_active = True
self.superuser.api_token.save()
default_group = self.groups.get(name=DEFAULT_GROUP)
self.superuser.groups.add(default_group)
self.header_data = {
"HTTP_ksptoken": self.superuser.api_token.token,
"HTTP_kspuser": self.superuser.username,
}

@ -60,9 +60,12 @@
</td>
<td class="align-middle">{{ deduction.surface|floatformat:2|intcomma }} m²</td>
<td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td>
<td>
<td class="align-middle float-right">
{% if is_default_member and has_access %}
<button data-form-url="{% url 'compensation:acc:remove-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove Deduction' %}">
<button data-form-url="{% url 'compensation:acc:edit-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit Deduction' %}">
{% fa5_icon 'edit' %}
</button>
<button data-form-url="{% url 'compensation:acc:remove-deduction' deduction.account.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove Deduction' %}">
{% fa5_icon 'trash' %}
</button>
{% endif %}

@ -21,29 +21,32 @@ class CompensationViewTestCase(BaseViewTestCase):
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
state = cls.create_dummy_states()
cls.compensation.before_states.set([state])
cls.compensation.after_states.set([state])
action = cls.create_dummy_action()
cls.compensation.actions.set([action])
def setUp(self) -> None:
super().setUp()
state = self.create_dummy_states()
self.compensation.before_states.set([state])
self.compensation.after_states.set([state])
action = self.create_dummy_action()
self.compensation.actions.set([action])
# Prepare urls
cls.index_url = reverse("compensation:index", args=())
cls.new_url = reverse("compensation:new", args=(cls.intervention.id,))
cls.new_id_url = reverse("compensation:new-id", args=())
cls.detail_url = reverse("compensation:detail", args=(cls.compensation.id,))
cls.log_url = reverse("compensation:log", args=(cls.compensation.id,))
cls.edit_url = reverse("compensation:edit", args=(cls.compensation.id,))
cls.remove_url = reverse("compensation:remove", args=(cls.compensation.id,))
cls.report_url = reverse("compensation:report", args=(cls.compensation.id,))
cls.state_new_url = reverse("compensation:new-state", args=(cls.compensation.id,))
cls.action_new_url = reverse("compensation:new-action", args=(cls.compensation.id,))
cls.deadline_new_url = reverse("compensation:new-deadline", args=(cls.compensation.id,))
cls.new_doc_url = reverse("compensation:new-doc", args=(cls.compensation.id,))
cls.state_remove_url = reverse("compensation:state-remove", args=(cls.compensation.id, cls.comp_state.id,))
cls.action_remove_url = reverse("compensation:action-remove", args=(cls.compensation.id, cls.comp_action.id,))
self.index_url = reverse("compensation:index", args=())
self.new_url = reverse("compensation:new", args=(self.intervention.id,))
self.new_id_url = reverse("compensation:new-id", args=())
self.detail_url = reverse("compensation:detail", args=(self.compensation.id,))
self.log_url = reverse("compensation:log", args=(self.compensation.id,))
self.edit_url = reverse("compensation:edit", args=(self.compensation.id,))
self.remove_url = reverse("compensation:remove", args=(self.compensation.id,))
self.report_url = reverse("compensation:report", args=(self.compensation.id,))
self.state_new_url = reverse("compensation:new-state", args=(self.compensation.id,))
self.action_new_url = reverse("compensation:new-action", args=(self.compensation.id,))
self.deadline_new_url = reverse("compensation:new-deadline", args=(self.compensation.id,))
self.new_doc_url = reverse("compensation:new-doc", args=(self.compensation.id,))
self.state_remove_url = reverse("compensation:state-remove", args=(self.compensation.id, self.comp_state.id,))
self.action_remove_url = reverse("compensation:action-remove", args=(self.compensation.id, self.comp_action.id,))
def test_anonymous_user(self):
""" Check correct status code for all requests

@ -21,17 +21,18 @@ class CompensationWorkflowTestCase(BaseWorkflowTestCase):
def setUpTestData(cls):
super().setUpTestData()
def setUp(self) -> None:
super().setUp()
# Give the user shared access to the dummy intervention -> inherits the access to the compensation
cls.intervention.share_with(cls.superuser)
self.intervention.share_with(self.superuser)
# Make sure the intervention itself would be fine with valid data
cls.intervention = cls.fill_out_intervention(cls.intervention)
self.intervention = self.fill_out_intervention(self.intervention)
# Make sure the compensation is linked to the intervention
cls.intervention.compensations.set([cls.compensation])
self.intervention.compensations.set([self.compensation])
def setUp(self) -> None:
super().setUp()
# Delete all existing compensations, which might be created by tests
Compensation.objects.all().delete()

@ -25,28 +25,31 @@ class EcoAccountViewTestCase(CompensationViewTestCase):
@classmethod
def setUpTestData(cls) -> None:
super().setUpTestData()
state = cls.create_dummy_states()
cls.eco_account.before_states.set([state])
cls.eco_account.after_states.set([state])
action = cls.create_dummy_action()
cls.eco_account.actions.set([action])
def setUp(self) -> None:
super().setUp()
state = self.create_dummy_states()
self.eco_account.before_states.set([state])
self.eco_account.after_states.set([state])
action = self.create_dummy_action()
self.eco_account.actions.set([action])
# Prepare urls
cls.index_url = reverse("compensation:acc:index", args=())
cls.new_url = reverse("compensation:acc:new", args=())
cls.new_id_url = reverse("compensation:acc:new-id", args=())
cls.detail_url = reverse("compensation:acc:detail", args=(cls.eco_account.id,))
cls.log_url = reverse("compensation:acc:log", args=(cls.eco_account.id,))
cls.edit_url = reverse("compensation:acc:edit", args=(cls.eco_account.id,))
cls.remove_url = reverse("compensation:acc:remove", args=(cls.eco_account.id,))
cls.report_url = reverse("compensation:acc:report", args=(cls.eco_account.id,))
cls.state_new_url = reverse("compensation:acc:new-state", args=(cls.eco_account.id,))
cls.action_new_url = reverse("compensation:acc:new-action", args=(cls.eco_account.id,))
cls.deadline_new_url = reverse("compensation:acc:new-deadline", args=(cls.eco_account.id,))
cls.new_doc_url = reverse("compensation:acc:new-doc", args=(cls.eco_account.id,))
cls.state_remove_url = reverse("compensation:acc:state-remove", args=(cls.eco_account.id, cls.comp_state.id,))
cls.action_remove_url = reverse("compensation:acc:action-remove", args=(cls.eco_account.id, cls.comp_action.id,))
self.index_url = reverse("compensation:acc:index", args=())
self.new_url = reverse("compensation:acc:new", args=())
self.new_id_url = reverse("compensation:acc:new-id", args=())
self.detail_url = reverse("compensation:acc:detail", args=(self.eco_account.id,))
self.log_url = reverse("compensation:acc:log", args=(self.eco_account.id,))
self.edit_url = reverse("compensation:acc:edit", args=(self.eco_account.id,))
self.remove_url = reverse("compensation:acc:remove", args=(self.eco_account.id,))
self.report_url = reverse("compensation:acc:report", args=(self.eco_account.id,))
self.state_new_url = reverse("compensation:acc:new-state", args=(self.eco_account.id,))
self.action_new_url = reverse("compensation:acc:new-action", args=(self.eco_account.id,))
self.deadline_new_url = reverse("compensation:acc:new-deadline", args=(self.eco_account.id,))
self.new_doc_url = reverse("compensation:acc:new-doc", args=(self.eco_account.id,))
self.state_remove_url = reverse("compensation:acc:state-remove", args=(self.eco_account.id, self.comp_state.id,))
self.action_remove_url = reverse("compensation:acc:action-remove", args=(self.eco_account.id, self.comp_action.id,))
def test_logged_in_no_groups_shared(self):
""" Check correct status code for all requests

@ -11,7 +11,7 @@ from django.contrib.gis.geos import MultiPolygon
from django.core.exceptions import ObjectDoesNotExist
from django.urls import reverse
from compensation.models import EcoAccount
from compensation.models import EcoAccount, EcoAccountDeduction
from konova.settings import ETS_GROUP, DEFAULT_GROUP
from konova.tests.test_views import BaseWorkflowTestCase
from user.models import UserAction
@ -168,7 +168,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
self.assertIn(recorded, self.eco_account.log.all())
self.assertEqual(pre_record_log_count + 1, self.eco_account.log.count())
def test_deductability(self):
def test_new_deduction(self):
"""
This tests the deductability of an eco account.
@ -187,7 +187,7 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
test_surface = 10.00
post_data = {
"surface": test_surface,
"account": self.id,
"account": self.eco_account.id,
"intervention": self.intervention.id,
}
# Perform request --> expect to fail
@ -228,4 +228,75 @@ class EcoAccountWorkflowTestCase(BaseWorkflowTestCase):
self.assertEqual(pre_deduction_int_log_count + 1, self.intervention.log.count())
self.assertTrue(self.intervention.log.first().action == UserAction.EDITED)
def test_edit_deduction(self):
test_surface = self.eco_account.get_available_rest()[0]
self.eco_account.set_recorded(self.superuser)
self.eco_account.refresh_from_db()
deduction = EcoAccountDeduction.objects.create(
intervention=self.intervention,
account=self.eco_account,
surface=0
)
self.assertEqual(1, self.intervention.deductions.count())
self.assertEqual(1, self.eco_account.deductions.count())
# Prepare url and form data to be posted
new_url = reverse("compensation:acc:edit-deduction", args=(self.eco_account.id, deduction.id))
post_data = {
"intervention": deduction.intervention.id,
"account": deduction.account.id,
"surface": test_surface,
}
pre_edit_intervention_log_count = self.intervention.log.count()
pre_edit_account_log_count = self.eco_account.log.count()
num_deductions_intervention = self.intervention.deductions.count()
num_deductions_account = self.eco_account.deductions.count()
self.client_user.post(new_url, post_data)
self.intervention.refresh_from_db()
self.eco_account.refresh_from_db()
deduction.refresh_from_db()
self.assertEqual(num_deductions_intervention, self.intervention.deductions.count())
self.assertEqual(num_deductions_account, self.eco_account.deductions.count())
self.assertEqual(deduction.surface, test_surface)
# Expect logs to be set
self.assertEqual(pre_edit_intervention_log_count + 1, self.intervention.log.count())
self.assertEqual(pre_edit_account_log_count + 1, self.eco_account.log.count())
self.assertEqual(self.intervention.log.first().action, UserAction.EDITED)
self.assertEqual(self.eco_account.log.first().action, UserAction.EDITED)
def test_remove_deduction(self):
intervention = self.deduction.intervention
account = self.deduction.account
# Prepare url and form data to be posted
new_url = reverse("compensation:acc:remove-deduction", args=(account.id, self.deduction.id))
post_data = {
"confirm": True,
}
intervention.share_with(self.superuser)
account.share_with(self.superuser)
pre_edit_intervention_log_count = intervention.log.count()
pre_edit_account_log_count = account.log.count()
num_deductions_intervention = intervention.deductions.count()
num_deductions_account = account.deductions.count()
self.client_user.post(new_url, post_data)
intervention.refresh_from_db()
account.refresh_from_db()
self.assertEqual(num_deductions_intervention - 1, intervention.deductions.count())
self.assertEqual(num_deductions_account - 1, account.deductions.count())
# Expect logs to be set
self.assertEqual(pre_edit_intervention_log_count + 1, intervention.log.count())
self.assertEqual(pre_edit_account_log_count + 1, account.log.count())
self.assertEqual(intervention.log.first().action, UserAction.EDITED)
self.assertEqual(account.log.first().action, UserAction.EDITED)

@ -19,16 +19,18 @@ class PaymentViewTestCase(BaseViewTestCase):
def setUpTestData(cls) -> None:
super().setUpTestData()
cls.payment = Payment.objects.get_or_create(
intervention=cls.intervention,
def setUp(self) -> None:
super().setUp()
self.payment = Payment.objects.get_or_create(
intervention=self.intervention,
amount=1,
due_on="2020-01-01",
comment="Testcomment"
)[0]
cls.new_url = reverse("compensation:pay:new", args=(cls.intervention.id,))
cls.edit_url = reverse("compensation:pay:edit", args=(cls.intervention.id, cls.payment.id))
cls.remove_url = reverse("compensation:pay:remove", args=(cls.intervention.id, cls.payment.id))
self.new_url = reverse("compensation:pay:new", args=(self.intervention.id,))
self.edit_url = reverse("compensation:pay:edit", args=(self.intervention.id, self.payment.id))
self.remove_url = reverse("compensation:pay:remove", args=(self.intervention.id, self.payment.id))
def test_anonymous_user(self):
""" Check correct status code for all requests

@ -18,11 +18,13 @@ class PaymentWorkflowTestCase(BaseWorkflowTestCase):
def setUpTestData(cls):
super().setUpTestData()
def setUp(self) -> None:
super().setUp()
# Give the user shared access to the dummy intervention
cls.intervention.share_with(cls.superuser)
self.intervention.share_with(self.superuser)
cls.payment = Payment.objects.get_or_create(
intervention=cls.intervention,
self.payment = Payment.objects.get_or_create(
intervention=self.intervention,
amount=1,
due_on="2020-01-01",
comment="Testcomment"

@ -34,7 +34,8 @@ urlpatterns = [
path('document/<doc_id>/remove/', remove_document_view, name='remove-doc'),
# Eco-account deductions
path('<id>/remove/<deduction_id>', deduction_remove_view, name='remove-deduction'),
path('<id>/deduction/<deduction_id>/remove', deduction_remove_view, name='remove-deduction'),
path('<id>/deduction/<deduction_id>/edit', deduction_edit_view, name='edit-deduction'),
path('<id>/deduct/new', new_deduction_view, name='new-deduction'),
]

@ -19,7 +19,8 @@ from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm,
NewEcoAccountDocumentForm, RemoveCompensationActionModalForm, RemoveCompensationStateModalForm
from compensation.models import EcoAccount, EcoAccountDocument, CompensationState, CompensationAction
from compensation.tables import EcoAccountTable
from intervention.forms.modalForms import NewDeductionModalForm, ShareModalForm, RemoveEcoAccountDeductionModalForm
from intervention.forms.modalForms import NewDeductionModalForm, ShareModalForm, RemoveEcoAccountDeductionModalForm, \
EditEcoAccountDeductionModalForm
from konova.contexts import BaseContext
from konova.decorators import any_group_check, default_group_required, conservation_office_group_required, \
shared_access_required
@ -31,7 +32,8 @@ from konova.utils.documents import get_document, remove_document
from konova.utils.generators import generate_qr_code
from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID, DATA_UNSHARED, DATA_UNSHARED_EXPLANATION, \
CANCEL_ACC_RECORDED_OR_DEDUCTED, DEDUCTION_REMOVED, DEDUCTION_ADDED, DOCUMENT_ADDED, COMPENSATION_STATE_REMOVED, \
COMPENSATION_STATE_ADDED, COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_ADDED, DEADLINE_ADDED, DEADLINE_REMOVED
COMPENSATION_STATE_ADDED, COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_ADDED, DEADLINE_ADDED, DEADLINE_REMOVED, \
DEDUCTION_EDITED
from konova.utils.user_checks import in_group
@ -294,6 +296,34 @@ def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str):
)
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")
def deduction_edit_view(request: HttpRequest, id: str, deduction_id: str):
""" Renders a modal view for editing deductions
Args:
request (HttpRequest): The incoming request
id (str): The eco account's id
deduction_id (str): The deduction's id
Returns:
"""
acc = get_object_or_404(EcoAccount, id=id)
try:
eco_deduction = acc.deductions.get(id=deduction_id)
except ObjectDoesNotExist:
raise Http404("Unknown deduction")
form = EditEcoAccountDeductionModalForm(request.POST or None, instance=acc, deduction=eco_deduction, request=request)
return form.process_request(
request=request,
msg_success=DEDUCTION_EDITED,
redirect_url=reverse("compensation:acc:detail", args=(id,)) + "#related_data"
)
@login_required
@default_group_required
@shared_access_required(EcoAccount, "id")

@ -31,42 +31,43 @@ class EmaViewTestCase(CompensationViewTestCase):
def setUpTestData(cls) -> None:
super().setUpTestData()
def setUp(self) -> None:
super().setUp()
# Create dummy data and related objects, like states or actions
cls.create_dummy_data()
state = cls.create_dummy_states()
action = cls.create_dummy_action()
cls.ema.before_states.set([state])
cls.ema.after_states.set([state])
cls.ema.actions.set([action])
self.create_dummy_data()
state = self.create_dummy_states()
action = self.create_dummy_action()
self.ema.before_states.set([state])
self.ema.after_states.set([state])
self.ema.actions.set([action])
# Prepare urls
cls.index_url = reverse("ema:index", args=())
cls.new_url = reverse("ema:new", args=())
cls.new_id_url = reverse("ema:new-id", args=())
cls.detail_url = reverse("ema:detail", args=(cls.ema.id,))
cls.log_url = reverse("ema:log", args=(cls.ema.id,))
cls.edit_url = reverse("ema:edit", args=(cls.ema.id,))
cls.remove_url = reverse("ema:remove", args=(cls.ema.id,))
cls.share_url = reverse("ema:share", args=(cls.ema.id, cls.ema.access_token,))
cls.share_create_url = reverse("ema:share-create", args=(cls.ema.id,))
cls.record_url = reverse("ema:record", args=(cls.ema.id,))
cls.report_url = reverse("ema:report", args=(cls.ema.id,))
cls.new_doc_url = reverse("ema:new-doc", args=(cls.ema.id,))
cls.state_new_url = reverse("ema:new-state", args=(cls.ema.id,))
cls.action_new_url = reverse("ema:new-action", args=(cls.ema.id,))
cls.deadline_new_url = reverse("ema:new-deadline", args=(cls.ema.id,))
cls.state_remove_url = reverse("ema:state-remove", args=(cls.ema.id, state.id,))
cls.action_remove_url = reverse("ema:action-remove", args=(cls.ema.id, action.id,))
@classmethod
def create_dummy_data(cls):
self.index_url = reverse("ema:index", args=())
self.new_url = reverse("ema:new", args=())
self.new_id_url = reverse("ema:new-id", args=())
self.detail_url = reverse("ema:detail", args=(self.ema.id,))
self.log_url = reverse("ema:log", args=(self.ema.id,))
self.edit_url = reverse("ema:edit", args=(self.ema.id,))
self.remove_url = reverse("ema:remove", args=(self.ema.id,))
self.share_url = reverse("ema:share", args=(self.ema.id, self.ema.access_token,))
self.share_create_url = reverse("ema:share-create", args=(self.ema.id,))
self.record_url = reverse("ema:record", args=(self.ema.id,))
self.report_url = reverse("ema:report", args=(self.ema.id,))
self.new_doc_url = reverse("ema:new-doc", args=(self.ema.id,))
self.state_new_url = reverse("ema:new-state", args=(self.ema.id,))
self.action_new_url = reverse("ema:new-action", args=(self.ema.id,))
self.deadline_new_url = reverse("ema:new-deadline", args=(self.ema.id,))
self.state_remove_url = reverse("ema:state-remove", args=(self.ema.id, state.id,))
self.action_remove_url = reverse("ema:action-remove", args=(self.ema.id, action.id,))
def create_dummy_data(self):
# Create dummy data
# Create log entry
action = UserActionLogEntry.get_created_action(cls.superuser)
action = UserActionLogEntry.get_created_action(self.superuser)
# Create responsible data object
responsibility_data = Responsibility.objects.create()
geometry = Geometry.objects.create()
cls.ema = Ema.objects.create(
self.ema = Ema.objects.create(
identifier="TEST",
title="Test_title",
created=action,

@ -7,7 +7,7 @@ Created on: 27.09.21
"""
from dal import autocomplete
from konova.utils.message_templates import DEDUCTION_ADDED, REVOCATION_ADDED, DEDUCTION_REMOVED
from konova.utils.message_templates import DEDUCTION_ADDED, REVOCATION_ADDED, DEDUCTION_REMOVED, DEDUCTION_EDITED
from user.models import User, UserActionLogEntry
from django.db import transaction
from django import forms
@ -349,6 +349,21 @@ class NewDeductionModalForm(BaseModalForm):
else:
raise NotImplementedError
def _get_available_surface(self, acc):
""" Calculates how much available surface is left on the account
Args:
acc (EcoAccount):
Returns:
"""
# Calculate valid surface
deductable_surface = acc.deductable_surface
sum_surface_deductions = acc.get_deductions_surface()
rest_surface = deductable_surface - sum_surface_deductions
return rest_surface
def is_valid(self):
""" Custom validity check
@ -367,10 +382,7 @@ class NewDeductionModalForm(BaseModalForm):
)
return False
# Calculate valid surface
deductable_surface = acc.deductable_surface
sum_surface_deductions = acc.get_deductions_surface()
rest_surface = deductable_surface - sum_surface_deductions
rest_surface = self._get_available_surface(acc)
form_surface = float(self.cleaned_data["surface"])
is_valid_surface = form_surface <= rest_surface
if not is_valid_surface:
@ -407,6 +419,57 @@ class NewDeductionModalForm(BaseModalForm):
return deduction
class EditEcoAccountDeductionModalForm(NewDeductionModalForm):
deduction = None
def __init__(self, *args, **kwargs):
self.deduction = kwargs.pop("deduction", None)
super().__init__(*args, **kwargs)
form_data = {
"account": self.deduction.account,
"intervention": self.deduction.intervention,
"surface": self.deduction.surface,
}
self.load_initial_data(form_data)
def _get_available_surface(self, acc):
rest_surface = super()._get_available_surface(acc)
# Increase available surface by the currently deducted surface, so we can 'deduct' the same amount again or
# increase the surface only a little, which will still be valid.
# Example: 200 m² left, 500 m² deducted. Entering 700 m² would fail if we would not add the 500 m² to the available
# surface again.
rest_surface += self.deduction.surface
return rest_surface
def save(self):
deduction = self.deduction
form_account = self.cleaned_data.get("account", None)
form_intervention = self.cleaned_data.get("intervention", None)
current_account = deduction.account
current_intervention = deduction.intervention
# If account or intervention has been changed, we put that change in the logs just as if the deduction has
# been removed for this entry. Act as if the deduction is newly created for the new entries
if current_account != form_account:
current_account.mark_as_edited(self.user, self.request, edit_comment=DEDUCTION_REMOVED)
form_account.mark_as_edited(self.user, self.request, edit_comment=DEDUCTION_ADDED)
else:
current_account.mark_as_edited(self.user, self.request, edit_comment=DEDUCTION_EDITED)
if current_intervention != form_intervention:
current_intervention.mark_as_edited(self.user, self.request, edit_comment=DEDUCTION_REMOVED)
form_intervention.mark_as_edited(self.user, self.request, edit_comment=DEDUCTION_ADDED)
else:
current_intervention.mark_as_edited(self.user, self.request, edit_comment=DEDUCTION_EDITED)
deduction.account = form_account
deduction.intervention = self.cleaned_data.get("intervention", None)
deduction.surface = self.cleaned_data.get("surface", None)
deduction.save()
return deduction
class RemoveEcoAccountDeductionModalForm(RemoveModalForm):
""" Removing modal form for EcoAccountDeduction

@ -55,9 +55,12 @@
</td>
<td class="align-middle">{{ deduction.surface|floatformat:2|intcomma }} m²</td>
<td class="align-middle">{{ deduction.created.timestamp|default_if_none:""|naturalday}}</td>
<td>
<td class="align-middle float-right">
{% if is_default_member and has_access %}
<button data-form-url="{% url 'intervention:remove-deduction' obj.id deduction.id %}" class="btn btn-default btn-modal float-right" title="{% trans 'Remove Deduction' %}">
<button data-form-url="{% url 'intervention:edit-deduction' obj.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Edit Deduction' %}">
{% fa5_icon 'edit' %}
</button>
<button data-form-url="{% url 'intervention:remove-deduction' obj.id deduction.id %}" class="btn btn-default btn-modal" title="{% trans 'Remove Deduction' %}">
{% fa5_icon 'trash' %}
</button>
{% endif %}

@ -21,30 +21,32 @@ 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,))
cls.deduction.intervention = cls.intervention
cls.deduction.save()
cls.deduction_new_url = reverse("intervention:new-deduction", args=(cls.intervention.id,))
cls.deduction_remove_url = reverse("intervention:remove-deduction", args=(cls.intervention.id, cls.deduction.id))
cls.revocation = Revocation.objects.create(
legal=cls.intervention.legal
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_remove_url = reverse("intervention:remove-deduction", args=(self.intervention.id, self.deduction.id))
self.revocation = Revocation.objects.create(
legal=self.intervention.legal
)
cls.revocation_new_url = reverse("intervention:new-revocation", args=(cls.intervention.id,))
cls.revocation_remove_url = reverse("intervention:remove-revocation", args=(cls.intervention.id, cls.revocation.id))
self.revocation_new_url = reverse("intervention:new-revocation", args=(self.intervention.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

@ -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
app_name = "intervention"
urlpatterns = [
@ -37,6 +37,7 @@ urlpatterns = [
# Deductions
path('<id>/deduction/new', new_deduction_view, name='new-deduction'),
path('<id>/deduction/<deduction_id>/edit', edit_deduction_view, name='edit-deduction'),
path('<id>/deduction/<deduction_id>/remove', remove_deduction_view, name='remove-deduction'),
# Revocation routes

@ -7,7 +7,7 @@ from django.shortcuts import render
from intervention.forms.forms import NewInterventionForm, EditInterventionForm
from intervention.forms.modalForms import ShareModalForm, NewRevocationModalForm, \
CheckModalForm, NewDeductionModalForm, NewInterventionDocumentForm, RemoveEcoAccountDeductionModalForm, \
RemoveRevocationModalForm
RemoveRevocationModalForm, EditEcoAccountDeductionModalForm
from intervention.models import Intervention, Revocation, InterventionDocument, RevocationDocument
from intervention.tables import InterventionTable
from konova.contexts import BaseContext
@ -18,7 +18,7 @@ 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
from konova.utils.user_checks import in_group
@ -536,6 +536,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")

@ -47,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 = ""):
@ -94,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:
@ -103,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
@ -122,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:
@ -155,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()
@ -172,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:
@ -181,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()
@ -196,41 +207,37 @@ 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:
@ -256,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:
@ -277,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:
@ -292,15 +297,14 @@ 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
@classmethod
def get_conservation_office_code(cls):
def get_conservation_office_code(self):
""" Returns a dummy KonovaCode as conservation office code
Returns:
@ -313,39 +317,37 @@ class BaseTestCase(TestCase):
codelist.codes.add(code)
return code
@classmethod
def fill_out_ema(cls, ema):
def fill_out_ema(self, ema):
""" Adds all required (dummy) data to an Ema
Returns:
"""
ema.responsible.conservation_office = cls.get_conservation_office_code()
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(cls.comp_state)
ema.before_states.add(cls.comp_state)
ema.actions.add(cls.comp_action)
ema.geometry.geom = cls.create_dummy_geometry()
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
@classmethod
def fill_out_eco_account(cls, eco_account):
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 = cls.get_conservation_office_code()
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(cls.comp_state)
eco_account.before_states.add(cls.comp_state)
eco_account.actions.add(cls.comp_action)
eco_account.geometry.geom = cls.create_dummy_geometry()
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()
@ -390,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
@ -549,22 +554,6 @@ class BaseWorkflowTestCase(BaseTestCase):
def setUpTestData(cls):
super().setUpTestData()
def setUp(self) -> None:
""" Setup data before each test run
Returns:
"""
super().setUp()
# 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

@ -30,18 +30,22 @@ 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
@ -51,6 +55,7 @@ PAYMENT_REMOVED = _("Payment removed")
# REVOCATIONS
REVOCATION_ADDED = _("Revocation added")
REVOCATION_EDITED = _("Revocation edited")
REVOCATION_REMOVED = _("Revocation removed")
# DOCUMENTS

Binary file not shown.

@ -5,7 +5,7 @@
#
#: compensation/filters.py:122 compensation/forms/modalForms.py:35
#: compensation/forms/modalForms.py:46 compensation/forms/modalForms.py:62
#: compensation/forms/modalForms.py:329 compensation/forms/modalForms.py:422
#: compensation/forms/modalForms.py:332 compensation/forms/modalForms.py:425
#: 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
@ -26,7 +26,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2022-02-09 09:50+0100\n"
"POT-Creation-Date: 2022-02-09 12:52+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -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:406
#: compensation/forms/modalForms.py:409
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:34
#: intervention/templates/intervention/detail/includes/deductions.html:31
msgid "Amount"
@ -213,7 +213,7 @@ 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:190
#: 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
@ -353,7 +353,7 @@ msgid "Compensation XY; Location ABC"
msgstr "Kompensation XY; Flur ABC"
#: compensation/forms/forms.py:57 compensation/forms/modalForms.py:61
#: compensation/forms/modalForms.py:328 compensation/forms/modalForms.py:421
#: compensation/forms/modalForms.py:331 compensation/forms/modalForms.py:424
#: 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
@ -371,7 +371,7 @@ msgstr "Kompensation XY; Flur ABC"
msgid "Comment"
msgstr "Kommentar"
#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:423
#: compensation/forms/forms.py:59 compensation/forms/modalForms.py:426
#: intervention/forms/forms.py:182
msgid "Additional comment"
msgstr "Zusätzlicher Kommentar"
@ -457,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:103
#: compensation/forms/forms.py:354 compensation/views/eco_account.py:105
msgid "New Eco-Account"
msgstr "Neues Ökokonto"
@ -482,7 +482,7 @@ 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:330
#: compensation/forms/modalForms.py:63 compensation/forms/modalForms.py:333
#: intervention/forms/modalForms.py:151 konova/forms.py:393
msgid "Additional comment, maximum {} letters"
msgstr "Zusätzlicher Kommentar, maximal {} Zeichen"
@ -495,47 +495,47 @@ 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:154 compensation/forms/modalForms.py:166
#: compensation/forms/modalForms.py:157 compensation/forms/modalForms.py:169
msgid "Biotope Type"
msgstr "Biotoptyp"
#: compensation/forms/modalForms.py:157
#: compensation/forms/modalForms.py:160
msgid "Select the biotope type"
msgstr "Biotoptyp wählen"
#: compensation/forms/modalForms.py:171 compensation/forms/modalForms.py:183
#: compensation/forms/modalForms.py:174 compensation/forms/modalForms.py:186
msgid "Biotope additional type"
msgstr "Zusatzbezeichnung"
#: compensation/forms/modalForms.py:174
#: compensation/forms/modalForms.py:177
msgid "Select an additional biotope type"
msgstr "Zusatzbezeichnung wählen"
#: compensation/forms/modalForms.py:193 intervention/forms/modalForms.py:313
#: compensation/forms/modalForms.py:196 intervention/forms/modalForms.py:313
msgid "in m²"
msgstr ""
#: compensation/forms/modalForms.py:204
#: compensation/forms/modalForms.py:207
msgid "New state"
msgstr "Neuer Zustand"
#: compensation/forms/modalForms.py:205
#: 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:212 konova/forms.py:191
#: compensation/forms/modalForms.py:215 konova/forms.py:191
msgid "Object removed"
msgstr "Objekt entfernt"
#: compensation/forms/modalForms.py:300
#: compensation/forms/modalForms.py:303
msgid "Deadline Type"
msgstr "Fristart"
#: compensation/forms/modalForms.py:303
#: compensation/forms/modalForms.py:306
msgid "Select the deadline type"
msgstr "Fristart wählen"
#: compensation/forms/modalForms.py:312
#: compensation/forms/modalForms.py:315
#: 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
@ -543,27 +543,27 @@ msgstr "Fristart wählen"
msgid "Date"
msgstr "Datum"
#: compensation/forms/modalForms.py:315
#: compensation/forms/modalForms.py:318
msgid "Select date"
msgstr "Datum wählen"
#: compensation/forms/modalForms.py:342
#: compensation/forms/modalForms.py:345
msgid "New deadline"
msgstr "Neue Frist"
#: compensation/forms/modalForms.py:343
#: compensation/forms/modalForms.py:346
msgid "Insert data for the new deadline"
msgstr "Geben Sie die Daten der neuen Frist ein"
#: compensation/forms/modalForms.py:360
#: compensation/forms/modalForms.py:363
msgid "Action Type"
msgstr "Maßnahmentyp"
#: compensation/forms/modalForms.py:363
#: compensation/forms/modalForms.py:366
msgid "Select the action type"
msgstr "Maßnahmentyp wählen"
#: compensation/forms/modalForms.py:372
#: compensation/forms/modalForms.py:375
#: 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
@ -589,31 +589,31 @@ msgstr "Maßnahmentyp wählen"
msgid "Action"
msgstr "Aktionen"
#: compensation/forms/modalForms.py:377 compensation/forms/modalForms.py:389
#: compensation/forms/modalForms.py:380 compensation/forms/modalForms.py:392
msgid "Action Type detail"
msgstr "Zusatzmerkmal"
#: compensation/forms/modalForms.py:380
#: compensation/forms/modalForms.py:383
msgid "Select the action type detail"
msgstr "Zusatzmerkmal wählen"
#: compensation/forms/modalForms.py:394
#: compensation/forms/modalForms.py:397
msgid "Unit"
msgstr "Einheit"
#: compensation/forms/modalForms.py:397
#: compensation/forms/modalForms.py:400
msgid "Select the unit"
msgstr "Einheit wählen"
#: compensation/forms/modalForms.py:409
#: compensation/forms/modalForms.py:412
msgid "Insert the amount"
msgstr "Menge eingeben"
#: compensation/forms/modalForms.py:434
#: compensation/forms/modalForms.py:437
msgid "New action"
msgstr "Neue Maßnahme"
#: compensation/forms/modalForms.py:435
#: compensation/forms/modalForms.py:438
msgid "Insert data for the new action"
msgstr "Geben Sie die Daten der neuen Maßnahme ein"
@ -992,7 +992,7 @@ msgid "Recorded on"
msgstr "Verzeichnet am"
#: compensation/templates/compensation/detail/eco_account/includes/deductions.html:65
#: intervention/templates/intervention/detail/includes/deductions.html:60
#: intervention/templates/intervention/detail/includes/deductions.html:63
msgid "Remove Deduction"
msgstr "Abbuchung entfernen"
@ -1084,63 +1084,63 @@ msgstr "Kompensationen - Übersicht"
msgid "Compensation {} edited"
msgstr "Kompensation {} bearbeitet"
#: compensation/views/compensation.py:159 compensation/views/eco_account.py:161
#: compensation/views/compensation.py:159 compensation/views/eco_account.py:163
#: ema/views.py:230 intervention/views.py:305
msgid "Edit {}"
msgstr "Bearbeite {}"
#: compensation/views/compensation.py:238 compensation/views/eco_account.py:317
#: compensation/views/compensation.py:238 compensation/views/eco_account.py:347
#: ema/views.py:191 intervention/views.py:483
msgid "Log"
msgstr "Log"
#: compensation/views/compensation.py:487 compensation/views/eco_account.py:590
#: ema/views.py:477 intervention/views.py:601
#: compensation/views/compensation.py:487 compensation/views/eco_account.py:620
#: ema/views.py:477 intervention/views.py:629
msgid "Report {}"
msgstr "Bericht {}"
#: compensation/views/eco_account.py:60
#: compensation/views/eco_account.py:62
msgid "Eco-account - Overview"
msgstr "Ökokonten - Übersicht"
#: compensation/views/eco_account.py:93
#: compensation/views/eco_account.py:95
msgid "Eco-Account {} added"
msgstr "Ökokonto {} hinzugefügt"
#: compensation/views/eco_account.py:151
#: compensation/views/eco_account.py:153
msgid "Eco-Account {} edited"
msgstr "Ökokonto {} bearbeitet"
#: compensation/views/eco_account.py:264
#: compensation/views/eco_account.py:266
msgid "Eco-account removed"
msgstr "Ökokonto entfernt"
#: compensation/views/eco_account.py:338 ema/views.py:272
#: intervention/views.py:554
#: compensation/views/eco_account.py:368 ema/views.py:272
#: intervention/views.py:582
msgid "{} unrecorded"
msgstr "{} entzeichnet"
#: compensation/views/eco_account.py:338 ema/views.py:272
#: intervention/views.py:554
#: compensation/views/eco_account.py:368 ema/views.py:272
#: intervention/views.py:582
msgid "{} recorded"
msgstr "{} verzeichnet"
#: compensation/views/eco_account.py:663 ema/views.py:543
#: compensation/views/eco_account.py:693 ema/views.py:543
#: intervention/views.py:380
msgid "{} has already been shared with you"
msgstr "{} wurde bereits für Sie freigegeben"
#: compensation/views/eco_account.py:668 ema/views.py:548
#: compensation/views/eco_account.py:698 ema/views.py:548
#: intervention/views.py:385
msgid "{} has been shared with you"
msgstr "{} ist nun für Sie freigegeben"
#: compensation/views/eco_account.py:675 ema/views.py:555
#: compensation/views/eco_account.py:705 ema/views.py:555
#: intervention/views.py:392
msgid "Share link invalid"
msgstr "Freigabelink ungültig"
#: compensation/views/eco_account.py:698 ema/views.py:578
#: compensation/views/eco_account.py:728 ema/views.py:578
#: intervention/views.py:415
msgid "Share settings updated"
msgstr "Freigabe Einstellungen aktualisiert"
@ -1337,7 +1337,7 @@ msgstr "Neue Abbuchung"
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:366
#: intervention/forms/modalForms.py:381
msgid ""
"Eco-account {} is not recorded yet. You can only deduct from recorded "
"accounts."
@ -1345,7 +1345,7 @@ msgstr ""
"Ökokonto {} ist noch nicht verzeichnet. Abbuchungen können nur von "
"verzeichneten Ökokonten erfolgen."
#: intervention/forms/modalForms.py:379
#: intervention/forms/modalForms.py:391
msgid ""
"The account {} has not enough surface for a deduction of {} m². There are "
"only {} m² left"
@ -1373,6 +1373,10 @@ msgstr "Ökokonto gelöscht! Abbuchung ungültig!"
msgid "Eco-account not recorded! Deduction invalid!"
msgstr "Ökokonto nicht verzeichnet! Abbuchung ungültig!"
#: intervention/templates/intervention/detail/includes/deductions.html:60
msgid "Edit Deduction"
msgstr "Abbuchung bearbeiten"
#: intervention/templates/intervention/detail/includes/payments.html:8
#: intervention/templates/intervention/report/report.html:73
msgid "Payments"
@ -1464,7 +1468,7 @@ msgstr "{} entfernt"
msgid "Check performed"
msgstr "Prüfung durchgeführt"
#: intervention/views.py:559
#: intervention/views.py:587
msgid "There are errors on this intervention:"
msgstr "Es liegen Fehler in diesem Eingriff vor:"
@ -1824,74 +1828,94 @@ msgid "State removed"
msgstr "Zustand gelöscht"
#: konova/utils/message_templates.py:33
msgid "State edited"
msgstr "Zustand bearbeitet"
#: konova/utils/message_templates.py:34
msgid "State added"
msgstr "Zustand hinzugefügt"
#: konova/utils/message_templates.py:36
#: konova/utils/message_templates.py:37
msgid "Action added"
msgstr "Maßnahme hinzugefügt"
#: konova/utils/message_templates.py:37
#: konova/utils/message_templates.py:38
msgid "Action edited"
msgstr "Maßnahme bearbeitet"
#: konova/utils/message_templates.py:39
msgid "Action removed"
msgstr "Maßnahme entfernt"
#: konova/utils/message_templates.py:40
#: konova/utils/message_templates.py:42
msgid "Deduction added"
msgstr "Abbuchung hinzugefügt"
#: konova/utils/message_templates.py:41
#: konova/utils/message_templates.py:43
msgid "Deduction edited"
msgstr "Abbuchung bearbeitet"
#: konova/utils/message_templates.py:44
msgid "Deduction removed"
msgstr "Abbuchung entfernt"
#: konova/utils/message_templates.py:44
#: konova/utils/message_templates.py:47
msgid "Deadline added"
msgstr "Frist/Termin hinzugefügt"
#: konova/utils/message_templates.py:45
#: konova/utils/message_templates.py:48
msgid "Deadline edited"
msgstr "Frist/Termin bearbeitet"
#: konova/utils/message_templates.py:49
msgid "Deadline removed"
msgstr "Frist/Termin gelöscht"
#: konova/utils/message_templates.py:48
#: konova/utils/message_templates.py:52
msgid "Payment added"
msgstr "Zahlung hinzugefügt"
#: konova/utils/message_templates.py:49
#: konova/utils/message_templates.py:53
msgid "Payment edited"
msgstr "Zahlung bearbeitet"
#: konova/utils/message_templates.py:50
#: konova/utils/message_templates.py:54
msgid "Payment removed"
msgstr "Zahlung gelöscht"
#: konova/utils/message_templates.py:53
#: konova/utils/message_templates.py:57
msgid "Revocation added"
msgstr "Widerspruch hinzugefügt"
#: konova/utils/message_templates.py:54
#: konova/utils/message_templates.py:58
msgid "Revocation edited"
msgstr "Widerspruch bearbeitet"
#: konova/utils/message_templates.py:59
msgid "Revocation removed"
msgstr "Widerspruch entfernt"
#: konova/utils/message_templates.py:57
#: konova/utils/message_templates.py:62
msgid "Document '{}' deleted"
msgstr "Dokument '{}' gelöscht"
#: konova/utils/message_templates.py:58
#: konova/utils/message_templates.py:63
msgid "Document added"
msgstr "Dokument hinzugefügt"
#: konova/utils/message_templates.py:61
#: konova/utils/message_templates.py:66
msgid "Edited general data"
msgstr "Allgemeine Daten bearbeitet"
#: konova/utils/message_templates.py:62
#: konova/utils/message_templates.py:67
msgid "Added deadline"
msgstr "Frist/Termin hinzugefügt"
#: konova/utils/message_templates.py:65
#: konova/utils/message_templates.py:70
msgid "Geometry conflict detected with {}"
msgstr "Geometriekonflikt mit folgenden Einträgen erkannt: {}"
#: konova/utils/message_templates.py:68
#: konova/utils/message_templates.py:73
msgid "This intervention has {} revocations"
msgstr "Dem Eingriff liegen {} Widersprüche vor"

Loading…
Cancel
Save