""" Author: Michel Peltriaux Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany Contact: michel.peltriaux@sgdnord.rlp.de Created on: 04.12.20 """ from bootstrap_modal_forms.utils import is_ajax from django import forms from django.contrib import messages from django.db import transaction from django.http import HttpRequest, HttpResponseRedirect from django.shortcuts import render from django.utils.translation import gettext_lazy as _ from compensation.models import Payment, CompensationState, CompensationAction, UnitChoices from konova.contexts import BaseContext from konova.forms import BaseForm, BaseModalForm from konova.models import Deadline, DeadlineType from konova.utils.message_templates import FORM_INVALID from user.models import UserActionLogEntry, UserAction class NewCompensationForm(BaseForm): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) def save(self): with transaction.atomic(): user_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.CREATED ) # Save action to log class NewPaymentForm(BaseModalForm): amount = forms.DecimalField( min_value=0.00, decimal_places=2, label=_("Amount"), label_suffix=_(""), help_text=_("Amount in Euro"), ) due = forms.DateField( label=_("Due on"), label_suffix=_(""), help_text=_("Due on which date"), widget=forms.DateInput( attrs={ "type": "date", "data-provide": "datepicker", }, format="%d.%m.%Y" ) ) transfer_note = forms.CharField( max_length=200, required=False, label_suffix=_(""), label=_("Transfer note"), help_text=_("Note for money transfer") ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.intervention = self.instance self.form_title = _("Payment") self.form_caption = _("Add a payment for intervention '{}'").format(self.intervention.title) self.add_placeholder_for_field("amount", "0,00") def save(self): with transaction.atomic(): created_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.CREATED, ) edited_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.EDITED, comment=_("Added payment"), ) pay = Payment.objects.create( created=created_action, amount=self.cleaned_data.get("amount", -1), due_on=self.cleaned_data.get("due", None), comment=self.cleaned_data.get("transfer_note", None), intervention=self.intervention, ) self.intervention.log.add(edited_action) return pay class NewStateModalForm(BaseModalForm): biotope_type = forms.CharField( label=_("Biotope Type"), label_suffix="", required=True, help_text=_("Select the biotope type") ) surface = forms.DecimalField( min_value=0.00, decimal_places=2, label=_("Surface"), label_suffix="", required=True, help_text=_("in m²") ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_title = _("New state") self.form_caption = _("Insert data for the new state") self.add_placeholder_for_field("surface", "0,00") def save(self, is_before_state: bool = False): with transaction.atomic(): user_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.EDITED, comment=_("Added state") ) self.instance.log.add(user_action) state = CompensationState.objects.create( biotope_type=self.cleaned_data["biotope_type"], surface=self.cleaned_data["surface"], ) if is_before_state: self.instance.before_states.add(state) else: self.instance.after_states.add(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 NewDeadlineModalForm(BaseModalForm): type = forms.ChoiceField( label=_("Deadline Type"), label_suffix="", required=True, help_text=_("Select the deadline type"), choices=DeadlineType.choices, widget=forms.Select( attrs={ "class": "custom-select" } ) ) date = forms.DateField( label=_("Date"), label_suffix="", required=True, help_text=_("Select date"), widget=forms.DateInput( attrs={ "type": "date", "data-provide": "datepicker", }, format="%d.%m.%Y" ) ) comment = forms.CharField( required=False, max_length=200, label=_("Comment"), label_suffix=_(""), help_text=_("Additional comment, maximum {} letters").format(200), widget=forms.Textarea( attrs={ "cols": 30, "rows": 5, } ) ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_title = _("New deadline") self.form_caption = _("Insert data for the new deadline") def save(self): with transaction.atomic(): created_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.CREATED ) deadline = Deadline.objects.create( type=self.cleaned_data["type"], date=self.cleaned_data["date"], comment=self.cleaned_data["comment"], created=created_action, ) edited_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.EDITED, comment=_("Added deadline") ) self.instance.log.add(edited_action) self.instance.deadlines.add(deadline) return deadline class NewActionModalForm(BaseModalForm): action_type = forms.CharField( label=_("Action Type"), label_suffix="", required=True, help_text=_("Select the action type"), ) unit = forms.ChoiceField( label=_("Unit"), label_suffix="", required=True, help_text=_("Select the unit"), choices=UnitChoices.choices, widget=forms.Select( attrs={ "class": "custom-select" } ) ) amount = forms.DecimalField( label=_("Amount"), label_suffix="", required=True, help_text=_("Insert the amount"), decimal_places=2, min_value=0.00, ) comment = forms.CharField( required=False, max_length=200, label=_("Comment"), label_suffix=_(""), help_text=_("Additional comment, maximum {} letters").format(200), widget=forms.Textarea( attrs={ "cols": 30, "rows": 5, } ) ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.form_title = _("New action") self.form_caption = _("Insert data for the new action") self.add_placeholder_for_field("amount", "0,00") def save(self): with transaction.atomic(): user_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.CREATED, ) comp_action = CompensationAction.objects.create( action_type=self.cleaned_data["action_type"], amount=self.cleaned_data["amount"], unit=self.cleaned_data["unit"], comment=self.cleaned_data["comment"], created=user_action, ) edited_action = UserActionLogEntry.objects.create( user=self.user, action=UserAction.EDITED, comment=_("Added action"), ) self.instance.log.add(edited_action) self.instance.actions.add(comp_action) return comp_action