From d106977c34b753114b3cd7d6573d797488e68bcc Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Wed, 9 Feb 2022 14:49:56 +0100 Subject: [PATCH] #86 Edit deductions * adds support for editing deductions * adds tests * improves major base test logic --- api/tests/v1/share/test_api_sharing.py | 20 +- .../eco_account/includes/deductions.html | 7 +- compensation/tests/compensation/test_views.py | 43 +++-- .../tests/compensation/test_workflow.py | 13 +- compensation/tests/ecoaccount/test_views.py | 41 ++-- .../tests/ecoaccount/test_workflow.py | 77 +++++++- compensation/tests/payment/test_views.py | 12 +- compensation/tests/payment/test_workflow.py | 8 +- compensation/urls/eco_account.py | 3 +- compensation/views/eco_account.py | 34 +++- ema/tests/test_views.py | 57 +++--- intervention/forms/modalForms.py | 73 +++++++- .../detail/includes/deductions.html | 7 +- intervention/tests/test_views.py | 46 ++--- intervention/urls.py | 3 +- intervention/views.py | 32 +++- konova/tests/test_views.py | 175 ++++++++---------- konova/utils/message_templates.py | 5 + locale/de/LC_MESSAGES/django.mo | Bin 36759 -> 37109 bytes locale/de/LC_MESSAGES/django.po | 162 +++++++++------- 20 files changed, 526 insertions(+), 292 deletions(-) diff --git a/api/tests/v1/share/test_api_sharing.py b/api/tests/v1/share/test_api_sharing.py index 9e7c9ee..1da0ce1 100644 --- a/api/tests/v1/share/test_api_sharing.py +++ b/api/tests/v1/share/test_api_sharing.py @@ -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, } diff --git a/compensation/templates/compensation/detail/eco_account/includes/deductions.html b/compensation/templates/compensation/detail/eco_account/includes/deductions.html index e72ab2a..76c116b 100644 --- a/compensation/templates/compensation/detail/eco_account/includes/deductions.html +++ b/compensation/templates/compensation/detail/eco_account/includes/deductions.html @@ -60,9 +60,12 @@ {{ deduction.surface|floatformat:2|intcomma }} m² {{ deduction.created.timestamp|default_if_none:""|naturalday}} - + {% if is_default_member and has_access %} - + {% endif %} diff --git a/compensation/tests/compensation/test_views.py b/compensation/tests/compensation/test_views.py index 465a102..5844e26 100644 --- a/compensation/tests/compensation/test_views.py +++ b/compensation/tests/compensation/test_views.py @@ -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]) + + def setUp(self) -> None: + super().setUp() + state = self.create_dummy_states() + self.compensation.before_states.set([state]) + self.compensation.after_states.set([state]) - action = cls.create_dummy_action() - cls.compensation.actions.set([action]) + 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 diff --git a/compensation/tests/compensation/test_workflow.py b/compensation/tests/compensation/test_workflow.py index d1f1378..7b73be8 100644 --- a/compensation/tests/compensation/test_workflow.py +++ b/compensation/tests/compensation/test_workflow.py @@ -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]) - - def setUp(self) -> None: - super().setUp() + self.intervention.compensations.set([self.compensation]) + # Delete all existing compensations, which might be created by tests Compensation.objects.all().delete() diff --git a/compensation/tests/ecoaccount/test_views.py b/compensation/tests/ecoaccount/test_views.py index c4e742f..670f4f0 100644 --- a/compensation/tests/ecoaccount/test_views.py +++ b/compensation/tests/ecoaccount/test_views.py @@ -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]) + + 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 = cls.create_dummy_action() - cls.eco_account.actions.set([action]) + 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 diff --git a/compensation/tests/ecoaccount/test_workflow.py b/compensation/tests/ecoaccount/test_workflow.py index f394ec7..1cdb030 100644 --- a/compensation/tests/ecoaccount/test_workflow.py +++ b/compensation/tests/ecoaccount/test_workflow.py @@ -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) diff --git a/compensation/tests/payment/test_views.py b/compensation/tests/payment/test_views.py index 69130e8..b1eca5a 100644 --- a/compensation/tests/payment/test_views.py +++ b/compensation/tests/payment/test_views.py @@ -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 diff --git a/compensation/tests/payment/test_workflow.py b/compensation/tests/payment/test_workflow.py index 09ff0e6..790fb61 100644 --- a/compensation/tests/payment/test_workflow.py +++ b/compensation/tests/payment/test_workflow.py @@ -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" diff --git a/compensation/urls/eco_account.py b/compensation/urls/eco_account.py index 7deb48f..0c3a029 100644 --- a/compensation/urls/eco_account.py +++ b/compensation/urls/eco_account.py @@ -34,7 +34,8 @@ urlpatterns = [ path('document//remove/', remove_document_view, name='remove-doc'), # Eco-account deductions - path('/remove/', deduction_remove_view, name='remove-deduction'), + path('/deduction//remove', deduction_remove_view, name='remove-deduction'), + path('/deduction//edit', deduction_edit_view, name='edit-deduction'), path('/deduct/new', new_deduction_view, name='new-deduction'), ] \ No newline at end of file diff --git a/compensation/views/eco_account.py b/compensation/views/eco_account.py index 7d1e560..08e01a6 100644 --- a/compensation/views/eco_account.py +++ b/compensation/views/eco_account.py @@ -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") diff --git a/ema/tests/test_views.py b/ema/tests/test_views.py index dd37fce..65f4d35 100644 --- a/ema/tests/test_views.py +++ b/ema/tests/test_views.py @@ -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, diff --git a/intervention/forms/modalForms.py b/intervention/forms/modalForms.py index 6e2a2a3..6a044c7 100644 --- a/intervention/forms/modalForms.py +++ b/intervention/forms/modalForms.py @@ -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 diff --git a/intervention/templates/intervention/detail/includes/deductions.html b/intervention/templates/intervention/detail/includes/deductions.html index 99f11cb..b11817d 100644 --- a/intervention/templates/intervention/detail/includes/deductions.html +++ b/intervention/templates/intervention/detail/includes/deductions.html @@ -55,9 +55,12 @@ {{ deduction.surface|floatformat:2|intcomma }} m² {{ deduction.created.timestamp|default_if_none:""|naturalday}} - + {% if is_default_member and has_access %} - + {% endif %} diff --git a/intervention/tests/test_views.py b/intervention/tests/test_views.py index 2cdb299..68e4b56 100644 --- a/intervention/tests/test_views.py +++ b/intervention/tests/test_views.py @@ -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 diff --git a/intervention/urls.py b/intervention/urls.py index 7d6ff32..8ad7f31 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 app_name = "intervention" urlpatterns = [ @@ -37,6 +37,7 @@ urlpatterns = [ # Deductions path('/deduction/new', new_deduction_view, name='new-deduction'), + path('/deduction//edit', edit_deduction_view, name='edit-deduction'), path('/deduction//remove', remove_deduction_view, name='remove-deduction'), # Revocation routes diff --git a/intervention/views.py b/intervention/views.py index 8a59d9a..6db3547 100644 --- a/intervention/views.py +++ b/intervention/views.py @@ -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") diff --git a/konova/tests/test_views.py b/konova/tests/test_views.py index 536a786..6218a6c 100644 --- a/konova/tests/test_views.py +++ b/konova/tests/test_views.py @@ -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 diff --git a/konova/utils/message_templates.py b/konova/utils/message_templates.py index b7eb525..ea778ea 100644 --- a/konova/utils/message_templates.py +++ b/konova/utils/message_templates.py @@ -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 diff --git a/locale/de/LC_MESSAGES/django.mo b/locale/de/LC_MESSAGES/django.mo index 85b75fdda447f5409f7dac392a4a7ff964a0e7fe..86cf2739bfdda76a4b610efe974b54aee72f0ad0 100644 GIT binary patch delta 10863 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 RAE}Y*M)*9E&B_id^M7fg6Dj}z delta 10631 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\n" "Language-Team: LANGUAGE \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"