""" Author: Michel Peltriaux Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany 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_ID 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 class NewCompensationStateModalForm(BaseModalForm): """ Form handling state related input Compensation states refer to 'before' and 'after' states of a compensated surface. Basically it means: What has been on this area before changes/compensations have been applied and what will be the result ('after')? """ biotope_type = forms.ChoiceField( label=_("Biotope Type"), label_suffix="", required=True, help_text=_("Select the biotope type"), widget=CompensationStateTreeRadioSelect(), ) biotope_extra = forms.ModelMultipleChoiceField( label=_("Biotope additional type"), label_suffix="", required=False, help_text=_("Select an additional biotope type"), queryset=KonovaCode.objects.filter( is_archived=False, is_leaf=True, code_lists__in=[CODELIST_BIOTOPES_EXTRA_CODES_ID], ), widget=autocomplete.ModelSelect2Multiple( url="codelist:biotope-extra-type-autocomplete", attrs={ "data-placeholder": _("Biotope additional type"), } ), ) surface = forms.DecimalField( min_value=0.00, decimal_places=2, label=_("Surface"), label_suffix="", required=True, help_text=_("in m²"), widget=forms.NumberInput( attrs={ "class": "form-control", "placeholder": "0,00" } ) ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_title = _("New state") self.form_caption = _("Insert data for the new state") choices = KonovaCode.objects.filter( code_lists__in=[CODELIST_BIOTOPES_ID], is_archived=False, is_leaf=True, ).values_list("id", flat=True) choices = [ (choice, choice) for choice in choices ] self.fields["biotope_type"].choices = choices def save(self, is_before_state: bool = False): state = self.instance.add_state(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) super().__init__(*args, **kwargs) self.form_title = _("Edit state") biotope_type_id = self.state.biotope_type.id if self.state.biotope_type else None form_data = { "biotope_type": biotope_type_id, "biotope_extra": self.state.biotope_type_details.all(), "surface": self.state.surface, } self.load_initial_data(form_data) def save(self, is_before_state: bool = False): state = self.state biotope_type_id = self.cleaned_data.get("biotope_type", None) state.biotope_type = KonovaCode.objects.get(id=biotope_type_id) state.biotope_type_details.set(self.cleaned_data.get("biotope_extra", [])) state.surface = self.cleaned_data.get("surface", None) state.save() self.instance.mark_as_edited(self.user, self.request, edit_comment=COMPENSATION_STATE_EDITED) return state class RemoveCompensationStateModalForm(RemoveModalForm): """ Removing modal form for CompensationState Can be used for anything, where removing shall be confirmed by the user a second time. """ state = None def __init__(self, *args, **kwargs): state = kwargs.pop("state", None) self.state = state super().__init__(*args, **kwargs) def save(self): self.instance.remove_state(self)