""" Author: Michel Peltriaux Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany Contact: michel.peltriaux@sgdnord.rlp.de Created on: 09.08.21 """ from django.contrib import messages from django.db.models import Sum from django.urls import reverse from django.utils.translation import gettext_lazy as _ from django.contrib.auth.decorators import login_required from django.core.exceptions import ObjectDoesNotExist from django.http import HttpRequest, Http404, JsonResponse from django.shortcuts import render, get_object_or_404, redirect from compensation.forms.forms import NewEcoAccountForm, EditEcoAccountForm from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm from compensation.models import EcoAccount, EcoAccountDocument from compensation.tables import EcoAccountTable from intervention.forms.modalForms import NewDeductionModalForm from konova.contexts import BaseContext from konova.decorators import any_group_check, default_group_required, conservation_office_group_required from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm, RecordModalForm from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP from konova.utils.documents import get_document, remove_document from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID from konova.utils.user_checks import in_group @login_required @any_group_check def index_view(request: HttpRequest): """ Renders the index view for eco accounts Args: request (HttpRequest): The incoming request Returns: A rendered view """ template = "generic_index.html" user = request.user eco_accounts = EcoAccount.objects.filter( deleted=None, ) table = EcoAccountTable( request=request, queryset=eco_accounts ) context = { "table": table, } context = BaseContext(request, context).context return render(request, template, context) @login_required @default_group_required def new_view(request: HttpRequest): """ Renders a view for a new eco account creation Args: request (HttpRequest): The incoming request Returns: """ template = "compensation/new/view.html" data_form = NewEcoAccountForm(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) acc = data_form.save(request.user, geom_form) if generated_identifier != acc.identifier: messages.info( request, IDENTIFIER_REPLACED.format( generated_identifier, acc.identifier ) ) messages.success(request, _("Eco-Account {} added").format(acc.identifier)) return redirect("compensation:acc-open", id=acc.id) else: messages.error(request, FORM_INVALID) else: # For clarification: nothing in this case pass context = { "form": data_form, "geom_form": geom_form, "url": reverse("compensation:acc-new-id") } context = BaseContext(request, context).context return render(request, template, context) @login_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={ "identifier": identifier } ) @login_required @default_group_required def edit_view(request: HttpRequest, id: str): """ Renders a view for editing compensations Args: request (HttpRequest): The incoming request Returns: """ template = "compensation/new/view.html" # Get object from db acc = get_object_or_404(EcoAccount, id=id) # Create forms, initialize with values from db/from POST request data_form = EditEcoAccountForm(request.POST or None, instance=acc) geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=acc) 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 acc = data_form.save(request.user, geom_form) messages.success(request, _("Eco-Account {} edited").format(acc.identifier)) return redirect("compensation:acc-open", id=acc.id) else: messages.error(request, FORM_INVALID) else: # For clarification: nothing in this case pass context = { "form": data_form, "geom_form": geom_form, } context = BaseContext(request, context).context return render(request, template, context) @login_required @any_group_check def open_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/eco_account/view.html" acc = get_object_or_404(EcoAccount, id=id) geom_form = SimpleGeomForm(instance=acc) _user = request.user is_data_shared = acc.is_shared_with(_user) # Order states according to surface before_states = acc.before_states.all().order_by("-surface") after_states = acc.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 = before_states.aggregate(Sum("surface"))["surface__sum"] or 0 sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0 diff_states = abs(sum_before_states - sum_after_states) # Calculate rest of available surface for deductions available_total, available_relative = acc.get_available_rest() deductions = acc.deductions.filter( intervention__deleted=None, ) context = { "obj": acc, "geom_form": geom_form, "has_access": 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": in_group(_user, DEFAULT_GROUP), "is_zb_member": in_group(_user, ZB_GROUP), "is_ets_member": in_group(_user, ETS_GROUP), "LANIS_LINK": acc.get_LANIS_link(), "deductions": deductions, } context = BaseContext(request, context).context return render(request, template, context) @login_required 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) form = RemoveModalForm(request.POST or None, instance=acc, user=request.user) return form.process_request( request=request, msg_success=_("Eco-account removed"), redirect_url=reverse("compensation:acc-index"), ) @login_required @default_group_required def deduction_remove_view(request: HttpRequest, id: str, deduction_id: str): """ Renders a modal view for removing deductions Args: request (HttpRequest): The incoming request id (str): The eco account's id deduction_id (str): The deduction's id Returns: """ acc = get_object_or_404(EcoAccount, id=id) try: eco_deduction = acc.deductions.get(id=deduction_id) except ObjectDoesNotExist: raise Http404("Unknown deduction") form = RemoveModalForm(request.POST or None, instance=eco_deduction, user=request.user) return form.process_request( request=request, msg_success=_("Deduction removed") ) @login_required @default_group_required def log_view(request: HttpRequest, id: str): """ Renders a log view using modal Args: request (HttpRequest): The incoming request id (str): The eco acount's id Returns: """ comp = get_object_or_404(EcoAccount, id=id) template = "modal/modal_generic.html" body_template = "log.html" context = { "modal_body_template": body_template, "log": comp.log.all(), "modal_title": _("Log"), } context = BaseContext(request, context).context return render(request, template, context) @login_required @conservation_office_group_required def record_view(request: HttpRequest, id:str): """ Renders a modal form for recording an eco account Args: request (HttpRequest): The incoming request id (str): The account's id Returns: """ acc = get_object_or_404(EcoAccount, id=id) form = RecordModalForm(request.POST or None, instance=acc, user=request.user) msg_succ = _("{} unrecorded") if acc.recorded else _("{} recorded") msg_succ = msg_succ.format(acc.identifier) return form.process_request( request, msg_succ ) @login_required def state_new_view(request: HttpRequest, id: str): """ Renders a form for adding new states for an eco account Args: request (HttpRequest): The incoming request id (str): The account's id to which the new state will be related Returns: """ acc = get_object_or_404(EcoAccount, id=id) form = NewStateModalForm(request.POST or None, instance=acc, user=request.user) return form.process_request( request, msg_success=_("State added") ) @login_required def action_new_view(request: HttpRequest, id: str): """ Renders a form for adding new actions for an eco account Args: request (HttpRequest): The incoming request id (str): The account's id to which the new state will be related Returns: """ acc = get_object_or_404(EcoAccount, id=id) form = NewActionModalForm(request.POST or None, instance=acc, user=request.user) return form.process_request( request, msg_success=_("Action added") ) @login_required def deadline_new_view(request: HttpRequest, id: str): """ Renders a form for adding new states for an eco account Args: request (HttpRequest): The incoming request id (str): The account's id to which the new state will be related Returns: """ acc = get_object_or_404(EcoAccount, id=id) form = NewDeadlineModalForm(request.POST or None, instance=acc, user=request.user) return form.process_request( request, msg_success=_("Deadline added") ) @login_required def new_document_view(request: HttpRequest, id: str): """ Renders a form for uploading new documents Args: request (HttpRequest): The incoming request id (str): The account's id to which the new document will be related Returns: """ acc = get_object_or_404(EcoAccount, id=id) form = NewDocumentForm(request.POST or None, request.FILES or None, instance=acc, user=request.user) return form.process_request( request, msg_success=_("Document added") ) @login_required def get_document_view(request: HttpRequest, doc_id: str): """ Returns the document as downloadable file Wraps the generic document fetcher function from konova.utils. Args: request (HttpRequest): The incoming request doc_id (str): The document id Returns: """ doc = get_object_or_404(EcoAccountDocument, id=doc_id) return get_document(doc) @login_required def remove_document_view(request: HttpRequest, doc_id: str): """ Removes the document from the database and file system Wraps the generic functionality from konova.utils. Args: request (HttpRequest): The incoming request doc_id (str): The document id Returns: """ doc = get_object_or_404(EcoAccountDocument, id=doc_id) return remove_document( request, doc ) @login_required @default_group_required def new_deduction_view(request: HttpRequest, id: str): """ Renders a modal form view for creating deductions Args: request (HttpRequest): THe incoming request id (str): The eco account's id Returns: """ acc = get_object_or_404(EcoAccount, id=id) form = NewDeductionModalForm(request.POST or None, instance=acc, user=request.user) return form.process_request( request, msg_success=_("Deduction added") )