WIP: 490_View_refactoring #491
@ -168,6 +168,17 @@ class NewCompensationForm(AbstractCompensationForm,
 | 
			
		||||
        comp.log.add(action)
 | 
			
		||||
        return comp, action
 | 
			
		||||
 | 
			
		||||
    def is_valid(self):
 | 
			
		||||
        valid = super().is_valid()
 | 
			
		||||
        intervention = self.cleaned_data.get("intervention", None)
 | 
			
		||||
        if intervention.is_recorded:
 | 
			
		||||
            valid &= False
 | 
			
		||||
            self.add_error(
 | 
			
		||||
                "intervention",
 | 
			
		||||
                _("This intervention is currently recorded. You cannot add further compensations as long as it is recorded.")
 | 
			
		||||
            )
 | 
			
		||||
        return valid
 | 
			
		||||
 | 
			
		||||
    def save(self, user: User, geom_form: SimpleGeomForm):
 | 
			
		||||
        with transaction.atomic():
 | 
			
		||||
            comp, action = self.__create_comp(user)
 | 
			
		||||
 | 
			
		||||
@ -7,10 +7,12 @@ Created on: 18.08.22
 | 
			
		||||
"""
 | 
			
		||||
from dal import autocomplete
 | 
			
		||||
from django import forms
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from codelist.models import KonovaCode
 | 
			
		||||
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_COMPENSATION_ACTION_DETAIL_ID
 | 
			
		||||
from compensation.models import CompensationAction
 | 
			
		||||
from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple
 | 
			
		||||
from konova.forms.modals import BaseModalForm, RemoveModalForm
 | 
			
		||||
from konova.utils.message_templates import COMPENSATION_ACTION_EDITED, ADDED_COMPENSATION_ACTION
 | 
			
		||||
@ -114,7 +116,8 @@ class EditCompensationActionModalForm(NewCompensationActionModalForm):
 | 
			
		||||
    action = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        self.action = kwargs.pop("action", None)
 | 
			
		||||
        action_id = kwargs.pop("action_id", None)
 | 
			
		||||
        self.action = get_object_or_404(CompensationAction, id=action_id)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.form_title = _("Edit action")
 | 
			
		||||
        form_data = {
 | 
			
		||||
@ -147,8 +150,8 @@ class RemoveCompensationActionModalForm(RemoveModalForm):
 | 
			
		||||
    action = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        action = kwargs.pop("action", None)
 | 
			
		||||
        self.action = action
 | 
			
		||||
        action_id = kwargs.pop("action_id", None)
 | 
			
		||||
        self.action = get_object_or_404(CompensationAction, id=action_id)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def save(self):
 | 
			
		||||
 | 
			
		||||
@ -6,10 +6,11 @@ Created on: 18.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django import forms
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.forms.modals import BaseModalForm
 | 
			
		||||
from konova.models import DeadlineType
 | 
			
		||||
from konova.models import DeadlineType, Deadline
 | 
			
		||||
from konova.utils import validators
 | 
			
		||||
from konova.utils.message_templates import DEADLINE_EDITED
 | 
			
		||||
 | 
			
		||||
@ -90,7 +91,8 @@ class EditDeadlineModalForm(NewDeadlineModalForm):
 | 
			
		||||
    deadline = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        self.deadline = kwargs.pop("deadline", None)
 | 
			
		||||
        deadline_id = kwargs.pop("deadline_id", None)
 | 
			
		||||
        self.deadline = get_object_or_404(Deadline, id=deadline_id)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.form_title = _("Edit deadline")
 | 
			
		||||
        form_data = {
 | 
			
		||||
 | 
			
		||||
@ -6,12 +6,27 @@ Created on: 18.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from compensation.models import CompensationDocument, EcoAccountDocument
 | 
			
		||||
from konova.forms.modals import NewDocumentModalForm
 | 
			
		||||
from konova.forms.modals import NewDocumentModalForm, EditDocumentModalForm, RemoveDocumentModalForm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewCompensationDocumentModalForm(NewDocumentModalForm):
 | 
			
		||||
    document_model = CompensationDocument
 | 
			
		||||
    _DOCUMENT_CLS = CompensationDocument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditCompensationDocumentModalForm(EditDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = CompensationDocument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveCompensationDocumentModalForm(RemoveDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = CompensationDocument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewEcoAccountDocumentModalForm(NewDocumentModalForm):
 | 
			
		||||
    document_model = EcoAccountDocument
 | 
			
		||||
    _DOCUMENT_CLS = EcoAccountDocument
 | 
			
		||||
 | 
			
		||||
class EditEcoAccountDocumentModalForm(EditDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = EcoAccountDocument
 | 
			
		||||
 | 
			
		||||
class RemoveEcoAccountDocumentModalForm(RemoveDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = EcoAccountDocument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										15
									
								
								compensation/forms/modals/resubmission.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								compensation/forms/modals/resubmission.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,15 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Created on: 21.10.25
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from compensation.models import Compensation, EcoAccount
 | 
			
		||||
from konova.forms.modals import ResubmissionModalForm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompensationResubmissionModalForm(ResubmissionModalForm):
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountResubmissionModalForm(ResubmissionModalForm):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
@ -5,21 +5,17 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 18.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from bootstrap_modal_forms.mixins import is_ajax
 | 
			
		||||
from dal import autocomplete
 | 
			
		||||
from django import forms
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.http import HttpResponseRedirect, HttpRequest
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from codelist.models import KonovaCode
 | 
			
		||||
from codelist.settings import CODELIST_BIOTOPES_ID, \
 | 
			
		||||
    CODELIST_BIOTOPES_EXTRA_CODES_FULL_ID
 | 
			
		||||
from compensation.models import CompensationState
 | 
			
		||||
from intervention.inputs import CompensationStateTreeRadioSelect
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.forms.modals import RemoveModalForm, BaseModalForm
 | 
			
		||||
from konova.utils.message_templates import COMPENSATION_STATE_EDITED, FORM_INVALID, ADDED_COMPENSATION_STATE
 | 
			
		||||
from konova.utils.message_templates import COMPENSATION_STATE_EDITED, ADDED_COMPENSATION_STATE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewCompensationStateModalForm(BaseModalForm):
 | 
			
		||||
@ -68,10 +64,13 @@ class NewCompensationStateModalForm(BaseModalForm):
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    _is_before_state: bool = False
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.form_title = _("New state")
 | 
			
		||||
        self.form_caption = _("Insert data for the new state")
 | 
			
		||||
        self._is_before_state = bool(self.request.GET.get("before", False))
 | 
			
		||||
        choices = KonovaCode.objects.filter(
 | 
			
		||||
            code_lists__in=[CODELIST_BIOTOPES_ID],
 | 
			
		||||
            is_archived=False,
 | 
			
		||||
@ -83,65 +82,19 @@ class NewCompensationStateModalForm(BaseModalForm):
 | 
			
		||||
        ]
 | 
			
		||||
        self.fields["biotope_type"].choices = choices
 | 
			
		||||
 | 
			
		||||
    def save(self, is_before_state: bool = False):
 | 
			
		||||
        state = self.instance.add_state(self, is_before_state)
 | 
			
		||||
    def save(self):
 | 
			
		||||
        state = self.instance.add_state(self, self._is_before_state)
 | 
			
		||||
        self.instance.mark_as_edited(self.user, self.request, ADDED_COMPENSATION_STATE)
 | 
			
		||||
        return state
 | 
			
		||||
 | 
			
		||||
    def process_request(self, request: HttpRequest, msg_success: str = _("Object removed"), msg_error: str = FORM_INVALID, redirect_url: str = None):
 | 
			
		||||
        """ Generic processing of request
 | 
			
		||||
 | 
			
		||||
        Wraps the request processing logic, so we don't need the same code everywhere a RemoveModalForm is being used
 | 
			
		||||
 | 
			
		||||
        +++
 | 
			
		||||
        The generic method from super class can not be used, since we need to do some request parameter check in here.
 | 
			
		||||
        +++
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            msg_success (str): The message in case of successful removing
 | 
			
		||||
            msg_error (str): The message in case of an error
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        redirect_url = redirect_url if redirect_url is not None else request.META.get("HTTP_REFERER", "home")
 | 
			
		||||
        template = self.template
 | 
			
		||||
        if request.method == "POST":
 | 
			
		||||
            if self.is_valid():
 | 
			
		||||
                # Modal forms send one POST for checking on data validity. This can be used to return possible errors
 | 
			
		||||
                # on the form. A second POST (if no errors occured) is sent afterwards and needs to process the
 | 
			
		||||
                # saving/commiting of the data to the database. is_ajax() performs this check. The first request is
 | 
			
		||||
                # an ajax call, the second is a regular form POST.
 | 
			
		||||
                if not is_ajax(request.META):
 | 
			
		||||
                    is_before_state = bool(request.GET.get("before", False))
 | 
			
		||||
                    self.save(is_before_state=is_before_state)
 | 
			
		||||
                    messages.success(
 | 
			
		||||
                        request,
 | 
			
		||||
                        msg_success
 | 
			
		||||
                    )
 | 
			
		||||
                return HttpResponseRedirect(redirect_url)
 | 
			
		||||
            else:
 | 
			
		||||
                context = {
 | 
			
		||||
                    "form": self,
 | 
			
		||||
                }
 | 
			
		||||
                context = BaseContext(request, context).context
 | 
			
		||||
                return render(request, template, context)
 | 
			
		||||
        elif request.method == "GET":
 | 
			
		||||
            context = {
 | 
			
		||||
                "form": self,
 | 
			
		||||
            }
 | 
			
		||||
            context = BaseContext(request, context).context
 | 
			
		||||
            return render(request, template, context)
 | 
			
		||||
        else:
 | 
			
		||||
            raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditCompensationStateModalForm(NewCompensationStateModalForm):
 | 
			
		||||
    state = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        self.state = kwargs.pop("state", None)
 | 
			
		||||
        state_id = kwargs.pop("state_id", None)
 | 
			
		||||
        self.state = CompensationState.objects.get(id=state_id)
 | 
			
		||||
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.form_title = _("Edit state")
 | 
			
		||||
        biotope_type_id = self.state.biotope_type.id if self.state.biotope_type else None
 | 
			
		||||
@ -172,8 +125,8 @@ class RemoveCompensationStateModalForm(RemoveModalForm):
 | 
			
		||||
    state = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        state = kwargs.pop("state", None)
 | 
			
		||||
        self.state = state
 | 
			
		||||
        state_id = kwargs.pop("state_id", None)
 | 
			
		||||
        self.state = CompensationState.objects.get(id=state_id)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def save(self):
 | 
			
		||||
 | 
			
		||||
@ -80,7 +80,11 @@ class EditCompensationActionModalFormTestCase(NewCompensationActionModalFormTest
 | 
			
		||||
        self.compensation.actions.add(self.comp_action)
 | 
			
		||||
 | 
			
		||||
    def test_init(self):
 | 
			
		||||
        form = EditCompensationActionModalForm(request=self.request, instance=self.compensation, action=self.comp_action)
 | 
			
		||||
        form = EditCompensationActionModalForm(
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            action_id=self.comp_action.id
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(form.form_title, str(_("Edit action")))
 | 
			
		||||
        self.assertEqual(len(form.fields["action_type"].initial), self.comp_action.action_type.count())
 | 
			
		||||
        self.assertEqual(len(form.fields["action_type_details"].initial), self.comp_action.action_type_details.count())
 | 
			
		||||
@ -101,7 +105,7 @@ class EditCompensationActionModalFormTestCase(NewCompensationActionModalFormTest
 | 
			
		||||
            "comment": comment,
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        form = EditCompensationActionModalForm(data, request=self.request, instance=self.compensation, action=self.comp_action)
 | 
			
		||||
        form = EditCompensationActionModalForm(data, request=self.request, instance=self.compensation, action_id=self.comp_action.id)
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(form.is_valid())
 | 
			
		||||
        action = form.save()
 | 
			
		||||
@ -126,7 +130,7 @@ class RemoveCompensationActionModalFormTestCase(EditCompensationActionModalFormT
 | 
			
		||||
        
 | 
			
		||||
    def test_init(self):
 | 
			
		||||
        self.assertIn(self.comp_action, self.compensation.actions.all())
 | 
			
		||||
        form = RemoveCompensationActionModalForm(request=self.request, instance=self.compensation, action=self.comp_action)
 | 
			
		||||
        form = RemoveCompensationActionModalForm(request=self.request, instance=self.compensation, action_id=self.comp_action.id)
 | 
			
		||||
        self.assertEqual(form.action, self.comp_action)
 | 
			
		||||
        
 | 
			
		||||
    def test_save(self):
 | 
			
		||||
@ -137,7 +141,7 @@ class RemoveCompensationActionModalFormTestCase(EditCompensationActionModalFormT
 | 
			
		||||
            data, 
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            action=self.comp_action
 | 
			
		||||
            action_id=self.comp_action.id
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(form.is_valid())
 | 
			
		||||
        self.assertIn(self.comp_action, self.compensation.actions.all())
 | 
			
		||||
@ -186,12 +190,20 @@ class NewCompensationStateModalFormTestCase(BaseTestCase):
 | 
			
		||||
        self.assertEqual(self.compensation.before_states.count(), 0)
 | 
			
		||||
        self.assertEqual(self.compensation.after_states.count(), 0)
 | 
			
		||||
 | 
			
		||||
        form = NewCompensationStateModalForm(data, request=self.request, instance=self.compensation)
 | 
			
		||||
 | 
			
		||||
        self.request.GET._mutable = True
 | 
			
		||||
        self.request.GET.update(
 | 
			
		||||
            {
 | 
			
		||||
                "before": True,
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
        self.request.GET._mutable = False
 | 
			
		||||
        form = NewCompensationStateModalForm(
 | 
			
		||||
            data,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(form.is_valid(), msg=form.errors)
 | 
			
		||||
 | 
			
		||||
        is_before_state = True
 | 
			
		||||
        state = form.save(is_before_state)
 | 
			
		||||
        state = form.save()
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(self.compensation.before_states.count(), 1)
 | 
			
		||||
        self.assertEqual(self.compensation.after_states.count(), 0)
 | 
			
		||||
@ -205,8 +217,16 @@ class NewCompensationStateModalFormTestCase(BaseTestCase):
 | 
			
		||||
        self.assertEqual(last_log.action, UserAction.EDITED)
 | 
			
		||||
        self.assertEqual(last_log.comment, ADDED_COMPENSATION_STATE)
 | 
			
		||||
 | 
			
		||||
        is_before_state = False
 | 
			
		||||
        state = form.save(is_before_state)
 | 
			
		||||
        self.request.GET._mutable = True
 | 
			
		||||
        del self.request.GET["before"]
 | 
			
		||||
        self.request.GET._mutable = False
 | 
			
		||||
        form = NewCompensationStateModalForm(
 | 
			
		||||
            data,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(form.is_valid(), msg=form.errors)
 | 
			
		||||
        state = form.save()
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(self.compensation.before_states.count(), 1)
 | 
			
		||||
        self.assertEqual(self.compensation.after_states.count(), 1)
 | 
			
		||||
@ -230,7 +250,11 @@ class EditCompensationStateModalFormTestCase(NewCompensationStateModalFormTestCa
 | 
			
		||||
        self.compensation.after_states.add(self.comp_state)
 | 
			
		||||
 | 
			
		||||
    def test_init(self):
 | 
			
		||||
        form = EditCompensationStateModalForm(request=self.request, instance=self.compensation, state=self.comp_state)
 | 
			
		||||
        form = EditCompensationStateModalForm(
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            state_id=self.comp_state.id
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(form.state, self.comp_state)
 | 
			
		||||
        self.assertEqual(form.form_title, str(_("Edit state")))
 | 
			
		||||
@ -261,7 +285,7 @@ class EditCompensationStateModalFormTestCase(NewCompensationStateModalFormTestCa
 | 
			
		||||
            data,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            state=self.comp_state
 | 
			
		||||
            state_id=self.comp_state.id
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(form.is_valid(), msg=form.errors)
 | 
			
		||||
 | 
			
		||||
@ -282,7 +306,11 @@ class RemoveCompensationStateModalFormTestCase(EditCompensationStateModalFormTes
 | 
			
		||||
        super().setUp()
 | 
			
		||||
 | 
			
		||||
    def test_init(self):
 | 
			
		||||
        form = RemoveCompensationStateModalForm(request=self.request, instance=self.compensation, state=self.comp_state)
 | 
			
		||||
        form = RemoveCompensationStateModalForm(
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            state_id=self.comp_state.id
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.assertEqual(form.state, self.comp_state)
 | 
			
		||||
 | 
			
		||||
@ -294,7 +322,7 @@ class RemoveCompensationStateModalFormTestCase(EditCompensationStateModalFormTes
 | 
			
		||||
            data,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            state=self.comp_state
 | 
			
		||||
            state_id=self.comp_state.id
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(form.is_valid(), msg=form.errors)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ class AbstractCompensationModelTestCase(BaseTestCase):
 | 
			
		||||
            data,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            deadline=self.finished_deadline,
 | 
			
		||||
            deadline_id=self.finished_deadline.id,
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(form.is_valid(), msg=form.errors)
 | 
			
		||||
        self.assertIn(self.finished_deadline, self.compensation.deadlines.all())
 | 
			
		||||
 | 
			
		||||
@ -10,27 +10,28 @@ from django.urls import path
 | 
			
		||||
from compensation.views.compensation.document import EditCompensationDocumentView, NewCompensationDocumentView, \
 | 
			
		||||
    GetCompensationDocumentView, RemoveCompensationDocumentView
 | 
			
		||||
from compensation.views.compensation.resubmission import CompensationResubmissionView
 | 
			
		||||
from compensation.views.compensation.report import report_view
 | 
			
		||||
from compensation.views.compensation.report import CompensationReportView
 | 
			
		||||
from compensation.views.compensation.deadline import NewCompensationDeadlineView, EditCompensationDeadlineView, \
 | 
			
		||||
    RemoveCompensationDeadlineView
 | 
			
		||||
from compensation.views.compensation.action import NewCompensationActionView, EditCompensationActionView, \
 | 
			
		||||
    RemoveCompensationActionView
 | 
			
		||||
from compensation.views.compensation.state import NewCompensationStateView, EditCompensationStateView, \
 | 
			
		||||
    RemoveCompensationStateView
 | 
			
		||||
from compensation.views.compensation.compensation import index_view, new_view, new_id_view, detail_view, edit_view, \
 | 
			
		||||
    remove_view
 | 
			
		||||
from compensation.views.compensation.compensation import \
 | 
			
		||||
    CompensationIndexView, CompensationIdentifierGeneratorView, CompensationDetailView, \
 | 
			
		||||
    NewCompensationFormView, EditCompensationFormView, RemoveCompensationView
 | 
			
		||||
from compensation.views.compensation.log import CompensationLogView
 | 
			
		||||
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    # Main compensation
 | 
			
		||||
    path("", index_view, name="index"),
 | 
			
		||||
    path('new/id', new_id_view, name='new-id'),
 | 
			
		||||
    path('new/<intervention_id>', new_view, name='new'),
 | 
			
		||||
    path('new', new_view, name='new'),
 | 
			
		||||
    path('<id>', detail_view, name='detail'),
 | 
			
		||||
    path("", CompensationIndexView.as_view(), name="index"),
 | 
			
		||||
    path('new/id', CompensationIdentifierGeneratorView.as_view(), name='new-id'),
 | 
			
		||||
    path('new/<intervention_id>', NewCompensationFormView.as_view(), name='new'),
 | 
			
		||||
    path('new', NewCompensationFormView.as_view(), name='new'),
 | 
			
		||||
    path('<id>', CompensationDetailView.as_view(), name='detail'),
 | 
			
		||||
    path('<id>/log', CompensationLogView.as_view(), name='log'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='remove'),
 | 
			
		||||
    path('<id>/edit', EditCompensationFormView.as_view(), name='edit'),
 | 
			
		||||
    path('<id>/remove', RemoveCompensationView.as_view(), name='remove'),
 | 
			
		||||
 | 
			
		||||
    path('<id>/state/new', NewCompensationStateView.as_view(), name='new-state'),
 | 
			
		||||
    path('<id>/state/<state_id>/edit', EditCompensationStateView.as_view(), name='state-edit'),
 | 
			
		||||
@ -43,7 +44,7 @@ urlpatterns = [
 | 
			
		||||
    path('<id>/deadline/new', NewCompensationDeadlineView.as_view(), name="new-deadline"),
 | 
			
		||||
    path('<id>/deadline/<deadline_id>/edit', EditCompensationDeadlineView.as_view(), name='deadline-edit'),
 | 
			
		||||
    path('<id>/deadline/<deadline_id>/remove', RemoveCompensationDeadlineView.as_view(), name='deadline-remove'),
 | 
			
		||||
    path('<id>/report', report_view, name='report'),
 | 
			
		||||
    path('<id>/report', CompensationReportView.as_view(), name='report'),
 | 
			
		||||
    path('<id>/resub', CompensationResubmissionView.as_view(), name='resubmission-create'),
 | 
			
		||||
 | 
			
		||||
    # Documents
 | 
			
		||||
 | 
			
		||||
@ -8,11 +8,11 @@ Created on: 24.08.21
 | 
			
		||||
from django.urls import path
 | 
			
		||||
 | 
			
		||||
from compensation.autocomplete.eco_account import EcoAccountAutocomplete
 | 
			
		||||
from compensation.views.eco_account.eco_account import index_view, new_view, new_id_view, edit_view, remove_view, \
 | 
			
		||||
    detail_view
 | 
			
		||||
from compensation.views.eco_account.eco_account import EcoAccountIndexView, EcoAccountIdentifierGeneratorView, \
 | 
			
		||||
    EcoAccountDetailView, NewEcoAccountFormView, EditEcoAccountFormView, RemoveEcoAccountView
 | 
			
		||||
from compensation.views.eco_account.log import EcoAccountLogView
 | 
			
		||||
from compensation.views.eco_account.record import EcoAccountRecordView
 | 
			
		||||
from compensation.views.eco_account.report import report_view
 | 
			
		||||
from compensation.views.eco_account.report import EcoAccountReportView
 | 
			
		||||
from compensation.views.eco_account.resubmission import EcoAccountResubmissionView
 | 
			
		||||
from compensation.views.eco_account.state import NewEcoAccountStateView, EditEcoAccountStateView, \
 | 
			
		||||
    RemoveEcoAccountStateView
 | 
			
		||||
@ -28,15 +28,15 @@ from compensation.views.eco_account.deduction import NewEcoAccountDeductionView,
 | 
			
		||||
 | 
			
		||||
app_name = "acc"
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path("", index_view, name="index"),
 | 
			
		||||
    path('new/', new_view, name='new'),
 | 
			
		||||
    path('new/id', new_id_view, name='new-id'),
 | 
			
		||||
    path('<id>', detail_view, name='detail'),
 | 
			
		||||
    path("", EcoAccountIndexView.as_view(), name="index"),
 | 
			
		||||
    path('new/', NewEcoAccountFormView.as_view(), name='new'),
 | 
			
		||||
    path('new/id', EcoAccountIdentifierGeneratorView.as_view(), name='new-id'),
 | 
			
		||||
    path('<id>', EcoAccountDetailView.as_view(), name='detail'),
 | 
			
		||||
    path('<id>/log', EcoAccountLogView.as_view(), name='log'),
 | 
			
		||||
    path('<id>/record', EcoAccountRecordView.as_view(), name='record'),
 | 
			
		||||
    path('<id>/report', report_view, name='report'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='remove'),
 | 
			
		||||
    path('<id>/report', EcoAccountReportView.as_view(), name='report'),
 | 
			
		||||
    path('<id>/edit', EditEcoAccountFormView.as_view(), name='edit'),
 | 
			
		||||
    path('<id>/remove', RemoveEcoAccountView.as_view(), name='remove'),
 | 
			
		||||
    path('<id>/resub', EcoAccountResubmissionView.as_view(), name='resubmission-create'),
 | 
			
		||||
 | 
			
		||||
    path('<id>/state/new', NewEcoAccountStateView.as_view(), name='new-state'),
 | 
			
		||||
 | 
			
		||||
@ -5,53 +5,23 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.compensation_action import RemoveCompensationActionModalForm, \
 | 
			
		||||
    EditCompensationActionModalForm, NewCompensationActionModalForm
 | 
			
		||||
from compensation.models import Compensation, CompensationAction
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.utils.message_templates import COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_EDITED, \
 | 
			
		||||
    COMPENSATION_ACTION_ADDED
 | 
			
		||||
from compensation.models import Compensation
 | 
			
		||||
from konova.views.action import AbstractNewCompensationActionView, AbstractEditCompensationActionView, \
 | 
			
		||||
    AbstractRemoveCompensationActionView
 | 
			
		||||
 | 
			
		||||
_COMPENSATION_DETAIL_URL_NAME = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
class NewCompensationActionView(AbstractNewCompensationActionView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditCompensationActionView(AbstractEditCompensationActionView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveCompensationActionView(AbstractRemoveCompensationActionView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,8 @@ Created on: 19.08.22
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.core.exceptions import ObjectDoesNotExist
 | 
			
		||||
from django.db.models import Sum
 | 
			
		||||
from django.http import HttpRequest, JsonResponse
 | 
			
		||||
from django.shortcuts import get_object_or_404, render, redirect
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
@ -18,300 +18,157 @@ from compensation.forms.compensation import EditCompensationForm, NewCompensatio
 | 
			
		||||
from compensation.models import Compensation
 | 
			
		||||
from compensation.tables.compensation import CompensationTable
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, any_group_check, login_required_modal, \
 | 
			
		||||
    uuid_required
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.forms.modals import RemoveModalForm
 | 
			
		||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.message_templates import COMPENSATION_REMOVED_TEMPLATE, DATA_CHECKED_PREVIOUSLY_TEMPLATE, \
 | 
			
		||||
    RECORDED_BLOCKS_EDIT, CHECK_STATE_RESET, FORM_INVALID, PARAMS_INVALID, IDENTIFIER_REPLACED, \
 | 
			
		||||
    COMPENSATION_ADDED_TEMPLATE, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
 | 
			
		||||
    RECORDED_BLOCKS_EDIT, PARAMS_INVALID
 | 
			
		||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
 | 
			
		||||
    BaseEditSpatialLocatedObjectFormView
 | 
			
		||||
from konova.views.detail import BaseDetailView
 | 
			
		||||
from konova.views.remove import BaseRemoveModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def index_view(request: HttpRequest):
 | 
			
		||||
    """
 | 
			
		||||
    Renders the index view for compensation
 | 
			
		||||
class CompensationIndexView(LoginRequiredMixin, BaseIndexView):
 | 
			
		||||
    _TAB_TITLE = _("Compensations - Overview")
 | 
			
		||||
    _INDEX_TABLE_CLS = CompensationTable
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        A rendered view
 | 
			
		||||
    """
 | 
			
		||||
    template = "generic_index.html"
 | 
			
		||||
    compensations = Compensation.objects.filter(
 | 
			
		||||
        deleted=None,  # only show those which are not deleted individually
 | 
			
		||||
        intervention__deleted=None,  # and don't show the ones whose intervention has been deleted
 | 
			
		||||
    ).order_by(
 | 
			
		||||
        "-modified__timestamp"
 | 
			
		||||
    )
 | 
			
		||||
    table = CompensationTable(
 | 
			
		||||
        request=request,
 | 
			
		||||
        queryset=compensations
 | 
			
		||||
    )
 | 
			
		||||
    context = {
 | 
			
		||||
        "table": table,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("Compensations - Overview"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
    def _get_queryset(self):
 | 
			
		||||
        qs = Compensation.objects.filter(
 | 
			
		||||
            deleted=None,  # only show those which are not deleted individually
 | 
			
		||||
            intervention__deleted=None,  # and don't show the ones whose intervention has been deleted
 | 
			
		||||
        ).order_by(
 | 
			
		||||
            "-modified__timestamp"
 | 
			
		||||
        )
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
@shared_access_required(Intervention, "intervention_id")
 | 
			
		||||
def new_view(request: HttpRequest, intervention_id: str = None):
 | 
			
		||||
    """
 | 
			
		||||
    Renders a view for a new compensation creation
 | 
			
		||||
class NewCompensationFormView(BaseNewSpatialLocatedObjectFormView):
 | 
			
		||||
    _FORM_CLS = NewCompensationForm
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _TEMPLATE = "compensation/form/view.html"
 | 
			
		||||
    _TAB_TITLE = _("New Compensation")
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # On a new compensation make sure the intervention (if call came directly through an intervention's detail
 | 
			
		||||
        # view) is shared with the user
 | 
			
		||||
        intervention_id = kwargs.get("intervention_id", None)
 | 
			
		||||
        if not intervention_id:
 | 
			
		||||
            return True
 | 
			
		||||
        else:
 | 
			
		||||
            intervention = get_object_or_404(Intervention, id=intervention_id)
 | 
			
		||||
            return intervention.is_shared_with(user)
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # User has to be an ets user
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "compensation/form/view.html"
 | 
			
		||||
    if intervention_id is not None:
 | 
			
		||||
        try:
 | 
			
		||||
            intervention = Intervention.objects.get(id=intervention_id)
 | 
			
		||||
        except ObjectDoesNotExist:
 | 
			
		||||
            messages.error(request, PARAMS_INVALID)
 | 
			
		||||
            return redirect("home")
 | 
			
		||||
        if intervention.is_recorded:
 | 
			
		||||
            messages.info(
 | 
			
		||||
                request,
 | 
			
		||||
                RECORDED_BLOCKS_EDIT
 | 
			
		||||
            )
 | 
			
		||||
            return redirect("intervention:detail", id=intervention_id)
 | 
			
		||||
 | 
			
		||||
    data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
 | 
			
		||||
    geom_form = SimpleGeomForm(request.POST or None, read_only=False)
 | 
			
		||||
    if request.method == "POST":
 | 
			
		||||
        if data_form.is_valid() and geom_form.is_valid():
 | 
			
		||||
            generated_identifier = data_form.cleaned_data.get("identifier", None)
 | 
			
		||||
            comp = data_form.save(request.user, geom_form)
 | 
			
		||||
            if generated_identifier != comp.identifier:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    IDENTIFIER_REPLACED.format(
 | 
			
		||||
                        generated_identifier,
 | 
			
		||||
                        comp.identifier
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        # Make sure there is an existing intervention based on the given id
 | 
			
		||||
        # Compensations can not exist without an intervention
 | 
			
		||||
        intervention_id = kwargs.get("intervention_id", None)
 | 
			
		||||
        if intervention_id:
 | 
			
		||||
            try:
 | 
			
		||||
                intervention = Intervention.objects.get(id=intervention_id)
 | 
			
		||||
                if intervention.is_recorded:
 | 
			
		||||
                    messages.info(
 | 
			
		||||
                        request,
 | 
			
		||||
                        RECORDED_BLOCKS_EDIT
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
 | 
			
		||||
            if geom_form.has_geometry_simplified():
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRY_SIMPLIFIED
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
 | 
			
		||||
            if num_ignored_geometries > 0:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            return redirect("compensation:detail", id=comp.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID, extra_tags="danger",)
 | 
			
		||||
    else:
 | 
			
		||||
        # For clarification: nothing in this case
 | 
			
		||||
        pass
 | 
			
		||||
    context = {
 | 
			
		||||
        "form": data_form,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("New compensation"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
                    return redirect("intervention:detail", id=intervention_id)
 | 
			
		||||
            except ObjectDoesNotExist:
 | 
			
		||||
                messages.error(request, PARAMS_INVALID, extra_tags="danger")
 | 
			
		||||
                return redirect("home")
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
def new_id_view(request: HttpRequest):
 | 
			
		||||
    """ JSON endpoint
 | 
			
		||||
class EditCompensationFormView(BaseEditSpatialLocatedObjectFormView):
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _FORM_CLS = EditCompensationForm
 | 
			
		||||
    _TEMPLATE = "compensation/form/view.html"
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    Provides fetching of free identifiers for e.g. AJAX calls
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # User has to be a default user
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    tmp = Compensation()
 | 
			
		||||
    identifier = tmp.generate_new_identifier()
 | 
			
		||||
    while Compensation.objects.filter(identifier=identifier).exists():
 | 
			
		||||
        identifier = tmp.generate_new_identifier()
 | 
			
		||||
    return JsonResponse(
 | 
			
		||||
        data={
 | 
			
		||||
            "gen_data": identifier
 | 
			
		||||
 | 
			
		||||
class CompensationIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = "compensation:index"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompensationDetailView(BaseDetailView):
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _TEMPLATE = "compensation/detail/compensation/view.html"
 | 
			
		||||
 | 
			
		||||
    def _get_object(self, id: str):
 | 
			
		||||
        """ Returns the compensation
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            id (str): The compensation's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            obj (Compensation): The compensation
 | 
			
		||||
        """
 | 
			
		||||
        comp = get_object_or_404(
 | 
			
		||||
            Compensation.objects.select_related(
 | 
			
		||||
                "modified",
 | 
			
		||||
                "created",
 | 
			
		||||
                "geometry"
 | 
			
		||||
            ),
 | 
			
		||||
            id=id,
 | 
			
		||||
            deleted=None,
 | 
			
		||||
            intervention__deleted=None,
 | 
			
		||||
        )
 | 
			
		||||
        return comp
 | 
			
		||||
 | 
			
		||||
    def _get_detail_context(self, obj: Compensation):
 | 
			
		||||
        """ Generate object specific detail context for  view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            obj (): The record
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        # Order states according to surface
 | 
			
		||||
        before_states = obj.before_states.all().prefetch_related("biotope_type").order_by("-surface")
 | 
			
		||||
        after_states = obj.after_states.all().prefetch_related("biotope_type").order_by("-surface")
 | 
			
		||||
        actions = obj.actions.all().prefetch_related("action_type")
 | 
			
		||||
 | 
			
		||||
        # Precalculate logical errors between before- and after-states
 | 
			
		||||
        # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
        sum_before_states = obj.get_surface_before_states()
 | 
			
		||||
        sum_after_states = obj.get_surface_after_states()
 | 
			
		||||
        diff_states = abs(sum_before_states - sum_after_states)
 | 
			
		||||
 | 
			
		||||
        last_checked = obj.intervention.get_last_checked_action()
 | 
			
		||||
        last_checked_tooltip = ""
 | 
			
		||||
        if last_checked:
 | 
			
		||||
            last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(
 | 
			
		||||
                last_checked.get_timestamp_str_formatted(),
 | 
			
		||||
                last_checked.user
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        context = {
 | 
			
		||||
            "last_checked": last_checked,
 | 
			
		||||
            "last_checked_tooltip": last_checked_tooltip,
 | 
			
		||||
            "actions": actions,
 | 
			
		||||
            "before_states": before_states,
 | 
			
		||||
            "after_states": after_states,
 | 
			
		||||
            "sum_before_states": sum_before_states,
 | 
			
		||||
            "sum_after_states": sum_after_states,
 | 
			
		||||
            "diff_states": diff_states,
 | 
			
		||||
            "has_finished_deadlines": obj.get_finished_deadlines().exists(),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
@shared_access_required(Compensation, "id")
 | 
			
		||||
def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
    """
 | 
			
		||||
    Renders a view for editing compensations
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "compensation/form/view.html"
 | 
			
		||||
    # Get object from db
 | 
			
		||||
    comp = get_object_or_404(Compensation, id=id)
 | 
			
		||||
    if comp.is_recorded:
 | 
			
		||||
        messages.info(
 | 
			
		||||
            request,
 | 
			
		||||
            RECORDED_BLOCKS_EDIT
 | 
			
		||||
        )
 | 
			
		||||
        return redirect("compensation:detail", id=id)
 | 
			
		||||
 | 
			
		||||
    # Create forms, initialize with values from db/from POST request
 | 
			
		||||
    data_form = EditCompensationForm(request.POST or None, instance=comp)
 | 
			
		||||
    geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
 | 
			
		||||
    if request.method == "POST":
 | 
			
		||||
        if data_form.is_valid() and geom_form.is_valid():
 | 
			
		||||
            # Preserve state of intervention checked to determine whether the user must be informed or not
 | 
			
		||||
            # about a change of the check state
 | 
			
		||||
            intervention_is_checked = comp.intervention.checked is not None
 | 
			
		||||
 | 
			
		||||
            # The data form takes the geom form for processing, as well as the performing user
 | 
			
		||||
            comp = data_form.save(request.user, geom_form)
 | 
			
		||||
            if intervention_is_checked:
 | 
			
		||||
                messages.info(request, CHECK_STATE_RESET)
 | 
			
		||||
            messages.success(request, _("Compensation {} edited").format(comp.identifier))
 | 
			
		||||
            if geom_form.has_geometry_simplified():
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRY_SIMPLIFIED
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
 | 
			
		||||
            if num_ignored_geometries > 0:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            return redirect("compensation:detail", id=comp.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID, extra_tags="danger",)
 | 
			
		||||
    else:
 | 
			
		||||
        # For clarification: nothing in this case
 | 
			
		||||
        pass
 | 
			
		||||
    context = {
 | 
			
		||||
        "form": data_form,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
@uuid_required
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a detail view for a compensation
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The compensation's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "compensation/detail/compensation/view.html"
 | 
			
		||||
    comp = get_object_or_404(
 | 
			
		||||
        Compensation.objects.select_related(
 | 
			
		||||
            "modified",
 | 
			
		||||
            "created",
 | 
			
		||||
            "geometry"
 | 
			
		||||
        ),
 | 
			
		||||
        id=id,
 | 
			
		||||
        deleted=None,
 | 
			
		||||
        intervention__deleted=None,
 | 
			
		||||
    )
 | 
			
		||||
    geom_form = SimpleGeomForm(instance=comp)
 | 
			
		||||
    parcels = comp.get_underlying_parcels()
 | 
			
		||||
    _user = request.user
 | 
			
		||||
    is_data_shared = comp.intervention.is_shared_with(_user)
 | 
			
		||||
 | 
			
		||||
    # Order states according to surface
 | 
			
		||||
    before_states = comp.before_states.all().prefetch_related("biotope_type").order_by("-surface")
 | 
			
		||||
    after_states = comp.after_states.all().prefetch_related("biotope_type").order_by("-surface")
 | 
			
		||||
    actions = comp.actions.all().prefetch_related("action_type")
 | 
			
		||||
 | 
			
		||||
    # Precalculate logical errors between before- and after-states
 | 
			
		||||
    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
    sum_before_states = comp.get_surface_before_states()
 | 
			
		||||
    sum_after_states = comp.get_surface_after_states()
 | 
			
		||||
    diff_states = abs(sum_before_states - sum_after_states)
 | 
			
		||||
 | 
			
		||||
    request = comp.set_status_messages(request)
 | 
			
		||||
 | 
			
		||||
    last_checked = comp.intervention.get_last_checked_action()
 | 
			
		||||
    last_checked_tooltip = ""
 | 
			
		||||
    if last_checked:
 | 
			
		||||
        last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(last_checked.get_timestamp_str_formatted(), last_checked.user)
 | 
			
		||||
 | 
			
		||||
    requesting_user_is_only_shared_user = comp.is_only_shared_with(_user)
 | 
			
		||||
    if requesting_user_is_only_shared_user:
 | 
			
		||||
        messages.info(
 | 
			
		||||
            request,
 | 
			
		||||
            DO_NOT_FORGET_TO_SHARE
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": comp,
 | 
			
		||||
        "last_checked": last_checked,
 | 
			
		||||
        "last_checked_tooltip": last_checked_tooltip,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "parcels": parcels,
 | 
			
		||||
        "is_entry_shared": is_data_shared,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "sum_before_states": sum_before_states,
 | 
			
		||||
        "sum_after_states": sum_after_states,
 | 
			
		||||
        "diff_states": diff_states,
 | 
			
		||||
        "is_default_member": _user.in_group(DEFAULT_GROUP),
 | 
			
		||||
        "is_zb_member": _user.in_group(ZB_GROUP),
 | 
			
		||||
        "is_ets_member": _user.in_group(ETS_GROUP),
 | 
			
		||||
        "LANIS_LINK": comp.get_LANIS_link(),
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: f"{comp.identifier} - {comp.title}",
 | 
			
		||||
        "has_finished_deadlines": comp.get_finished_deadlines().exists(),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required_modal
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
@shared_access_required(Compensation, "id")
 | 
			
		||||
def remove_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a modal view for removing the compensation
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The compensation's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    comp = get_object_or_404(Compensation, id=id)
 | 
			
		||||
    form = RemoveModalForm(request.POST or None, instance=comp, request=request)
 | 
			
		||||
    return form.process_request(
 | 
			
		||||
        request=request,
 | 
			
		||||
        msg_success=COMPENSATION_REMOVED_TEMPLATE.format(comp.identifier),
 | 
			
		||||
        redirect_url=reverse("compensation:index"),
 | 
			
		||||
    )
 | 
			
		||||
class RemoveCompensationView(LoginRequiredMixin, BaseRemoveModalFormView):
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _FORM_CLS = RemoveModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:index"
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
@ -5,45 +5,21 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.models import Compensation
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.deadline import AbstractRemoveDeadlineView, AbstractEditDeadlineView, AbstractNewDeadlineView
 | 
			
		||||
 | 
			
		||||
_COMPENSATION_DETAIL_URL_NAME = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
class NewCompensationDeadlineView(AbstractNewDeadlineView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditCompensationDeadlineView(AbstractEditDeadlineView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveCompensationDeadlineView(AbstractRemoveDeadlineView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = _COMPENSATION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
@ -5,62 +5,33 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.document import NewCompensationDocumentModalForm
 | 
			
		||||
from compensation.forms.modals.document import NewCompensationDocumentModalForm, EditCompensationDocumentModalForm, \
 | 
			
		||||
    RemoveCompensationDocumentModalForm
 | 
			
		||||
from compensation.models import Compensation, CompensationDocument
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.forms.modals import EditDocumentModalForm
 | 
			
		||||
from konova.views.document import AbstractNewDocumentView, AbstractGetDocumentView, AbstractRemoveDocumentView, \
 | 
			
		||||
    AbstractEditDocumentView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewCompensationDocumentView(AbstractNewDocumentView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    form = NewCompensationDocumentModalForm
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _FORM_CLS = NewCompensationDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GetCompensationDocumentView(AbstractGetDocumentView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    document_model = CompensationDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _DOCUMENT_CLS = CompensationDocument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveCompensationDocumentView(AbstractRemoveDocumentView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    document_model = CompensationDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _DOCUMENT_CLS = CompensationDocument
 | 
			
		||||
    _FORM_CLS = RemoveCompensationDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditCompensationDocumentView(AbstractEditDocumentView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    document_model = CompensationDocument
 | 
			
		||||
    form = EditDocumentModalForm
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _DOCUMENT_CLS = CompensationDocument
 | 
			
		||||
    _FORM_CLS = EditCompensationDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,20 +5,11 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from compensation.models import Compensation
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.log import AbstractLogView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompensationLogView(AbstractLogView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class CompensationLogView(LoginRequiredMixin, AbstractLogView):
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
 | 
			
		||||
@ -5,77 +5,48 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from compensation.models import Compensation
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import uuid_required
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from konova.sub_settings.django_settings import BASE_URL
 | 
			
		||||
from konova.utils.qrcode import QrCode
 | 
			
		||||
from konova.views.report import BaseReportView
 | 
			
		||||
 | 
			
		||||
@uuid_required
 | 
			
		||||
def report_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
class BaseCompensationReportView(BaseReportView):
 | 
			
		||||
    def _get_compensation_report_context(self, obj):
 | 
			
		||||
        # Order states by surface
 | 
			
		||||
        before_states = obj.before_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
        after_states = obj.after_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
        actions = obj.actions.all().prefetch_related("action_type")
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    # Reuse the compensation report template since compensations are structurally identical
 | 
			
		||||
    template = "compensation/report/compensation/report.html"
 | 
			
		||||
    comp = get_object_or_404(Compensation, id=id)
 | 
			
		||||
 | 
			
		||||
    tab_title = _("Report {}").format(comp.identifier)
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not comp.is_ready_for_publish():
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        context = {
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
        return {
 | 
			
		||||
            "before_states": before_states,
 | 
			
		||||
            "after_states": after_states,
 | 
			
		||||
            "actions": actions,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=comp
 | 
			
		||||
    )
 | 
			
		||||
    parcels = comp.get_underlying_parcels()
 | 
			
		||||
 | 
			
		||||
    qrcode_url = request.build_absolute_uri(reverse("compensation:report", args=(id,)))
 | 
			
		||||
    qrcode_img = generate_qr_code(qrcode_url, 10)
 | 
			
		||||
    qrcode_lanis_url = comp.get_LANIS_link()
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
 | 
			
		||||
class CompensationReportView(BaseCompensationReportView):
 | 
			
		||||
    _MODEL = Compensation
 | 
			
		||||
    _TEMPLATE = "compensation/report/compensation/report.html"
 | 
			
		||||
 | 
			
		||||
    # Order states by surface
 | 
			
		||||
    before_states = comp.before_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    after_states = comp.after_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    actions = comp.actions.all().prefetch_related("action_type")
 | 
			
		||||
    def _get_report_context(self, obj):
 | 
			
		||||
        report_url = BASE_URL + reverse("compensation:report", args=(obj.id,))
 | 
			
		||||
        qrcode_report = QrCode(report_url, 10)
 | 
			
		||||
        qrcode_lanis = QrCode(obj.get_LANIS_link(), 7)
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": comp,
 | 
			
		||||
        "qrcode": {
 | 
			
		||||
            "img": qrcode_img,
 | 
			
		||||
            "url": qrcode_url,
 | 
			
		||||
        },
 | 
			
		||||
        "qrcode_lanis": {
 | 
			
		||||
            "img": qrcode_img_lanis,
 | 
			
		||||
            "url": qrcode_lanis_url,
 | 
			
		||||
        },
 | 
			
		||||
        "is_entry_shared": False,  # disables action buttons during rendering
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "parcels": parcels,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
        "tables_scrollable": False,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
        report_context = {
 | 
			
		||||
            "qrcode": {
 | 
			
		||||
                "img": qrcode_report.get_img(),
 | 
			
		||||
                "url": qrcode_report.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "qrcode_lanis": {
 | 
			
		||||
                "img": qrcode_lanis.get_img(),
 | 
			
		||||
                "url": qrcode_lanis.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "is_entry_shared": False,  # disables action buttons during rendering
 | 
			
		||||
            "tables_scrollable": False,
 | 
			
		||||
        }
 | 
			
		||||
        report_context.update(self._get_compensation_report_context(obj))
 | 
			
		||||
        return report_context
 | 
			
		||||
@ -5,22 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.resubmission import CompensationResubmissionModalForm
 | 
			
		||||
from compensation.models import Compensation
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.resubmission import AbstractResubmissionView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class CompensationResubmissionView(AbstractResubmissionView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url_base = "compensation:detail"
 | 
			
		||||
    form_action_url_base = "compensation:resubmission-create"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _FORM_CLS = CompensationResubmissionModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,46 +5,21 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.models import Compensation
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.state import AbstractNewCompensationStateView, AbstractEditCompensationStateView, \
 | 
			
		||||
    AbstractRemoveCompensationStateView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewCompensationStateView(AbstractNewCompensationStateView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditCompensationStateView(AbstractEditCompensationStateView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveCompensationStateView(AbstractRemoveCompensationStateView):
 | 
			
		||||
    model = Compensation
 | 
			
		||||
    redirect_url = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Compensation, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Compensation
 | 
			
		||||
    _REDIRECT_URL = "compensation:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,46 +5,22 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.action import AbstractNewCompensationActionView, AbstractEditCompensationActionView, \
 | 
			
		||||
    AbstractRemoveCompensationActionView
 | 
			
		||||
 | 
			
		||||
_ECO_ACCOUNT_DETAIL_URL_NAME = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
class NewEcoAccountActionView(AbstractNewCompensationActionView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEcoAccountActionView(AbstractEditCompensationActionView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEcoAccountActionView(AbstractRemoveCompensationActionView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
@ -5,45 +5,22 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.deadline import AbstractNewDeadlineView, AbstractEditDeadlineView, AbstractRemoveDeadlineView
 | 
			
		||||
 | 
			
		||||
_ECO_ACCOUNT_DETAIL_URL_NAME = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
class NewEcoAccountDeadlineView(AbstractNewDeadlineView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEcoAccountDeadlineView(AbstractEditDeadlineView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEcoAccountDeadlineView(AbstractRemoveDeadlineView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
@ -5,54 +5,33 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import Http404
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import default_group_required, login_required_modal
 | 
			
		||||
from konova.views.deduction import AbstractNewDeductionView, AbstractEditDeductionView, AbstractRemoveDeductionView
 | 
			
		||||
 | 
			
		||||
_ECO_ACCOUNT_DETAIl_URL_NAME = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
class NewEcoAccountDeductionView(AbstractNewDeductionView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class NewEcoAccountDeductionView(LoginRequiredMixin, AbstractNewDeductionView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIl_URL_NAME
 | 
			
		||||
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        # New deductions can only be created if the eco account has been recorded
 | 
			
		||||
        if not obj.recorded:
 | 
			
		||||
            raise Http404()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEcoAccountDeductionView(AbstractEditDeductionView):
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _check_for_recorded_instance(self, obj):
 | 
			
		||||
        # Deductions can be created on recorded as well as on non-recorded entries
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEcoAccountDeductionView(AbstractRemoveDeductionView):
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        pass
 | 
			
		||||
class EditEcoAccountDeductionView(LoginRequiredMixin, AbstractEditDeductionView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIl_URL_NAME
 | 
			
		||||
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
class RemoveEcoAccountDeductionView(LoginRequiredMixin, AbstractRemoveDeductionView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = _ECO_ACCOUNT_DETAIl_URL_NAME
 | 
			
		||||
 | 
			
		||||
@ -5,65 +5,33 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.document import NewEcoAccountDocumentModalForm
 | 
			
		||||
from compensation.forms.modals.document import NewEcoAccountDocumentModalForm, RemoveEcoAccountDocumentModalForm, \
 | 
			
		||||
    EditEcoAccountDocumentModalForm
 | 
			
		||||
from compensation.models import EcoAccount, EcoAccountDocument
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.forms.modals import EditDocumentModalForm
 | 
			
		||||
from konova.views.document import AbstractNewDocumentView, AbstractGetDocumentView, AbstractRemoveDocumentView, \
 | 
			
		||||
    AbstractEditDocumentView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewEcoAccountDocumentView(AbstractNewDocumentView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    form = NewEcoAccountDocumentModalForm
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _FORM_CLS = NewEcoAccountDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GetEcoAccountDocumentView(AbstractGetDocumentView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    document_model = EcoAccountDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _DOCUMENT_CLS = EcoAccountDocument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEcoAccountDocumentView(AbstractRemoveDocumentView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    document_model = EcoAccountDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _DOCUMENT_CLS = EcoAccountDocument
 | 
			
		||||
    _FORM_CLS = RemoveEcoAccountDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEcoAccountDocumentView(AbstractEditDocumentView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    document_model = EcoAccountDocument
 | 
			
		||||
    form = EditDocumentModalForm
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _DOCUMENT_CLS = EcoAccountDocument
 | 
			
		||||
    _FORM_CLS = EditEcoAccountDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
@ -7,8 +7,8 @@ Created on: 19.08.22
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.db.models import Sum
 | 
			
		||||
from django.http import HttpRequest, JsonResponse
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
@ -17,43 +17,52 @@ from compensation.forms.eco_account import EditEcoAccountForm, NewEcoAccountForm
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from compensation.tables.eco_account import EcoAccountTable
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, any_group_check, login_required_modal, \
 | 
			
		||||
    uuid_required
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.settings import ETS_GROUP, DEFAULT_GROUP, ZB_GROUP
 | 
			
		||||
from konova.settings import ETS_GROUP
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.message_templates import CANCEL_ACC_RECORDED_OR_DEDUCTED, RECORDED_BLOCKS_EDIT, FORM_INVALID, \
 | 
			
		||||
    IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
 | 
			
		||||
    IDENTIFIER_REPLACED, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
 | 
			
		||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
 | 
			
		||||
    BaseEditSpatialLocatedObjectFormView
 | 
			
		||||
from konova.views.detail import BaseDetailView
 | 
			
		||||
from konova.views.remove import BaseRemoveModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def index_view(request: HttpRequest):
 | 
			
		||||
    """
 | 
			
		||||
    Renders the index view for eco accounts
 | 
			
		||||
class EcoAccountIndexView(LoginRequiredMixin, BaseIndexView):
 | 
			
		||||
    _INDEX_TABLE_CLS = EcoAccountTable
 | 
			
		||||
    _TAB_TITLE = _("Eco-account - Overview")
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
    def _get_queryset(self):
 | 
			
		||||
        qs = EcoAccount.objects.filter(
 | 
			
		||||
            deleted=None,
 | 
			
		||||
        ).order_by(
 | 
			
		||||
            "-modified__timestamp"
 | 
			
		||||
        )
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        A rendered view
 | 
			
		||||
    """
 | 
			
		||||
    template = "generic_index.html"
 | 
			
		||||
    eco_accounts = EcoAccount.objects.filter(
 | 
			
		||||
        deleted=None,
 | 
			
		||||
    ).order_by(
 | 
			
		||||
        "-modified__timestamp"
 | 
			
		||||
    )
 | 
			
		||||
    table = EcoAccountTable(
 | 
			
		||||
        request=request,
 | 
			
		||||
        queryset=eco_accounts
 | 
			
		||||
    )
 | 
			
		||||
    context = {
 | 
			
		||||
        "table": table,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("Eco-account - Overview"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
class NewEcoAccountFormView(BaseNewSpatialLocatedObjectFormView):
 | 
			
		||||
    _FORM_CLS = NewEcoAccountForm
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _TEMPLATE = "compensation/form/view.html"
 | 
			
		||||
    _TAB_TITLE = _("New Eco-Account")
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # User has to be a default user
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEcoAccountFormView(BaseEditSpatialLocatedObjectFormView):
 | 
			
		||||
    _FORM_CLS = EditEcoAccountForm
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _TEMPLATE = "compensation/form/view.html"
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # User has to be a default user
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@ -112,23 +121,9 @@ def new_view(request: HttpRequest):
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
def new_id_view(request: HttpRequest):
 | 
			
		||||
    """ JSON endpoint
 | 
			
		||||
 | 
			
		||||
    Provides fetching of free identifiers for e.g. AJAX calls
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    tmp = EcoAccount()
 | 
			
		||||
    identifier = tmp.generate_new_identifier()
 | 
			
		||||
    while EcoAccount.objects.filter(identifier=identifier).exists():
 | 
			
		||||
        identifier = tmp.generate_new_identifier()
 | 
			
		||||
    return JsonResponse(
 | 
			
		||||
        data={
 | 
			
		||||
            "gen_data": identifier
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
class EcoAccountIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:index"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@ -192,116 +187,78 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
@uuid_required
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a detail view for a compensation
 | 
			
		||||
class EcoAccountDetailView(BaseDetailView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _TEMPLATE = "compensation/detail/eco_account/view.html"
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The compensation's id
 | 
			
		||||
    def _get_object(self, id: str):
 | 
			
		||||
        """ Fetch object for detail view
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        Args:
 | 
			
		||||
            id (str): The record's id'
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "compensation/detail/eco_account/view.html"
 | 
			
		||||
    acc = get_object_or_404(
 | 
			
		||||
        EcoAccount.objects.prefetch_related(
 | 
			
		||||
            "deadlines",
 | 
			
		||||
        ).select_related(
 | 
			
		||||
            'geometry',
 | 
			
		||||
            'responsible',
 | 
			
		||||
        ),
 | 
			
		||||
        id=id,
 | 
			
		||||
        deleted=None,
 | 
			
		||||
    )
 | 
			
		||||
    geom_form = SimpleGeomForm(instance=acc)
 | 
			
		||||
    parcels = acc.get_underlying_parcels()
 | 
			
		||||
    _user = request.user
 | 
			
		||||
    is_data_shared = acc.is_shared_with(_user)
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
    # Order states according to surface
 | 
			
		||||
    before_states = acc.before_states.order_by("-surface")
 | 
			
		||||
    after_states = acc.after_states.order_by("-surface")
 | 
			
		||||
 | 
			
		||||
    # Precalculate logical errors between before- and after-states
 | 
			
		||||
    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
    sum_before_states = acc.get_surface_before_states()
 | 
			
		||||
    sum_after_states = acc.get_surface_after_states()
 | 
			
		||||
    diff_states = abs(sum_before_states - sum_after_states)
 | 
			
		||||
    # Calculate rest of available surface for deductions
 | 
			
		||||
    available_total = acc.deductable_rest
 | 
			
		||||
    available_relative = acc.get_deductable_rest_relative()
 | 
			
		||||
 | 
			
		||||
    # Prefetch related data to decrease the amount of db connections
 | 
			
		||||
    deductions = acc.deductions.filter(
 | 
			
		||||
        intervention__deleted=None,
 | 
			
		||||
    )
 | 
			
		||||
    actions = acc.actions.all()
 | 
			
		||||
 | 
			
		||||
    request = acc.set_status_messages(request)
 | 
			
		||||
 | 
			
		||||
    requesting_user_is_only_shared_user = acc.is_only_shared_with(_user)
 | 
			
		||||
    if requesting_user_is_only_shared_user:
 | 
			
		||||
        messages.info(
 | 
			
		||||
            request,
 | 
			
		||||
            DO_NOT_FORGET_TO_SHARE
 | 
			
		||||
        """
 | 
			
		||||
        acc = get_object_or_404(
 | 
			
		||||
            EcoAccount.objects.prefetch_related(
 | 
			
		||||
                "deadlines",
 | 
			
		||||
            ).select_related(
 | 
			
		||||
                'geometry',
 | 
			
		||||
                'responsible',
 | 
			
		||||
            ),
 | 
			
		||||
            id=id,
 | 
			
		||||
            deleted=None,
 | 
			
		||||
        )
 | 
			
		||||
        return acc
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": acc,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "parcels": parcels,
 | 
			
		||||
        "is_entry_shared": is_data_shared,
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "sum_before_states": sum_before_states,
 | 
			
		||||
        "sum_after_states": sum_after_states,
 | 
			
		||||
        "diff_states": diff_states,
 | 
			
		||||
        "available": available_relative,
 | 
			
		||||
        "available_total": available_total,
 | 
			
		||||
        "is_default_member": _user.in_group(DEFAULT_GROUP),
 | 
			
		||||
        "is_zb_member": _user.in_group(ZB_GROUP),
 | 
			
		||||
        "is_ets_member": _user.in_group(ETS_GROUP),
 | 
			
		||||
        "LANIS_LINK": acc.get_LANIS_link(),
 | 
			
		||||
        "deductions": deductions,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: f"{acc.identifier} - {acc.title}",
 | 
			
		||||
        "has_finished_deadlines": acc.get_finished_deadlines().exists(),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
    def _get_detail_context(self, obj: EcoAccount):
 | 
			
		||||
        """ Generate object specific detail context for  view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            obj (): The record
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        # Order states according to surface
 | 
			
		||||
        before_states = obj.before_states.order_by("-surface")
 | 
			
		||||
        after_states = obj.after_states.order_by("-surface")
 | 
			
		||||
 | 
			
		||||
        # Precalculate logical errors between before- and after-states
 | 
			
		||||
        # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
        sum_before_states = obj.get_surface_before_states()
 | 
			
		||||
        sum_after_states = obj.get_surface_after_states()
 | 
			
		||||
        diff_states = abs(sum_before_states - sum_after_states)
 | 
			
		||||
        # Calculate rest of available surface for deductions
 | 
			
		||||
        available_total = obj.deductable_rest
 | 
			
		||||
        available_relative = obj.get_deductable_rest_relative()
 | 
			
		||||
 | 
			
		||||
        # Prefetch related data to decrease the amount of db connections
 | 
			
		||||
        deductions = obj.deductions.filter(
 | 
			
		||||
            intervention__deleted=None,
 | 
			
		||||
        )
 | 
			
		||||
        actions = obj.actions.all()
 | 
			
		||||
 | 
			
		||||
        context = {
 | 
			
		||||
            "before_states": before_states,
 | 
			
		||||
            "after_states": after_states,
 | 
			
		||||
            "sum_before_states": sum_before_states,
 | 
			
		||||
            "sum_after_states": sum_after_states,
 | 
			
		||||
            "diff_states": diff_states,
 | 
			
		||||
            "available": available_relative,
 | 
			
		||||
            "available_total": available_total,
 | 
			
		||||
            "deductions": deductions,
 | 
			
		||||
            "actions": actions,
 | 
			
		||||
            "has_finished_deadlines": obj.get_finished_deadlines().exists(),
 | 
			
		||||
        }
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required_modal
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
@shared_access_required(EcoAccount, "id")
 | 
			
		||||
def remove_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a modal view for removing the eco account
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The account's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    acc = get_object_or_404(EcoAccount, id=id)
 | 
			
		||||
 | 
			
		||||
    # If the eco account has already been recorded OR there are already deductions, it can not be deleted by a regular
 | 
			
		||||
    # default group user
 | 
			
		||||
    if acc.recorded is not None or acc.deductions.exists():
 | 
			
		||||
        user = request.user
 | 
			
		||||
        if not user.in_group(ETS_GROUP):
 | 
			
		||||
            messages.info(request, CANCEL_ACC_RECORDED_OR_DEDUCTED)
 | 
			
		||||
            return redirect("compensation:acc:detail", id=id)
 | 
			
		||||
 | 
			
		||||
    form = RemoveEcoAccountModalForm(request.POST or None, instance=acc, request=request)
 | 
			
		||||
    return form.process_request(
 | 
			
		||||
        request=request,
 | 
			
		||||
        msg_success=_("Eco-account removed"),
 | 
			
		||||
        redirect_url=reverse("compensation:acc:index"),
 | 
			
		||||
    )
 | 
			
		||||
class RemoveEcoAccountView(LoginRequiredMixin, BaseRemoveModalFormView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _FORM_CLS = RemoveEcoAccountModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:index"
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
@ -5,20 +5,11 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.log import AbstractLogView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountLogView(AbstractLogView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class EcoAccountLogView(LoginRequiredMixin, AbstractLogView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
 | 
			
		||||
@ -5,20 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
 | 
			
		||||
from konova.views.record import AbstractRecordView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountRecordView(AbstractRecordView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class EcoAccountRecordView(LoginRequiredMixin, AbstractRecordView):
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,85 +5,41 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import uuid_required
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from compensation.views.compensation.report import BaseCompensationReportView
 | 
			
		||||
from konova.sub_settings.django_settings import BASE_URL
 | 
			
		||||
from konova.utils.qrcode import QrCode
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@uuid_required
 | 
			
		||||
def report_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
class EcoAccountReportView(BaseCompensationReportView):
 | 
			
		||||
    _MODEL = EcoAccount
 | 
			
		||||
    _TEMPLATE = "compensation/report/eco_account/report.html"
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
    def _get_report_context(self, obj):
 | 
			
		||||
        report_url = BASE_URL + reverse("compensation:acc:report", args=(obj.id,))
 | 
			
		||||
        qrcode_report = QrCode(report_url, 10)
 | 
			
		||||
        qrcode_lanis = QrCode(obj.get_LANIS_link(), 7)
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        # Reduce amount of db fetched data to the bare minimum we need in the template (deduction's intervention id and identifier)
 | 
			
		||||
        deductions = obj.deductions.all() \
 | 
			
		||||
            .distinct("intervention") \
 | 
			
		||||
            .select_related("intervention") \
 | 
			
		||||
            .values_list("intervention__id", "intervention__identifier", "intervention__title", named=True)
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    # Reuse the compensation report template since EcoAccounts are structurally identical
 | 
			
		||||
    template = "compensation/report/eco_account/report.html"
 | 
			
		||||
    acc = get_object_or_404(EcoAccount, id=id)
 | 
			
		||||
 | 
			
		||||
    tab_title = _("Report {}").format(acc.identifier)
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not acc.is_ready_for_publish():
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        context = {
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
        report_context = {
 | 
			
		||||
            "qrcode": {
 | 
			
		||||
                "img": qrcode_report.get_img(),
 | 
			
		||||
                "url": qrcode_report.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "qrcode_lanis": {
 | 
			
		||||
                "img": qrcode_lanis.get_img(),
 | 
			
		||||
                "url": qrcode_lanis.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "is_entry_shared": False,  # disables action buttons during rendering
 | 
			
		||||
            "deductions": deductions,
 | 
			
		||||
            "tables_scrollable": False,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=acc
 | 
			
		||||
    )
 | 
			
		||||
    parcels = acc.get_underlying_parcels()
 | 
			
		||||
 | 
			
		||||
    qrcode_url = request.build_absolute_uri(reverse("compensation:acc:report", args=(id,)))
 | 
			
		||||
    qrcode_img = generate_qr_code(qrcode_url, 10)
 | 
			
		||||
    qrcode_lanis_url = acc.get_LANIS_link()
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
 | 
			
		||||
 | 
			
		||||
    # Order states by surface
 | 
			
		||||
    before_states = acc.before_states.all().order_by("-surface").select_related("biotope_type__parent")
 | 
			
		||||
    after_states = acc.after_states.all().order_by("-surface").select_related("biotope_type__parent")
 | 
			
		||||
    actions = acc.actions.all().prefetch_related("action_type__parent")
 | 
			
		||||
 | 
			
		||||
    # Reduce amount of db fetched data to the bare minimum we need in the template (deduction's intervention id and identifier)
 | 
			
		||||
    deductions = acc.deductions.all()\
 | 
			
		||||
        .distinct("intervention")\
 | 
			
		||||
        .select_related("intervention")\
 | 
			
		||||
        .values_list("intervention__id", "intervention__identifier", "intervention__title", named=True)
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": acc,
 | 
			
		||||
        "qrcode": {
 | 
			
		||||
            "img": qrcode_img,
 | 
			
		||||
            "url": qrcode_url,
 | 
			
		||||
        },
 | 
			
		||||
        "qrcode_lanis": {
 | 
			
		||||
            "img": qrcode_img_lanis,
 | 
			
		||||
            "url": qrcode_lanis_url,
 | 
			
		||||
        },
 | 
			
		||||
        "is_entry_shared": False,  # disables action buttons during rendering
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "parcels": parcels,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
        "deductions": deductions,
 | 
			
		||||
        "tables_scrollable": False,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
        report_context.update(self._get_compensation_report_context(obj))
 | 
			
		||||
        return report_context
 | 
			
		||||
 | 
			
		||||
@ -5,22 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.resubmission import EcoAccountResubmissionModalForm
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.resubmission import AbstractResubmissionView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountResubmissionView(AbstractResubmissionView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url_base = "compensation:acc:detail"
 | 
			
		||||
    form_action_url_base = "compensation:acc:resubmission-create"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _FORM_CLS = EcoAccountResubmissionModalForm
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,29 +5,15 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.share import AbstractShareByTokenView, AbstractShareFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountShareByTokenView(AbstractShareByTokenView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EcoAccountShareFormView(AbstractShareFormView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,46 +5,21 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required, login_required_modal
 | 
			
		||||
from konova.views.state import AbstractNewCompensationStateView, AbstractEditCompensationStateView, \
 | 
			
		||||
    AbstractRemoveCompensationStateView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewEcoAccountStateView(AbstractNewCompensationStateView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEcoAccountStateView(AbstractEditCompensationStateView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEcoAccountStateView(AbstractRemoveCompensationStateView):
 | 
			
		||||
    model = EcoAccount
 | 
			
		||||
    redirect_url = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(EcoAccount, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = EcoAccount
 | 
			
		||||
    _REDIRECT_URL = "compensation:acc:detail"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								ema/forms.py
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								ema/forms.py
									
									
									
									
									
								
							@ -15,7 +15,8 @@ from compensation.forms.compensation import AbstractCompensationForm
 | 
			
		||||
from ema.models import Ema, EmaDocument
 | 
			
		||||
from intervention.models import Responsibility, Handler
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.forms.modals import NewDocumentModalForm
 | 
			
		||||
from konova.forms.modals import NewDocumentModalForm, EditDocumentModalForm, RemoveDocumentModalForm, \
 | 
			
		||||
    ResubmissionModalForm
 | 
			
		||||
from user.models import UserActionLogEntry
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -170,4 +171,13 @@ class EditEmaForm(NewEmaForm):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewEmaDocumentModalForm(NewDocumentModalForm):
 | 
			
		||||
    document_model = EmaDocument
 | 
			
		||||
    _DOCUMENT_CLS = EmaDocument
 | 
			
		||||
 | 
			
		||||
class EditEmaDocumentModalForm(EditDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = EmaDocument
 | 
			
		||||
 | 
			
		||||
class RemoveEmaDocumentModalForm(RemoveDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = EmaDocument
 | 
			
		||||
 | 
			
		||||
class EmaResubmissionModalForm(ResubmissionModalForm):
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										19
									
								
								ema/urls.py
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								ema/urls.py
									
									
									
									
									
								
							@ -10,25 +10,26 @@ from django.urls import path
 | 
			
		||||
from ema.views.action import NewEmaActionView, EditEmaActionView, RemoveEmaActionView
 | 
			
		||||
from ema.views.deadline import NewEmaDeadlineView, EditEmaDeadlineView, RemoveEmaDeadlineView
 | 
			
		||||
from ema.views.document import NewEmaDocumentView, EditEmaDocumentView, RemoveEmaDocumentView, GetEmaDocumentView
 | 
			
		||||
from ema.views.ema import index_view, new_view, new_id_view, detail_view, edit_view, remove_view
 | 
			
		||||
from ema.views.ema import EmaIndexView, EmaIdentifierGeneratorView, EmaDetailView, EditEmaFormView, NewEmaFormView, \
 | 
			
		||||
    RemoveEmaView
 | 
			
		||||
from ema.views.log import EmaLogView
 | 
			
		||||
from ema.views.record import EmaRecordView
 | 
			
		||||
from ema.views.report import report_view
 | 
			
		||||
from ema.views.report import EmaReportView
 | 
			
		||||
from ema.views.resubmission import EmaResubmissionView
 | 
			
		||||
from ema.views.share import EmaShareFormView, EmaShareByTokenView
 | 
			
		||||
from ema.views.state import NewEmaStateView, EditEmaStateView, RemoveEmaStateView
 | 
			
		||||
 | 
			
		||||
app_name = "ema"
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path("", index_view, name="index"),
 | 
			
		||||
    path("new/", new_view, name="new"),
 | 
			
		||||
    path("new/id", new_id_view, name="new-id"),
 | 
			
		||||
    path("<id>", detail_view, name="detail"),
 | 
			
		||||
    path("", EmaIndexView.as_view(), name="index"),
 | 
			
		||||
    path("new/", NewEmaFormView.as_view(), name="new"),
 | 
			
		||||
    path("new/id", EmaIdentifierGeneratorView.as_view(), name="new-id"),
 | 
			
		||||
    path("<id>", EmaDetailView.as_view(), name="detail"),
 | 
			
		||||
    path('<id>/log', EmaLogView.as_view(), name='log'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='remove'),
 | 
			
		||||
    path('<id>/edit', EditEmaFormView.as_view(), name='edit'),
 | 
			
		||||
    path('<id>/remove', RemoveEmaView.as_view(), name='remove'),
 | 
			
		||||
    path('<id>/record', EmaRecordView.as_view(), name='record'),
 | 
			
		||||
    path('<id>/report', report_view, name='report'),
 | 
			
		||||
    path('<id>/report', EmaReportView.as_view(), name='report'),
 | 
			
		||||
    path('<id>/resub', EmaResubmissionView.as_view(), name='resubmission-create'),
 | 
			
		||||
 | 
			
		||||
    path('<id>/state/new', NewEmaStateView.as_view(), name='new-state'),
 | 
			
		||||
 | 
			
		||||
@ -5,46 +5,31 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
 | 
			
		||||
from konova.views.action import AbstractNewCompensationActionView, AbstractEditCompensationActionView, \
 | 
			
		||||
    AbstractRemoveCompensationActionView
 | 
			
		||||
 | 
			
		||||
_EMA_ACCOUNT_DETAIL_URL_NAME = "ema:detail"
 | 
			
		||||
 | 
			
		||||
class NewEmaActionView(AbstractNewCompensationActionView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
class EditEmaActionView(AbstractEditCompensationActionView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEmaActionView(AbstractRemoveCompensationActionView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = _EMA_ACCOUNT_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
@ -5,46 +5,30 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
 | 
			
		||||
from konova.views.deadline import AbstractNewDeadlineView, AbstractRemoveDeadlineView, AbstractEditDeadlineView
 | 
			
		||||
 | 
			
		||||
_EMA_DETAIL_URL_NAME = "ema:detail"
 | 
			
		||||
 | 
			
		||||
class NewEmaDeadlineView(AbstractNewDeadlineView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = _EMA_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEmaDeadlineView(AbstractEditDeadlineView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = _EMA_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEmaDeadlineView(AbstractRemoveDeadlineView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = _EMA_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
@ -5,62 +5,41 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from ema.forms import NewEmaDocumentModalForm
 | 
			
		||||
from ema.forms import NewEmaDocumentModalForm, RemoveEmaDocumentModalForm, EditEmaDocumentModalForm
 | 
			
		||||
from ema.models import Ema, EmaDocument
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
 | 
			
		||||
from konova.forms.modals import EditDocumentModalForm
 | 
			
		||||
from konova.views.document import AbstractEditDocumentView, AbstractRemoveDocumentView, AbstractGetDocumentView, \
 | 
			
		||||
    AbstractNewDocumentView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewEmaDocumentView(AbstractNewDocumentView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    form = NewEmaDocumentModalForm
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _FORM_CLS = NewEmaDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
class GetEmaDocumentView(AbstractGetDocumentView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    document_model = EmaDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _DOCUMENT_CLS = EmaDocument
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
class RemoveEmaDocumentView(AbstractRemoveDocumentView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    document_model = EmaDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _DOCUMENT_CLS = EmaDocument
 | 
			
		||||
    _FORM_CLS = RemoveEmaDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
class EditEmaDocumentView(AbstractEditDocumentView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    document_model = EmaDocument
 | 
			
		||||
    form = EditDocumentModalForm
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _FORM_CLS = EditEmaDocumentModalForm
 | 
			
		||||
    _DOCUMENT_CLS = EmaDocument
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										339
									
								
								ema/views/ema.py
									
									
									
									
									
								
							
							
						
						
									
										339
									
								
								ema/views/ema.py
									
									
									
									
									
								
							@ -5,269 +5,112 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.db.models import Sum
 | 
			
		||||
from django.http import HttpRequest, JsonResponse
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from ema.forms import NewEmaForm, EditEmaForm
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from ema.tables import EmaTable
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal, \
 | 
			
		||||
    uuid_required
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.forms.modals import RemoveModalForm
 | 
			
		||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.message_templates import RECORDED_BLOCKS_EDIT, IDENTIFIER_REPLACED, FORM_INVALID, \
 | 
			
		||||
    DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
 | 
			
		||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
 | 
			
		||||
    BaseEditSpatialLocatedObjectFormView
 | 
			
		||||
from konova.views.detail import BaseDetailView
 | 
			
		||||
from konova.views.remove import BaseRemoveModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
def index_view(request: HttpRequest):
 | 
			
		||||
    """ Renders the index view for EMAs
 | 
			
		||||
class EmaIndexView(LoginRequiredMixin, BaseIndexView):
 | 
			
		||||
    _TAB_TITLE = _("EMAs - Overview")
 | 
			
		||||
    _INDEX_TABLE_CLS = EmaTable
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "generic_index.html"
 | 
			
		||||
    emas = Ema.objects.filter(
 | 
			
		||||
        deleted=None,
 | 
			
		||||
    ).order_by(
 | 
			
		||||
        "-modified__timestamp"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    table = EmaTable(
 | 
			
		||||
        request,
 | 
			
		||||
        queryset=emas
 | 
			
		||||
    )
 | 
			
		||||
    context = {
 | 
			
		||||
        "table": table,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("EMAs - Overview"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
    def _get_queryset(self):
 | 
			
		||||
        qs = Ema.objects.filter(
 | 
			
		||||
            deleted=None,
 | 
			
		||||
        ).order_by(
 | 
			
		||||
            "-modified__timestamp"
 | 
			
		||||
        )
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@conservation_office_group_required
 | 
			
		||||
def new_view(request: HttpRequest):
 | 
			
		||||
    """
 | 
			
		||||
    Renders a view for a new eco account creation
 | 
			
		||||
class NewEmaFormView(BaseNewSpatialLocatedObjectFormView):
 | 
			
		||||
    _FORM_CLS = NewEmaForm
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _TEMPLATE = "ema/form/view.html"
 | 
			
		||||
    _TAB_TITLE = _("New EMA")
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "ema/form/view.html"
 | 
			
		||||
    data_form = NewEmaForm(request.POST or None)
 | 
			
		||||
    geom_form = SimpleGeomForm(request.POST or None, read_only=False)
 | 
			
		||||
    if request.method == "POST":
 | 
			
		||||
        if data_form.is_valid() and geom_form.is_valid():
 | 
			
		||||
            generated_identifier = data_form.cleaned_data.get("identifier", None)
 | 
			
		||||
            ema = data_form.save(request.user, geom_form)
 | 
			
		||||
            if generated_identifier != ema.identifier:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    IDENTIFIER_REPLACED.format(
 | 
			
		||||
                        generated_identifier,
 | 
			
		||||
                        ema.identifier
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, _("EMA {} added").format(ema.identifier))
 | 
			
		||||
            if geom_form.has_geometry_simplified():
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRY_SIMPLIFIED
 | 
			
		||||
                )
 | 
			
		||||
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
 | 
			
		||||
            if num_ignored_geometries > 0:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            return redirect("ema:detail", id=ema.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID, extra_tags="danger",)
 | 
			
		||||
    else:
 | 
			
		||||
        # For clarification: nothing in this case
 | 
			
		||||
        pass
 | 
			
		||||
    context = {
 | 
			
		||||
        "form": data_form,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("New EMA"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # User has to be an ets user
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@conservation_office_group_required
 | 
			
		||||
def new_id_view(request: HttpRequest):
 | 
			
		||||
    """ JSON endpoint
 | 
			
		||||
class EditEmaFormView(BaseEditSpatialLocatedObjectFormView):
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _FORM_CLS = EditEmaForm
 | 
			
		||||
    _TEMPLATE = "ema/form/view.html"
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
    _TAB_TITLE = _("Edit {}")
 | 
			
		||||
 | 
			
		||||
    Provides fetching of free identifiers for e.g. AJAX calls
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # User has to be an ets user
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    tmp = Ema()
 | 
			
		||||
    identifier = tmp.generate_new_identifier()
 | 
			
		||||
    while Ema.objects.filter(identifier=identifier).exists():
 | 
			
		||||
        identifier = tmp.generate_new_identifier()
 | 
			
		||||
    return JsonResponse(
 | 
			
		||||
        data={
 | 
			
		||||
            "gen_data": identifier
 | 
			
		||||
 | 
			
		||||
class EmaIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:index"
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmaDetailView(BaseDetailView):
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _TEMPLATE = "ema/detail/view.html"
 | 
			
		||||
 | 
			
		||||
    def _get_object(self, id: str):
 | 
			
		||||
        """ Fetch object for detail view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            id (str): The record's id'
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        ema = get_object_or_404(Ema, id=id, deleted=None)
 | 
			
		||||
        return ema
 | 
			
		||||
 | 
			
		||||
    def _get_detail_context(self, obj: Ema):
 | 
			
		||||
        """ Generate object specific detail context for  view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            obj (): The record
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        # Order states according to surface
 | 
			
		||||
        before_states = obj.before_states.all().order_by("-surface")
 | 
			
		||||
        after_states = obj.after_states.all().order_by("-surface")
 | 
			
		||||
 | 
			
		||||
        # Precalculate logical errors between before- and after-states
 | 
			
		||||
        # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
        sum_before_states = obj.get_surface_before_states()
 | 
			
		||||
        sum_after_states = obj.get_surface_after_states()
 | 
			
		||||
        diff_states = abs(sum_before_states - sum_after_states)
 | 
			
		||||
 | 
			
		||||
        context = {
 | 
			
		||||
            "before_states": before_states,
 | 
			
		||||
            "after_states": after_states,
 | 
			
		||||
            "sum_before_states": sum_before_states,
 | 
			
		||||
            "sum_after_states": sum_after_states,
 | 
			
		||||
            "diff_states": diff_states,
 | 
			
		||||
            "has_finished_deadlines": obj.get_finished_deadlines().exists(),
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
class RemoveEmaView(LoginRequiredMixin, BaseRemoveModalFormView):
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:index"
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@uuid_required
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders the detail view of an EMA
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The EMA id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "ema/detail/view.html"
 | 
			
		||||
    ema = get_object_or_404(Ema, id=id, deleted=None)
 | 
			
		||||
 | 
			
		||||
    geom_form = SimpleGeomForm(instance=ema)
 | 
			
		||||
    parcels = ema.get_underlying_parcels()
 | 
			
		||||
    _user = request.user
 | 
			
		||||
    is_entry_shared = ema.is_shared_with(_user)
 | 
			
		||||
 | 
			
		||||
    # Order states according to surface
 | 
			
		||||
    before_states = ema.before_states.all().order_by("-surface")
 | 
			
		||||
    after_states = ema.after_states.all().order_by("-surface")
 | 
			
		||||
 | 
			
		||||
    # Precalculate logical errors between before- and after-states
 | 
			
		||||
    # Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
 | 
			
		||||
    sum_before_states = ema.get_surface_before_states()
 | 
			
		||||
    sum_after_states = ema.get_surface_after_states()
 | 
			
		||||
    diff_states = abs(sum_before_states - sum_after_states)
 | 
			
		||||
 | 
			
		||||
    ema.set_status_messages(request)
 | 
			
		||||
 | 
			
		||||
    requesting_user_is_only_shared_user = ema.is_only_shared_with(_user)
 | 
			
		||||
    if requesting_user_is_only_shared_user:
 | 
			
		||||
        messages.info(
 | 
			
		||||
            request,
 | 
			
		||||
            DO_NOT_FORGET_TO_SHARE
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": ema,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "parcels": parcels,
 | 
			
		||||
        "is_entry_shared": is_entry_shared,
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "sum_before_states": sum_before_states,
 | 
			
		||||
        "sum_after_states": sum_after_states,
 | 
			
		||||
        "diff_states": diff_states,
 | 
			
		||||
        "is_default_member": _user.in_group(DEFAULT_GROUP),
 | 
			
		||||
        "is_zb_member": _user.in_group(ZB_GROUP),
 | 
			
		||||
        "is_ets_member": _user.in_group(ETS_GROUP),
 | 
			
		||||
        "LANIS_LINK": ema.get_LANIS_link(),
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}",
 | 
			
		||||
        "has_finished_deadlines": ema.get_finished_deadlines().exists(),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@conservation_office_group_required
 | 
			
		||||
@shared_access_required(Ema, "id")
 | 
			
		||||
def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
    """
 | 
			
		||||
    Renders a view for editing compensations
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "compensation/form/view.html"
 | 
			
		||||
    # Get object from db
 | 
			
		||||
    ema = get_object_or_404(Ema, id=id)
 | 
			
		||||
    if ema.is_recorded:
 | 
			
		||||
        messages.info(
 | 
			
		||||
            request,
 | 
			
		||||
            RECORDED_BLOCKS_EDIT
 | 
			
		||||
        )
 | 
			
		||||
        return redirect("ema:detail", id=id)
 | 
			
		||||
 | 
			
		||||
    # Create forms, initialize with values from db/from POST request
 | 
			
		||||
    data_form = EditEmaForm(request.POST or None, instance=ema)
 | 
			
		||||
    geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=ema)
 | 
			
		||||
    if request.method == "POST":
 | 
			
		||||
        if data_form.is_valid() and geom_form.is_valid():
 | 
			
		||||
            # The data form takes the geom form for processing, as well as the performing user
 | 
			
		||||
            ema = data_form.save(request.user, geom_form)
 | 
			
		||||
            messages.success(request, _("EMA {} edited").format(ema.identifier))
 | 
			
		||||
            if geom_form.has_geometry_simplified():
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRY_SIMPLIFIED
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
 | 
			
		||||
            if num_ignored_geometries > 0:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            return redirect("ema:detail", id=ema.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID, extra_tags="danger",)
 | 
			
		||||
    else:
 | 
			
		||||
        # For clarification: nothing in this case
 | 
			
		||||
        pass
 | 
			
		||||
    context = {
 | 
			
		||||
        "form": data_form,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("Edit {}").format(ema.identifier),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required_modal
 | 
			
		||||
@login_required
 | 
			
		||||
@conservation_office_group_required
 | 
			
		||||
@shared_access_required(Ema, "id")
 | 
			
		||||
def remove_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a modal view for removing the EMA
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The EMA's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    ema = get_object_or_404(Ema, id=id)
 | 
			
		||||
    form = RemoveModalForm(request.POST or None, instance=ema, request=request)
 | 
			
		||||
    return form.process_request(
 | 
			
		||||
        request=request,
 | 
			
		||||
        msg_success=_("EMA removed"),
 | 
			
		||||
        redirect_url=reverse("ema:index"),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
@ -5,20 +5,14 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
 | 
			
		||||
from konova.views.log import AbstractLogView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmaLogView(AbstractLogView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
class EmaLogView(LoginRequiredMixin, AbstractLogView):
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
@ -5,20 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
 | 
			
		||||
from konova.views.record import AbstractRecordView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmaRecordView(AbstractRecordView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class EmaRecordView(LoginRequiredMixin, AbstractRecordView):
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,77 +5,36 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from compensation.views.compensation.report import BaseCompensationReportView
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import uuid_required
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from konova.sub_settings.django_settings import BASE_URL
 | 
			
		||||
from konova.utils.qrcode import QrCode
 | 
			
		||||
 | 
			
		||||
@uuid_required
 | 
			
		||||
def report_view(request:HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
class EmaReportView(BaseCompensationReportView):
 | 
			
		||||
    _TEMPLATE = "ema/report/report.html"
 | 
			
		||||
    _MODEL = Ema
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
    def _get_report_context(self, obj):
 | 
			
		||||
        report_url = BASE_URL + reverse("ema:report", args=(obj.id,))
 | 
			
		||||
        qrcode_report = QrCode(report_url, 10)
 | 
			
		||||
        qrcode_lanis = QrCode(obj.get_LANIS_link(), 7)
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    # Reuse the compensation report template since EMAs are structurally identical
 | 
			
		||||
    template = "ema/report/report.html"
 | 
			
		||||
    ema = get_object_or_404(Ema, id=id)
 | 
			
		||||
        generic_compensation_report_context = self._get_compensation_report_context(obj)
 | 
			
		||||
 | 
			
		||||
    tab_title = _("Report {}").format(ema.identifier)
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not ema.is_ready_for_publish():
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        context = {
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
        report_context = {
 | 
			
		||||
            "qrcode": {
 | 
			
		||||
                "img": qrcode_report.get_img(),
 | 
			
		||||
                "url": qrcode_report.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "qrcode_lanis": {
 | 
			
		||||
                "img": qrcode_lanis.get_img(),
 | 
			
		||||
                "url": qrcode_lanis.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "is_entry_shared": False,  # disables action buttons during rendering
 | 
			
		||||
            "tables_scrollable": False,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=ema,
 | 
			
		||||
    )
 | 
			
		||||
    parcels = ema.get_underlying_parcels()
 | 
			
		||||
 | 
			
		||||
    qrcode_url = request.build_absolute_uri(reverse("ema:report", args=(id,)))
 | 
			
		||||
    qrcode_img = generate_qr_code(qrcode_url, 10)
 | 
			
		||||
    qrcode_lanis_url = ema.get_LANIS_link()
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
 | 
			
		||||
 | 
			
		||||
    # Order states by surface
 | 
			
		||||
    before_states = ema.before_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    after_states = ema.after_states.all().order_by("-surface").prefetch_related("biotope_type")
 | 
			
		||||
    actions = ema.actions.all().prefetch_related("action_type")
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": ema,
 | 
			
		||||
        "qrcode": {
 | 
			
		||||
            "img": qrcode_img,
 | 
			
		||||
            "url": qrcode_url
 | 
			
		||||
        },
 | 
			
		||||
        "qrcode_lanis": {
 | 
			
		||||
            "img": qrcode_img_lanis,
 | 
			
		||||
            "url": qrcode_lanis_url
 | 
			
		||||
        },
 | 
			
		||||
        "is_entry_shared": False,  # disables action buttons during rendering
 | 
			
		||||
        "before_states": before_states,
 | 
			
		||||
        "after_states": after_states,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "parcels": parcels,
 | 
			
		||||
        "actions": actions,
 | 
			
		||||
        "tables_scrollable": False,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
        report_context.update(generic_compensation_report_context)
 | 
			
		||||
        return report_context
 | 
			
		||||
@ -5,22 +5,16 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from ema.forms import EmaResubmissionModalForm
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.decorators import shared_access_required, conservation_office_group_required, login_required_modal
 | 
			
		||||
from konova.views.resubmission import AbstractResubmissionView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmaResubmissionView(AbstractResubmissionView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url_base = "ema:detail"
 | 
			
		||||
    form_action_url_base = "ema:resubmission-create"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _FORM_CLS = EmaResubmissionModalForm
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
    action_url = "ema:resubmission-create"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
@ -5,29 +5,17 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.decorators import conservation_office_group_required, shared_access_required, login_required_modal
 | 
			
		||||
from konova.views.share import AbstractShareByTokenView, AbstractShareFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EmaShareByTokenView(AbstractShareByTokenView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
class EmaShareFormView(AbstractShareFormView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
@ -5,46 +5,30 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from ema.models import Ema
 | 
			
		||||
from konova.decorators import conservation_office_group_required, shared_access_required, login_required_modal
 | 
			
		||||
from konova.views.state import AbstractNewCompensationStateView, AbstractEditCompensationStateView, \
 | 
			
		||||
    AbstractRemoveCompensationStateView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewEmaStateView(AbstractNewCompensationStateView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditEmaStateView(AbstractEditCompensationStateView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveEmaStateView(AbstractRemoveCompensationStateView):
 | 
			
		||||
    model = Ema
 | 
			
		||||
    redirect_url = "ema:detail"
 | 
			
		||||
    _MODEL_CLS = Ema
 | 
			
		||||
    _REDIRECT_URL = "ema:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Ema, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
@ -172,7 +172,8 @@ class EditEcoAccountDeductionModalForm(NewEcoAccountDeductionModalForm):
 | 
			
		||||
    deduction = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        self.deduction = kwargs.pop("deduction", None)
 | 
			
		||||
        deduction_id = kwargs.pop("deduction_id", None)
 | 
			
		||||
        self.deduction = EcoAccountDeduction.objects.get(id=deduction_id)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.form_title = _("Edit Deduction")
 | 
			
		||||
        form_data = {
 | 
			
		||||
@ -252,19 +253,20 @@ class RemoveEcoAccountDeductionModalForm(RemoveModalForm):
 | 
			
		||||
    Can be used for anything, where removing shall be confirmed by the user a second time.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    deduction = None
 | 
			
		||||
    _DEDUCTION_OBJ = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        deduction = kwargs.pop("deduction", None)
 | 
			
		||||
        self.deduction = deduction
 | 
			
		||||
        deduction_id = kwargs.pop("deduction_id", None)
 | 
			
		||||
        deduction = EcoAccountDeduction.objects.get(id=deduction_id)
 | 
			
		||||
        self._DEDUCTION_OBJ = deduction
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def save(self):
 | 
			
		||||
        with transaction.atomic():
 | 
			
		||||
            self.deduction.intervention.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
 | 
			
		||||
            self.deduction.account.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
 | 
			
		||||
            self.deduction.delete()
 | 
			
		||||
            self._DEDUCTION_OBJ.intervention.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
 | 
			
		||||
            self._DEDUCTION_OBJ.account.mark_as_edited(self.user, edit_comment=DEDUCTION_REMOVED)
 | 
			
		||||
            self._DEDUCTION_OBJ.delete()
 | 
			
		||||
 | 
			
		||||
    def check_for_recorded_instance(self):
 | 
			
		||||
        if self.deduction.intervention.is_recorded:
 | 
			
		||||
        if self._DEDUCTION_OBJ.intervention.is_recorded:
 | 
			
		||||
            self.block_form()
 | 
			
		||||
 | 
			
		||||
@ -6,11 +6,11 @@ Created on: 18.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from intervention.models import InterventionDocument
 | 
			
		||||
from konova.forms.modals import NewDocumentModalForm
 | 
			
		||||
from konova.forms.modals import NewDocumentModalForm, EditDocumentModalForm, RemoveDocumentModalForm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewInterventionDocumentModalForm(NewDocumentModalForm):
 | 
			
		||||
    document_model = InterventionDocument
 | 
			
		||||
    _DOCUMENT_CLS = InterventionDocument
 | 
			
		||||
 | 
			
		||||
    def save(self, *args, **kwargs):
 | 
			
		||||
        """ Extension of regular NewDocumentModalForm
 | 
			
		||||
@ -28,3 +28,31 @@ class NewInterventionDocumentModalForm(NewDocumentModalForm):
 | 
			
		||||
        self.instance.send_data_to_egon()
 | 
			
		||||
 | 
			
		||||
        return doc
 | 
			
		||||
 | 
			
		||||
class EditInterventionDocumentModalForm(EditDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = InterventionDocument
 | 
			
		||||
 | 
			
		||||
    def save(self, *args, **kwargs):
 | 
			
		||||
        """ Extension of regular EditDocumentModalForm
 | 
			
		||||
 | 
			
		||||
        Checks whether payments exist on the intervention and sends the data to EGON
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            *args ():
 | 
			
		||||
            **kwargs ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        doc = super().save(*args, **kwargs)
 | 
			
		||||
        self.instance.send_data_to_egon()
 | 
			
		||||
 | 
			
		||||
        return doc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveInterventionDocumentModalForm(RemoveDocumentModalForm):
 | 
			
		||||
    _DOCUMENT_CLS = InterventionDocument
 | 
			
		||||
 | 
			
		||||
    def save(self, *args, **kwargs):
 | 
			
		||||
        super().save(*args, **kwargs)
 | 
			
		||||
        self.instance.send_data_to_egon()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										11
									
								
								intervention/forms/modals/resubmission.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								intervention/forms/modals/resubmission.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,11 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Created on: 21.10.25
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.forms.modals import ResubmissionModalForm
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionResubmissionModalForm(ResubmissionModalForm):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
@ -8,16 +8,17 @@ Created on: 30.11.20
 | 
			
		||||
from django.urls import path
 | 
			
		||||
 | 
			
		||||
from intervention.autocomplete.intervention import InterventionAutocomplete
 | 
			
		||||
from intervention.views.check import check_view
 | 
			
		||||
from intervention.views.check import InterventionCheckView
 | 
			
		||||
from intervention.views.compensation import remove_compensation_view
 | 
			
		||||
from intervention.views.deduction import NewInterventionDeductionView, EditInterventionDeductionView, \
 | 
			
		||||
    RemoveInterventionDeductionView
 | 
			
		||||
from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \
 | 
			
		||||
    RemoveInterventionDocumentView, EditInterventionDocumentView
 | 
			
		||||
from intervention.views.intervention import index_view, new_view, new_id_view, detail_view, edit_view, remove_view
 | 
			
		||||
from intervention.views.intervention import InterventionIndexView, InterventionIdentifierGeneratorView, \
 | 
			
		||||
    InterventionDetailView, NewInterventionFormView, EditInterventionFormView, RemoveInterventionView
 | 
			
		||||
from intervention.views.log import InterventionLogView
 | 
			
		||||
from intervention.views.record import InterventionRecordView
 | 
			
		||||
from intervention.views.report import report_view
 | 
			
		||||
from intervention.views.report import InterventionReportView
 | 
			
		||||
from intervention.views.resubmission import InterventionResubmissionView
 | 
			
		||||
from intervention.views.revocation import new_revocation_view, edit_revocation_view, remove_revocation_view, \
 | 
			
		||||
    get_revocation_view
 | 
			
		||||
@ -25,18 +26,18 @@ from intervention.views.share import InterventionShareFormView, InterventionShar
 | 
			
		||||
 | 
			
		||||
app_name = "intervention"
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path("", index_view, name="index"),
 | 
			
		||||
    path('new/', new_view, name='new'),
 | 
			
		||||
    path('new/id', new_id_view, name='new-id'),
 | 
			
		||||
    path('<id>', detail_view, name='detail'),
 | 
			
		||||
    path("", InterventionIndexView.as_view(), name="index"),
 | 
			
		||||
    path('new/', NewInterventionFormView.as_view(), name='new'),
 | 
			
		||||
    path('new/id', InterventionIdentifierGeneratorView.as_view(), name='new-id'),
 | 
			
		||||
    path('<id>', InterventionDetailView.as_view(), name='detail'),
 | 
			
		||||
    path('<id>/log', InterventionLogView.as_view(), name='log'),
 | 
			
		||||
    path('<id>/edit', edit_view, name='edit'),
 | 
			
		||||
    path('<id>/remove', remove_view, name='remove'),
 | 
			
		||||
    path('<id>/edit', EditInterventionFormView.as_view(), name='edit'),
 | 
			
		||||
    path('<id>/remove', RemoveInterventionView.as_view(), name='remove'),
 | 
			
		||||
    path('<id>/share/<token>', InterventionShareByTokenView.as_view(), name='share-token'),
 | 
			
		||||
    path('<id>/share', InterventionShareFormView.as_view(), name='share-form'),
 | 
			
		||||
    path('<id>/check', check_view, name='check'),
 | 
			
		||||
    path('<id>/check', InterventionCheckView.as_view(), name='check'),
 | 
			
		||||
    path('<id>/record', InterventionRecordView.as_view(), name='record'),
 | 
			
		||||
    path('<id>/report', report_view, name='report'),
 | 
			
		||||
    path('<id>/report', InterventionReportView.as_view(), name='report'),
 | 
			
		||||
    path('<id>/resub', InterventionResubmissionView.as_view(), name='resubmission-create'),
 | 
			
		||||
 | 
			
		||||
    # Compensations
 | 
			
		||||
 | 
			
		||||
@ -5,35 +5,24 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from intervention.forms.modals.check import CheckModalForm
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.decorators import registration_office_group_required, shared_access_required
 | 
			
		||||
from konova.utils.message_templates import INTERVENTION_INVALID
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@registration_office_group_required
 | 
			
		||||
@shared_access_required(Intervention, "id")
 | 
			
		||||
def check_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders check form for an intervention
 | 
			
		||||
class InterventionCheckView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _FORM_CLS = CheckModalForm
 | 
			
		||||
    _MSG_SUCCESS = _("Check performed")
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): Intervention's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    intervention = get_object_or_404(Intervention, id=id)
 | 
			
		||||
    form = CheckModalForm(request.POST or None, instance=intervention, request=request)
 | 
			
		||||
    return form.process_request(
 | 
			
		||||
        request,
 | 
			
		||||
        msg_success=_("Check performed"),
 | 
			
		||||
        msg_error=INTERVENTION_INVALID
 | 
			
		||||
    )
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_zb_user()
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        redirect_url = super()._get_redirect_url(*args, **kwargs)
 | 
			
		||||
        redirect_url += "#related_data"
 | 
			
		||||
        return redirect_url
 | 
			
		||||
 | 
			
		||||
@ -5,51 +5,27 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.decorators import default_group_required, shared_access_required
 | 
			
		||||
from konova.utils.message_templates import DEDUCTION_ADDED, DEDUCTION_EDITED, DEDUCTION_REMOVED
 | 
			
		||||
from konova.views.deduction import AbstractNewDeductionView, AbstractEditDeductionView, AbstractRemoveDeductionView
 | 
			
		||||
 | 
			
		||||
_INTERVENTION_DETAIL_URL_NAME = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
class NewInterventionDeductionView(AbstractNewDeductionView):
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    redirect_url = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class NewInterventionDeductionView(LoginRequiredMixin, AbstractNewDeductionView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _MSG_SUCCESS = DEDUCTION_ADDED
 | 
			
		||||
    _REDIRECT_URL = _INTERVENTION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class EditInterventionDeductionView(AbstractEditDeductionView):
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    redirect_url = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class EditInterventionDeductionView(LoginRequiredMixin, AbstractEditDeductionView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _MSG_SUCCESS = DEDUCTION_EDITED
 | 
			
		||||
    _REDIRECT_URL = _INTERVENTION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveInterventionDeductionView(AbstractRemoveDeductionView):
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    redirect_url = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class RemoveInterventionDeductionView(LoginRequiredMixin, AbstractRemoveDeductionView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _MSG_SUCCESS = DEDUCTION_REMOVED
 | 
			
		||||
    _REDIRECT_URL = _INTERVENTION_DETAIL_URL_NAME
 | 
			
		||||
 | 
			
		||||
@ -5,59 +5,33 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from intervention.forms.modals.document import NewInterventionDocumentModalForm
 | 
			
		||||
from intervention.forms.modals.document import NewInterventionDocumentModalForm, EditInterventionDocumentModalForm, \
 | 
			
		||||
    RemoveInterventionDocumentModalForm
 | 
			
		||||
from intervention.models import Intervention, InterventionDocument
 | 
			
		||||
from konova.decorators import default_group_required, shared_access_required
 | 
			
		||||
from konova.forms.modals import EditDocumentModalForm
 | 
			
		||||
from konova.views.document import AbstractNewDocumentView, AbstractGetDocumentView, AbstractRemoveDocumentView, \
 | 
			
		||||
    AbstractEditDocumentView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class NewInterventionDocumentView(AbstractNewDocumentView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    form = NewInterventionDocumentModalForm
 | 
			
		||||
    redirect_url = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _DOCUMENT_MODEL = InterventionDocument
 | 
			
		||||
    _FORM_CLS = NewInterventionDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GetInterventionDocumentView(AbstractGetDocumentView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    document_model = InterventionDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _DOCUMENT_CLS = InterventionDocument
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveInterventionDocumentView(AbstractRemoveDocumentView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    document_model = InterventionDocument
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _DOCUMENT_CLS = InterventionDocument
 | 
			
		||||
    _FORM_CLS = RemoveInterventionDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
class EditInterventionDocumentView(AbstractEditDocumentView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    document_model = InterventionDocument
 | 
			
		||||
    form = EditDocumentModalForm
 | 
			
		||||
    redirect_url = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _DOCUMENT_CLS = InterventionDocument
 | 
			
		||||
    _FORM_CLS = EditInterventionDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
@ -7,207 +7,115 @@ Created on: 19.08.22
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.http import JsonResponse, HttpRequest
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404, render, redirect
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from intervention.forms.intervention import EditInterventionForm, NewInterventionForm
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from intervention.tables import InterventionTable
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import default_group_required, shared_access_required, any_group_check, login_required_modal, \
 | 
			
		||||
    uuid_required
 | 
			
		||||
from konova.decorators import default_group_required, shared_access_required
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.forms.modals import RemoveModalForm
 | 
			
		||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, RECORDED_BLOCKS_EDIT, \
 | 
			
		||||
    CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, \
 | 
			
		||||
    GEOMETRIES_IGNORED_TEMPLATE
 | 
			
		||||
    CHECK_STATE_RESET, FORM_INVALID, GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE
 | 
			
		||||
from konova.views.base import BaseIndexView, BaseIdentifierGeneratorView, BaseNewSpatialLocatedObjectFormView, \
 | 
			
		||||
    BaseEditSpatialLocatedObjectFormView
 | 
			
		||||
from konova.views.detail import BaseDetailView
 | 
			
		||||
from konova.views.remove import BaseRemoveModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def index_view(request: HttpRequest):
 | 
			
		||||
    """
 | 
			
		||||
    Renders the index view for Interventions
 | 
			
		||||
class InterventionIndexView(LoginRequiredMixin, BaseIndexView):
 | 
			
		||||
    _INDEX_TABLE_CLS = InterventionTable
 | 
			
		||||
    _TAB_TITLE = _("Interventions - Overview")
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        A rendered view
 | 
			
		||||
    """
 | 
			
		||||
    template = "generic_index.html"
 | 
			
		||||
 | 
			
		||||
    # Filtering by user access is performed in table filter inside InterventionTableFilter class
 | 
			
		||||
    interventions = Intervention.objects.filter(
 | 
			
		||||
        deleted=None,  # not deleted
 | 
			
		||||
    ).select_related(
 | 
			
		||||
        "legal"
 | 
			
		||||
    ).order_by(
 | 
			
		||||
        "-modified__timestamp"
 | 
			
		||||
    )
 | 
			
		||||
    table = InterventionTable(
 | 
			
		||||
        request=request,
 | 
			
		||||
        queryset=interventions
 | 
			
		||||
    )
 | 
			
		||||
    context = {
 | 
			
		||||
        "table": table,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("Interventions - Overview"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
    def _get_queryset(self):
 | 
			
		||||
        qs = Intervention.objects.filter(
 | 
			
		||||
            deleted=None,
 | 
			
		||||
        ).select_related(
 | 
			
		||||
            "legal"
 | 
			
		||||
        ).order_by(
 | 
			
		||||
            "-modified__timestamp"
 | 
			
		||||
        )
 | 
			
		||||
        return qs
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
def new_view(request: HttpRequest):
 | 
			
		||||
    """
 | 
			
		||||
    Renders a view for a new intervention creation
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "intervention/form/view.html"
 | 
			
		||||
    data_form = NewInterventionForm(request.POST or None)
 | 
			
		||||
    geom_form = SimpleGeomForm(request.POST or None, read_only=False)
 | 
			
		||||
    if request.method == "POST":
 | 
			
		||||
        if data_form.is_valid() and geom_form.is_valid():
 | 
			
		||||
            generated_identifier = data_form.cleaned_data.get("identifier", None)
 | 
			
		||||
            intervention = data_form.save(request.user, geom_form)
 | 
			
		||||
            if generated_identifier != intervention.identifier:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    IDENTIFIER_REPLACED.format(
 | 
			
		||||
                        generated_identifier,
 | 
			
		||||
                        intervention.identifier
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, _("Intervention {} added").format(intervention.identifier))
 | 
			
		||||
            if geom_form.has_geometry_simplified():
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRY_SIMPLIFIED
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
 | 
			
		||||
            if num_ignored_geometries > 0:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            return redirect("intervention:detail", id=intervention.id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(request, FORM_INVALID, extra_tags="danger",)
 | 
			
		||||
    else:
 | 
			
		||||
        # For clarification: nothing in this case
 | 
			
		||||
        pass
 | 
			
		||||
    context = {
 | 
			
		||||
        "form": data_form,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("New intervention"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
class NewInterventionFormView(BaseNewSpatialLocatedObjectFormView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _FORM_CLS = NewInterventionForm
 | 
			
		||||
    _TEMPLATE = "intervention/form/view.html"
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
    _TAB_TITLE = _("New intervention")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
def new_id_view(request: HttpRequest):
 | 
			
		||||
    """ JSON endpoint
 | 
			
		||||
class EditInterventionFormView(BaseEditSpatialLocatedObjectFormView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _FORM_CLS = EditInterventionForm
 | 
			
		||||
    _TEMPLATE = "intervention/form/view.html"
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
    _TAB_TITLE = _("Edit {}")
 | 
			
		||||
 | 
			
		||||
    Provides fetching of free identifiers for e.g. AJAX calls
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    tmp_intervention = Intervention()
 | 
			
		||||
    identifier = tmp_intervention.generate_new_identifier()
 | 
			
		||||
    while Intervention.objects.filter(identifier=identifier).exists():
 | 
			
		||||
        identifier = tmp_intervention.generate_new_identifier()
 | 
			
		||||
    return JsonResponse(
 | 
			
		||||
        data={
 | 
			
		||||
            "gen_data": identifier
 | 
			
		||||
class InterventionIdentifierGeneratorView(LoginRequiredMixin, BaseIdentifierGeneratorView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _REDIRECT_URL = "intervention:index"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionDetailView(BaseDetailView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _TEMPLATE = "intervention/detail/view.html"
 | 
			
		||||
 | 
			
		||||
    def _get_object(self, id: str):
 | 
			
		||||
        """ Returns the intervention
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            id (str): The intervention's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            obj (Intervention): The intervention
 | 
			
		||||
        """
 | 
			
		||||
        # Fetch data, filter out deleted related data
 | 
			
		||||
        obj = get_object_or_404(
 | 
			
		||||
            self._MODEL_CLS.objects.select_related(
 | 
			
		||||
                "geometry",
 | 
			
		||||
                "legal",
 | 
			
		||||
                "responsible",
 | 
			
		||||
            ).prefetch_related(
 | 
			
		||||
                "legal__revocations",
 | 
			
		||||
            ),
 | 
			
		||||
            id=id,
 | 
			
		||||
            deleted=None
 | 
			
		||||
        )
 | 
			
		||||
        return obj
 | 
			
		||||
 | 
			
		||||
    def _get_detail_context(self, obj: Intervention):
 | 
			
		||||
        """ Generate object specific detail context for  view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            obj (): The record
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        compensations = obj.compensations.filter(deleted=None)
 | 
			
		||||
        last_checked = obj.get_last_checked_action()
 | 
			
		||||
        last_checked_tooltip = ""
 | 
			
		||||
        if last_checked:
 | 
			
		||||
            last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(
 | 
			
		||||
                last_checked.get_timestamp_str_formatted(),
 | 
			
		||||
                last_checked.user
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        has_payment_without_document = obj.payments.exists() and not obj.get_documents()[1].exists()
 | 
			
		||||
        context = {
 | 
			
		||||
            "last_checked": last_checked,
 | 
			
		||||
            "last_checked_tooltip": last_checked_tooltip,
 | 
			
		||||
            "compensations": compensations,
 | 
			
		||||
            "has_payment_without_document": has_payment_without_document,
 | 
			
		||||
        }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
@uuid_required
 | 
			
		||||
def detail_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a detail view for viewing an intervention's data
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The intervention's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "intervention/detail/view.html"
 | 
			
		||||
 | 
			
		||||
    # Fetch data, filter out deleted related data
 | 
			
		||||
    intervention = get_object_or_404(
 | 
			
		||||
        Intervention.objects.select_related(
 | 
			
		||||
            "geometry",
 | 
			
		||||
            "legal",
 | 
			
		||||
            "responsible",
 | 
			
		||||
        ).prefetch_related(
 | 
			
		||||
            "legal__revocations",
 | 
			
		||||
        ),
 | 
			
		||||
        id=id,
 | 
			
		||||
        deleted=None
 | 
			
		||||
    )
 | 
			
		||||
    compensations = intervention.compensations.filter(
 | 
			
		||||
        deleted=None,
 | 
			
		||||
    )
 | 
			
		||||
    _user = request.user
 | 
			
		||||
    is_data_shared = intervention.is_shared_with(user=_user)
 | 
			
		||||
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=intervention,
 | 
			
		||||
    )
 | 
			
		||||
    last_checked = intervention.get_last_checked_action()
 | 
			
		||||
    last_checked_tooltip = ""
 | 
			
		||||
    if last_checked:
 | 
			
		||||
        last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(
 | 
			
		||||
            last_checked.get_timestamp_str_formatted(),
 | 
			
		||||
            last_checked.user
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    has_payment_without_document = intervention.payments.exists() and not intervention.get_documents()[1].exists()
 | 
			
		||||
 | 
			
		||||
    requesting_user_is_only_shared_user = intervention.is_only_shared_with(_user)
 | 
			
		||||
    if requesting_user_is_only_shared_user:
 | 
			
		||||
        messages.info(
 | 
			
		||||
            request,
 | 
			
		||||
            DO_NOT_FORGET_TO_SHARE
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": intervention,
 | 
			
		||||
        "last_checked": last_checked,
 | 
			
		||||
        "last_checked_tooltip": last_checked_tooltip,
 | 
			
		||||
        "compensations": compensations,
 | 
			
		||||
        "is_entry_shared": is_data_shared,
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "is_default_member": _user.in_group(DEFAULT_GROUP),
 | 
			
		||||
        "is_zb_member": _user.in_group(ZB_GROUP),
 | 
			
		||||
        "is_ets_member": _user.in_group(ETS_GROUP),
 | 
			
		||||
        "LANIS_LINK": intervention.get_LANIS_link(),
 | 
			
		||||
        "has_payment_without_document": has_payment_without_document,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: f"{intervention.identifier} - {intervention.title}",
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    request = intervention.set_status_messages(request)
 | 
			
		||||
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@ -272,26 +180,6 @@ def edit_view(request: HttpRequest, id: str):
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required_modal
 | 
			
		||||
@login_required
 | 
			
		||||
@default_group_required
 | 
			
		||||
@shared_access_required(Intervention, "id")
 | 
			
		||||
def remove_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders a remove view for this intervention
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The uuid id as string
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    obj = Intervention.objects.get(id=id)
 | 
			
		||||
    identifier = obj.identifier
 | 
			
		||||
    form = RemoveModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
    return form.process_request(
 | 
			
		||||
        request,
 | 
			
		||||
        _("{} removed").format(identifier),
 | 
			
		||||
        redirect_url=reverse("intervention:index")
 | 
			
		||||
    )
 | 
			
		||||
class RemoveInterventionView(LoginRequiredMixin, BaseRemoveModalFormView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _REDIRECT_URL = "intervention:index"
 | 
			
		||||
 | 
			
		||||
@ -5,19 +5,11 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.decorators import shared_access_required, default_group_required
 | 
			
		||||
from konova.views.log import AbstractLogView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionLogView(AbstractLogView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class InterventionLogView(LoginRequiredMixin, AbstractLogView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
 | 
			
		||||
@ -5,19 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.decorators import conservation_office_group_required, shared_access_required
 | 
			
		||||
from konova.views.record import AbstractRecordView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionRecordView(AbstractRecordView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(conservation_office_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
class InterventionRecordView(LoginRequiredMixin, AbstractRecordView):
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,72 +5,41 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404, render
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import uuid_required
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.generators import generate_qr_code
 | 
			
		||||
from konova.sub_settings.django_settings import BASE_URL
 | 
			
		||||
from konova.utils.qrcode import QrCode
 | 
			
		||||
from konova.views.report import BaseReportView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@uuid_required
 | 
			
		||||
def report_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders the public report view
 | 
			
		||||
class InterventionReportView(BaseReportView):
 | 
			
		||||
    _TEMPLATE = 'intervention/report/report.html'
 | 
			
		||||
    _MODEL = Intervention
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The id of the intervention
 | 
			
		||||
    def _get_report_context(self, obj: Intervention):
 | 
			
		||||
        """ Returns the specific context needed for an intervention report
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        Args:
 | 
			
		||||
            obj (Intervention): The object for the report
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "intervention/report/report.html"
 | 
			
		||||
    intervention = get_object_or_404(Intervention, id=id)
 | 
			
		||||
        Returns:
 | 
			
		||||
            dict: The object specific context for rendering the report
 | 
			
		||||
        """
 | 
			
		||||
        distinct_deductions = obj.deductions.all().distinct("account")
 | 
			
		||||
        report_url = BASE_URL + reverse("intervention:report", args=(obj.id,))
 | 
			
		||||
        qrcode_report = QrCode(report_url, 10)
 | 
			
		||||
        qrcode_lanis = QrCode(obj.get_LANIS_link(), 7)
 | 
			
		||||
 | 
			
		||||
    tab_title = _("Report {}").format(intervention.identifier)
 | 
			
		||||
    # If intervention is not recorded (yet or currently) we need to render another template without any data
 | 
			
		||||
    if not intervention.is_ready_for_publish():
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        context = {
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
        return {
 | 
			
		||||
            "deductions": distinct_deductions,
 | 
			
		||||
            "qrcode": {
 | 
			
		||||
                "img": qrcode_report.get_img(),
 | 
			
		||||
                "url": qrcode_report.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "qrcode_lanis": {
 | 
			
		||||
                "img": qrcode_lanis.get_img(),
 | 
			
		||||
                "url": qrcode_lanis.get_content(),
 | 
			
		||||
            },
 | 
			
		||||
            "tables_scrollable": False,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
    # Prepare data for map viewer
 | 
			
		||||
    geom_form = SimpleGeomForm(
 | 
			
		||||
        instance=intervention
 | 
			
		||||
    )
 | 
			
		||||
    parcels = intervention.get_underlying_parcels()
 | 
			
		||||
 | 
			
		||||
    distinct_deductions = intervention.deductions.all().distinct(
 | 
			
		||||
        "account"
 | 
			
		||||
    )
 | 
			
		||||
    qrcode_url = request.build_absolute_uri(reverse("intervention:report", args=(id,)))
 | 
			
		||||
    qrcode_img = generate_qr_code(qrcode_url, 10)
 | 
			
		||||
    qrcode_lanis_url = intervention.get_LANIS_link()
 | 
			
		||||
    qrcode_img_lanis = generate_qr_code(qrcode_lanis_url, 7)
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "obj": intervention,
 | 
			
		||||
        "deductions": distinct_deductions,
 | 
			
		||||
        "qrcode": {
 | 
			
		||||
            "img": qrcode_img,
 | 
			
		||||
            "url": qrcode_url,
 | 
			
		||||
        },
 | 
			
		||||
        "qrcode_lanis": {
 | 
			
		||||
            "img": qrcode_img_lanis,
 | 
			
		||||
            "url": qrcode_lanis_url,
 | 
			
		||||
        },
 | 
			
		||||
        "geom_form": geom_form,
 | 
			
		||||
        "parcels": parcels,
 | 
			
		||||
        "tables_scrollable": False,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
@ -5,22 +5,12 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from intervention.forms.modals.resubmission import InterventionResubmissionModalForm
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.decorators import default_group_required, shared_access_required, login_required_modal
 | 
			
		||||
from konova.views.resubmission import AbstractResubmissionView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionResubmissionView(AbstractResubmissionView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    redirect_url_base = "intervention:detail"
 | 
			
		||||
    form_action_url_base = "intervention:resubmission-create"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _FORM_CLS = InterventionResubmissionModalForm
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
@ -5,29 +5,15 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.decorators import default_group_required, shared_access_required, login_required_modal
 | 
			
		||||
from konova.views.share import AbstractShareByTokenView, AbstractShareFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionShareByTokenView(AbstractShareByTokenView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
    redirect_url = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class InterventionShareFormView(AbstractShareFormView):
 | 
			
		||||
    model = Intervention
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required_modal)
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    @method_decorator(default_group_required)
 | 
			
		||||
    @method_decorator(shared_access_required(Intervention, "id"))
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
    _MODEL_CLS = Intervention
 | 
			
		||||
    _REDIRECT_URL = "intervention:detail"
 | 
			
		||||
@ -10,21 +10,18 @@ from abc import abstractmethod
 | 
			
		||||
from django import forms
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount
 | 
			
		||||
from konova.models import BaseObject
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseForm(forms.Form):
 | 
			
		||||
    """
 | 
			
		||||
    Basic form for that holds attributes needed in all other forms
 | 
			
		||||
    """
 | 
			
		||||
    template = None
 | 
			
		||||
    action_url = None
 | 
			
		||||
    action_btn_label = _("Save")
 | 
			
		||||
    form_title = None
 | 
			
		||||
    cancel_redirect = None
 | 
			
		||||
    form_caption = None
 | 
			
		||||
    instance = None  # The data holding model object
 | 
			
		||||
    user = None  # The performing user
 | 
			
		||||
    request = None
 | 
			
		||||
    form_attrs = {}  # Holds additional attributes, that can be used in the template
 | 
			
		||||
    has_required_fields = False  # Automatically set. Triggers hint rendering in templates
 | 
			
		||||
@ -33,6 +30,7 @@ class BaseForm(forms.Form):
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        self.instance = kwargs.pop("instance", None)
 | 
			
		||||
        self.user = kwargs.pop("user", None)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        if self.request is not None:
 | 
			
		||||
            self.user = self.request.user
 | 
			
		||||
@ -42,11 +40,10 @@ class BaseForm(forms.Form):
 | 
			
		||||
                self.has_required_fields = True
 | 
			
		||||
                break
 | 
			
		||||
 | 
			
		||||
        self.check_for_recorded_instance()
 | 
			
		||||
        self.__check_valid_label_input_ratio()
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def save(self):
 | 
			
		||||
    def save(self, *arg, **kwargs):
 | 
			
		||||
        # To be implemented in subclasses!
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
@ -136,34 +133,3 @@ class BaseForm(forms.Form):
 | 
			
		||||
        set_class = self.fields[field].widget.attrs.get("class", "")
 | 
			
		||||
        set_class = set_class.replace(cls, "")
 | 
			
		||||
        self.fields[field].widget.attrs["class"] = set_class
 | 
			
		||||
 | 
			
		||||
    def check_for_recorded_instance(self):
 | 
			
		||||
        """ Checks if the instance is recorded and runs some special logic if yes
 | 
			
		||||
 | 
			
		||||
        If the instance is recorded, the form shall not display any possibility to
 | 
			
		||||
        edit any data. Instead, the users should get some information about why they can not edit anything.
 | 
			
		||||
 | 
			
		||||
        There are situations where the form should be rendered regularly,
 | 
			
		||||
        e.g deduction forms for (recorded) eco accounts.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        is_none = self.instance is None
 | 
			
		||||
        is_other_data_type = not isinstance(self.instance, BaseObject)
 | 
			
		||||
 | 
			
		||||
        if is_none or is_other_data_type:
 | 
			
		||||
            # Do nothing
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if self.instance.is_recorded:
 | 
			
		||||
            self.block_form()
 | 
			
		||||
 | 
			
		||||
    def block_form(self):
 | 
			
		||||
        """
 | 
			
		||||
        Overwrites template, providing no actions
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self.template = "form/recorded_no_edit.html"
 | 
			
		||||
@ -23,7 +23,7 @@ class BaseModalForm(BaseForm, BSModalForm):
 | 
			
		||||
    """
 | 
			
		||||
    is_modal_form = True
 | 
			
		||||
    render_submit = True
 | 
			
		||||
    template = "modal/modal_form.html"
 | 
			
		||||
    _TEMPLATE = "modal/modal_form.html"
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
@ -43,7 +43,7 @@ class BaseModalForm(BaseForm, BSModalForm):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        redirect_url = redirect_url if redirect_url is not None else request.META.get("HTTP_REFERER", "home")
 | 
			
		||||
        template = self.template
 | 
			
		||||
        template = self._TEMPLATE
 | 
			
		||||
        if request.method == "POST":
 | 
			
		||||
            if self.is_valid():
 | 
			
		||||
                if not is_ajax(request.META):
 | 
			
		||||
 | 
			
		||||
@ -8,10 +8,10 @@ Created on: 15.08.22
 | 
			
		||||
from django import forms
 | 
			
		||||
from django.db import transaction
 | 
			
		||||
from django.db.models.fields.files import FieldFile
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.forms.modals.base_form import BaseModalForm
 | 
			
		||||
from konova.models import AbstractDocument
 | 
			
		||||
from konova.utils import validators
 | 
			
		||||
from konova.utils.message_templates import DOCUMENT_EDITED, FILE_SIZE_TOO_LARGE, FILE_TYPE_UNSUPPORTED
 | 
			
		||||
from user.models import UserActionLogEntry
 | 
			
		||||
@ -69,7 +69,7 @@ class NewDocumentModalForm(BaseModalForm):
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
    )
 | 
			
		||||
    document_model = None
 | 
			
		||||
    _DOCUMENT_CLS = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
@ -81,7 +81,7 @@ class NewDocumentModalForm(BaseModalForm):
 | 
			
		||||
        self.form_attrs = {
 | 
			
		||||
            "enctype": "multipart/form-data",  # important for file upload
 | 
			
		||||
        }
 | 
			
		||||
        if not self.document_model:
 | 
			
		||||
        if not self._DOCUMENT_CLS:
 | 
			
		||||
            raise NotImplementedError("Unsupported document type for {}".format(self.instance.__class__))
 | 
			
		||||
 | 
			
		||||
    def is_valid(self):
 | 
			
		||||
@ -93,14 +93,14 @@ class NewDocumentModalForm(BaseModalForm):
 | 
			
		||||
            # FieldFile declares that no new file has been uploaded and we do not need to check on the file again
 | 
			
		||||
            return super_valid
 | 
			
		||||
 | 
			
		||||
        mime_type_valid = self.document_model.is_mime_type_valid(_file)
 | 
			
		||||
        mime_type_valid = self._DOCUMENT_CLS.is_mime_type_valid(_file)
 | 
			
		||||
        if not mime_type_valid:
 | 
			
		||||
            self.add_error(
 | 
			
		||||
                "file",
 | 
			
		||||
                FILE_TYPE_UNSUPPORTED
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
        file_size_valid = self.document_model.is_file_size_valid(_file)
 | 
			
		||||
        file_size_valid = self._DOCUMENT_CLS.is_file_size_valid(_file)
 | 
			
		||||
        if not file_size_valid:
 | 
			
		||||
            self.add_error(
 | 
			
		||||
                "file",
 | 
			
		||||
@ -115,7 +115,7 @@ class NewDocumentModalForm(BaseModalForm):
 | 
			
		||||
            action = UserActionLogEntry.get_created_action(self.user)
 | 
			
		||||
            edited_action = UserActionLogEntry.get_edited_action(self.user, _("Added document"))
 | 
			
		||||
 | 
			
		||||
            doc = self.document_model.objects.create(
 | 
			
		||||
            doc = self._DOCUMENT_CLS.objects.create(
 | 
			
		||||
                created=action,
 | 
			
		||||
                title=self.cleaned_data["title"],
 | 
			
		||||
                comment=self.cleaned_data["comment"],
 | 
			
		||||
@ -133,10 +133,12 @@ class NewDocumentModalForm(BaseModalForm):
 | 
			
		||||
 | 
			
		||||
class EditDocumentModalForm(NewDocumentModalForm):
 | 
			
		||||
    document = None
 | 
			
		||||
    document_model = AbstractDocument
 | 
			
		||||
    _DOCUMENT_CLS = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        self.document = kwargs.pop("document", None)
 | 
			
		||||
        doc_id = kwargs.pop("doc_id", None)
 | 
			
		||||
        self.document = get_object_or_404(self._DOCUMENT_CLS, id=doc_id)
 | 
			
		||||
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.form_title = _("Edit document")
 | 
			
		||||
        form_data = {
 | 
			
		||||
 | 
			
		||||
@ -6,10 +6,11 @@ Created on: 15.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django import forms
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.forms.modals.base_form import BaseModalForm
 | 
			
		||||
from konova.models import BaseObject
 | 
			
		||||
from konova.models import BaseObject, Deadline
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveModalForm(BaseModalForm):
 | 
			
		||||
@ -51,9 +52,19 @@ class RemoveDeadlineModalForm(RemoveModalForm):
 | 
			
		||||
    deadline = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        deadline = kwargs.pop("deadline", None)
 | 
			
		||||
        self.deadline = deadline
 | 
			
		||||
        deadline_id = kwargs.pop("deadline_id", None)
 | 
			
		||||
        self.deadline = get_object_or_404(Deadline, id=deadline_id)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def save(self):
 | 
			
		||||
        self.instance.remove_deadline(self)
 | 
			
		||||
        self.instance.remove_deadline(self)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class RemoveDocumentModalForm(RemoveModalForm):
 | 
			
		||||
    instance = None
 | 
			
		||||
    _DOCUMENT_CLS = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, *args, **kwargs):
 | 
			
		||||
        document_id = kwargs.pop("doc_id", None)
 | 
			
		||||
        super().__init__(*args, **kwargs)
 | 
			
		||||
        self.instance = get_object_or_404(self._DOCUMENT_CLS, id=document_id)
 | 
			
		||||
 | 
			
		||||
@ -288,4 +288,8 @@ Overwrites netgis.css attributes
 | 
			
		||||
    Overwrites gradient used on default css of netgis map client
 | 
			
		||||
     */
 | 
			
		||||
    background: var(--rlp-red) !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.netgis-menu{
 | 
			
		||||
    z-index: 100 !important;
 | 
			
		||||
}
 | 
			
		||||
@ -543,7 +543,7 @@ class BaseViewTestCase(BaseTestCase):
 | 
			
		||||
        for url, redirect_to in urls.items():
 | 
			
		||||
            response = client.get(url, follow=True)
 | 
			
		||||
            # Expect redirects to the landing page
 | 
			
		||||
            self.assertEqual(response.redirect_chain[0], (redirect_to, 302), msg=f"Failed for {url}")
 | 
			
		||||
            self.assertEqual(response.redirect_chain[0], (redirect_to, 302), msg=f"Failed for {url}. Expected {redirect_to}")
 | 
			
		||||
 | 
			
		||||
    def assert_url_fail(self, client: Client, urls: list):
 | 
			
		||||
        """ Assert for all given urls a direct 302 response
 | 
			
		||||
 | 
			
		||||
@ -103,7 +103,7 @@ class EditDeadlineModalFormTestCase(NewDeadlineModalFormTestCase):
 | 
			
		||||
            data,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            deadline=self.finished_deadline,
 | 
			
		||||
            deadline_id=self.finished_deadline.id,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        self.assertTrue(form.is_valid(), msg=form.errors)
 | 
			
		||||
 | 
			
		||||
@ -17,9 +17,9 @@ from django.utils.timezone import now
 | 
			
		||||
from compensation.forms.modals.document import NewEcoAccountDocumentModalForm, NewCompensationDocumentModalForm
 | 
			
		||||
from compensation.models import Payment
 | 
			
		||||
from ema.forms import NewEmaDocumentModalForm
 | 
			
		||||
from intervention.forms.modals.document import NewInterventionDocumentModalForm
 | 
			
		||||
from intervention.forms.modals.document import NewInterventionDocumentModalForm, EditInterventionDocumentModalForm
 | 
			
		||||
from intervention.models import InterventionDocument
 | 
			
		||||
from konova.forms.modals import EditDocumentModalForm, NewDocumentModalForm, RecordModalForm, RemoveModalForm, \
 | 
			
		||||
from konova.forms.modals import NewDocumentModalForm, RecordModalForm, RemoveModalForm, \
 | 
			
		||||
    RemoveDeadlineModalForm, ResubmissionModalForm
 | 
			
		||||
from konova.models import Resubmission
 | 
			
		||||
from konova.tests.test_views import BaseTestCase
 | 
			
		||||
@ -106,12 +106,12 @@ class EditDocumentModalFormTestCase(NewDocumentModalFormTestCase):
 | 
			
		||||
            InterventionDocument,
 | 
			
		||||
            instance=self.intervention
 | 
			
		||||
        )
 | 
			
		||||
        self.form = EditDocumentModalForm(
 | 
			
		||||
        self.form = EditInterventionDocumentModalForm(
 | 
			
		||||
            self.data,
 | 
			
		||||
            dummy_file_dict,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.intervention,
 | 
			
		||||
            document=self.doc
 | 
			
		||||
            doc_id=self.doc.id
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def test_init(self):
 | 
			
		||||
@ -122,7 +122,6 @@ class EditDocumentModalFormTestCase(NewDocumentModalFormTestCase):
 | 
			
		||||
        self.assertEqual(self.form.fields["title"].initial, self.doc.title)
 | 
			
		||||
        self.assertEqual(self.form.fields["comment"].initial, self.doc.comment)
 | 
			
		||||
        self.assertEqual(self.form.fields["creation_date"].initial, self.doc.date_of_creation)
 | 
			
		||||
        self.assertEqual(self.form.fields["file"].initial, self.doc.file)
 | 
			
		||||
 | 
			
		||||
    def test_save(self):
 | 
			
		||||
        self.assertTrue(self.form.is_valid(), msg=self.form.errors)
 | 
			
		||||
@ -256,7 +255,7 @@ class RemoveDeadlineTestCase(BaseTestCase):
 | 
			
		||||
        form = RemoveDeadlineModalForm(
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            deadline=self.finished_deadline
 | 
			
		||||
            deadline_id=self.finished_deadline.id
 | 
			
		||||
        )
 | 
			
		||||
        self.assertEqual(form.form_title, str(_("Remove")))
 | 
			
		||||
        self.assertEqual(form.form_caption, str(_("Are you sure?")))
 | 
			
		||||
@ -273,7 +272,7 @@ class RemoveDeadlineTestCase(BaseTestCase):
 | 
			
		||||
            data,
 | 
			
		||||
            request=self.request,
 | 
			
		||||
            instance=self.compensation,
 | 
			
		||||
            deadline=self.finished_deadline
 | 
			
		||||
            deadline_id=self.finished_deadline.id
 | 
			
		||||
        )
 | 
			
		||||
        self.assertTrue(form.is_valid(), msg=form.errors)
 | 
			
		||||
        form.save()
 | 
			
		||||
 | 
			
		||||
@ -7,9 +7,7 @@ Created on: 01.09.21
 | 
			
		||||
"""
 | 
			
		||||
from django.http import FileResponse, HttpRequest, Http404
 | 
			
		||||
 | 
			
		||||
from konova.forms.modals import RemoveModalForm
 | 
			
		||||
from konova.models import AbstractDocument
 | 
			
		||||
from konova.utils.message_templates import DOCUMENT_REMOVED_TEMPLATE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def get_document(doc: AbstractDocument):
 | 
			
		||||
@ -26,28 +24,3 @@ def get_document(doc: AbstractDocument):
 | 
			
		||||
        return FileResponse(doc.file, as_attachment=True)
 | 
			
		||||
    except FileNotFoundError:
 | 
			
		||||
        raise Http404()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def remove_document(request: HttpRequest, doc: AbstractDocument):
 | 
			
		||||
    """ Renders a form for uploading new documents
 | 
			
		||||
 | 
			
		||||
    This function works using a modal. We are not using the regular way, the django bootstrap modal forms are
 | 
			
		||||
    intended to be used. Instead of View classes we work using the classic way of dealing with forms (see below).
 | 
			
		||||
    It is important to mention, that modal forms, which should reload the page afterwards, must provide a
 | 
			
		||||
    'reload_page' bool in the context. This way, the modal may reload the page or not.
 | 
			
		||||
 | 
			
		||||
    For further details see the comments in templates/modal or
 | 
			
		||||
    https://github.com/trco/django-bootstrap-modal-forms
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    title = doc.title
 | 
			
		||||
    form = RemoveModalForm(request.POST or None, instance=doc, request=request)
 | 
			
		||||
    return form.process_request(
 | 
			
		||||
        request=request,
 | 
			
		||||
        msg_success=DOCUMENT_REMOVED_TEMPLATE.format(title),
 | 
			
		||||
    )
 | 
			
		||||
@ -5,6 +5,11 @@ Contact: michel.peltriaux@sgdnord.rlp.de
 | 
			
		||||
Created on: 17.09.21
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from uuid import UUID
 | 
			
		||||
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from django.http import HttpRequest, Http404
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def format_german_float(num) -> str:
 | 
			
		||||
@ -19,3 +24,27 @@ def format_german_float(num) -> str:
 | 
			
		||||
        num (str): The number as german Gleitkommazahl
 | 
			
		||||
    """
 | 
			
		||||
    return format(num, "0,.2f").replace(",", "X").replace(".", ",").replace("X", ".")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def check_user_is_in_any_group(request: HttpRequest):
 | 
			
		||||
    """
 | 
			
		||||
    Checks for any group membership. Adds a message in case of having none.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    user = request.user
 | 
			
		||||
    # Inform user about missing group privileges!
 | 
			
		||||
    groups = user.groups.all()
 | 
			
		||||
    if not groups:
 | 
			
		||||
        messages.info(
 | 
			
		||||
            request,
 | 
			
		||||
            _("+++ Attention: You are not part of any group. You won't be able to create, edit or do anything. Please contact an administrator. +++")
 | 
			
		||||
        )
 | 
			
		||||
    return request
 | 
			
		||||
 | 
			
		||||
def check_id_is_valid_uuid(uuid: str):
 | 
			
		||||
    if uuid:
 | 
			
		||||
        try:
 | 
			
		||||
            # Check whether the id is a proper uuid or something that would break a db fetch
 | 
			
		||||
            UUID(uuid)
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            raise Http404
 | 
			
		||||
 | 
			
		||||
@ -7,10 +7,6 @@ Created on: 09.11.20
 | 
			
		||||
"""
 | 
			
		||||
import random
 | 
			
		||||
import string
 | 
			
		||||
import qrcode
 | 
			
		||||
import qrcode.image.svg
 | 
			
		||||
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_token() -> str:
 | 
			
		||||
@ -42,23 +38,3 @@ def generate_random_string(length: int, use_numbers: bool = False, use_letters_l
 | 
			
		||||
    ret_val = "".join(random.choice(elements) for i in range(length))
 | 
			
		||||
    return ret_val
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def generate_qr_code(content: str, size: int = 20) -> str:
 | 
			
		||||
    """ Generates a qr code from given content
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        content (str): The content for the qr code
 | 
			
		||||
        size (int): The image size
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        qrcode_svg (str): The qr code as svg
 | 
			
		||||
    """
 | 
			
		||||
    qrcode_factory = qrcode.image.svg.SvgImage
 | 
			
		||||
    qrcode_img = qrcode.make(
 | 
			
		||||
        content,
 | 
			
		||||
        image_factory=qrcode_factory,
 | 
			
		||||
        box_size=size
 | 
			
		||||
    )
 | 
			
		||||
    stream = BytesIO()
 | 
			
		||||
    qrcode_img.save(stream)
 | 
			
		||||
    return stream.getvalue().decode()
 | 
			
		||||
 | 
			
		||||
@ -19,7 +19,14 @@ IDENTIFIER_REPLACED = _("The identifier '{}' had to be changed to '{}' since ano
 | 
			
		||||
ENTRY_REMOVE_MISSING_PERMISSION = _("Only conservation or registration office users are allowed to remove entries.")
 | 
			
		||||
MISSING_GROUP_PERMISSION = _("You need to be part of another user group.")
 | 
			
		||||
CHECK_STATE_RESET = _("Status of Checked reset")
 | 
			
		||||
 | 
			
		||||
# REMOVED
 | 
			
		||||
GENERIC_REMOVED_TEMPLATE = _("{} removed")
 | 
			
		||||
 | 
			
		||||
# RECORDING
 | 
			
		||||
RECORDED_BLOCKS_EDIT = _("Entry is recorded. To edit data, the entry first needs to be unrecorded.")
 | 
			
		||||
ENTRY_RECORDED = _("{} recorded")
 | 
			
		||||
ENTRY_UNRECORDED = _("{} unrecorded")
 | 
			
		||||
 | 
			
		||||
# SHARE
 | 
			
		||||
DATA_UNSHARED = _("This data is not shared with you")
 | 
			
		||||
@ -94,4 +101,7 @@ DATA_CHECKED_PREVIOUSLY_TEMPLATE = _("Data has changed since last check on {} by
 | 
			
		||||
DATA_IS_UNCHECKED = _("Current data not checked yet")
 | 
			
		||||
 | 
			
		||||
# API TOKEN SETTINGS
 | 
			
		||||
NEW_API_TOKEN_GENERATED = _("New token generated. Administrators need to validate.")
 | 
			
		||||
NEW_API_TOKEN_GENERATED = _("New token generated. Administrators need to validate.")
 | 
			
		||||
 | 
			
		||||
# RESUBMISSION
 | 
			
		||||
NEW_RESUBMISSION_CREATED = _("Resubmission set")
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										47
									
								
								konova/utils/qrcode.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								konova/utils/qrcode.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,47 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Created on: 17.10.25
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from io import BytesIO
 | 
			
		||||
 | 
			
		||||
import qrcode
 | 
			
		||||
import qrcode.image.svg as svg
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class QrCode:
 | 
			
		||||
    """ A wrapping class for creating a qr code with content
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    _content = None
 | 
			
		||||
    _img = None
 | 
			
		||||
 | 
			
		||||
    def __init__(self, content: str, size: int):
 | 
			
		||||
        self._content = content
 | 
			
		||||
        self._img = self._generate_qr_code(content, size)
 | 
			
		||||
 | 
			
		||||
    def _generate_qr_code(self, content: str, size: int = 20) -> str:
 | 
			
		||||
        """ Generates a qr code from given content
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            content (str): The content for the qr code
 | 
			
		||||
            size (int): The image size
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            qrcode_svg (str): The qr code as svg
 | 
			
		||||
        """
 | 
			
		||||
        img_factory = svg.SvgImage
 | 
			
		||||
        qrcode_img = qrcode.make(
 | 
			
		||||
            content,
 | 
			
		||||
            image_factory=img_factory,
 | 
			
		||||
            box_size=size
 | 
			
		||||
        )
 | 
			
		||||
        stream = BytesIO()
 | 
			
		||||
        qrcode_img.save(stream)
 | 
			
		||||
        return stream.getvalue().decode()
 | 
			
		||||
 | 
			
		||||
    def get_img(self):
 | 
			
		||||
        return self._img
 | 
			
		||||
 | 
			
		||||
    def get_content(self):
 | 
			
		||||
        return self._content
 | 
			
		||||
@ -5,104 +5,47 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 22.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.views import View
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.compensation_action import NewCompensationActionModalForm, \
 | 
			
		||||
    EditCompensationActionModalForm, RemoveCompensationActionModalForm
 | 
			
		||||
from compensation.models import CompensationAction
 | 
			
		||||
from konova.utils.message_templates import COMPENSATION_STATE_ADDED, COMPENSATION_STATE_EDITED, \
 | 
			
		||||
    COMPENSATION_STATE_REMOVED
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractCompensationActionView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractCompensationActionView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return super()._get_redirect_url(*args, **kwargs) + "#related_data"
 | 
			
		||||
 | 
			
		||||
class AbstractNewCompensationActionView(AbstractCompensationActionView):
 | 
			
		||||
    _FORM_CLS =  NewCompensationActionModalForm
 | 
			
		||||
    _MSG_SUCCESS = COMPENSATION_STATE_ADDED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders a form for adding new actions 
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object's id to which the new action will be related
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        form = NewCompensationActionModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=COMPENSATION_STATE_ADDED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
class AbstractEditCompensationActionView(AbstractCompensationActionView):
 | 
			
		||||
    _FORM_CLS = EditCompensationActionModalForm
 | 
			
		||||
    _MSG_SUCCESS = COMPENSATION_STATE_EDITED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, action_id: str):
 | 
			
		||||
        """ Renders a form for editing a action
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object id
 | 
			
		||||
            action_id (str): The action's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        action = get_object_or_404(CompensationAction, id=action_id)
 | 
			
		||||
        form = EditCompensationActionModalForm(request.POST or None, instance=obj, action=action, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=COMPENSATION_STATE_EDITED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, action_id: str):
 | 
			
		||||
        return self.get(request, id, action_id)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
class AbstractRemoveCompensationActionView(AbstractCompensationActionView):
 | 
			
		||||
    _FORM_CLS = RemoveCompensationActionModalForm
 | 
			
		||||
    _MSG_SUCCESS = COMPENSATION_STATE_REMOVED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, action_id: str):
 | 
			
		||||
        """ Renders a form for removing aaction
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object id
 | 
			
		||||
            action_id (str): The action's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        action = get_object_or_404(CompensationAction, id=action_id)
 | 
			
		||||
        form = RemoveCompensationActionModalForm(request.POST or None, instance=obj, action=action, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=COMPENSATION_STATE_REMOVED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, action_id: str):
 | 
			
		||||
        return self.get(request, id, action_id)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										424
									
								
								konova/views/base.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										424
									
								
								konova/views/base.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,424 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Created on: 15.10.25
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from abc import abstractmethod
 | 
			
		||||
 | 
			
		||||
from bootstrap_modal_forms.mixins import is_ajax
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import HttpRequest, JsonResponse, HttpResponseRedirect
 | 
			
		||||
from django.shortcuts import render, redirect, get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.views import View
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.forms import BaseForm, SimpleGeomForm
 | 
			
		||||
from konova.models import BaseObject
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.general import check_user_is_in_any_group
 | 
			
		||||
from konova.utils.message_templates import MISSING_GROUP_PERMISSION, DATA_UNSHARED, IDENTIFIER_REPLACED, \
 | 
			
		||||
    GEOMETRY_SIMPLIFIED, GEOMETRIES_IGNORED_TEMPLATE, RECORDED_BLOCKS_EDIT, FORM_INVALID
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseView(View):
 | 
			
		||||
    _TEMPLATE: str = "CHANGE_ME"
 | 
			
		||||
    _TAB_TITLE: str = "CHANGE_ME"
 | 
			
		||||
    _REDIRECT_URL: str = "CHANGE_ME"
 | 
			
		||||
    _REDIRECT_URL_ERROR: str = "home"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        request = check_user_is_in_any_group(request)
 | 
			
		||||
 | 
			
		||||
        if not self._user_has_permission(request.user):
 | 
			
		||||
            messages.info(request, MISSING_GROUP_PERMISSION)
 | 
			
		||||
            return redirect(reverse(self._REDIRECT_URL_ERROR))
 | 
			
		||||
 | 
			
		||||
        if not self._user_has_shared_access(request.user, **kwargs):
 | 
			
		||||
            messages.info(request, DATA_UNSHARED)
 | 
			
		||||
            return redirect(reverse(self._REDIRECT_URL_ERROR))
 | 
			
		||||
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        """ Has to be implemented properly by inheriting classes
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            user ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError("User permission not checked!")
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        """ Has to be implemented properly by inheriting classes
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            user ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError("Shared access not checked!")
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return self._REDIRECT_URL
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url_error(self, *args, **kwargs):
 | 
			
		||||
        return self._REDIRECT_URL_ERROR
 | 
			
		||||
 | 
			
		||||
class BaseModalFormView(BaseView):
 | 
			
		||||
    _TEMPLATE = "modal/modal_form.html"
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = None
 | 
			
		||||
    _MSG_SUCCESS = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get("id"))
 | 
			
		||||
        return obj.is_shared_with(user)
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest, id: str, *args, **kwargs):
 | 
			
		||||
        obj = self._MODEL_CLS.objects.get(id=id)
 | 
			
		||||
        self._check_for_recorded_instance(obj)
 | 
			
		||||
        form = self._FORM_CLS(
 | 
			
		||||
            request.POST or None,
 | 
			
		||||
            request.FILES or None,
 | 
			
		||||
            instance=obj,
 | 
			
		||||
            request=request,
 | 
			
		||||
            **kwargs
 | 
			
		||||
        )
 | 
			
		||||
        context = {
 | 
			
		||||
            "form": form,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def post(self, request: HttpRequest, id: str, *args, **kwargs):
 | 
			
		||||
        obj = self._MODEL_CLS.objects.get(id=id)
 | 
			
		||||
        self._check_for_recorded_instance(obj)
 | 
			
		||||
        form = self._FORM_CLS(
 | 
			
		||||
            request.POST or None,
 | 
			
		||||
            request.FILES or None,
 | 
			
		||||
            instance=obj,
 | 
			
		||||
            request=request,
 | 
			
		||||
            **kwargs
 | 
			
		||||
        )
 | 
			
		||||
        redirect_url = self._get_redirect_url(obj=obj)
 | 
			
		||||
        if form.is_valid():
 | 
			
		||||
            if not is_ajax(request.META):
 | 
			
		||||
                # Modal forms send one POST for checking on data validity. This can be used to return possible errors
 | 
			
		||||
                # on the form. A second POST (if no errors occurs) is sent afterward and needs to process the
 | 
			
		||||
                # saving/commiting of the data to the database. is_ajax() performs this check. The first request is
 | 
			
		||||
                # an ajax call, the second is a regular form POST.
 | 
			
		||||
                msg_success = self._get_msg_success(obj=obj, *args, **kwargs)
 | 
			
		||||
                form.save()
 | 
			
		||||
                messages.success(
 | 
			
		||||
                    request,
 | 
			
		||||
                    msg_success
 | 
			
		||||
                )
 | 
			
		||||
            return HttpResponseRedirect(redirect_url)
 | 
			
		||||
        else:
 | 
			
		||||
            context = {
 | 
			
		||||
                "form": form,
 | 
			
		||||
            }
 | 
			
		||||
            context = BaseContext(request, context).context
 | 
			
		||||
            return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        obj = kwargs.get("obj", None)
 | 
			
		||||
        assert obj is not None
 | 
			
		||||
        return reverse(self._REDIRECT_URL, args=(obj.id,))
 | 
			
		||||
 | 
			
		||||
    def _get_msg_success(self, *args, **kwargs):
 | 
			
		||||
        return self._MSG_SUCCESS
 | 
			
		||||
 | 
			
		||||
    def _check_for_recorded_instance(self, obj):
 | 
			
		||||
        """ Checks if the object on this view is recorded and runs some special logic if yes
 | 
			
		||||
 | 
			
		||||
        If the instance is recorded, the view should provide some information about why the user can not edit anything.
 | 
			
		||||
 | 
			
		||||
        There are situations where the form should be rendered regularly,
 | 
			
		||||
        e.g deduction forms for (recorded) eco accounts.
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        is_none = obj is None
 | 
			
		||||
        is_other_data_type = not isinstance(obj, BaseObject)
 | 
			
		||||
 | 
			
		||||
        if is_none or is_other_data_type:
 | 
			
		||||
            # Do nothing
 | 
			
		||||
            return
 | 
			
		||||
 | 
			
		||||
        if obj.is_recorded:
 | 
			
		||||
            self._block_form()
 | 
			
		||||
 | 
			
		||||
    def _block_form(self):
 | 
			
		||||
        """
 | 
			
		||||
        Overwrites template, providing no actions
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        self._TEMPLATE = "form/recorded_no_edit.html"
 | 
			
		||||
 | 
			
		||||
class BaseIndexView(BaseView):
 | 
			
		||||
    """ Base class for index views
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    _TEMPLATE = "generic_index.html"
 | 
			
		||||
    _INDEX_TABLE_CLS = None
 | 
			
		||||
    _REDIRECT_URL = "home"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest):
 | 
			
		||||
        qs = self._get_queryset()
 | 
			
		||||
        table = self._INDEX_TABLE_CLS(
 | 
			
		||||
            request=request,
 | 
			
		||||
            queryset=qs
 | 
			
		||||
        )
 | 
			
		||||
        context = {
 | 
			
		||||
            "table": table,
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def _get_queryset(self):
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # No specific permissions needed for opening base index view
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # No specific constraints for shared access of index views
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseIdentifierGeneratorView(BaseView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _REDIRECT_URL: str = "home"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest):
 | 
			
		||||
        tmp_obj = self._MODEL_CLS()
 | 
			
		||||
        identifier = tmp_obj.generate_new_identifier()
 | 
			
		||||
        while self._MODEL_CLS.objects.filter(identifier=identifier).exists():
 | 
			
		||||
            identifier = tmp_obj.generate_new_identifier()
 | 
			
		||||
        return JsonResponse(
 | 
			
		||||
            data={
 | 
			
		||||
                "gen_data": identifier
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        """ Should be overwritten in inheriting classes!
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            user ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # No specific constraints for shared access
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseFormView(BaseView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def _get_additional_context(self, **kwargs):
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            **kwargs ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        return {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseSpatialLocatedObjectFormView(LoginRequiredMixin, BaseFormView):
 | 
			
		||||
    _GEOMETRY_FORM_CLS = SimpleGeomForm
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseNewSpatialLocatedObjectFormView(BaseSpatialLocatedObjectFormView):
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # User has to have default privilege to call this endpoint
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # There is no shared access control since nothing exists yet
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest, **kwargs):
 | 
			
		||||
        form: BaseForm = self._FORM_CLS(None, **kwargs, user=request.user)
 | 
			
		||||
        geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, user=request.user, read_only=False)
 | 
			
		||||
 | 
			
		||||
        context = self._get_additional_context()
 | 
			
		||||
        context = BaseContext(request, additional_context=context).context
 | 
			
		||||
        context.update(
 | 
			
		||||
            {
 | 
			
		||||
                "form": form,
 | 
			
		||||
                "geom_form": geom_form,
 | 
			
		||||
                TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def post(self, request: HttpRequest, **kwargs):
 | 
			
		||||
        form: BaseForm = self._FORM_CLS(request.POST or None, **kwargs, user=request.user)
 | 
			
		||||
        geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, user=request.user, read_only=False)
 | 
			
		||||
 | 
			
		||||
        if form.is_valid() and geom_form.is_valid():
 | 
			
		||||
            obj = form.save(request.user, geom_form)
 | 
			
		||||
            obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
 | 
			
		||||
 | 
			
		||||
            generated_identifier = form.cleaned_data.get("identifier", None)
 | 
			
		||||
 | 
			
		||||
            if generated_identifier != obj.identifier:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    IDENTIFIER_REPLACED.format(
 | 
			
		||||
                        generated_identifier,
 | 
			
		||||
                        obj.identifier
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            messages.success(request, _("{} added").format(obj.identifier))
 | 
			
		||||
            if geom_form.has_geometry_simplified():
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRY_SIMPLIFIED
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
 | 
			
		||||
            if num_ignored_geometries > 0:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            return redirect(obj_redirect_url)
 | 
			
		||||
        else:
 | 
			
		||||
            context = self._get_additional_context()
 | 
			
		||||
            messages.error(request, FORM_INVALID, extra_tags="danger",)
 | 
			
		||||
 | 
			
		||||
        context = BaseContext(request, additional_context=context).context
 | 
			
		||||
        context.update(
 | 
			
		||||
            {
 | 
			
		||||
                "form": form,
 | 
			
		||||
                "geom_form": geom_form,
 | 
			
		||||
                TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseEditSpatialLocatedObjectFormView(BaseSpatialLocatedObjectFormView):
 | 
			
		||||
    _TAB_TITLE = _("Edit {}")
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest, id: str):
 | 
			
		||||
        obj = get_object_or_404(
 | 
			
		||||
            self._MODEL_CLS,
 | 
			
		||||
            id=id
 | 
			
		||||
        )
 | 
			
		||||
        obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
 | 
			
		||||
 | 
			
		||||
        if obj.is_recorded:
 | 
			
		||||
            messages.info(
 | 
			
		||||
                request,
 | 
			
		||||
                RECORDED_BLOCKS_EDIT
 | 
			
		||||
            )
 | 
			
		||||
            return redirect(obj_redirect_url)
 | 
			
		||||
 | 
			
		||||
        form: BaseForm = self._FORM_CLS(None, instance=obj, user=request.user)
 | 
			
		||||
        geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(None, instance=obj, read_only=False)
 | 
			
		||||
 | 
			
		||||
        context = self._get_additional_context()
 | 
			
		||||
        context = BaseContext(request, additional_context=context).context
 | 
			
		||||
        context.update(
 | 
			
		||||
            {
 | 
			
		||||
                "form": form,
 | 
			
		||||
                "geom_form": geom_form,
 | 
			
		||||
                TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def post(self, request: HttpRequest, id: str):
 | 
			
		||||
        obj = get_object_or_404(
 | 
			
		||||
            self._MODEL_CLS,
 | 
			
		||||
            id=id
 | 
			
		||||
        )
 | 
			
		||||
        obj_redirect_url = reverse(self._REDIRECT_URL, args=(obj.id,))
 | 
			
		||||
 | 
			
		||||
        form: BaseForm = self._FORM_CLS(request.POST or None, instance=obj, user=request.user)
 | 
			
		||||
        geom_form: SimpleGeomForm = self._GEOMETRY_FORM_CLS(request.POST or None, instance=obj, read_only=False)
 | 
			
		||||
 | 
			
		||||
        if form.is_valid() and geom_form.is_valid():
 | 
			
		||||
            obj = form.save(request.user, geom_form)
 | 
			
		||||
            messages.success(request, _("{} edited").format(obj.identifier))
 | 
			
		||||
 | 
			
		||||
            if geom_form.has_geometry_simplified():
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRY_SIMPLIFIED
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            num_ignored_geometries = geom_form.get_num_geometries_ignored()
 | 
			
		||||
            if num_ignored_geometries > 0:
 | 
			
		||||
                messages.info(
 | 
			
		||||
                    request,
 | 
			
		||||
                    GEOMETRIES_IGNORED_TEMPLATE.format(num_ignored_geometries)
 | 
			
		||||
                )
 | 
			
		||||
 | 
			
		||||
            return redirect(obj_redirect_url)
 | 
			
		||||
        else:
 | 
			
		||||
            context = self._get_additional_context()
 | 
			
		||||
            messages.error(request, FORM_INVALID, extra_tags="danger",)
 | 
			
		||||
 | 
			
		||||
        context = BaseContext(request, additional_context=context).context
 | 
			
		||||
        context.update(
 | 
			
		||||
            {
 | 
			
		||||
                "form": form,
 | 
			
		||||
                "geom_form": geom_form,
 | 
			
		||||
                TAB_TITLE_IDENTIFIER: self._TAB_TITLE.format(obj.identifier),
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        obj = get_object_or_404(self._MODEL_CLS, id=kwargs.get('id', None))
 | 
			
		||||
        return obj.is_shared_with(user)
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
@ -5,102 +5,57 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 22.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.views import View
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.deadline import NewDeadlineModalForm, EditDeadlineModalForm
 | 
			
		||||
from konova.forms.modals import RemoveDeadlineModalForm
 | 
			
		||||
from konova.models import Deadline
 | 
			
		||||
from konova.utils.message_templates import DEADLINE_ADDED, DEADLINE_EDITED, DEADLINE_REMOVED
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractNewDeadlineView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractNewDeadlineView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = NewDeadlineModalForm
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    _MSG_SUCCESS = DEADLINE_ADDED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders a form for adding new deadlines
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return super()._get_redirect_url(*args, **kwargs) + "#related_data"
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The account's id to which the new state will be related
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        form = NewDeadlineModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=DEADLINE_ADDED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractEditDeadlineView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractEditDeadlineView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = EditDeadlineModalForm
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    _MSG_SUCCESS = DEADLINE_EDITED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, deadline_id: str):
 | 
			
		||||
        """ Renders a form for editing deadlines
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return super()._get_redirect_url(*args, **kwargs) + "#related_data"
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The compensation's id
 | 
			
		||||
            deadline_id (str): The deadline's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        deadline = get_object_or_404(Deadline, id=deadline_id)
 | 
			
		||||
        form = EditDeadlineModalForm(request.POST or None, instance=obj, deadline=deadline, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=DEADLINE_EDITED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, deadline_id: str):
 | 
			
		||||
        return self.get(request, id, deadline_id)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractRemoveDeadlineView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractRemoveDeadlineView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = RemoveDeadlineModalForm
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    _MSG_SUCCESS = DEADLINE_REMOVED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, deadline_id: str):
 | 
			
		||||
        """ Renders a form for removing deadlines
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return super()._get_redirect_url(*args, **kwargs) + "#related_data"
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The compensation's id
 | 
			
		||||
            deadline_id (str): The deadline's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        deadline = get_object_or_404(Deadline, id=deadline_id)
 | 
			
		||||
        form = RemoveDeadlineModalForm(request.POST or None, instance=obj, deadline=deadline, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=DEADLINE_REMOVED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, deadline_id: str):
 | 
			
		||||
        return self.get(request, id, deadline_id)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
@ -6,126 +6,88 @@ Created on: 22.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.core.exceptions import ObjectDoesNotExist
 | 
			
		||||
from django.http import Http404
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.views import View
 | 
			
		||||
 | 
			
		||||
from intervention.forms.modals.deduction import NewEcoAccountDeductionModalForm, EditEcoAccountDeductionModalForm, \
 | 
			
		||||
    RemoveEcoAccountDeductionModalForm
 | 
			
		||||
from konova.utils.message_templates import DEDUCTION_ADDED, DEDUCTION_EDITED, DEDUCTION_REMOVED, DEDUCTION_UNKNOWN
 | 
			
		||||
from konova.utils.general import check_id_is_valid_uuid
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractDeductionView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractDeductionView(BaseModalFormView):
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        check_id_is_valid_uuid(kwargs.get("id"))
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        """
 | 
			
		||||
        Can be used by inheriting classes to provide custom checks before further processing
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError("Must be implemented in subclasses")
 | 
			
		||||
        pass
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user) -> bool:
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            user ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs) -> bool:
 | 
			
		||||
        """ A user has shared access on
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            user (User): The performing user
 | 
			
		||||
            kwargs (dict): Parameters
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            bool: True if the user has access to the requested object, False otherwise
 | 
			
		||||
        """
 | 
			
		||||
        ret_val: bool = False
 | 
			
		||||
        try:
 | 
			
		||||
            obj = self._MODEL_CLS.objects.get(
 | 
			
		||||
                id=kwargs.get("id")
 | 
			
		||||
            )
 | 
			
		||||
            ret_val = obj.is_shared_with(user)
 | 
			
		||||
        except ObjectDoesNotExist:
 | 
			
		||||
            ret_val = False
 | 
			
		||||
        return ret_val
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        obj = kwargs.get("obj", None)
 | 
			
		||||
        assert obj is not None
 | 
			
		||||
        return reverse(self._REDIRECT_URL, args=(obj.id,)) + "#related_data"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractNewDeductionView(AbstractDeductionView):
 | 
			
		||||
    _FORM_CLS = NewEcoAccountDeductionModalForm
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders a modal form view for creating deductions
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The obj's id which shall benefit from this deduction
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        self._custom_check(obj)
 | 
			
		||||
        form = NewEcoAccountDeductionModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=DEDUCTION_ADDED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data",
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractEditDeductionView(AbstractDeductionView):
 | 
			
		||||
    _FORM_CLS = EditEcoAccountDeductionModalForm
 | 
			
		||||
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        pass
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        check_id_is_valid_uuid(kwargs.get("deduction_id"))
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, deduction_id: str):
 | 
			
		||||
        """ Renders a modal view for editing deductions
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object's id
 | 
			
		||||
            deduction_id (str): The deduction's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        self._custom_check(obj)
 | 
			
		||||
        try:
 | 
			
		||||
            eco_deduction = obj.deductions.get(id=deduction_id)
 | 
			
		||||
        except ObjectDoesNotExist:
 | 
			
		||||
            raise Http404(DEDUCTION_UNKNOWN)
 | 
			
		||||
 | 
			
		||||
        form = EditEcoAccountDeductionModalForm(request.POST or None, instance=obj, deduction=eco_deduction,
 | 
			
		||||
                                                request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request=request,
 | 
			
		||||
            msg_success=DEDUCTION_EDITED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, deduction_id: str):
 | 
			
		||||
        return self.get(request, id, deduction_id)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractRemoveDeductionView(AbstractDeductionView):
 | 
			
		||||
    _FORM_CLS = RemoveEcoAccountDeductionModalForm
 | 
			
		||||
 | 
			
		||||
    def _custom_check(self, obj):
 | 
			
		||||
        pass
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        check_id_is_valid_uuid(kwargs.get("deduction_id"))
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, deduction_id: str):
 | 
			
		||||
        """ Renders a modal view for removing deductions
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object's id
 | 
			
		||||
            deduction_id (str): The deduction's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        self._custom_check(obj)
 | 
			
		||||
        try:
 | 
			
		||||
            eco_deduction = obj.deductions.get(id=deduction_id)
 | 
			
		||||
        except ObjectDoesNotExist:
 | 
			
		||||
            raise Http404(DEDUCTION_UNKNOWN)
 | 
			
		||||
        form = RemoveEcoAccountDeductionModalForm(request.POST or None, instance=obj, deduction=eco_deduction,
 | 
			
		||||
                                                  request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request=request,
 | 
			
		||||
            msg_success=DEDUCTION_REMOVED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, deduction_id: str):
 | 
			
		||||
        return self.get(request, id, deduction_id)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										107
									
								
								konova/views/detail.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								konova/views/detail.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,107 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Created on: 17.10.25
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from abc import abstractmethod
 | 
			
		||||
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.utils.general import check_id_is_valid_uuid
 | 
			
		||||
from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE
 | 
			
		||||
from konova.views.base import BaseView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseDetailView(LoginRequiredMixin, BaseView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        check_id_is_valid_uuid(kwargs.get('id'))
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        """ Check if user has shared access to this object
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            user ():
 | 
			
		||||
            **kwargs ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        # Access to an entry's detail view is not restricted by the state of being-shared or not
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # Detail views have no restrictions
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest, id: str):
 | 
			
		||||
        """ Get endpoint for detail view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The record's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = self._get_object(id)
 | 
			
		||||
        geom_form = SimpleGeomForm(instance=obj)
 | 
			
		||||
        user = request.user
 | 
			
		||||
 | 
			
		||||
        requesting_user_is_only_shared_user = obj.is_only_shared_with(user)
 | 
			
		||||
        if requesting_user_is_only_shared_user:
 | 
			
		||||
            messages.info(request, DO_NOT_FORGET_TO_SHARE)
 | 
			
		||||
 | 
			
		||||
        obj.set_status_messages(request)
 | 
			
		||||
 | 
			
		||||
        detail_context = self._get_detail_context(obj)
 | 
			
		||||
        context = BaseContext(request, detail_context).context
 | 
			
		||||
        context.update(
 | 
			
		||||
            {
 | 
			
		||||
                "obj": obj,
 | 
			
		||||
                "geom_form": geom_form,
 | 
			
		||||
                "is_default_member": user.in_group(DEFAULT_GROUP),
 | 
			
		||||
                "is_zb_member": user.in_group(ZB_GROUP),
 | 
			
		||||
                "is_ets_member": user.in_group(ETS_GROUP),
 | 
			
		||||
                "LANIS_LINK": obj.get_LANIS_link(),
 | 
			
		||||
                "is_entry_shared": obj.is_shared_with(user=user),
 | 
			
		||||
                TAB_TITLE_IDENTIFIER: f"{obj.identifier} - {obj.title}"
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
        return render(request,self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def _get_detail_context(self, obj):
 | 
			
		||||
        """ Generate object specific detail context for  view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            obj (): The record
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def _get_object(self, id: str):
 | 
			
		||||
        """ Fetch object for detail view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            id (str): The record's id'
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
@ -5,46 +5,35 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 22.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.views import View
 | 
			
		||||
 | 
			
		||||
from konova.utils.documents import get_document, remove_document
 | 
			
		||||
from konova.utils.message_templates import DOCUMENT_ADDED, DOCUMENT_EDITED
 | 
			
		||||
from konova.forms.modals import EditDocumentModalForm
 | 
			
		||||
from konova.utils.documents import get_document
 | 
			
		||||
from konova.utils.message_templates import DOCUMENT_ADDED, DOCUMENT_EDITED, DOCUMENT_REMOVED_TEMPLATE
 | 
			
		||||
from konova.views.base import BaseModalFormView, BaseView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractNewDocumentView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    form = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractNewDocumentView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = None
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    _MSG_SUCCESS = DOCUMENT_ADDED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders a form for uploading new documents
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return super()._get_redirect_url(*args, **kwargs) + "#related_data"
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object's id to which the new document will be related
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        intervention = get_object_or_404(self.model, id=id)
 | 
			
		||||
        form = self.form(request.POST or None, request.FILES or None, instance=intervention, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=DOCUMENT_ADDED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractGetDocumentView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    document_model = None
 | 
			
		||||
class AbstractGetDocumentView(LoginRequiredMixin, BaseView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _DOCUMENT_CLS = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
@ -62,77 +51,57 @@ class AbstractGetDocumentView(View):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        get_object_or_404(self.model, id=id)
 | 
			
		||||
        doc = get_object_or_404(self.document_model, id=doc_id)
 | 
			
		||||
        get_object_or_404(self._MODEL_CLS, id=id)
 | 
			
		||||
        doc = get_object_or_404(self._DOCUMENT_CLS, id=doc_id)
 | 
			
		||||
        return get_document(doc)
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, doc_id: str):
 | 
			
		||||
        return self.get(request, id, doc_id)
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
class AbstractRemoveDocumentView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    document_model = None
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        obj = kwargs.get("id", None)
 | 
			
		||||
        assert obj is not None
 | 
			
		||||
        obj = get_object_or_404(self._MODEL_CLS, id=obj)
 | 
			
		||||
        return obj.is_shared_with(user)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractRemoveDocumentView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _DOCUMENT_CLS = None
 | 
			
		||||
    _FORM_CLS = None
 | 
			
		||||
    _MSG_SUCCESS = DOCUMENT_REMOVED_TEMPLATE
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, doc_id: str):
 | 
			
		||||
        """ Removes the document from the database and file system
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return super()._get_redirect_url(*args, **kwargs) + "#related_data"
 | 
			
		||||
 | 
			
		||||
        Wraps the generic functionality from konova.utils.
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The intervention id
 | 
			
		||||
            doc_id (str): The document id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        get_object_or_404(self.model, id=id)
 | 
			
		||||
        doc = get_object_or_404(self.document_model, id=doc_id)
 | 
			
		||||
        return remove_document(
 | 
			
		||||
            request,
 | 
			
		||||
            doc
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, doc_id: str):
 | 
			
		||||
        return self.get(request, id, doc_id)
 | 
			
		||||
    def _get_msg_success(self, *args, **kwargs):
 | 
			
		||||
        doc_id = kwargs.get("doc_id", None)
 | 
			
		||||
        assert doc_id is not None
 | 
			
		||||
        doc = get_object_or_404(self._DOCUMENT_CLS, id=doc_id)
 | 
			
		||||
        return self._MSG_SUCCESS.format(doc.title)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractEditDocumentView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    document_model = None
 | 
			
		||||
    form = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractEditDocumentView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _DOCUMENT_CLS = None
 | 
			
		||||
    _FORM_CLS = EditDocumentModalForm
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    _MSG_SUCCESS = DOCUMENT_EDITED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, doc_id: str):
 | 
			
		||||
        """ GET handling for editing of existing document
 | 
			
		||||
 | 
			
		||||
        Wraps the generic functionality from konova.utils.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The intervention id
 | 
			
		||||
            doc_id (str): The document id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        doc = get_object_or_404(self.document_model, id=doc_id)
 | 
			
		||||
        form = self.form(request.POST or None, request.FILES or None, instance=obj, document=doc,
 | 
			
		||||
                                     request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            DOCUMENT_EDITED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(obj.id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, doc_id: str):
 | 
			
		||||
        return self.get(request, id, doc_id)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return super()._get_redirect_url(*args, **kwargs) + "#related_data"
 | 
			
		||||
@ -10,15 +10,16 @@ from django.http import HttpResponse, HttpRequest
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.template.loader import render_to_string
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.views import View
 | 
			
		||||
 | 
			
		||||
from konova.models import Geometry
 | 
			
		||||
from konova.settings import GEOM_THRESHOLD_RECALCULATION_SECONDS
 | 
			
		||||
from konova.sub_settings.lanis_settings import DEFAULT_SRID_RLP
 | 
			
		||||
from konova.tasks import celery_update_parcels
 | 
			
		||||
from konova.views.base import BaseView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GeomParcelsView(View):
 | 
			
		||||
class GeomParcelsView(BaseView):
 | 
			
		||||
    _TEMPLATE = "konova/includes/parcels/parcel_table_frame.html"
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest, id: str):
 | 
			
		||||
        """ Getter for HTMX
 | 
			
		||||
@ -32,7 +33,6 @@ class GeomParcelsView(View):
 | 
			
		||||
        Returns:
 | 
			
		||||
            A rendered piece of HTML
 | 
			
		||||
        """
 | 
			
		||||
        template = "konova/includes/parcels/parcel_table_frame.html"
 | 
			
		||||
 | 
			
		||||
        geom = get_object_or_404(Geometry, id=id)
 | 
			
		||||
        geos_geom = geom.geom or MultiPolygon(srid=DEFAULT_SRID_RLP)
 | 
			
		||||
@ -85,7 +85,7 @@ class GeomParcelsView(View):
 | 
			
		||||
                "geom_id": str(id),
 | 
			
		||||
                "next_page": next_page,
 | 
			
		||||
            }
 | 
			
		||||
            html = render_to_string(template, context, request)
 | 
			
		||||
            html = render_to_string(self._TEMPLATE, context, request)
 | 
			
		||||
            return HttpResponse(html, status=status_code)
 | 
			
		||||
        else:
 | 
			
		||||
            return HttpResponse(None, status=404)
 | 
			
		||||
@ -107,8 +107,15 @@ class GeomParcelsView(View):
 | 
			
		||||
        waiting_too_long = (pcs_diff >= wait_for_seconds)
 | 
			
		||||
        return waiting_too_long
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
class GeomParcelsContentView(View):
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class GeomParcelsContentView(BaseView):
 | 
			
		||||
    _TEMPLATE = "konova/includes/parcels/parcel_table_content.html"
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest, id: str, page: int):
 | 
			
		||||
        """ Getter for infinite scroll of HTMX
 | 
			
		||||
@ -130,7 +137,6 @@ class GeomParcelsContentView(View):
 | 
			
		||||
        # HTTP code 286 states that the HTMX should stop polling for updates
 | 
			
		||||
        # https://htmx.org/docs/#polling
 | 
			
		||||
        status_code = 286
 | 
			
		||||
        template = "konova/includes/parcels/parcel_table_content.html"
 | 
			
		||||
        geom = get_object_or_404(Geometry, id=id)
 | 
			
		||||
        parcels = geom.get_underlying_parcels()
 | 
			
		||||
 | 
			
		||||
@ -148,5 +154,11 @@ class GeomParcelsContentView(View):
 | 
			
		||||
            "geom_id": str(id),
 | 
			
		||||
            "next_page": next_page,
 | 
			
		||||
        }
 | 
			
		||||
        html = render_to_string(template, context, request)
 | 
			
		||||
        html = render_to_string(self._TEMPLATE, context, request)
 | 
			
		||||
        return HttpResponse(html, status=status_code)
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
@ -9,21 +9,19 @@ from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.db.models import Q
 | 
			
		||||
from django.http import HttpRequest
 | 
			
		||||
from django.shortcuts import render
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from django.views import View
 | 
			
		||||
 | 
			
		||||
from compensation.models import EcoAccount, Compensation
 | 
			
		||||
from intervention.models import Intervention
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import any_group_check
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.views.base import BaseView
 | 
			
		||||
from news.models import ServerMessage
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class HomeView(LoginRequiredMixin, View):
 | 
			
		||||
class HomeView(LoginRequiredMixin, BaseView):
 | 
			
		||||
    _TEMPLATE = "konova/home.html"
 | 
			
		||||
 | 
			
		||||
    @method_decorator(any_group_check)
 | 
			
		||||
    def get(self, request: HttpRequest):
 | 
			
		||||
        """
 | 
			
		||||
        Renders the landing page
 | 
			
		||||
@ -34,7 +32,6 @@ class HomeView(LoginRequiredMixin, View):
 | 
			
		||||
        Returns:
 | 
			
		||||
            A redirect
 | 
			
		||||
        """
 | 
			
		||||
        template = "konova/home.html"
 | 
			
		||||
        user = request.user
 | 
			
		||||
        user_teams = user.shared_teams
 | 
			
		||||
 | 
			
		||||
@ -75,5 +72,12 @@ class HomeView(LoginRequiredMixin, View):
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: _("Home"),
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, additional_context).context
 | 
			
		||||
        return render(request, template, context)
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # No specific permission needed for home view
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # No specific constraint needed for home view
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
@ -6,14 +6,15 @@ Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.shortcuts import get_object_or_404, render
 | 
			
		||||
from django.views import View
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.views.base import BaseView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractLogView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
class AbstractLogView(BaseView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _TEMPLATE = "modal/modal_generic.html"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
@ -28,14 +29,22 @@ class AbstractLogView(View):
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        intervention = get_object_or_404(self.model, id=id)
 | 
			
		||||
        template = "modal/modal_generic.html"
 | 
			
		||||
        intervention = get_object_or_404(self._MODEL_CLS, id=id)
 | 
			
		||||
        body_template = "log.html"
 | 
			
		||||
 | 
			
		||||
        context = {
 | 
			
		||||
            "modal_body_template": body_template,
 | 
			
		||||
            "log": intervention.log.all(),
 | 
			
		||||
            "log": intervention.log.iterator(),
 | 
			
		||||
            "modal_title": _("Log"),
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, template, context)
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        obj_id = kwargs.get('id', None)
 | 
			
		||||
        assert obj_id is not None
 | 
			
		||||
        obj = get_object_or_404(self._MODEL_CLS, id=obj_id)
 | 
			
		||||
        return obj.is_shared_with(user)
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
@ -10,9 +10,8 @@ from json import JSONDecodeError
 | 
			
		||||
 | 
			
		||||
import requests
 | 
			
		||||
import urllib3.util
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.http import JsonResponse, HttpRequest, HttpResponse
 | 
			
		||||
from django.utils.decorators import method_decorator
 | 
			
		||||
from django.utils.http import urlencode
 | 
			
		||||
from django.views import View
 | 
			
		||||
 | 
			
		||||
@ -22,17 +21,13 @@ from konova.sub_settings.lanis_settings import MAP_PROXY_HOST_WHITELIST
 | 
			
		||||
from konova.sub_settings.proxy_settings import PROXIES, GEOPORTAL_RLP_USER, GEOPORTAL_RLP_PASSWORD
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseClientProxyView(View):
 | 
			
		||||
class BaseClientProxyView(LoginRequiredMixin, View):
 | 
			
		||||
    """ Provides proxy functionality for NETGIS map client.
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    @method_decorator(login_required)
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def _check_with_whitelist(self, url):
 | 
			
		||||
        parsed_url = urllib3.util.parse_url(url)
 | 
			
		||||
        parsed_url_host = parsed_url.host
 | 
			
		||||
@ -67,7 +62,6 @@ class BaseClientProxyView(View):
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ClientProxyParcelSearch(BaseClientProxyView):
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest):
 | 
			
		||||
        url = request.META.get("QUERY_STRING")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -5,46 +5,28 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.views import View
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.forms.modals import RecordModalForm
 | 
			
		||||
from konova.utils.message_templates import ENTRY_RECORDED, ENTRY_UNRECORDED
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractRecordView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
class AbstractRecordView(BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = RecordModalForm
 | 
			
		||||
    _MSG_SUCCESS = None
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders a modal form for recording an object
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_ets_user()
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object's id
 | 
			
		||||
    def _get_msg_success(self, *args, **kwargs):
 | 
			
		||||
        obj = kwargs.get("obj")
 | 
			
		||||
        assert obj is not None
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
        if obj.is_recorded:
 | 
			
		||||
            return ENTRY_RECORDED.format(obj.identifier)
 | 
			
		||||
        else:
 | 
			
		||||
            return ENTRY_UNRECORDED.format(obj.identifier)
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        form = RecordModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
        msg_succ = _("{} unrecorded") if obj.recorded else _("{} recorded")
 | 
			
		||||
        msg_succ = msg_succ.format(obj.identifier)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_succ,
 | 
			
		||||
            msg_error=_("Errors found:")
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        BaseModalForm provides the method process_request() which handles GET as well as POST requests. It was written
 | 
			
		||||
        for easier handling of function based views. To support process_request() on class based views, the post()
 | 
			
		||||
        call needs to be treated the same way as the get() call.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): Intervention's id
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
    def _check_for_recorded_instance(self, obj):
 | 
			
		||||
        # Do not block record view if instance might be recorded
 | 
			
		||||
        return None
 | 
			
		||||
							
								
								
									
										28
									
								
								konova/views/remove.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								konova/views/remove.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Created on: 21.10.25
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
 | 
			
		||||
from konova.forms.modals import RemoveModalForm
 | 
			
		||||
from konova.utils.message_templates import GENERIC_REMOVED_TEMPLATE
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseRemoveModalFormView(BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = RemoveModalForm
 | 
			
		||||
    _MSG_SUCCESS = GENERIC_REMOVED_TEMPLATE
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        return reverse(self._REDIRECT_URL)
 | 
			
		||||
 | 
			
		||||
    def _get_msg_success(self, *args, **kwargs):
 | 
			
		||||
        obj = kwargs.get("obj", None)
 | 
			
		||||
        assert obj is not None
 | 
			
		||||
        return self._MSG_SUCCESS.format(obj.identifier)
 | 
			
		||||
							
								
								
									
										106
									
								
								konova/views/report.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								konova/views/report.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,106 @@
 | 
			
		||||
"""
 | 
			
		||||
Author: Michel Peltriaux
 | 
			
		||||
Created on: 17.10.25
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from abc import abstractmethod
 | 
			
		||||
from uuid import UUID
 | 
			
		||||
 | 
			
		||||
from django.http import HttpRequest, Http404
 | 
			
		||||
from django.shortcuts import get_object_or_404, render
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.forms import SimpleGeomForm
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.views.base import BaseView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class BaseReportView(BaseView):
 | 
			
		||||
    _TEMPLATE = None
 | 
			
		||||
    _TAB_TITLE = _("Report {}")
 | 
			
		||||
    _MODEL = None
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def dispatch(self, request, *args, **kwargs):
 | 
			
		||||
        # If the given id is not a uuid we act as the result was not found
 | 
			
		||||
        try:
 | 
			
		||||
            UUID(kwargs.get('id'))
 | 
			
		||||
        except ValueError:
 | 
			
		||||
            raise Http404()
 | 
			
		||||
        return super().dispatch(request, *args, **kwargs)
 | 
			
		||||
 | 
			
		||||
    def _return_unpublishable_content_response(self, request: HttpRequest, tab_title: str):
 | 
			
		||||
        """ Handles HttpResponse return in case the object is not ready for publish
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request ():
 | 
			
		||||
            tab_title ():
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        template = "report/unavailable.html"
 | 
			
		||||
        context = {
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, template, context)
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest, id: str):
 | 
			
		||||
        """ Renders the public report view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The id of the intervention
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self._MODEL, id=id)
 | 
			
		||||
        tab_title = self._TAB_TITLE.format(obj.identifier)
 | 
			
		||||
 | 
			
		||||
        # If object is not recorded we need to render another template without any data
 | 
			
		||||
        if not obj.is_ready_for_publish():
 | 
			
		||||
            return self._return_unpublishable_content_response(request, tab_title)
 | 
			
		||||
 | 
			
		||||
        # First get specific report context for different types of objects due to inheritance
 | 
			
		||||
        report_context = self._get_report_context(obj)
 | 
			
		||||
 | 
			
		||||
        # Then generate and add default report context (the same for all models)
 | 
			
		||||
        geom_form = SimpleGeomForm(instance=obj)
 | 
			
		||||
        parcels = obj.get_underlying_parcels()
 | 
			
		||||
        report_context.update(
 | 
			
		||||
            {
 | 
			
		||||
                TAB_TITLE_IDENTIFIER: tab_title,
 | 
			
		||||
                "parcels": parcels,
 | 
			
		||||
                "geom_form": geom_form,
 | 
			
		||||
                "obj": obj
 | 
			
		||||
            }
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        # Then generate the general context based on the report specific data
 | 
			
		||||
        context = BaseContext(request, report_context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    @abstractmethod
 | 
			
		||||
    def _get_report_context(self, obj):
 | 
			
		||||
        """ Returns the specific context needed for this report view
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            obj (RecordableObjectMixin): The object for the report
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
            dict: The object specific context for rendering the report
 | 
			
		||||
        """
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # Reports do not need specific permissions to be callable
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # Reports do not need specific share states to be callable
 | 
			
		||||
        return True
 | 
			
		||||
@ -5,51 +5,24 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 19.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.views import View
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
 | 
			
		||||
from konova.forms.modals import ResubmissionModalForm
 | 
			
		||||
from konova.utils.message_templates import NEW_RESUBMISSION_CREATED
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractResubmissionView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    form_action_url_base = None
 | 
			
		||||
    redirect_url_base = None
 | 
			
		||||
class AbstractResubmissionView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = None
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    _MSG_SUCCESS = NEW_RESUBMISSION_CREATED
 | 
			
		||||
    
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
    
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders resubmission form for an object
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): Object's id
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        form = ResubmissionModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
        form.action_url = reverse(self.form_action_url_base, args=(id,))
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=_("Resubmission set"),
 | 
			
		||||
            redirect_url=reverse(self.redirect_url_base, args=(id,))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        """
 | 
			
		||||
 | 
			
		||||
        BaseModalForm provides the method process_request() which handles GET as well as POST requests. It was written
 | 
			
		||||
        for easier handling of function based views. To support process_request() on class based views, the post()
 | 
			
		||||
        call needs to be treated the same way as the get() call.
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): Intervention's id
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
    def _check_for_recorded_instance(self, obj):
 | 
			
		||||
        # Resubmissions are allowed despite an entry being recorded
 | 
			
		||||
        return None
 | 
			
		||||
@ -6,24 +6,24 @@ Created on: 22.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.shortcuts import get_object_or_404, redirect
 | 
			
		||||
from django.views import View
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from intervention.forms.modals.share import ShareModalForm
 | 
			
		||||
from konova.utils.message_templates import DATA_SHARE_SET
 | 
			
		||||
from konova.views.base import BaseView, BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractShareByTokenView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractShareByTokenView(LoginRequiredMixin, BaseView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, token: str):
 | 
			
		||||
 | 
			
		||||
        """ Performs sharing of an intervention
 | 
			
		||||
        """ Performs sharing of an entry
 | 
			
		||||
 | 
			
		||||
        If token given in url is not valid, the user will be redirected to the dashboard
 | 
			
		||||
 | 
			
		||||
@ -36,7 +36,7 @@ class AbstractShareByTokenView(View):
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        user = request.user
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        obj = get_object_or_404(self._MODEL_CLS, id=id)
 | 
			
		||||
        # Check tokens
 | 
			
		||||
        if obj.access_token == token:
 | 
			
		||||
            # Send different messages in case user has already been added to list of sharing users
 | 
			
		||||
@ -51,7 +51,7 @@ class AbstractShareByTokenView(View):
 | 
			
		||||
                    _("{} has been shared with you").format(obj.identifier)
 | 
			
		||||
                )
 | 
			
		||||
                obj.share_with_user(user)
 | 
			
		||||
            return redirect(self.redirect_url, id=id)
 | 
			
		||||
            return redirect(self._REDIRECT_URL, id=id)
 | 
			
		||||
        else:
 | 
			
		||||
            messages.error(
 | 
			
		||||
                request,
 | 
			
		||||
@ -60,29 +60,22 @@ class AbstractShareByTokenView(View):
 | 
			
		||||
            )
 | 
			
		||||
            return redirect("home")
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # No permissions are needed to get shared access via token
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
class AbstractShareFormView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # The user does not need to have shared access to call the endpoint which gives them shared access
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractShareFormView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = ShareModalForm
 | 
			
		||||
    _MSG_SUCCESS = DATA_SHARE_SET
 | 
			
		||||
    
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
        
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders sharing form 
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): Object's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        form = ShareModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=DATA_SHARE_SET
 | 
			
		||||
        )
 | 
			
		||||
    
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
@ -5,103 +5,53 @@ Contact: ksp-servicestelle@sgdnord.rlp.de
 | 
			
		||||
Created on: 22.08.22
 | 
			
		||||
 | 
			
		||||
"""
 | 
			
		||||
from django.shortcuts import get_object_or_404
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
from django.views import View
 | 
			
		||||
 | 
			
		||||
from compensation.forms.modals.state import NewCompensationStateModalForm, EditCompensationStateModalForm, \
 | 
			
		||||
    RemoveCompensationStateModalForm
 | 
			
		||||
from compensation.models import CompensationState
 | 
			
		||||
from konova.utils.message_templates import COMPENSATION_STATE_ADDED, COMPENSATION_STATE_EDITED, \
 | 
			
		||||
    COMPENSATION_STATE_REMOVED
 | 
			
		||||
from konova.views.base import BaseModalFormView
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class AbstractCompensationStateView(View):
 | 
			
		||||
    model = None
 | 
			
		||||
    redirect_url = None
 | 
			
		||||
class AbstractCompensationStateView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = None
 | 
			
		||||
    _REDIRECT_URL = None
 | 
			
		||||
    
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return user.is_default_user()
 | 
			
		||||
 | 
			
		||||
    def _get_redirect_url(self, *args, **kwargs):
 | 
			
		||||
        obj = kwargs.get("obj", None)
 | 
			
		||||
        assert obj is not None
 | 
			
		||||
        return reverse(self._REDIRECT_URL, args=(obj.id,)) + "#related_data"
 | 
			
		||||
 | 
			
		||||
class AbstractNewCompensationStateView(AbstractCompensationStateView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = NewCompensationStateModalForm
 | 
			
		||||
    _MSG_SUCCESS = COMPENSATION_STATE_ADDED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str):
 | 
			
		||||
        """ Renders a form for adding new states 
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object's id to which the new state will be related
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        form = NewCompensationStateModalForm(request.POST or None, instance=obj, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=COMPENSATION_STATE_ADDED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str):
 | 
			
		||||
        return self.get(request, id)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
class AbstractEditCompensationStateView(AbstractCompensationStateView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = EditCompensationStateModalForm
 | 
			
		||||
    _MSG_SUCCESS = COMPENSATION_STATE_EDITED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, state_id: str):
 | 
			
		||||
        """ Renders a form for editing a state
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object id
 | 
			
		||||
            state_id (str): The state's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        state = get_object_or_404(CompensationState, id=state_id)
 | 
			
		||||
        form = EditCompensationStateModalForm(request.POST or None, instance=obj, state=state, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=COMPENSATION_STATE_EDITED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, state_id: str):
 | 
			
		||||
        return self.get(request, id, state_id)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
class AbstractRemoveCompensationStateView(AbstractCompensationStateView):
 | 
			
		||||
    _MODEL_CLS = None
 | 
			
		||||
    _FORM_CLS = RemoveCompensationStateModalForm
 | 
			
		||||
    _MSG_SUCCESS = COMPENSATION_STATE_REMOVED
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        abstract = True
 | 
			
		||||
 | 
			
		||||
    def get(self, request, id: str, state_id: str):
 | 
			
		||||
        """ Renders a form for removing astate
 | 
			
		||||
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The object id
 | 
			
		||||
            state_id (str): The state's id
 | 
			
		||||
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
        """
 | 
			
		||||
        obj = get_object_or_404(self.model, id=id)
 | 
			
		||||
        state = get_object_or_404(CompensationState, id=state_id)
 | 
			
		||||
        form = RemoveCompensationStateModalForm(request.POST or None, instance=obj, state=state, request=request)
 | 
			
		||||
        return form.process_request(
 | 
			
		||||
            request,
 | 
			
		||||
            msg_success=COMPENSATION_STATE_REMOVED,
 | 
			
		||||
            redirect_url=reverse(self.redirect_url, args=(id,)) + "#related_data"
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def post(self, request, id: str, state_id: str):
 | 
			
		||||
        return self.get(request, id, state_id)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@ -45,7 +45,7 @@ msgid ""
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Project-Id-Version: PACKAGE VERSION\n"
 | 
			
		||||
"Report-Msgid-Bugs-To: \n"
 | 
			
		||||
"POT-Creation-Date: 2025-10-15 09:11+0200\n"
 | 
			
		||||
"POT-Creation-Date: 2025-10-19 13:56+0200\n"
 | 
			
		||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 | 
			
		||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 | 
			
		||||
"Language-Team: LANGUAGE <LL@li.org>\n"
 | 
			
		||||
@ -448,11 +448,19 @@ msgid "Select the intervention for which this compensation compensates"
 | 
			
		||||
msgstr "Wählen Sie den Eingriff, für den diese Kompensation bestimmt ist"
 | 
			
		||||
 | 
			
		||||
#: compensation/forms/compensation.py:114
 | 
			
		||||
#: compensation/views/compensation/compensation.py:120
 | 
			
		||||
#: compensation/views/compensation/compensation.py:161
 | 
			
		||||
msgid "New compensation"
 | 
			
		||||
msgstr "Neue Kompensation"
 | 
			
		||||
 | 
			
		||||
#: compensation/forms/compensation.py:190
 | 
			
		||||
#: compensation/forms/compensation.py:179
 | 
			
		||||
msgid ""
 | 
			
		||||
"This intervention is currently recorded. You cannot add further "
 | 
			
		||||
"compensations as long as it is recorded."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Dieser Eingriff ist derzeit verzeichnet. "
 | 
			
		||||
"Sie können keine weiteren Kompensationen hinzufügen, so lange er verzeichnet ist."
 | 
			
		||||
 | 
			
		||||
#: compensation/forms/compensation.py:202
 | 
			
		||||
msgid "Edit compensation"
 | 
			
		||||
msgstr "Bearbeite Kompensation"
 | 
			
		||||
 | 
			
		||||
@ -475,7 +483,7 @@ msgid "When did the parties agree on this?"
 | 
			
		||||
msgstr "Wann wurde dieses Ökokonto offiziell vereinbart?"
 | 
			
		||||
 | 
			
		||||
#: compensation/forms/eco_account.py:72
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:101
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:93
 | 
			
		||||
msgid "New Eco-Account"
 | 
			
		||||
msgstr "Neues Ökokonto"
 | 
			
		||||
 | 
			
		||||
@ -1288,44 +1296,45 @@ msgstr ""
 | 
			
		||||
msgid "Responsible data"
 | 
			
		||||
msgstr "Daten zu den verantwortlichen Stellen"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/compensation/compensation.py:58
 | 
			
		||||
#: compensation/views/compensation/compensation.py:35
 | 
			
		||||
msgid "Compensations - Overview"
 | 
			
		||||
msgstr "Kompensationen - Übersicht"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/compensation/compensation.py:181
 | 
			
		||||
#: compensation/views/compensation/compensation.py:52
 | 
			
		||||
#, fuzzy
 | 
			
		||||
#| msgid "New compensation"
 | 
			
		||||
msgid "New Compensation"
 | 
			
		||||
msgstr "Neue Kompensation"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/compensation/compensation.py:208
 | 
			
		||||
#: konova/utils/message_templates.py:40
 | 
			
		||||
msgid "Compensation {} edited"
 | 
			
		||||
msgstr "Kompensation {} bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/compensation/compensation.py:196
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:173 ema/views/ema.py:238
 | 
			
		||||
#: intervention/views/intervention.py:253
 | 
			
		||||
#: compensation/views/compensation/compensation.py:231
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:159 ema/views/ema.py:59
 | 
			
		||||
#: intervention/views/intervention.py:59 intervention/views/intervention.py:179
 | 
			
		||||
#: konova/views/base.py:239
 | 
			
		||||
msgid "Edit {}"
 | 
			
		||||
msgstr "Bearbeite {}"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/compensation/report.py:35
 | 
			
		||||
#: compensation/views/eco_account/report.py:36 ema/views/report.py:35
 | 
			
		||||
#: intervention/views/report.py:35
 | 
			
		||||
msgid "Report {}"
 | 
			
		||||
msgstr "Bericht {}"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:53
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:32
 | 
			
		||||
msgid "Eco-account - Overview"
 | 
			
		||||
msgstr "Ökokonten - Übersicht"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:86
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:70
 | 
			
		||||
msgid "Eco-Account {} added"
 | 
			
		||||
msgstr "Ökokonto {} hinzugefügt"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:158
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:136
 | 
			
		||||
msgid "Eco-Account {} edited"
 | 
			
		||||
msgstr "Ökokonto {} bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:288
 | 
			
		||||
#: compensation/views/eco_account/eco_account.py:260
 | 
			
		||||
msgid "Eco-account removed"
 | 
			
		||||
msgstr "Ökokonto entfernt"
 | 
			
		||||
 | 
			
		||||
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:108
 | 
			
		||||
#: ema/forms.py:42 ema/tests/unit/test_forms.py:27 ema/views/ema.py:42
 | 
			
		||||
msgid "New EMA"
 | 
			
		||||
msgstr "Neue EMA hinzufügen"
 | 
			
		||||
 | 
			
		||||
@ -1353,19 +1362,11 @@ msgstr ""
 | 
			
		||||
msgid "Payment funded compensation"
 | 
			
		||||
msgstr "Ersatzzahlungsmaßnahme"
 | 
			
		||||
 | 
			
		||||
#: ema/views/ema.py:53
 | 
			
		||||
#: ema/views/ema.py:26
 | 
			
		||||
msgid "EMAs - Overview"
 | 
			
		||||
msgstr "EMAs - Übersicht"
 | 
			
		||||
 | 
			
		||||
#: ema/views/ema.py:86
 | 
			
		||||
msgid "EMA {} added"
 | 
			
		||||
msgstr "EMA {} hinzugefügt"
 | 
			
		||||
 | 
			
		||||
#: ema/views/ema.py:223
 | 
			
		||||
msgid "EMA {} edited"
 | 
			
		||||
msgstr "EMA {} bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: ema/views/ema.py:262
 | 
			
		||||
#: ema/views/ema.py:138
 | 
			
		||||
msgid "EMA removed"
 | 
			
		||||
msgstr "EMA entfernt"
 | 
			
		||||
 | 
			
		||||
@ -1429,7 +1430,7 @@ msgstr "Datum Bestandskraft bzw. Rechtskraft"
 | 
			
		||||
 | 
			
		||||
#: intervention/forms/intervention.py:216
 | 
			
		||||
#: intervention/tests/unit/test_forms.py:36
 | 
			
		||||
#: intervention/views/intervention.py:105
 | 
			
		||||
#: intervention/views/intervention.py:51
 | 
			
		||||
msgid "New intervention"
 | 
			
		||||
msgstr "Neuer Eingriff"
 | 
			
		||||
 | 
			
		||||
@ -1665,19 +1666,15 @@ msgstr ""
 | 
			
		||||
msgid "Check performed"
 | 
			
		||||
msgstr "Prüfung durchgeführt"
 | 
			
		||||
 | 
			
		||||
#: intervention/views/intervention.py:57
 | 
			
		||||
#: intervention/views/intervention.py:33
 | 
			
		||||
msgid "Interventions - Overview"
 | 
			
		||||
msgstr "Eingriffe - Übersicht"
 | 
			
		||||
 | 
			
		||||
#: intervention/views/intervention.py:90
 | 
			
		||||
msgid "Intervention {} added"
 | 
			
		||||
msgstr "Eingriff {} hinzugefügt"
 | 
			
		||||
 | 
			
		||||
#: intervention/views/intervention.py:236
 | 
			
		||||
#: intervention/views/intervention.py:154
 | 
			
		||||
msgid "Intervention {} edited"
 | 
			
		||||
msgstr "Eingriff {} bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: intervention/views/intervention.py:278
 | 
			
		||||
#: intervention/views/intervention.py:204
 | 
			
		||||
msgid "{} removed"
 | 
			
		||||
msgstr "{} entfernt"
 | 
			
		||||
 | 
			
		||||
@ -1689,7 +1686,7 @@ msgstr "Hierfür müssen Sie Mitarbeiter sein!"
 | 
			
		||||
msgid "You need to be administrator to perform this action!"
 | 
			
		||||
msgstr "Hierfür müssen Sie Administrator sein!"
 | 
			
		||||
 | 
			
		||||
#: konova/decorators.py:65
 | 
			
		||||
#: konova/decorators.py:65 konova/utils/general.py:40
 | 
			
		||||
msgid ""
 | 
			
		||||
"+++ Attention: You are not part of any group. You won't be able to create, "
 | 
			
		||||
"edit or do anything. Please contact an administrator. +++"
 | 
			
		||||
@ -1801,7 +1798,7 @@ msgstr "Sucht nach Einträgen, an denen diese Person gearbeitet hat"
 | 
			
		||||
msgid "Save"
 | 
			
		||||
msgstr "Speichern"
 | 
			
		||||
 | 
			
		||||
#: konova/forms/base_form.py:72
 | 
			
		||||
#: konova/forms/base_form.py:74
 | 
			
		||||
msgid "Not editable"
 | 
			
		||||
msgstr "Nicht editierbar"
 | 
			
		||||
 | 
			
		||||
@ -1810,7 +1807,7 @@ msgstr "Nicht editierbar"
 | 
			
		||||
msgid "Geometry"
 | 
			
		||||
msgstr "Geometrie"
 | 
			
		||||
 | 
			
		||||
#: konova/forms/geometry_form.py:100
 | 
			
		||||
#: konova/forms/geometry_form.py:101
 | 
			
		||||
msgid "Only surfaces allowed. Points or lines must be buffered."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Nur Flächen erlaubt. Punkte oder Linien müssen zu Flächen gepuffert werden."
 | 
			
		||||
@ -2268,8 +2265,9 @@ msgid ""
 | 
			
		||||
"too small to be valid). These parts have been removed. Please check the "
 | 
			
		||||
"stored geometry."
 | 
			
		||||
msgstr ""
 | 
			
		||||
"Die Geometrie enthielt {} invalide Bestandteile (z.B. unaussagekräftige Kleinstflächen)."
 | 
			
		||||
"Diese Bestandteile wurden automatisch entfernt. Bitte überprüfen Sie die angepasste Geometrie."
 | 
			
		||||
"Die Geometrie enthielt {} invalide Bestandteile (z.B. unaussagekräftige "
 | 
			
		||||
"Kleinstflächen).Diese Bestandteile wurden automatisch entfernt. Bitte "
 | 
			
		||||
"überprüfen Sie die angepasste Geometrie."
 | 
			
		||||
 | 
			
		||||
#: konova/utils/message_templates.py:89
 | 
			
		||||
msgid "This intervention has {} revocations"
 | 
			
		||||
@ -2310,7 +2308,15 @@ msgstr ""
 | 
			
		||||
"Dieses Datum ist unrealistisch. Geben Sie bitte das korrekte Datum ein "
 | 
			
		||||
"(>1950)."
 | 
			
		||||
 | 
			
		||||
#: konova/views/home.py:75 templates/navbars/navbar.html:16
 | 
			
		||||
#: konova/views/base.py:209
 | 
			
		||||
msgid "{} added"
 | 
			
		||||
msgstr "{} hinzugefügt"
 | 
			
		||||
 | 
			
		||||
#: konova/views/base.py:281
 | 
			
		||||
msgid "{} edited"
 | 
			
		||||
msgstr "{} bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: konova/views/home.py:72 templates/navbars/navbar.html:16
 | 
			
		||||
msgid "Home"
 | 
			
		||||
msgstr "Home"
 | 
			
		||||
 | 
			
		||||
@ -2330,6 +2336,10 @@ msgstr "{} verzeichnet"
 | 
			
		||||
msgid "Errors found:"
 | 
			
		||||
msgstr "Fehler gefunden:"
 | 
			
		||||
 | 
			
		||||
#: konova/views/report.py:21
 | 
			
		||||
msgid "Report {}"
 | 
			
		||||
msgstr "Bericht {}"
 | 
			
		||||
 | 
			
		||||
#: konova/views/resubmission.py:39
 | 
			
		||||
msgid "Resubmission set"
 | 
			
		||||
msgstr "Wiedervorlage gesetzt"
 | 
			
		||||
@ -3056,7 +3066,7 @@ msgid "Manage teams"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
#: user/templates/user/index.html:53 user/templates/user/team/index.html:19
 | 
			
		||||
#: user/views/views.py:135
 | 
			
		||||
#: user/views/views.py:134
 | 
			
		||||
msgid "Teams"
 | 
			
		||||
msgstr ""
 | 
			
		||||
 | 
			
		||||
@ -3116,34 +3126,40 @@ msgstr "Läuft ab am"
 | 
			
		||||
msgid "User API token"
 | 
			
		||||
msgstr "API Nutzer Token"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:33
 | 
			
		||||
#: user/views/views.py:31
 | 
			
		||||
msgid "User settings"
 | 
			
		||||
msgstr "Einstellungen"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:59
 | 
			
		||||
msgid "Notifications edited"
 | 
			
		||||
msgstr "Benachrichtigungen bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:71
 | 
			
		||||
#: user/views/views.py:44
 | 
			
		||||
msgid "User notifications"
 | 
			
		||||
msgstr "Benachrichtigungen"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:147
 | 
			
		||||
#: user/views/views.py:64
 | 
			
		||||
msgid "Notifications edited"
 | 
			
		||||
msgstr "Benachrichtigungen bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:152
 | 
			
		||||
msgid "New team added"
 | 
			
		||||
msgstr "Neues Team hinzugefügt"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:162
 | 
			
		||||
#: user/views/views.py:167
 | 
			
		||||
msgid "Team edited"
 | 
			
		||||
msgstr "Team bearbeitet"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:177
 | 
			
		||||
#: user/views/views.py:182
 | 
			
		||||
msgid "Team removed"
 | 
			
		||||
msgstr "Team gelöscht"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:192
 | 
			
		||||
#: user/views/views.py:197
 | 
			
		||||
msgid "You are not a member of this team"
 | 
			
		||||
msgstr "Sie sind kein Mitglied dieses Teams"
 | 
			
		||||
 | 
			
		||||
#: user/views/views.py:199
 | 
			
		||||
#: user/views/views.py:204
 | 
			
		||||
msgid "Left Team"
 | 
			
		||||
msgstr "Team verlassen"
 | 
			
		||||
 | 
			
		||||
#~ msgid "EMA {} added"
 | 
			
		||||
#~ msgstr "EMA {} hinzugefügt"
 | 
			
		||||
 | 
			
		||||
#~ msgid "EMA {} edited"
 | 
			
		||||
#~ msgstr "EMA {} bearbeitet"
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,7 @@
 | 
			
		||||
                    {% if user.is_staff or user.is_superuser %}
 | 
			
		||||
                    <a class="dropdown-item" target="_blank" href="{% url 'admin:index' %}">{% fa5_icon 'tools' %}  {% trans 'Admin' %}</a>
 | 
			
		||||
                    {% endif %}
 | 
			
		||||
                    <a class="dropdown-item" href="{% url 'user:index' %}">{% fa5_icon 'cogs' %}  {% trans 'Settings' %}</a>
 | 
			
		||||
                    <a class="dropdown-item" href="{% url 'user:detail' %}">{% fa5_icon 'cogs' %}  {% trans 'Settings' %}</a>
 | 
			
		||||
                    <a class="dropdown-item" href="{% url 'logout' %}">{% fa5_icon 'sign-out-alt' %}  {% trans 'Logout' %}</a>
 | 
			
		||||
                </div>
 | 
			
		||||
            </li>
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ class UserNotificationForm(BaseForm):
 | 
			
		||||
        self.form_title = _("Edit notifications")
 | 
			
		||||
        self.form_caption = _("")
 | 
			
		||||
        self.action_url = reverse("user:notifications")
 | 
			
		||||
        self.cancel_redirect = reverse("user:index")
 | 
			
		||||
        self.cancel_redirect = reverse("user:detail")
 | 
			
		||||
 | 
			
		||||
        # Insert all notifications into form field by creating choices as tuples
 | 
			
		||||
        notifications = UserNotification.objects.filter(
 | 
			
		||||
 | 
			
		||||
@ -26,7 +26,7 @@ class UserViewTestCase(BaseViewTestCase):
 | 
			
		||||
        self.team.users.add(self.superuser)
 | 
			
		||||
        self.team.admins.add(self.superuser)
 | 
			
		||||
        # Prepare urls
 | 
			
		||||
        self.index_url = reverse("user:index", args=())
 | 
			
		||||
        self.index_url = reverse("user:detail", args=())
 | 
			
		||||
        self.notification_url = reverse("user:notifications", args=())
 | 
			
		||||
        self.api_token_url = reverse("user:api-token", args=())
 | 
			
		||||
        self.contact_url = reverse("user:contact", args=(self.superuser.id,))
 | 
			
		||||
 | 
			
		||||
@ -233,7 +233,7 @@ class UserNotificationFormTestCase(BaseTestCase):
 | 
			
		||||
        self.assertEqual(form.form_title, str(_("Edit notifications")))
 | 
			
		||||
        self.assertEqual(form.form_caption, "")
 | 
			
		||||
        self.assertEqual(form.action_url, reverse("user:notifications"))
 | 
			
		||||
        self.assertEqual(form.cancel_redirect, reverse("user:index"))
 | 
			
		||||
        self.assertEqual(form.cancel_redirect, reverse("user:detail"))
 | 
			
		||||
 | 
			
		||||
    def test_save(self):
 | 
			
		||||
        selected_notification = UserNotification.objects.first()
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										10
									
								
								user/urls.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								user/urls.py
									
									
									
									
									
								
							@ -15,15 +15,15 @@ from user.views.views import *
 | 
			
		||||
 | 
			
		||||
app_name = "user"
 | 
			
		||||
urlpatterns = [
 | 
			
		||||
    path("", index_view, name="index"),
 | 
			
		||||
    path("", UserDetailView.as_view(), name="detail"),
 | 
			
		||||
    path("propagate/", PropagateUserView.as_view(), name="propagate"),
 | 
			
		||||
    path("notifications/", notifications_view, name="notifications"),
 | 
			
		||||
    path("notifications/", NotificationsView.as_view(), name="notifications"),
 | 
			
		||||
    path("token/api", APITokenView.as_view(), name="api-token"),
 | 
			
		||||
    path("token/api/new", new_api_token_view, name="api-token-new"),
 | 
			
		||||
    path("contact/<id>", contact_view, name="contact"),
 | 
			
		||||
    path("team/", index_team_view, name="team-index"),
 | 
			
		||||
    path("contact/<id>", ContactView.as_view(), name="contact"),
 | 
			
		||||
    path("team/", TeamIndexView.as_view(), name="team-index"),
 | 
			
		||||
    path("team/new", new_team_view, name="team-new"),
 | 
			
		||||
    path("team/<id>", data_team_view, name="team-data"),
 | 
			
		||||
    path("team/<id>", TeamDetailModalView.as_view(), name="team-data"),
 | 
			
		||||
    path("team/<id>/edit", edit_team_view, name="team-edit"),
 | 
			
		||||
    path("team/<id>/remove", remove_team_view, name="team-remove"),
 | 
			
		||||
    path("team/<id>/leave", leave_team_view, name="team-leave"),
 | 
			
		||||
 | 
			
		||||
@ -1,8 +1,10 @@
 | 
			
		||||
from django.contrib import messages
 | 
			
		||||
from django.contrib.auth.decorators import login_required
 | 
			
		||||
from django.contrib.auth.mixins import LoginRequiredMixin
 | 
			
		||||
from django.urls import reverse
 | 
			
		||||
 | 
			
		||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
 | 
			
		||||
from konova.views.base import BaseView, BaseModalFormView
 | 
			
		||||
from user.forms.modals.team import NewTeamModalForm, EditTeamModalForm, RemoveTeamModalForm, LeaveTeamModalForm
 | 
			
		||||
from user.forms.modals.user import UserContactForm
 | 
			
		||||
from user.forms.team import TeamDataForm
 | 
			
		||||
@ -13,129 +15,132 @@ from django.shortcuts import render, redirect, get_object_or_404
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
 | 
			
		||||
from konova.contexts import BaseContext
 | 
			
		||||
from konova.decorators import any_group_check, login_required_modal
 | 
			
		||||
from konova.decorators import login_required_modal
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def index_view(request: HttpRequest):
 | 
			
		||||
    """ Renders the user's data index view
 | 
			
		||||
class UserBaseView(BaseView):
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request ():
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "user/index.html"
 | 
			
		||||
    context = {
 | 
			
		||||
        "user": request.user,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("User settings"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
@any_group_check
 | 
			
		||||
def notifications_view(request: HttpRequest):
 | 
			
		||||
    """ Renders the notifications settings view
 | 
			
		||||
class UserDetailView(LoginRequiredMixin, UserBaseView):
 | 
			
		||||
    _TEMPLATE = "user/index.html"
 | 
			
		||||
    _TAB_TITLE = _("User settings")
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request ():
 | 
			
		||||
    def get(self, request: HttpRequest):
 | 
			
		||||
        context = {
 | 
			
		||||
            "user": request.user,
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    template = "user/notifications.html"
 | 
			
		||||
    user = request.user
 | 
			
		||||
class NotificationsView(LoginRequiredMixin, UserBaseView):
 | 
			
		||||
    _TEMPLATE = "user/notifications.html"
 | 
			
		||||
    _TAB_TITLE = _("User notifications")
 | 
			
		||||
 | 
			
		||||
    form = UserNotificationForm(user=user, data=request.POST or None)
 | 
			
		||||
    if request.method == "POST":
 | 
			
		||||
    def get(self, request: HttpRequest):
 | 
			
		||||
        user = request.user
 | 
			
		||||
        form = UserNotificationForm(user=user, data=None)
 | 
			
		||||
        context = {
 | 
			
		||||
            "user": user,
 | 
			
		||||
            "form": form,
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def post(self, request: HttpRequest):
 | 
			
		||||
        user = request.user
 | 
			
		||||
        form = UserNotificationForm(user=user, data=request.POST)
 | 
			
		||||
        if form.is_valid():
 | 
			
		||||
            form.save()
 | 
			
		||||
            messages.success(
 | 
			
		||||
                request,
 | 
			
		||||
                _("Notifications edited")
 | 
			
		||||
            )
 | 
			
		||||
            return redirect("user:index")
 | 
			
		||||
    elif request.method == "GET":
 | 
			
		||||
        # Implicit
 | 
			
		||||
        pass
 | 
			
		||||
    else:
 | 
			
		||||
        raise NotImplementedError
 | 
			
		||||
 | 
			
		||||
    context = {
 | 
			
		||||
        "user": user,
 | 
			
		||||
        "form": form,
 | 
			
		||||
        TAB_TITLE_IDENTIFIER: _("User notifications"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
            return redirect("user:detail")
 | 
			
		||||
        context = {
 | 
			
		||||
            "user": user,
 | 
			
		||||
            "form": form,
 | 
			
		||||
            TAB_TITLE_IDENTIFIER: self._TAB_TITLE,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required_modal
 | 
			
		||||
@login_required
 | 
			
		||||
def contact_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders contact modal view of a users contact data
 | 
			
		||||
class ContactView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    def get(self, request: HttpRequest, id: str):
 | 
			
		||||
        """ Renders contact modal view of a users contact data
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The user's id
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The user's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    user = get_object_or_404(User, id=id)
 | 
			
		||||
    form = UserContactForm(request.POST or None, instance=user, request=request)
 | 
			
		||||
    template = "modal/modal_form.html"
 | 
			
		||||
    context = {
 | 
			
		||||
        "form": form,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(
 | 
			
		||||
        request,
 | 
			
		||||
        template,
 | 
			
		||||
        context
 | 
			
		||||
    )
 | 
			
		||||
        """
 | 
			
		||||
        user = get_object_or_404(User, id=id)
 | 
			
		||||
        form = UserContactForm(request.POST or None, instance=user, request=request)
 | 
			
		||||
        context = {
 | 
			
		||||
            "form": form,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # No specific constraints
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # No specific constraints
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required_modal
 | 
			
		||||
@login_required
 | 
			
		||||
def data_team_view(request: HttpRequest, id: str):
 | 
			
		||||
    """ Renders team data
 | 
			
		||||
class TeamDetailModalView(LoginRequiredMixin, BaseModalFormView):
 | 
			
		||||
    def get(self, request: HttpRequest, id: str):
 | 
			
		||||
        """ Renders team data
 | 
			
		||||
 | 
			
		||||
    Args:
 | 
			
		||||
        request (HttpRequest): The incoming request
 | 
			
		||||
        id (str): The team's id
 | 
			
		||||
        Args:
 | 
			
		||||
            request (HttpRequest): The incoming request
 | 
			
		||||
            id (str): The team's id
 | 
			
		||||
 | 
			
		||||
    Returns:
 | 
			
		||||
        Returns:
 | 
			
		||||
 | 
			
		||||
    """
 | 
			
		||||
    team = get_object_or_404(Team, id=id)
 | 
			
		||||
    form = TeamDataForm(request.POST or None, instance=team, request=request)
 | 
			
		||||
    template = "modal/modal_form.html"
 | 
			
		||||
    context = {
 | 
			
		||||
        "form": form,
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(
 | 
			
		||||
        request,
 | 
			
		||||
        template,
 | 
			
		||||
        context
 | 
			
		||||
    )
 | 
			
		||||
        """
 | 
			
		||||
        team = get_object_or_404(Team, id=id)
 | 
			
		||||
        form = TeamDataForm(request.POST or None, instance=team, request=request)
 | 
			
		||||
        context = {
 | 
			
		||||
            "form": form,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
    def _user_has_shared_access(self, user, **kwargs):
 | 
			
		||||
        # No specific constraints
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
    def _user_has_permission(self, user):
 | 
			
		||||
        # No specific constraints
 | 
			
		||||
        return True
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required
 | 
			
		||||
def index_team_view(request: HttpRequest):
 | 
			
		||||
    template = "user/team/index.html"
 | 
			
		||||
    user = request.user
 | 
			
		||||
    context = {
 | 
			
		||||
        "teams": user.shared_teams,
 | 
			
		||||
        "tab_title": _("Teams"),
 | 
			
		||||
    }
 | 
			
		||||
    context = BaseContext(request, context).context
 | 
			
		||||
    return render(request, template, context)
 | 
			
		||||
class TeamIndexView(LoginRequiredMixin, UserBaseView):
 | 
			
		||||
    _TEMPLATE = "user/team/index.html"
 | 
			
		||||
    _TAB_TITLE = _("Teams")
 | 
			
		||||
 | 
			
		||||
    def get(self, request: HttpRequest):
 | 
			
		||||
        user = request.user
 | 
			
		||||
        context = {
 | 
			
		||||
            "teams": user.shared_teams,
 | 
			
		||||
            "tab_title": self._TAB_TITLE,
 | 
			
		||||
        }
 | 
			
		||||
        context = BaseContext(request, context).context
 | 
			
		||||
        return render(request, self._TEMPLATE, context)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@login_required_modal
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user