#7 New Form
* adds NewCompensationForm content and functionality * renames CODELIST_COMPENSATION_COMBINATION_ID into CODELIST_COMPENSATION_FUNDING_ID for more clarity * reorganizes compensation forms into compensation/forms/forms.py and forms/modalForms.py * adds new compensation html template in compensation/templates/compensation/new * adds new default message template in message_templates.py: IDENTIFIER_REPLACED * adds/updates translations
This commit is contained in:
@@ -12,6 +12,7 @@ urlpatterns = [
|
||||
# Main compensation
|
||||
path("", index_view, name="index"),
|
||||
path('new', new_view, name='new'),
|
||||
path('new/id', new_id_view, name='new-id'),
|
||||
path('<id>', open_view, name='open'),
|
||||
path('<id>/log', log_view, name='log'),
|
||||
path('<id>/edit', edit_view, name='edit'),
|
||||
|
||||
136
compensation/forms/forms.py
Normal file
136
compensation/forms/forms.py
Normal file
@@ -0,0 +1,136 @@
|
||||
"""
|
||||
Author: Michel Peltriaux
|
||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 04.12.20
|
||||
|
||||
"""
|
||||
from dal import autocomplete
|
||||
from django.contrib.auth.models import User
|
||||
from django.db import transaction
|
||||
from django.urls import reverse_lazy, reverse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from django import forms
|
||||
|
||||
from codelist.models import KonovaCode
|
||||
from codelist.settings import CODELIST_COMPENSATION_FUNDING_ID
|
||||
from compensation.models import Compensation
|
||||
from intervention.inputs import GenerateInput
|
||||
from intervention.models import Intervention
|
||||
from konova.forms import BaseForm, SimpleGeomForm
|
||||
from user.models import UserActionLogEntry, UserAction
|
||||
|
||||
|
||||
class NewCompensationForm(BaseForm):
|
||||
identifier = forms.CharField(
|
||||
label=_("Identifier"),
|
||||
label_suffix="",
|
||||
max_length=255,
|
||||
help_text=_("Generated automatically"),
|
||||
widget=GenerateInput(
|
||||
attrs={
|
||||
"class": "form-control",
|
||||
"url": reverse_lazy("compensation:new-id"),
|
||||
}
|
||||
)
|
||||
)
|
||||
title = forms.CharField(
|
||||
label=_("Title"),
|
||||
label_suffix="",
|
||||
help_text=_("An explanatory name"),
|
||||
max_length=255,
|
||||
widget=forms.TextInput(
|
||||
attrs={
|
||||
"placeholder": _("Compensation XY; Location ABC"),
|
||||
"class": "form-control",
|
||||
}
|
||||
)
|
||||
)
|
||||
intervention = forms.ModelChoiceField(
|
||||
label=_("compensates intervention"),
|
||||
label_suffix="",
|
||||
help_text=_("Select the intervention for which this compensation compensates"),
|
||||
queryset=Intervention.objects.filter(
|
||||
deleted=None,
|
||||
),
|
||||
widget=autocomplete.ModelSelect2(
|
||||
url="interventions-autocomplete",
|
||||
attrs={
|
||||
"data-placeholder": _("Intervention"),
|
||||
"data-minimum-input-length": 3,
|
||||
}
|
||||
),
|
||||
)
|
||||
fundings = forms.ModelMultipleChoiceField(
|
||||
label=_("Fundings"),
|
||||
label_suffix="",
|
||||
required=False,
|
||||
help_text=_("Select fundings for this compensation"),
|
||||
queryset=KonovaCode.objects.filter(
|
||||
is_archived=False,
|
||||
is_leaf=True,
|
||||
code_lists__in=[CODELIST_COMPENSATION_FUNDING_ID],
|
||||
),
|
||||
widget=autocomplete.ModelSelect2Multiple(
|
||||
url="codes-compensation-funding-autocomplete",
|
||||
attrs={
|
||||
"data-placeholder": _("Funding by..."),
|
||||
}
|
||||
),
|
||||
)
|
||||
comment = forms.CharField(
|
||||
label_suffix="",
|
||||
label=_("Comment"),
|
||||
required=False,
|
||||
help_text=_("Additional comment"),
|
||||
widget=forms.Textarea(
|
||||
attrs={
|
||||
"rows": 5,
|
||||
"class": "form-control"
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.form_title = _("New compensation")
|
||||
self.action_url = reverse("compensation:new")
|
||||
self.cancel_redirect = reverse("compensation:index")
|
||||
|
||||
tmp = Compensation()
|
||||
identifier = tmp._generate_new_identifier()
|
||||
self.initialize_form_field("identifier", identifier)
|
||||
|
||||
def save(self, user: User, geom_form: SimpleGeomForm):
|
||||
with transaction.atomic():
|
||||
# Fetch data from cleaned POST values
|
||||
identifier = self.cleaned_data.get("identifier", None)
|
||||
title = self.cleaned_data.get("title", None)
|
||||
fundings = self.cleaned_data.get("fundings", None)
|
||||
intervention = self.cleaned_data.get("intervention", None)
|
||||
comment = self.cleaned_data.get("comment", None)
|
||||
|
||||
# Create log entry
|
||||
action = UserActionLogEntry.objects.create(
|
||||
user=user,
|
||||
action=UserAction.CREATED,
|
||||
)
|
||||
# Process the geometry form
|
||||
geometry = geom_form.save(action)
|
||||
|
||||
# Finally create main object
|
||||
comp = Compensation.objects.create(
|
||||
identifier=identifier,
|
||||
title=title,
|
||||
intervention=intervention,
|
||||
created=action,
|
||||
geometry=geometry,
|
||||
comment=comment,
|
||||
)
|
||||
comp.fundings.set(fundings)
|
||||
|
||||
# Add the log entry to the main objects log list
|
||||
comp.log.add(action)
|
||||
return comp
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
Author: Michel Peltriaux
|
||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
||||
Created on: 04.12.20
|
||||
Created on: 04.10.21
|
||||
|
||||
"""
|
||||
from bootstrap_modal_forms.utils import is_ajax
|
||||
@@ -12,34 +12,22 @@ 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 django.utils.translation import pgettext_lazy as _con
|
||||
from django.utils.translation import pgettext_lazy as _con, gettext_lazy as _
|
||||
|
||||
from codelist.models import KonovaCode
|
||||
from codelist.settings import CODELIST_BIOTOPES_ID, CODELIST_COMPENSATION_ACTION_ID
|
||||
from compensation.models import Payment, CompensationState, CompensationAction, UnitChoices
|
||||
from compensation.models import Payment, CompensationState, UnitChoices, CompensationAction
|
||||
from konova.contexts import BaseContext
|
||||
from konova.forms import BaseForm, BaseModalForm
|
||||
from konova.models import Deadline, DeadlineType
|
||||
from konova.forms import BaseModalForm
|
||||
from konova.models import DeadlineType, Deadline
|
||||
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):
|
||||
""" Form handling payment related input
|
||||
|
||||
"""
|
||||
amount = forms.DecimalField(
|
||||
min_value=0.00,
|
||||
decimal_places=2,
|
||||
@@ -135,6 +123,12 @@ class NewPaymentForm(BaseModalForm):
|
||||
|
||||
|
||||
class NewStateModalForm(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.ModelChoiceField(
|
||||
label=_("Biotope Type"),
|
||||
label_suffix="",
|
||||
@@ -243,6 +237,9 @@ class NewStateModalForm(BaseModalForm):
|
||||
|
||||
|
||||
class NewDeadlineModalForm(BaseModalForm):
|
||||
""" Form handling deadline related input
|
||||
|
||||
"""
|
||||
type = forms.ChoiceField(
|
||||
label=_("Deadline Type"),
|
||||
label_suffix="",
|
||||
@@ -314,6 +311,13 @@ class NewDeadlineModalForm(BaseModalForm):
|
||||
|
||||
|
||||
class NewActionModalForm(BaseModalForm):
|
||||
""" Form handling action related input
|
||||
|
||||
Compensation actions are the actions performed on the area, which shall be compensated. Actions will change the
|
||||
surface of the area, the biotopes, and have an environmental impact. With actions the before-after states can change
|
||||
(not in the process logic in Konova, but in the real world).
|
||||
|
||||
"""
|
||||
action_type = forms.ModelChoiceField(
|
||||
label=_("Action Type"),
|
||||
label_suffix="",
|
||||
@@ -398,5 +402,4 @@ class NewActionModalForm(BaseModalForm):
|
||||
self.instance.save()
|
||||
self.instance.log.add(edited_action)
|
||||
self.instance.actions.add(comp_action)
|
||||
return comp_action
|
||||
|
||||
return comp_action
|
||||
@@ -16,7 +16,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from codelist.models import KonovaCode
|
||||
from codelist.settings import CODELIST_COMPENSATION_ACTION_ID, CODELIST_BIOTOPES_ID, \
|
||||
CODELIST_COMPENSATION_COMBINATION_ID
|
||||
CODELIST_COMPENSATION_FUNDING_ID
|
||||
from intervention.models import Intervention, ResponsibilityData
|
||||
from konova.models import BaseObject, BaseResource, Geometry, UuidModel, AbstractDocument, \
|
||||
generate_document_file_upload_path
|
||||
@@ -144,7 +144,7 @@ class AbstractCompensation(BaseObject):
|
||||
null=True,
|
||||
blank=True,
|
||||
limit_choices_to={
|
||||
"code_lists__in": [CODELIST_COMPENSATION_COMBINATION_ID],
|
||||
"code_lists__in": [CODELIST_COMPENSATION_FUNDING_ID],
|
||||
"is_selectable": True,
|
||||
"is_archived": False,
|
||||
},
|
||||
|
||||
16
compensation/templates/compensation/new/view.html
Normal file
16
compensation/templates/compensation/new/view.html
Normal file
@@ -0,0 +1,16 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load i18n l10n %}
|
||||
|
||||
{% block head %}
|
||||
{% comment %}
|
||||
dal documentation (django-autocomplete-light) states using form.media for adding needed scripts.
|
||||
This does not work properly with modal forms, as the scripts are not loaded properly inside the modal.
|
||||
Therefore the script linkages from form.media have been extracted and put inside dal/scripts.html to ensure
|
||||
these scripts are loaded when needed.
|
||||
{% endcomment %}
|
||||
{% include 'dal/scripts.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
{% include 'form/main_data_collapse_form.html' %}
|
||||
{% endblock %}
|
||||
@@ -1,16 +1,18 @@
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.db.models import Sum
|
||||
from django.http import HttpRequest
|
||||
from django.http import HttpRequest, JsonResponse
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from compensation.forms import NewStateModalForm, NewDeadlineModalForm, NewActionModalForm
|
||||
from compensation.forms.forms import NewCompensationForm
|
||||
from compensation.forms.modalForms import NewStateModalForm, NewDeadlineModalForm, NewActionModalForm
|
||||
from compensation.models import Compensation, CompensationState, CompensationAction, CompensationDocument
|
||||
from compensation.tables import CompensationTable
|
||||
from konova.contexts import BaseContext
|
||||
from konova.decorators import *
|
||||
from konova.forms import RemoveModalForm, SimpleGeomForm, NewDocumentForm
|
||||
from konova.utils.documents import get_document, remove_document
|
||||
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED
|
||||
from konova.utils.user_checks import in_group
|
||||
|
||||
|
||||
@@ -45,8 +47,62 @@ def index_view(request: HttpRequest):
|
||||
@login_required
|
||||
@default_group_required
|
||||
def new_view(request: HttpRequest):
|
||||
# ToDo
|
||||
pass
|
||||
"""
|
||||
Renders a view for a new compensation creation
|
||||
|
||||
Args:
|
||||
request (HttpRequest): The incoming request
|
||||
|
||||
Returns:
|
||||
|
||||
"""
|
||||
template = "compensation/new/view.html"
|
||||
data_form = NewCompensationForm(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)
|
||||
comp = data_form.save(request.user, geom_form)
|
||||
if generated_identifier != comp.identifier:
|
||||
messages.info(
|
||||
request,
|
||||
IDENTIFIER_REPLACED.format(
|
||||
generated_identifier,
|
||||
comp.identifier
|
||||
)
|
||||
)
|
||||
messages.success(request, _("Compensation {} added").format(comp.identifier))
|
||||
return redirect("compensation:open", id=comp.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: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 = Compensation()
|
||||
identifier = tmp._generate_new_identifier()
|
||||
while Compensation.objects.filter(identifier=identifier).exists():
|
||||
identifier = tmp._generate_new_identifier()
|
||||
return JsonResponse(
|
||||
data={
|
||||
"identifier": identifier
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@login_required
|
||||
|
||||
@@ -13,7 +13,7 @@ from django.core.exceptions import ObjectDoesNotExist
|
||||
from django.http import HttpRequest, Http404
|
||||
from django.shortcuts import render, get_object_or_404
|
||||
|
||||
from compensation.forms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm
|
||||
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
|
||||
|
||||
@@ -10,7 +10,7 @@ from django.contrib.auth.decorators import login_required
|
||||
from django.http import HttpRequest
|
||||
from django.shortcuts import get_object_or_404
|
||||
|
||||
from compensation.forms import NewPaymentForm
|
||||
from compensation.forms.modalForms import NewPaymentForm
|
||||
from compensation.models import Payment
|
||||
from intervention.models import Intervention
|
||||
from konova.decorators import default_group_required
|
||||
|
||||
Reference in New Issue
Block a user