Compensation forms refactoring
* splits compensation/forms.py and /modalForms.py into individual files inside new packages * general forms stay in new files in compensation/forms * modal forms stay in new files in compensation/forms/modals
This commit is contained in:
parent
180ee293ca
commit
1367fd2b5f
7
compensation/forms/__init__.py
Normal file
7
compensation/forms/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
238
compensation/forms/compensation.py
Normal file
238
compensation/forms/compensation.py
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
from dal import autocomplete
|
||||||
|
from django import forms
|
||||||
|
from django.db import transaction
|
||||||
|
from django.urls import reverse, reverse_lazy
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from compensation.forms.mixins import CEFCompensationFormMixin, CoherenceCompensationFormMixin, PikCompensationFormMixin
|
||||||
|
from compensation.models import Compensation
|
||||||
|
from intervention.inputs import GenerateInput
|
||||||
|
from intervention.models import Intervention
|
||||||
|
from konova.forms import BaseForm, SimpleGeomForm
|
||||||
|
from konova.utils.message_templates import COMPENSATION_ADDED_TEMPLATE, EDITED_GENERAL_DATA
|
||||||
|
from user.models import UserActionLogEntry, User
|
||||||
|
|
||||||
|
|
||||||
|
class AbstractCompensationForm(BaseForm):
|
||||||
|
""" Abstract form for compensations
|
||||||
|
|
||||||
|
Holds all important form fields, which are used in compensation and eco account forms
|
||||||
|
|
||||||
|
"""
|
||||||
|
identifier = forms.CharField(
|
||||||
|
label=_("Identifier"),
|
||||||
|
label_suffix="",
|
||||||
|
max_length=255,
|
||||||
|
help_text=_("Generated automatically"),
|
||||||
|
widget=GenerateInput(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control",
|
||||||
|
"url": None, # Needs to be set in inheriting constructors
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
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",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
comment = forms.CharField(
|
||||||
|
label_suffix="",
|
||||||
|
label=_("Comment"),
|
||||||
|
required=False,
|
||||||
|
help_text=_("Additional comment"),
|
||||||
|
widget=forms.Textarea(
|
||||||
|
attrs={
|
||||||
|
"rows": 5,
|
||||||
|
"class": "form-control"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
|
||||||
|
class NewCompensationForm(AbstractCompensationForm,
|
||||||
|
CEFCompensationFormMixin,
|
||||||
|
CoherenceCompensationFormMixin,
|
||||||
|
PikCompensationFormMixin):
|
||||||
|
""" Form for creating new compensations.
|
||||||
|
|
||||||
|
Can be initialized with an intervention id for preselecting the related intervention.
|
||||||
|
form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
|
||||||
|
...
|
||||||
|
The intervention id will not be resolved into the intervention ORM object but instead will be used to initialize
|
||||||
|
the related form field.
|
||||||
|
|
||||||
|
"""
|
||||||
|
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": _("Click for selection"),
|
||||||
|
"data-minimum-input-length": 3,
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
# Define a field order for a nicer layout instead of running with the inheritance result
|
||||||
|
field_order = [
|
||||||
|
"identifier",
|
||||||
|
"title",
|
||||||
|
"intervention",
|
||||||
|
"is_pik",
|
||||||
|
"is_cef",
|
||||||
|
"is_coherence_keeping",
|
||||||
|
"comment",
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
intervention_id = kwargs.pop("intervention_id", None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.form_title = _("New compensation")
|
||||||
|
|
||||||
|
# If the compensation shall directly be initialized from an intervention, we need to fill in the intervention id
|
||||||
|
# and disable the form field.
|
||||||
|
# Furthermore the action_url needs to be set accordingly.
|
||||||
|
if intervention_id is not None:
|
||||||
|
self.initialize_form_field("intervention", intervention_id)
|
||||||
|
self.disable_form_field("intervention")
|
||||||
|
self.action_url = reverse("compensation:new", args=(intervention_id,))
|
||||||
|
self.cancel_redirect = reverse("intervention:detail", args=(intervention_id,))
|
||||||
|
else:
|
||||||
|
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)
|
||||||
|
self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:new-id")
|
||||||
|
|
||||||
|
def __create_comp(self, user, geom_form) -> Compensation:
|
||||||
|
""" Creates the compensation from form data
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user (User): The performing user
|
||||||
|
geom_form (SimpleGeomForm): The geometry form
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
comp (Compensation): The compensation object
|
||||||
|
"""
|
||||||
|
# Fetch data from cleaned POST values
|
||||||
|
identifier = self.cleaned_data.get("identifier", None)
|
||||||
|
title = self.cleaned_data.get("title", None)
|
||||||
|
intervention = self.cleaned_data.get("intervention", None)
|
||||||
|
is_cef = self.cleaned_data.get("is_cef", None)
|
||||||
|
is_coherence_keeping = self.cleaned_data.get("is_coherence_keeping", None)
|
||||||
|
is_pik = self.cleaned_data.get("is_pik", None)
|
||||||
|
comment = self.cleaned_data.get("comment", None)
|
||||||
|
|
||||||
|
# Create log entry
|
||||||
|
action = UserActionLogEntry.get_created_action(user)
|
||||||
|
# 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,
|
||||||
|
is_cef=is_cef,
|
||||||
|
is_coherence_keeping=is_coherence_keeping,
|
||||||
|
is_pik=is_pik,
|
||||||
|
geometry=geometry,
|
||||||
|
comment=comment,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add the log entry to the main objects log list
|
||||||
|
comp.log.add(action)
|
||||||
|
return comp
|
||||||
|
|
||||||
|
def save(self, user: User, geom_form: SimpleGeomForm):
|
||||||
|
with transaction.atomic():
|
||||||
|
comp = self.__create_comp(user, geom_form)
|
||||||
|
comp.intervention.mark_as_edited(user, edit_comment=COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
|
||||||
|
return comp
|
||||||
|
|
||||||
|
|
||||||
|
class EditCompensationForm(NewCompensationForm):
|
||||||
|
""" Form for editing compensations
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.form_title = _("Edit compensation")
|
||||||
|
self.action_url = reverse("compensation:edit", args=(self.instance.id,))
|
||||||
|
self.cancel_redirect = reverse("compensation:detail", args=(self.instance.id,))
|
||||||
|
|
||||||
|
# Initialize form data
|
||||||
|
form_data = {
|
||||||
|
"identifier": self.instance.identifier,
|
||||||
|
"title": self.instance.title,
|
||||||
|
"intervention": self.instance.intervention,
|
||||||
|
"is_cef": self.instance.is_cef,
|
||||||
|
"is_coherence_keeping": self.instance.is_coherence_keeping,
|
||||||
|
"is_pik": self.instance.is_pik,
|
||||||
|
"comment": self.instance.comment,
|
||||||
|
}
|
||||||
|
disabled_fields = []
|
||||||
|
self.load_initial_data(
|
||||||
|
form_data,
|
||||||
|
disabled_fields
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
intervention = self.cleaned_data.get("intervention", None)
|
||||||
|
is_cef = self.cleaned_data.get("is_cef", None)
|
||||||
|
is_coherence_keeping = self.cleaned_data.get("is_coherence_keeping", None)
|
||||||
|
is_pik = self.cleaned_data.get("is_pik", None)
|
||||||
|
comment = self.cleaned_data.get("comment", None)
|
||||||
|
|
||||||
|
# Create log entry
|
||||||
|
action = UserActionLogEntry.get_edited_action(user)
|
||||||
|
|
||||||
|
# Process the geometry form
|
||||||
|
geometry = geom_form.save(action)
|
||||||
|
|
||||||
|
# Finally create main object
|
||||||
|
self.instance.identifier = identifier
|
||||||
|
self.instance.title = title
|
||||||
|
self.instance.intervention = intervention
|
||||||
|
self.instance.geometry = geometry
|
||||||
|
self.instance.is_cef = is_cef
|
||||||
|
self.instance.is_coherence_keeping = is_coherence_keeping
|
||||||
|
self.instance.comment = comment
|
||||||
|
self.instance.is_pik = is_pik
|
||||||
|
self.instance.modified = action
|
||||||
|
self.instance.save()
|
||||||
|
|
||||||
|
self.instance.log.add(action)
|
||||||
|
|
||||||
|
intervention.mark_as_edited(user, self.request, EDITED_GENERAL_DATA)
|
||||||
|
return self.instance
|
212
compensation/forms/eco_account.py
Normal file
212
compensation/forms/eco_account.py
Normal file
@ -0,0 +1,212 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django import forms
|
||||||
|
from django.db import transaction
|
||||||
|
from django.urls import reverse, reverse_lazy
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
from compensation.forms.compensation import AbstractCompensationForm
|
||||||
|
from compensation.forms.mixins import CompensationResponsibleFormMixin, PikCompensationFormMixin
|
||||||
|
from compensation.models import EcoAccount
|
||||||
|
from intervention.models import Handler, Responsibility, Legal
|
||||||
|
from konova.forms import SimpleGeomForm
|
||||||
|
from user.models import User, UserActionLogEntry
|
||||||
|
|
||||||
|
|
||||||
|
class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMixin, PikCompensationFormMixin):
|
||||||
|
""" Form for creating eco accounts
|
||||||
|
|
||||||
|
Inherits from basic AbstractCompensationForm and further form fields from CompensationResponsibleFormMixin
|
||||||
|
|
||||||
|
"""
|
||||||
|
surface = forms.DecimalField(
|
||||||
|
min_value=0.00,
|
||||||
|
decimal_places=2,
|
||||||
|
label=_("Available Surface"),
|
||||||
|
label_suffix="",
|
||||||
|
required=False,
|
||||||
|
help_text=_("The amount that can be used for deductions"),
|
||||||
|
widget=forms.NumberInput(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control",
|
||||||
|
"placeholder": "0,00"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
registration_date = forms.DateField(
|
||||||
|
label=_("Agreement date"),
|
||||||
|
label_suffix="",
|
||||||
|
help_text=_("When did the parties agree on this?"),
|
||||||
|
required=False,
|
||||||
|
widget=forms.DateInput(
|
||||||
|
attrs={
|
||||||
|
"type": "date",
|
||||||
|
"class": "form-control",
|
||||||
|
},
|
||||||
|
format="%d.%m.%Y"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
field_order = [
|
||||||
|
"identifier",
|
||||||
|
"title",
|
||||||
|
"conservation_office",
|
||||||
|
"registration_date",
|
||||||
|
"surface",
|
||||||
|
"conservation_file_number",
|
||||||
|
"is_pik",
|
||||||
|
"handler_type",
|
||||||
|
"handler_detail",
|
||||||
|
"comment",
|
||||||
|
]
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.form_title = _("New Eco-Account")
|
||||||
|
|
||||||
|
self.action_url = reverse("compensation:acc:new")
|
||||||
|
self.cancel_redirect = reverse("compensation:acc:index")
|
||||||
|
|
||||||
|
tmp = EcoAccount()
|
||||||
|
identifier = tmp.generate_new_identifier()
|
||||||
|
self.initialize_form_field("identifier", identifier)
|
||||||
|
self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:acc:new-id")
|
||||||
|
self.fields["title"].widget.attrs["placeholder"] = _("Eco-Account XY; Location ABC")
|
||||||
|
|
||||||
|
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)
|
||||||
|
registration_date = self.cleaned_data.get("registration_date", None)
|
||||||
|
handler_type = self.cleaned_data.get("handler_type", None)
|
||||||
|
handler_detail = self.cleaned_data.get("handler_detail", None)
|
||||||
|
surface = self.cleaned_data.get("surface", None)
|
||||||
|
conservation_office = self.cleaned_data.get("conservation_office", None)
|
||||||
|
conservation_file_number = self.cleaned_data.get("conservation_file_number", None)
|
||||||
|
is_pik = self.cleaned_data.get("is_pik", None)
|
||||||
|
comment = self.cleaned_data.get("comment", None)
|
||||||
|
|
||||||
|
# Create log entry
|
||||||
|
action = UserActionLogEntry.get_created_action(user)
|
||||||
|
# Process the geometry form
|
||||||
|
geometry = geom_form.save(action)
|
||||||
|
|
||||||
|
handler = Handler.objects.create(
|
||||||
|
type=handler_type,
|
||||||
|
detail=handler_detail,
|
||||||
|
)
|
||||||
|
|
||||||
|
responsible = Responsibility.objects.create(
|
||||||
|
handler=handler,
|
||||||
|
conservation_file_number=conservation_file_number,
|
||||||
|
conservation_office=conservation_office,
|
||||||
|
)
|
||||||
|
|
||||||
|
legal = Legal.objects.create(
|
||||||
|
registration_date=registration_date
|
||||||
|
)
|
||||||
|
|
||||||
|
# Finally create main object
|
||||||
|
acc = EcoAccount.objects.create(
|
||||||
|
identifier=identifier,
|
||||||
|
title=title,
|
||||||
|
responsible=responsible,
|
||||||
|
deductable_surface=surface,
|
||||||
|
created=action,
|
||||||
|
geometry=geometry,
|
||||||
|
comment=comment,
|
||||||
|
is_pik=is_pik,
|
||||||
|
legal=legal
|
||||||
|
)
|
||||||
|
acc.share_with_user(user)
|
||||||
|
|
||||||
|
# Add the log entry to the main objects log list
|
||||||
|
acc.log.add(action)
|
||||||
|
return acc
|
||||||
|
|
||||||
|
|
||||||
|
class EditEcoAccountForm(NewEcoAccountForm):
|
||||||
|
""" Form for editing eco accounts
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.form_title = _("Edit Eco-Account")
|
||||||
|
|
||||||
|
self.action_url = reverse("compensation:acc:edit", args=(self.instance.id,))
|
||||||
|
self.cancel_redirect = reverse("compensation:acc:detail", args=(self.instance.id,))
|
||||||
|
|
||||||
|
# Initialize form data
|
||||||
|
reg_date = self.instance.legal.registration_date
|
||||||
|
if reg_date is not None:
|
||||||
|
reg_date = reg_date.isoformat()
|
||||||
|
|
||||||
|
form_data = {
|
||||||
|
"identifier": self.instance.identifier,
|
||||||
|
"title": self.instance.title,
|
||||||
|
"surface": self.instance.deductable_surface,
|
||||||
|
"handler_type": self.instance.responsible.handler.type,
|
||||||
|
"handler_detail": self.instance.responsible.handler.detail,
|
||||||
|
"registration_date": reg_date,
|
||||||
|
"conservation_office": self.instance.responsible.conservation_office,
|
||||||
|
"conservation_file_number": self.instance.responsible.conservation_file_number,
|
||||||
|
"is_pik": self.instance.is_pik,
|
||||||
|
"comment": self.instance.comment,
|
||||||
|
}
|
||||||
|
disabled_fields = []
|
||||||
|
self.load_initial_data(
|
||||||
|
form_data,
|
||||||
|
disabled_fields
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
registration_date = self.cleaned_data.get("registration_date", None)
|
||||||
|
handler_type = self.cleaned_data.get("handler_type", None)
|
||||||
|
handler_detail = self.cleaned_data.get("handler_detail", None)
|
||||||
|
surface = self.cleaned_data.get("surface", None)
|
||||||
|
conservation_office = self.cleaned_data.get("conservation_office", None)
|
||||||
|
conservation_file_number = self.cleaned_data.get("conservation_file_number", None)
|
||||||
|
comment = self.cleaned_data.get("comment", None)
|
||||||
|
is_pik = self.cleaned_data.get("is_pik", None)
|
||||||
|
|
||||||
|
# Create log entry
|
||||||
|
action = UserActionLogEntry.get_edited_action(user)
|
||||||
|
|
||||||
|
# Process the geometry form
|
||||||
|
geometry = geom_form.save(action)
|
||||||
|
|
||||||
|
# Update responsible data
|
||||||
|
self.instance.responsible.handler.type = handler_type
|
||||||
|
self.instance.responsible.handler.detail = handler_detail
|
||||||
|
self.instance.responsible.handler.save()
|
||||||
|
self.instance.responsible.conservation_office = conservation_office
|
||||||
|
self.instance.responsible.conservation_file_number = conservation_file_number
|
||||||
|
self.instance.responsible.save()
|
||||||
|
|
||||||
|
# Update legal data
|
||||||
|
self.instance.legal.registration_date = registration_date
|
||||||
|
self.instance.legal.save()
|
||||||
|
|
||||||
|
# Update main oject data
|
||||||
|
self.instance.identifier = identifier
|
||||||
|
self.instance.title = title
|
||||||
|
self.instance.deductable_surface = surface
|
||||||
|
self.instance.geometry = geometry
|
||||||
|
self.instance.comment = comment
|
||||||
|
self.instance.is_pik = is_pik
|
||||||
|
self.instance.modified = action
|
||||||
|
self.instance.save()
|
||||||
|
|
||||||
|
# Add the log entry to the main objects log list
|
||||||
|
self.instance.log.add(action)
|
||||||
|
return self.instance
|
@ -1,539 +0,0 @@
|
|||||||
"""
|
|
||||||
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 user.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_CONSERVATION_OFFICE_ID, CODELIST_HANDLER_ID
|
|
||||||
from compensation.models import Compensation, EcoAccount
|
|
||||||
from intervention.inputs import GenerateInput
|
|
||||||
from intervention.models import Intervention, Responsibility, Legal, Handler
|
|
||||||
from konova.forms import BaseForm, SimpleGeomForm
|
|
||||||
from konova.utils.message_templates import EDITED_GENERAL_DATA, COMPENSATION_ADDED_TEMPLATE
|
|
||||||
from user.models import UserActionLogEntry
|
|
||||||
|
|
||||||
|
|
||||||
class AbstractCompensationForm(BaseForm):
|
|
||||||
""" Abstract form for compensations
|
|
||||||
|
|
||||||
Holds all important form fields, which are used in compensation and eco account forms
|
|
||||||
|
|
||||||
"""
|
|
||||||
identifier = forms.CharField(
|
|
||||||
label=_("Identifier"),
|
|
||||||
label_suffix="",
|
|
||||||
max_length=255,
|
|
||||||
help_text=_("Generated automatically"),
|
|
||||||
widget=GenerateInput(
|
|
||||||
attrs={
|
|
||||||
"class": "form-control",
|
|
||||||
"url": None, # Needs to be set in inheriting constructors
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
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",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
comment = forms.CharField(
|
|
||||||
label_suffix="",
|
|
||||||
label=_("Comment"),
|
|
||||||
required=False,
|
|
||||||
help_text=_("Additional comment"),
|
|
||||||
widget=forms.Textarea(
|
|
||||||
attrs={
|
|
||||||
"rows": 5,
|
|
||||||
"class": "form-control"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
abstract = True
|
|
||||||
|
|
||||||
|
|
||||||
class CompensationResponsibleFormMixin(forms.Form):
|
|
||||||
""" Encapsulates form fields used in different compensation related models like EcoAccount or EMA
|
|
||||||
|
|
||||||
"""
|
|
||||||
conservation_office = forms.ModelChoiceField(
|
|
||||||
label=_("Conservation office"),
|
|
||||||
label_suffix="",
|
|
||||||
help_text=_("Select the responsible office"),
|
|
||||||
queryset=KonovaCode.objects.filter(
|
|
||||||
is_archived=False,
|
|
||||||
is_leaf=True,
|
|
||||||
code_lists__in=[CODELIST_CONSERVATION_OFFICE_ID],
|
|
||||||
),
|
|
||||||
widget=autocomplete.ModelSelect2(
|
|
||||||
url="codes-conservation-office-autocomplete",
|
|
||||||
attrs={
|
|
||||||
"data-placeholder": _("Click for selection")
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
conservation_file_number = forms.CharField(
|
|
||||||
label=_("Conservation office file number"),
|
|
||||||
label_suffix="",
|
|
||||||
max_length=255,
|
|
||||||
required=False,
|
|
||||||
widget=forms.TextInput(
|
|
||||||
attrs={
|
|
||||||
"placeholder": _("ETS-123/ABC.456"),
|
|
||||||
"class": "form-control",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
handler_type = forms.ModelChoiceField(
|
|
||||||
label=_("Eco-Account handler type"),
|
|
||||||
label_suffix="",
|
|
||||||
help_text=_("What type of handler is responsible for the ecoaccount?"),
|
|
||||||
required=False,
|
|
||||||
queryset=KonovaCode.objects.filter(
|
|
||||||
is_archived=False,
|
|
||||||
is_leaf=True,
|
|
||||||
code_lists__in=[CODELIST_HANDLER_ID],
|
|
||||||
),
|
|
||||||
widget=autocomplete.ModelSelect2(
|
|
||||||
url="codes-handler-autocomplete",
|
|
||||||
attrs={
|
|
||||||
"data-placeholder": _("Click for selection"),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
handler_detail = forms.CharField(
|
|
||||||
label=_("Eco-Account handler detail"),
|
|
||||||
label_suffix="",
|
|
||||||
max_length=255,
|
|
||||||
required=False,
|
|
||||||
help_text=_("Detail input on the handler"),
|
|
||||||
widget=forms.TextInput(
|
|
||||||
attrs={
|
|
||||||
"placeholder": _("Company Mustermann"),
|
|
||||||
"class": "form-control",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CEFCompensationFormMixin(forms.Form):
|
|
||||||
""" A form mixin, providing CEF compensation field
|
|
||||||
|
|
||||||
"""
|
|
||||||
is_cef = forms.BooleanField(
|
|
||||||
label_suffix="",
|
|
||||||
label=_("Is CEF"),
|
|
||||||
help_text=_("Optionally: Whether this compensation is a CEF compensation?"),
|
|
||||||
required=False,
|
|
||||||
widget=forms.CheckboxInput()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CoherenceCompensationFormMixin(forms.Form):
|
|
||||||
""" A form mixin, providing coherence compensation field
|
|
||||||
|
|
||||||
"""
|
|
||||||
is_coherence_keeping = forms.BooleanField(
|
|
||||||
label_suffix="",
|
|
||||||
label=_("Is coherence keeping"),
|
|
||||||
help_text=_("Optionally: Whether this compensation is a coherence keeping compensation?"),
|
|
||||||
required=False,
|
|
||||||
widget=forms.CheckboxInput()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PikCompensationFormMixin(forms.Form):
|
|
||||||
""" A form mixin, providing PIK compensation field
|
|
||||||
|
|
||||||
"""
|
|
||||||
is_pik = forms.BooleanField(
|
|
||||||
label_suffix="",
|
|
||||||
label=_("Is PIK"),
|
|
||||||
help_text=_("Optionally: Whether this compensation is a compensation integrated in production?"),
|
|
||||||
required=False,
|
|
||||||
widget=forms.CheckboxInput()
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class NewCompensationForm(AbstractCompensationForm,
|
|
||||||
CEFCompensationFormMixin,
|
|
||||||
CoherenceCompensationFormMixin,
|
|
||||||
PikCompensationFormMixin):
|
|
||||||
""" Form for creating new compensations.
|
|
||||||
|
|
||||||
Can be initialized with an intervention id for preselecting the related intervention.
|
|
||||||
form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
|
|
||||||
...
|
|
||||||
The intervention id will not be resolved into the intervention ORM object but instead will be used to initialize
|
|
||||||
the related form field.
|
|
||||||
|
|
||||||
"""
|
|
||||||
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": _("Click for selection"),
|
|
||||||
"data-minimum-input-length": 3,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
# Define a field order for a nicer layout instead of running with the inheritance result
|
|
||||||
field_order = [
|
|
||||||
"identifier",
|
|
||||||
"title",
|
|
||||||
"intervention",
|
|
||||||
"is_pik",
|
|
||||||
"is_cef",
|
|
||||||
"is_coherence_keeping",
|
|
||||||
"comment",
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
intervention_id = kwargs.pop("intervention_id", None)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.form_title = _("New compensation")
|
|
||||||
|
|
||||||
# If the compensation shall directly be initialized from an intervention, we need to fill in the intervention id
|
|
||||||
# and disable the form field.
|
|
||||||
# Furthermore the action_url needs to be set accordingly.
|
|
||||||
if intervention_id is not None:
|
|
||||||
self.initialize_form_field("intervention", intervention_id)
|
|
||||||
self.disable_form_field("intervention")
|
|
||||||
self.action_url = reverse("compensation:new", args=(intervention_id,))
|
|
||||||
self.cancel_redirect = reverse("intervention:detail", args=(intervention_id,))
|
|
||||||
else:
|
|
||||||
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)
|
|
||||||
self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:new-id")
|
|
||||||
|
|
||||||
def __create_comp(self, user, geom_form) -> Compensation:
|
|
||||||
""" Creates the compensation from form data
|
|
||||||
|
|
||||||
Args:
|
|
||||||
user (User): The performing user
|
|
||||||
geom_form (SimpleGeomForm): The geometry form
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
comp (Compensation): The compensation object
|
|
||||||
"""
|
|
||||||
# Fetch data from cleaned POST values
|
|
||||||
identifier = self.cleaned_data.get("identifier", None)
|
|
||||||
title = self.cleaned_data.get("title", None)
|
|
||||||
intervention = self.cleaned_data.get("intervention", None)
|
|
||||||
is_cef = self.cleaned_data.get("is_cef", None)
|
|
||||||
is_coherence_keeping = self.cleaned_data.get("is_coherence_keeping", None)
|
|
||||||
is_pik = self.cleaned_data.get("is_pik", None)
|
|
||||||
comment = self.cleaned_data.get("comment", None)
|
|
||||||
|
|
||||||
# Create log entry
|
|
||||||
action = UserActionLogEntry.get_created_action(user)
|
|
||||||
# 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,
|
|
||||||
is_cef=is_cef,
|
|
||||||
is_coherence_keeping=is_coherence_keeping,
|
|
||||||
is_pik=is_pik,
|
|
||||||
geometry=geometry,
|
|
||||||
comment=comment,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Add the log entry to the main objects log list
|
|
||||||
comp.log.add(action)
|
|
||||||
return comp
|
|
||||||
|
|
||||||
def save(self, user: User, geom_form: SimpleGeomForm):
|
|
||||||
with transaction.atomic():
|
|
||||||
comp = self.__create_comp(user, geom_form)
|
|
||||||
comp.intervention.mark_as_edited(user, edit_comment=COMPENSATION_ADDED_TEMPLATE.format(comp.identifier))
|
|
||||||
return comp
|
|
||||||
|
|
||||||
|
|
||||||
class EditCompensationForm(NewCompensationForm):
|
|
||||||
""" Form for editing compensations
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.form_title = _("Edit compensation")
|
|
||||||
self.action_url = reverse("compensation:edit", args=(self.instance.id,))
|
|
||||||
self.cancel_redirect = reverse("compensation:detail", args=(self.instance.id,))
|
|
||||||
|
|
||||||
# Initialize form data
|
|
||||||
form_data = {
|
|
||||||
"identifier": self.instance.identifier,
|
|
||||||
"title": self.instance.title,
|
|
||||||
"intervention": self.instance.intervention,
|
|
||||||
"is_cef": self.instance.is_cef,
|
|
||||||
"is_coherence_keeping": self.instance.is_coherence_keeping,
|
|
||||||
"is_pik": self.instance.is_pik,
|
|
||||||
"comment": self.instance.comment,
|
|
||||||
}
|
|
||||||
disabled_fields = []
|
|
||||||
self.load_initial_data(
|
|
||||||
form_data,
|
|
||||||
disabled_fields
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
|
||||||
intervention = self.cleaned_data.get("intervention", None)
|
|
||||||
is_cef = self.cleaned_data.get("is_cef", None)
|
|
||||||
is_coherence_keeping = self.cleaned_data.get("is_coherence_keeping", None)
|
|
||||||
is_pik = self.cleaned_data.get("is_pik", None)
|
|
||||||
comment = self.cleaned_data.get("comment", None)
|
|
||||||
|
|
||||||
# Create log entry
|
|
||||||
action = UserActionLogEntry.get_edited_action(user)
|
|
||||||
|
|
||||||
# Process the geometry form
|
|
||||||
geometry = geom_form.save(action)
|
|
||||||
|
|
||||||
# Finally create main object
|
|
||||||
self.instance.identifier = identifier
|
|
||||||
self.instance.title = title
|
|
||||||
self.instance.intervention = intervention
|
|
||||||
self.instance.geometry = geometry
|
|
||||||
self.instance.is_cef = is_cef
|
|
||||||
self.instance.is_coherence_keeping = is_coherence_keeping
|
|
||||||
self.instance.comment = comment
|
|
||||||
self.instance.is_pik = is_pik
|
|
||||||
self.instance.modified = action
|
|
||||||
self.instance.save()
|
|
||||||
|
|
||||||
self.instance.log.add(action)
|
|
||||||
|
|
||||||
intervention.mark_as_edited(user, self.request, EDITED_GENERAL_DATA)
|
|
||||||
return self.instance
|
|
||||||
|
|
||||||
|
|
||||||
class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMixin, PikCompensationFormMixin):
|
|
||||||
""" Form for creating eco accounts
|
|
||||||
|
|
||||||
Inherits from basic AbstractCompensationForm and further form fields from CompensationResponsibleFormMixin
|
|
||||||
|
|
||||||
"""
|
|
||||||
surface = forms.DecimalField(
|
|
||||||
min_value=0.00,
|
|
||||||
decimal_places=2,
|
|
||||||
label=_("Available Surface"),
|
|
||||||
label_suffix="",
|
|
||||||
required=False,
|
|
||||||
help_text=_("The amount that can be used for deductions"),
|
|
||||||
widget=forms.NumberInput(
|
|
||||||
attrs={
|
|
||||||
"class": "form-control",
|
|
||||||
"placeholder": "0,00"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
registration_date = forms.DateField(
|
|
||||||
label=_("Agreement date"),
|
|
||||||
label_suffix="",
|
|
||||||
help_text=_("When did the parties agree on this?"),
|
|
||||||
required=False,
|
|
||||||
widget=forms.DateInput(
|
|
||||||
attrs={
|
|
||||||
"type": "date",
|
|
||||||
"class": "form-control",
|
|
||||||
},
|
|
||||||
format="%d.%m.%Y"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
field_order = [
|
|
||||||
"identifier",
|
|
||||||
"title",
|
|
||||||
"conservation_office",
|
|
||||||
"registration_date",
|
|
||||||
"surface",
|
|
||||||
"conservation_file_number",
|
|
||||||
"is_pik",
|
|
||||||
"handler_type",
|
|
||||||
"handler_detail",
|
|
||||||
"comment",
|
|
||||||
]
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.form_title = _("New Eco-Account")
|
|
||||||
|
|
||||||
self.action_url = reverse("compensation:acc:new")
|
|
||||||
self.cancel_redirect = reverse("compensation:acc:index")
|
|
||||||
|
|
||||||
tmp = EcoAccount()
|
|
||||||
identifier = tmp.generate_new_identifier()
|
|
||||||
self.initialize_form_field("identifier", identifier)
|
|
||||||
self.fields["identifier"].widget.attrs["url"] = reverse_lazy("compensation:acc:new-id")
|
|
||||||
self.fields["title"].widget.attrs["placeholder"] = _("Eco-Account XY; Location ABC")
|
|
||||||
|
|
||||||
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)
|
|
||||||
registration_date = self.cleaned_data.get("registration_date", None)
|
|
||||||
handler_type = self.cleaned_data.get("handler_type", None)
|
|
||||||
handler_detail = self.cleaned_data.get("handler_detail", None)
|
|
||||||
surface = self.cleaned_data.get("surface", None)
|
|
||||||
conservation_office = self.cleaned_data.get("conservation_office", None)
|
|
||||||
conservation_file_number = self.cleaned_data.get("conservation_file_number", None)
|
|
||||||
is_pik = self.cleaned_data.get("is_pik", None)
|
|
||||||
comment = self.cleaned_data.get("comment", None)
|
|
||||||
|
|
||||||
# Create log entry
|
|
||||||
action = UserActionLogEntry.get_created_action(user)
|
|
||||||
# Process the geometry form
|
|
||||||
geometry = geom_form.save(action)
|
|
||||||
|
|
||||||
handler = Handler.objects.create(
|
|
||||||
type=handler_type,
|
|
||||||
detail=handler_detail,
|
|
||||||
)
|
|
||||||
|
|
||||||
responsible = Responsibility.objects.create(
|
|
||||||
handler=handler,
|
|
||||||
conservation_file_number=conservation_file_number,
|
|
||||||
conservation_office=conservation_office,
|
|
||||||
)
|
|
||||||
|
|
||||||
legal = Legal.objects.create(
|
|
||||||
registration_date=registration_date
|
|
||||||
)
|
|
||||||
|
|
||||||
# Finally create main object
|
|
||||||
acc = EcoAccount.objects.create(
|
|
||||||
identifier=identifier,
|
|
||||||
title=title,
|
|
||||||
responsible=responsible,
|
|
||||||
deductable_surface=surface,
|
|
||||||
created=action,
|
|
||||||
geometry=geometry,
|
|
||||||
comment=comment,
|
|
||||||
is_pik=is_pik,
|
|
||||||
legal=legal
|
|
||||||
)
|
|
||||||
acc.share_with_user(user)
|
|
||||||
|
|
||||||
# Add the log entry to the main objects log list
|
|
||||||
acc.log.add(action)
|
|
||||||
return acc
|
|
||||||
|
|
||||||
|
|
||||||
class EditEcoAccountForm(NewEcoAccountForm):
|
|
||||||
""" Form for editing eco accounts
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.form_title = _("Edit Eco-Account")
|
|
||||||
|
|
||||||
self.action_url = reverse("compensation:acc:edit", args=(self.instance.id,))
|
|
||||||
self.cancel_redirect = reverse("compensation:acc:detail", args=(self.instance.id,))
|
|
||||||
|
|
||||||
# Initialize form data
|
|
||||||
reg_date = self.instance.legal.registration_date
|
|
||||||
if reg_date is not None:
|
|
||||||
reg_date = reg_date.isoformat()
|
|
||||||
|
|
||||||
form_data = {
|
|
||||||
"identifier": self.instance.identifier,
|
|
||||||
"title": self.instance.title,
|
|
||||||
"surface": self.instance.deductable_surface,
|
|
||||||
"handler_type": self.instance.responsible.handler.type,
|
|
||||||
"handler_detail": self.instance.responsible.handler.detail,
|
|
||||||
"registration_date": reg_date,
|
|
||||||
"conservation_office": self.instance.responsible.conservation_office,
|
|
||||||
"conservation_file_number": self.instance.responsible.conservation_file_number,
|
|
||||||
"is_pik": self.instance.is_pik,
|
|
||||||
"comment": self.instance.comment,
|
|
||||||
}
|
|
||||||
disabled_fields = []
|
|
||||||
self.load_initial_data(
|
|
||||||
form_data,
|
|
||||||
disabled_fields
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
|
||||||
registration_date = self.cleaned_data.get("registration_date", None)
|
|
||||||
handler_type = self.cleaned_data.get("handler_type", None)
|
|
||||||
handler_detail = self.cleaned_data.get("handler_detail", None)
|
|
||||||
surface = self.cleaned_data.get("surface", None)
|
|
||||||
conservation_office = self.cleaned_data.get("conservation_office", None)
|
|
||||||
conservation_file_number = self.cleaned_data.get("conservation_file_number", None)
|
|
||||||
comment = self.cleaned_data.get("comment", None)
|
|
||||||
is_pik = self.cleaned_data.get("is_pik", None)
|
|
||||||
|
|
||||||
# Create log entry
|
|
||||||
action = UserActionLogEntry.get_edited_action(user)
|
|
||||||
|
|
||||||
# Process the geometry form
|
|
||||||
geometry = geom_form.save(action)
|
|
||||||
|
|
||||||
# Update responsible data
|
|
||||||
self.instance.responsible.handler.type = handler_type
|
|
||||||
self.instance.responsible.handler.detail = handler_detail
|
|
||||||
self.instance.responsible.handler.save()
|
|
||||||
self.instance.responsible.conservation_office = conservation_office
|
|
||||||
self.instance.responsible.conservation_file_number = conservation_file_number
|
|
||||||
self.instance.responsible.save()
|
|
||||||
|
|
||||||
# Update legal data
|
|
||||||
self.instance.legal.registration_date = registration_date
|
|
||||||
self.instance.legal.save()
|
|
||||||
|
|
||||||
# Update main oject data
|
|
||||||
self.instance.identifier = identifier
|
|
||||||
self.instance.title = title
|
|
||||||
self.instance.deductable_surface = surface
|
|
||||||
self.instance.geometry = geometry
|
|
||||||
self.instance.comment = comment
|
|
||||||
self.instance.is_pik = is_pik
|
|
||||||
self.instance.modified = action
|
|
||||||
self.instance.save()
|
|
||||||
|
|
||||||
# Add the log entry to the main objects log list
|
|
||||||
self.instance.log.add(action)
|
|
||||||
return self.instance
|
|
117
compensation/forms/mixins.py
Normal file
117
compensation/forms/mixins.py
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
from dal import autocomplete
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from codelist.models import KonovaCode
|
||||||
|
from codelist.settings import CODELIST_CONSERVATION_OFFICE_ID, CODELIST_HANDLER_ID
|
||||||
|
|
||||||
|
|
||||||
|
class CompensationResponsibleFormMixin(forms.Form):
|
||||||
|
""" Encapsulates form fields used in different compensation related models like EcoAccount or EMA
|
||||||
|
|
||||||
|
"""
|
||||||
|
conservation_office = forms.ModelChoiceField(
|
||||||
|
label=_("Conservation office"),
|
||||||
|
label_suffix="",
|
||||||
|
help_text=_("Select the responsible office"),
|
||||||
|
queryset=KonovaCode.objects.filter(
|
||||||
|
is_archived=False,
|
||||||
|
is_leaf=True,
|
||||||
|
code_lists__in=[CODELIST_CONSERVATION_OFFICE_ID],
|
||||||
|
),
|
||||||
|
widget=autocomplete.ModelSelect2(
|
||||||
|
url="codes-conservation-office-autocomplete",
|
||||||
|
attrs={
|
||||||
|
"data-placeholder": _("Click for selection")
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
conservation_file_number = forms.CharField(
|
||||||
|
label=_("Conservation office file number"),
|
||||||
|
label_suffix="",
|
||||||
|
max_length=255,
|
||||||
|
required=False,
|
||||||
|
widget=forms.TextInput(
|
||||||
|
attrs={
|
||||||
|
"placeholder": _("ETS-123/ABC.456"),
|
||||||
|
"class": "form-control",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
handler_type = forms.ModelChoiceField(
|
||||||
|
label=_("Eco-Account handler type"),
|
||||||
|
label_suffix="",
|
||||||
|
help_text=_("What type of handler is responsible for the ecoaccount?"),
|
||||||
|
required=False,
|
||||||
|
queryset=KonovaCode.objects.filter(
|
||||||
|
is_archived=False,
|
||||||
|
is_leaf=True,
|
||||||
|
code_lists__in=[CODELIST_HANDLER_ID],
|
||||||
|
),
|
||||||
|
widget=autocomplete.ModelSelect2(
|
||||||
|
url="codes-handler-autocomplete",
|
||||||
|
attrs={
|
||||||
|
"data-placeholder": _("Click for selection"),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
handler_detail = forms.CharField(
|
||||||
|
label=_("Eco-Account handler detail"),
|
||||||
|
label_suffix="",
|
||||||
|
max_length=255,
|
||||||
|
required=False,
|
||||||
|
help_text=_("Detail input on the handler"),
|
||||||
|
widget=forms.TextInput(
|
||||||
|
attrs={
|
||||||
|
"placeholder": _("Company Mustermann"),
|
||||||
|
"class": "form-control",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CEFCompensationFormMixin(forms.Form):
|
||||||
|
""" A form mixin, providing CEF compensation field
|
||||||
|
|
||||||
|
"""
|
||||||
|
is_cef = forms.BooleanField(
|
||||||
|
label_suffix="",
|
||||||
|
label=_("Is CEF"),
|
||||||
|
help_text=_("Optionally: Whether this compensation is a CEF compensation?"),
|
||||||
|
required=False,
|
||||||
|
widget=forms.CheckboxInput()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class CoherenceCompensationFormMixin(forms.Form):
|
||||||
|
""" A form mixin, providing coherence compensation field
|
||||||
|
|
||||||
|
"""
|
||||||
|
is_coherence_keeping = forms.BooleanField(
|
||||||
|
label_suffix="",
|
||||||
|
label=_("Is coherence keeping"),
|
||||||
|
help_text=_("Optionally: Whether this compensation is a coherence keeping compensation?"),
|
||||||
|
required=False,
|
||||||
|
widget=forms.CheckboxInput()
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PikCompensationFormMixin(forms.Form):
|
||||||
|
""" A form mixin, providing PIK compensation field
|
||||||
|
|
||||||
|
"""
|
||||||
|
is_pik = forms.BooleanField(
|
||||||
|
label_suffix="",
|
||||||
|
label=_("Is PIK"),
|
||||||
|
help_text=_("Optionally: Whether this compensation is a compensation integrated in production?"),
|
||||||
|
required=False,
|
||||||
|
widget=forms.CheckboxInput()
|
||||||
|
)
|
@ -1,534 +0,0 @@
|
|||||||
"""
|
|
||||||
Author: Michel Peltriaux
|
|
||||||
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
|
||||||
Contact: michel.peltriaux@sgdnord.rlp.de
|
|
||||||
Created on: 04.10.21
|
|
||||||
|
|
||||||
"""
|
|
||||||
from bootstrap_modal_forms.utils import is_ajax
|
|
||||||
from dal import autocomplete
|
|
||||||
from django import forms
|
|
||||||
from django.contrib import messages
|
|
||||||
from django.http import HttpRequest, HttpResponseRedirect
|
|
||||||
from django.shortcuts import render
|
|
||||||
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, CODELIST_BIOTOPES_EXTRA_CODES_ID, \
|
|
||||||
CODELIST_COMPENSATION_ACTION_DETAIL_ID
|
|
||||||
from compensation.models import CompensationDocument, EcoAccountDocument
|
|
||||||
from intervention.inputs import CompensationActionTreeCheckboxSelectMultiple, \
|
|
||||||
CompensationStateTreeRadioSelect
|
|
||||||
from konova.contexts import BaseContext
|
|
||||||
from konova.forms.modals import BaseModalForm, NewDocumentModalForm, RemoveModalForm
|
|
||||||
from konova.models import DeadlineType
|
|
||||||
from konova.utils.message_templates import FORM_INVALID, ADDED_COMPENSATION_STATE, \
|
|
||||||
ADDED_COMPENSATION_ACTION, PAYMENT_EDITED, COMPENSATION_STATE_EDITED, COMPENSATION_ACTION_EDITED, DEADLINE_EDITED
|
|
||||||
|
|
||||||
|
|
||||||
class NewPaymentForm(BaseModalForm):
|
|
||||||
""" Form handling payment related input
|
|
||||||
|
|
||||||
"""
|
|
||||||
amount = forms.DecimalField(
|
|
||||||
min_value=0.00,
|
|
||||||
decimal_places=2,
|
|
||||||
label=_con("money", "Amount"), # contextual translation
|
|
||||||
label_suffix=_(""),
|
|
||||||
help_text=_("in Euro"),
|
|
||||||
widget=forms.NumberInput(
|
|
||||||
attrs={
|
|
||||||
"class": "form-control",
|
|
||||||
"placeholder": "0,00",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
due = forms.DateField(
|
|
||||||
label=_("Due on"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
required=False,
|
|
||||||
help_text=_("Due on which date"),
|
|
||||||
widget=forms.DateInput(
|
|
||||||
attrs={
|
|
||||||
"type": "date",
|
|
||||||
"data-provide": "datepicker",
|
|
||||||
"class": "form-control",
|
|
||||||
},
|
|
||||||
format="%d.%m.%Y"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
comment = forms.CharField(
|
|
||||||
max_length=200,
|
|
||||||
required=False,
|
|
||||||
label=_("Comment"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
help_text=_("Additional comment, maximum {} letters").format(200),
|
|
||||||
widget=forms.Textarea(
|
|
||||||
attrs={
|
|
||||||
"rows": 5,
|
|
||||||
"class": "form-control"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
def is_valid(self):
|
|
||||||
"""
|
|
||||||
Checks on form validity.
|
|
||||||
|
|
||||||
For this form we need to make sure that a date or a comment is set.
|
|
||||||
If both are missing, the user needs to enter at least an explanation why
|
|
||||||
there is no date to be entered.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
is_valid (bool): True if valid, False otherwise
|
|
||||||
"""
|
|
||||||
super_valid = super().is_valid()
|
|
||||||
date = self.cleaned_data["due"]
|
|
||||||
comment = self.cleaned_data["comment"] or None
|
|
||||||
if not date and not comment:
|
|
||||||
# At least one needs to be set!
|
|
||||||
self.add_error(
|
|
||||||
"comment",
|
|
||||||
_("If there is no date you can enter, please explain why.")
|
|
||||||
)
|
|
||||||
return False
|
|
||||||
return super_valid
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
pay = self.instance.add_payment(self)
|
|
||||||
return pay
|
|
||||||
|
|
||||||
|
|
||||||
class EditPaymentModalForm(NewPaymentForm):
|
|
||||||
""" Form handling edit for Payment
|
|
||||||
|
|
||||||
"""
|
|
||||||
payment = None
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.payment = kwargs.pop("payment", None)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.form_title = _("Edit payment")
|
|
||||||
form_date = {
|
|
||||||
"amount": self.payment.amount,
|
|
||||||
"due": str(self.payment.due_on),
|
|
||||||
"comment": self.payment.comment,
|
|
||||||
}
|
|
||||||
self.load_initial_data(form_date, disabled_fields=[])
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
payment = self.payment
|
|
||||||
payment.amount = self.cleaned_data.get("amount", None)
|
|
||||||
payment.due_on = self.cleaned_data.get("due", None)
|
|
||||||
payment.comment = self.cleaned_data.get("comment", None)
|
|
||||||
payment.save()
|
|
||||||
self.instance.mark_as_edited(self.user, self.request, edit_comment=PAYMENT_EDITED)
|
|
||||||
self.instance.send_data_to_egon()
|
|
||||||
return payment
|
|
||||||
|
|
||||||
|
|
||||||
class RemovePaymentModalForm(RemoveModalForm):
|
|
||||||
""" Removing modal form for Payment
|
|
||||||
|
|
||||||
Can be used for anything, where removing shall be confirmed by the user a second time.
|
|
||||||
|
|
||||||
"""
|
|
||||||
payment = None
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
payment = kwargs.pop("payment", None)
|
|
||||||
self.payment = payment
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
self.instance.remove_payment(self)
|
|
||||||
|
|
||||||
|
|
||||||
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.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="codes-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(NewStateModalForm):
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
||||||
class RemoveCompensationActionModalForm(RemoveModalForm):
|
|
||||||
""" Removing modal form for CompensationAction
|
|
||||||
|
|
||||||
Can be used for anything, where removing shall be confirmed by the user a second time.
|
|
||||||
|
|
||||||
"""
|
|
||||||
action = None
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
action = kwargs.pop("action", None)
|
|
||||||
self.action = action
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
self.instance.remove_action(self)
|
|
||||||
|
|
||||||
|
|
||||||
class NewDeadlineModalForm(BaseModalForm):
|
|
||||||
""" Form handling deadline related input
|
|
||||||
|
|
||||||
"""
|
|
||||||
type = forms.ChoiceField(
|
|
||||||
label=_("Deadline Type"),
|
|
||||||
label_suffix="",
|
|
||||||
required=True,
|
|
||||||
help_text=_("Select the deadline type"),
|
|
||||||
choices=DeadlineType.choices,
|
|
||||||
widget=forms.Select(
|
|
||||||
attrs={
|
|
||||||
"class": "form-control"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
date = forms.DateField(
|
|
||||||
label=_("Date"),
|
|
||||||
label_suffix="",
|
|
||||||
required=True,
|
|
||||||
help_text=_("Select date"),
|
|
||||||
widget=forms.DateInput(
|
|
||||||
attrs={
|
|
||||||
"type": "date",
|
|
||||||
"data-provide": "datepicker",
|
|
||||||
"class": "form-control",
|
|
||||||
},
|
|
||||||
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,
|
|
||||||
"class": "form-control",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
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):
|
|
||||||
deadline = self.instance.add_deadline(self)
|
|
||||||
return deadline
|
|
||||||
|
|
||||||
|
|
||||||
class EditDeadlineModalForm(NewDeadlineModalForm):
|
|
||||||
deadline = None
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.deadline = kwargs.pop("deadline", None)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.form_title = _("Edit deadline")
|
|
||||||
form_data = {
|
|
||||||
"type": self.deadline.type,
|
|
||||||
"date": str(self.deadline.date),
|
|
||||||
"comment": self.deadline.comment,
|
|
||||||
}
|
|
||||||
self.load_initial_data(form_data)
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
deadline = self.deadline
|
|
||||||
deadline.type = self.cleaned_data.get("type", None)
|
|
||||||
deadline.date = self.cleaned_data.get("date", None)
|
|
||||||
deadline.comment = self.cleaned_data.get("comment", None)
|
|
||||||
deadline.save()
|
|
||||||
self.instance.mark_as_edited(self.user, self.request, edit_comment=DEADLINE_EDITED)
|
|
||||||
return deadline
|
|
||||||
|
|
||||||
|
|
||||||
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).
|
|
||||||
|
|
||||||
"""
|
|
||||||
from compensation.models import UnitChoices
|
|
||||||
action_type = forms.MultipleChoiceField(
|
|
||||||
label=_("Action Type"),
|
|
||||||
label_suffix="",
|
|
||||||
required=True,
|
|
||||||
help_text=_("An action can consist of multiple different action types. All the selected action types are expected to be performed according to the amount and unit below on this form."),
|
|
||||||
choices=[],
|
|
||||||
widget=CompensationActionTreeCheckboxSelectMultiple(),
|
|
||||||
)
|
|
||||||
action_type_details = forms.ModelMultipleChoiceField(
|
|
||||||
label=_("Action Type detail"),
|
|
||||||
label_suffix="",
|
|
||||||
required=False,
|
|
||||||
help_text=_("Select the action type detail"),
|
|
||||||
queryset=KonovaCode.objects.filter(
|
|
||||||
is_archived=False,
|
|
||||||
is_leaf=True,
|
|
||||||
code_lists__in=[CODELIST_COMPENSATION_ACTION_DETAIL_ID],
|
|
||||||
),
|
|
||||||
widget=autocomplete.ModelSelect2Multiple(
|
|
||||||
url="codes-compensation-action-detail-autocomplete",
|
|
||||||
attrs={
|
|
||||||
"data-placeholder": _("Action Type detail"),
|
|
||||||
}
|
|
||||||
),
|
|
||||||
)
|
|
||||||
unit = forms.ChoiceField(
|
|
||||||
label=_("Unit"),
|
|
||||||
label_suffix="",
|
|
||||||
required=True,
|
|
||||||
help_text=_("Select the unit"),
|
|
||||||
choices=UnitChoices.choices,
|
|
||||||
widget=forms.Select(
|
|
||||||
attrs={
|
|
||||||
"class": "form-control"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
amount = forms.DecimalField(
|
|
||||||
label=_("Amount"),
|
|
||||||
label_suffix="",
|
|
||||||
required=True,
|
|
||||||
help_text=_("Insert the amount"),
|
|
||||||
decimal_places=2,
|
|
||||||
min_value=0.00,
|
|
||||||
widget=forms.NumberInput(
|
|
||||||
attrs={
|
|
||||||
"class": "form-control",
|
|
||||||
"placeholder": "0,00",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
)
|
|
||||||
comment = forms.CharField(
|
|
||||||
required=False,
|
|
||||||
label=_("Comment"),
|
|
||||||
label_suffix=_(""),
|
|
||||||
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 action")
|
|
||||||
self.form_caption = _("Insert data for the new action")
|
|
||||||
choices =KonovaCode.objects.filter(
|
|
||||||
code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
|
|
||||||
is_archived=False,
|
|
||||||
is_leaf=True,
|
|
||||||
).values_list("id", flat=True)
|
|
||||||
choices = [
|
|
||||||
(choice, choice)
|
|
||||||
for choice in choices
|
|
||||||
]
|
|
||||||
self.fields["action_type"].choices = choices
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
action = self.instance.add_action(self)
|
|
||||||
self.instance.mark_as_edited(self.user, self.request, ADDED_COMPENSATION_ACTION)
|
|
||||||
return action
|
|
||||||
|
|
||||||
|
|
||||||
class EditCompensationActionModalForm(NewActionModalForm):
|
|
||||||
action = None
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
self.action = kwargs.pop("action", None)
|
|
||||||
super().__init__(*args, **kwargs)
|
|
||||||
self.form_title = _("Edit action")
|
|
||||||
form_data = {
|
|
||||||
"action_type": list(self.action.action_type.values_list("id", flat=True)),
|
|
||||||
"action_type_details": self.action.action_type_details.all(),
|
|
||||||
"amount": self.action.amount,
|
|
||||||
"unit": self.action.unit,
|
|
||||||
"comment": self.action.comment,
|
|
||||||
}
|
|
||||||
self.load_initial_data(form_data)
|
|
||||||
|
|
||||||
def save(self):
|
|
||||||
action = self.action
|
|
||||||
action.action_type.set(self.cleaned_data.get("action_type", []))
|
|
||||||
action.action_type_details.set(self.cleaned_data.get("action_type_details", []))
|
|
||||||
action.amount = self.cleaned_data.get("amount", None)
|
|
||||||
action.unit = self.cleaned_data.get("unit", None)
|
|
||||||
action.comment = self.cleaned_data.get("comment", None)
|
|
||||||
action.save()
|
|
||||||
self.instance.mark_as_edited(self.user, self.request, edit_comment=COMPENSATION_ACTION_EDITED)
|
|
||||||
return action
|
|
||||||
|
|
||||||
|
|
||||||
class NewCompensationDocumentModalForm(NewDocumentModalForm):
|
|
||||||
document_model = CompensationDocument
|
|
||||||
|
|
||||||
|
|
||||||
class NewEcoAccountDocumentModalForm(NewDocumentModalForm):
|
|
||||||
document_model = EcoAccountDocument
|
|
7
compensation/forms/modals/__init__.py
Normal file
7
compensation/forms/modals/__init__.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
155
compensation/forms/modals/compensation_action.py
Normal file
155
compensation/forms/modals/compensation_action.py
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
from dal import autocomplete
|
||||||
|
from django import forms
|
||||||
|
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 intervention.inputs import CompensationActionTreeCheckboxSelectMultiple
|
||||||
|
from konova.forms.modals import BaseModalForm, RemoveModalForm
|
||||||
|
from konova.utils.message_templates import COMPENSATION_ACTION_EDITED, ADDED_COMPENSATION_ACTION
|
||||||
|
|
||||||
|
|
||||||
|
class NewCompensationActionModalForm(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).
|
||||||
|
|
||||||
|
"""
|
||||||
|
from compensation.models import UnitChoices
|
||||||
|
action_type = forms.MultipleChoiceField(
|
||||||
|
label=_("Action Type"),
|
||||||
|
label_suffix="",
|
||||||
|
required=True,
|
||||||
|
help_text=_("An action can consist of multiple different action types. All the selected action types are expected to be performed according to the amount and unit below on this form."),
|
||||||
|
choices=[],
|
||||||
|
widget=CompensationActionTreeCheckboxSelectMultiple(),
|
||||||
|
)
|
||||||
|
action_type_details = forms.ModelMultipleChoiceField(
|
||||||
|
label=_("Action Type detail"),
|
||||||
|
label_suffix="",
|
||||||
|
required=False,
|
||||||
|
help_text=_("Select the action type detail"),
|
||||||
|
queryset=KonovaCode.objects.filter(
|
||||||
|
is_archived=False,
|
||||||
|
is_leaf=True,
|
||||||
|
code_lists__in=[CODELIST_COMPENSATION_ACTION_DETAIL_ID],
|
||||||
|
),
|
||||||
|
widget=autocomplete.ModelSelect2Multiple(
|
||||||
|
url="codes-compensation-action-detail-autocomplete",
|
||||||
|
attrs={
|
||||||
|
"data-placeholder": _("Action Type detail"),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
)
|
||||||
|
unit = forms.ChoiceField(
|
||||||
|
label=_("Unit"),
|
||||||
|
label_suffix="",
|
||||||
|
required=True,
|
||||||
|
help_text=_("Select the unit"),
|
||||||
|
choices=UnitChoices.choices,
|
||||||
|
widget=forms.Select(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
amount = forms.DecimalField(
|
||||||
|
label=_("Amount"),
|
||||||
|
label_suffix="",
|
||||||
|
required=True,
|
||||||
|
help_text=_("Insert the amount"),
|
||||||
|
decimal_places=2,
|
||||||
|
min_value=0.00,
|
||||||
|
widget=forms.NumberInput(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control",
|
||||||
|
"placeholder": "0,00",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
comment = forms.CharField(
|
||||||
|
required=False,
|
||||||
|
label=_("Comment"),
|
||||||
|
label_suffix=_(""),
|
||||||
|
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 action")
|
||||||
|
self.form_caption = _("Insert data for the new action")
|
||||||
|
choices =KonovaCode.objects.filter(
|
||||||
|
code_lists__in=[CODELIST_COMPENSATION_ACTION_ID],
|
||||||
|
is_archived=False,
|
||||||
|
is_leaf=True,
|
||||||
|
).values_list("id", flat=True)
|
||||||
|
choices = [
|
||||||
|
(choice, choice)
|
||||||
|
for choice in choices
|
||||||
|
]
|
||||||
|
self.fields["action_type"].choices = choices
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
action = self.instance.add_action(self)
|
||||||
|
self.instance.mark_as_edited(self.user, self.request, ADDED_COMPENSATION_ACTION)
|
||||||
|
return action
|
||||||
|
|
||||||
|
|
||||||
|
class EditCompensationActionModalForm(NewCompensationActionModalForm):
|
||||||
|
action = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.action = kwargs.pop("action", None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.form_title = _("Edit action")
|
||||||
|
form_data = {
|
||||||
|
"action_type": list(self.action.action_type.values_list("id", flat=True)),
|
||||||
|
"action_type_details": self.action.action_type_details.all(),
|
||||||
|
"amount": self.action.amount,
|
||||||
|
"unit": self.action.unit,
|
||||||
|
"comment": self.action.comment,
|
||||||
|
}
|
||||||
|
self.load_initial_data(form_data)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
action = self.action
|
||||||
|
action.action_type.set(self.cleaned_data.get("action_type", []))
|
||||||
|
action.action_type_details.set(self.cleaned_data.get("action_type_details", []))
|
||||||
|
action.amount = self.cleaned_data.get("amount", None)
|
||||||
|
action.unit = self.cleaned_data.get("unit", None)
|
||||||
|
action.comment = self.cleaned_data.get("comment", None)
|
||||||
|
action.save()
|
||||||
|
self.instance.mark_as_edited(self.user, self.request, edit_comment=COMPENSATION_ACTION_EDITED)
|
||||||
|
return action
|
||||||
|
|
||||||
|
|
||||||
|
class RemoveCompensationActionModalForm(RemoveModalForm):
|
||||||
|
""" Removing modal form for CompensationAction
|
||||||
|
|
||||||
|
Can be used for anything, where removing shall be confirmed by the user a second time.
|
||||||
|
|
||||||
|
"""
|
||||||
|
action = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
action = kwargs.pop("action", None)
|
||||||
|
self.action = action
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
self.instance.remove_action(self)
|
92
compensation/forms/modals/deadline.py
Normal file
92
compensation/forms/modals/deadline.py
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
|
from konova.forms.modals import BaseModalForm
|
||||||
|
from konova.models import DeadlineType
|
||||||
|
from konova.utils.message_templates import DEADLINE_EDITED
|
||||||
|
|
||||||
|
|
||||||
|
class NewDeadlineModalForm(BaseModalForm):
|
||||||
|
""" Form handling deadline related input
|
||||||
|
|
||||||
|
"""
|
||||||
|
type = forms.ChoiceField(
|
||||||
|
label=_("Deadline Type"),
|
||||||
|
label_suffix="",
|
||||||
|
required=True,
|
||||||
|
help_text=_("Select the deadline type"),
|
||||||
|
choices=DeadlineType.choices,
|
||||||
|
widget=forms.Select(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
date = forms.DateField(
|
||||||
|
label=_("Date"),
|
||||||
|
label_suffix="",
|
||||||
|
required=True,
|
||||||
|
help_text=_("Select date"),
|
||||||
|
widget=forms.DateInput(
|
||||||
|
attrs={
|
||||||
|
"type": "date",
|
||||||
|
"data-provide": "datepicker",
|
||||||
|
"class": "form-control",
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
"class": "form-control",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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):
|
||||||
|
deadline = self.instance.add_deadline(self)
|
||||||
|
return deadline
|
||||||
|
|
||||||
|
|
||||||
|
class EditDeadlineModalForm(NewDeadlineModalForm):
|
||||||
|
deadline = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.deadline = kwargs.pop("deadline", None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.form_title = _("Edit deadline")
|
||||||
|
form_data = {
|
||||||
|
"type": self.deadline.type,
|
||||||
|
"date": str(self.deadline.date),
|
||||||
|
"comment": self.deadline.comment,
|
||||||
|
}
|
||||||
|
self.load_initial_data(form_data)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
deadline = self.deadline
|
||||||
|
deadline.type = self.cleaned_data.get("type", None)
|
||||||
|
deadline.date = self.cleaned_data.get("date", None)
|
||||||
|
deadline.comment = self.cleaned_data.get("comment", None)
|
||||||
|
deadline.save()
|
||||||
|
self.instance.mark_as_edited(self.user, self.request, edit_comment=DEADLINE_EDITED)
|
||||||
|
return deadline
|
17
compensation/forms/modals/document.py
Normal file
17
compensation/forms/modals/document.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
from compensation.models import CompensationDocument, EcoAccountDocument
|
||||||
|
from konova.forms.modals import NewDocumentModalForm
|
||||||
|
|
||||||
|
|
||||||
|
class NewCompensationDocumentModalForm(NewDocumentModalForm):
|
||||||
|
document_model = CompensationDocument
|
||||||
|
|
||||||
|
|
||||||
|
class NewEcoAccountDocumentModalForm(NewDocumentModalForm):
|
||||||
|
document_model = EcoAccountDocument
|
136
compensation/forms/modals/payment.py
Normal file
136
compensation/forms/modals/payment.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
"""
|
||||||
|
Author: Michel Peltriaux
|
||||||
|
Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
|
||||||
|
Contact: ksp-servicestelle@sgdnord.rlp.de
|
||||||
|
Created on: 18.08.22
|
||||||
|
|
||||||
|
"""
|
||||||
|
from django import forms
|
||||||
|
from django.utils.translation import pgettext_lazy as _con, gettext_lazy as _
|
||||||
|
|
||||||
|
from konova.forms.modals import RemoveModalForm, BaseModalForm
|
||||||
|
from konova.utils.message_templates import PAYMENT_EDITED
|
||||||
|
|
||||||
|
|
||||||
|
class NewPaymentForm(BaseModalForm):
|
||||||
|
""" Form handling payment related input
|
||||||
|
|
||||||
|
"""
|
||||||
|
amount = forms.DecimalField(
|
||||||
|
min_value=0.00,
|
||||||
|
decimal_places=2,
|
||||||
|
label=_con("money", "Amount"), # contextual translation
|
||||||
|
label_suffix=_(""),
|
||||||
|
help_text=_("in Euro"),
|
||||||
|
widget=forms.NumberInput(
|
||||||
|
attrs={
|
||||||
|
"class": "form-control",
|
||||||
|
"placeholder": "0,00",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
due = forms.DateField(
|
||||||
|
label=_("Due on"),
|
||||||
|
label_suffix=_(""),
|
||||||
|
required=False,
|
||||||
|
help_text=_("Due on which date"),
|
||||||
|
widget=forms.DateInput(
|
||||||
|
attrs={
|
||||||
|
"type": "date",
|
||||||
|
"data-provide": "datepicker",
|
||||||
|
"class": "form-control",
|
||||||
|
},
|
||||||
|
format="%d.%m.%Y"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
comment = forms.CharField(
|
||||||
|
max_length=200,
|
||||||
|
required=False,
|
||||||
|
label=_("Comment"),
|
||||||
|
label_suffix=_(""),
|
||||||
|
help_text=_("Additional comment, maximum {} letters").format(200),
|
||||||
|
widget=forms.Textarea(
|
||||||
|
attrs={
|
||||||
|
"rows": 5,
|
||||||
|
"class": "form-control"
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
def is_valid(self):
|
||||||
|
"""
|
||||||
|
Checks on form validity.
|
||||||
|
|
||||||
|
For this form we need to make sure that a date or a comment is set.
|
||||||
|
If both are missing, the user needs to enter at least an explanation why
|
||||||
|
there is no date to be entered.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
is_valid (bool): True if valid, False otherwise
|
||||||
|
"""
|
||||||
|
super_valid = super().is_valid()
|
||||||
|
date = self.cleaned_data["due"]
|
||||||
|
comment = self.cleaned_data["comment"] or None
|
||||||
|
if not date and not comment:
|
||||||
|
# At least one needs to be set!
|
||||||
|
self.add_error(
|
||||||
|
"comment",
|
||||||
|
_("If there is no date you can enter, please explain why.")
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
return super_valid
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
pay = self.instance.add_payment(self)
|
||||||
|
return pay
|
||||||
|
|
||||||
|
|
||||||
|
class EditPaymentModalForm(NewPaymentForm):
|
||||||
|
""" Form handling edit for Payment
|
||||||
|
|
||||||
|
"""
|
||||||
|
payment = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.payment = kwargs.pop("payment", None)
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.form_title = _("Edit payment")
|
||||||
|
form_date = {
|
||||||
|
"amount": self.payment.amount,
|
||||||
|
"due": str(self.payment.due_on),
|
||||||
|
"comment": self.payment.comment,
|
||||||
|
}
|
||||||
|
self.load_initial_data(form_date, disabled_fields=[])
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
payment = self.payment
|
||||||
|
payment.amount = self.cleaned_data.get("amount", None)
|
||||||
|
payment.due_on = self.cleaned_data.get("due", None)
|
||||||
|
payment.comment = self.cleaned_data.get("comment", None)
|
||||||
|
payment.save()
|
||||||
|
self.instance.mark_as_edited(self.user, self.request, edit_comment=PAYMENT_EDITED)
|
||||||
|
self.instance.send_data_to_egon()
|
||||||
|
return payment
|
||||||
|
|
||||||
|
|
||||||
|
class RemovePaymentModalForm(RemoveModalForm):
|
||||||
|
""" Removing modal form for Payment
|
||||||
|
|
||||||
|
Can be used for anything, where removing shall be confirmed by the user a second time.
|
||||||
|
|
||||||
|
"""
|
||||||
|
payment = None
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
payment = kwargs.pop("payment", None)
|
||||||
|
self.payment = payment
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
def save(self):
|
||||||
|
self.instance.remove_payment(self)
|
179
compensation/forms/modals/state.py
Normal file
179
compensation/forms/modals/state.py
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
"""
|
||||||
|
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.utils 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="codes-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)
|
@ -5,10 +5,12 @@ from django.http import HttpRequest, JsonResponse
|
|||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from compensation.forms.forms import NewCompensationForm, EditCompensationForm
|
from compensation.forms.compensation import NewCompensationForm, EditCompensationForm
|
||||||
from compensation.forms.modalForms import NewStateModalForm, NewDeadlineModalForm, NewActionModalForm, \
|
from compensation.forms.modals.state import NewCompensationStateModalForm, RemoveCompensationStateModalForm, EditCompensationStateModalForm
|
||||||
NewCompensationDocumentModalForm, RemoveCompensationActionModalForm, RemoveCompensationStateModalForm, \
|
from compensation.forms.modals.document import NewCompensationDocumentModalForm
|
||||||
EditCompensationStateModalForm, EditCompensationActionModalForm, EditDeadlineModalForm
|
from compensation.forms.modals.compensation_action import NewCompensationActionModalForm, \
|
||||||
|
EditCompensationActionModalForm, RemoveCompensationActionModalForm
|
||||||
|
from compensation.forms.modals.deadline import NewDeadlineModalForm, EditDeadlineModalForm
|
||||||
from compensation.models import Compensation, CompensationState, CompensationAction, CompensationDocument
|
from compensation.models import Compensation, CompensationState, CompensationAction, CompensationDocument
|
||||||
from compensation.tables import CompensationTable
|
from compensation.tables import CompensationTable
|
||||||
from intervention.models import Intervention
|
from intervention.models import Intervention
|
||||||
@ -21,7 +23,7 @@ from konova.models import Deadline
|
|||||||
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
||||||
from konova.utils.documents import get_document, remove_document
|
from konova.utils.documents import get_document, remove_document
|
||||||
from konova.utils.generators import generate_qr_code
|
from konova.utils.generators import generate_qr_code
|
||||||
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, DATA_UNSHARED_EXPLANATION, \
|
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, \
|
||||||
CHECKED_RECORDED_RESET, COMPENSATION_ADDED_TEMPLATE, COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED, \
|
CHECKED_RECORDED_RESET, COMPENSATION_ADDED_TEMPLATE, COMPENSATION_REMOVED_TEMPLATE, DOCUMENT_ADDED, \
|
||||||
COMPENSATION_STATE_REMOVED, COMPENSATION_STATE_ADDED, COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_ADDED, \
|
COMPENSATION_STATE_REMOVED, COMPENSATION_STATE_ADDED, COMPENSATION_ACTION_REMOVED, COMPENSATION_ACTION_ADDED, \
|
||||||
DEADLINE_ADDED, DEADLINE_REMOVED, DOCUMENT_EDITED, COMPENSATION_STATE_EDITED, COMPENSATION_ACTION_EDITED, \
|
DEADLINE_ADDED, DEADLINE_REMOVED, DOCUMENT_EDITED, COMPENSATION_STATE_EDITED, COMPENSATION_ACTION_EDITED, \
|
||||||
@ -402,7 +404,7 @@ def state_new_view(request: HttpRequest, id: str):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
comp = get_object_or_404(Compensation, id=id)
|
comp = get_object_or_404(Compensation, id=id)
|
||||||
form = NewStateModalForm(request.POST or None, instance=comp, request=request)
|
form = NewCompensationStateModalForm(request.POST or None, instance=comp, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request,
|
request,
|
||||||
msg_success=COMPENSATION_STATE_ADDED,
|
msg_success=COMPENSATION_STATE_ADDED,
|
||||||
@ -424,7 +426,7 @@ def action_new_view(request: HttpRequest, id: str):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
comp = get_object_or_404(Compensation, id=id)
|
comp = get_object_or_404(Compensation, id=id)
|
||||||
form = NewActionModalForm(request.POST or None, instance=comp, request=request)
|
form = NewCompensationActionModalForm(request.POST or None, instance=comp, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request,
|
request,
|
||||||
msg_success=COMPENSATION_ACTION_ADDED,
|
msg_success=COMPENSATION_ACTION_ADDED,
|
||||||
|
@ -14,10 +14,13 @@ from django.core.exceptions import ObjectDoesNotExist
|
|||||||
from django.http import HttpRequest, Http404, JsonResponse
|
from django.http import HttpRequest, Http404, JsonResponse
|
||||||
from django.shortcuts import render, get_object_or_404, redirect
|
from django.shortcuts import render, get_object_or_404, redirect
|
||||||
|
|
||||||
from compensation.forms.forms import NewEcoAccountForm, EditEcoAccountForm
|
from compensation.forms.eco_account import NewEcoAccountForm, EditEcoAccountForm
|
||||||
from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm, \
|
from compensation.forms.modals.compensation_action import NewCompensationActionModalForm, \
|
||||||
NewEcoAccountDocumentModalForm, RemoveCompensationActionModalForm, RemoveCompensationStateModalForm, \
|
RemoveCompensationActionModalForm, EditCompensationActionModalForm
|
||||||
EditCompensationStateModalForm, EditCompensationActionModalForm, EditDeadlineModalForm
|
from compensation.forms.modals.deadline import EditDeadlineModalForm, NewDeadlineModalForm
|
||||||
|
from compensation.forms.modals.document import NewEcoAccountDocumentModalForm
|
||||||
|
from compensation.forms.modals.state import NewCompensationStateModalForm, RemoveCompensationStateModalForm, \
|
||||||
|
EditCompensationStateModalForm
|
||||||
from compensation.models import EcoAccount, EcoAccountDocument, CompensationState, CompensationAction
|
from compensation.models import EcoAccount, EcoAccountDocument, CompensationState, CompensationAction
|
||||||
from compensation.tables import EcoAccountTable
|
from compensation.tables import EcoAccountTable
|
||||||
from intervention.forms.modalForms import NewDeductionModalForm, ShareModalForm, RemoveEcoAccountDeductionModalForm, \
|
from intervention.forms.modalForms import NewDeductionModalForm, ShareModalForm, RemoveEcoAccountDeductionModalForm, \
|
||||||
@ -401,7 +404,7 @@ def state_new_view(request: HttpRequest, id: str):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
acc = get_object_or_404(EcoAccount, id=id)
|
acc = get_object_or_404(EcoAccount, id=id)
|
||||||
form = NewStateModalForm(request.POST or None, instance=acc, request=request)
|
form = NewCompensationStateModalForm(request.POST or None, instance=acc, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request,
|
request,
|
||||||
msg_success=COMPENSATION_STATE_ADDED,
|
msg_success=COMPENSATION_STATE_ADDED,
|
||||||
@ -423,7 +426,7 @@ def action_new_view(request: HttpRequest, id: str):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
acc = get_object_or_404(EcoAccount, id=id)
|
acc = get_object_or_404(EcoAccount, id=id)
|
||||||
form = NewActionModalForm(request.POST or None, instance=acc, request=request)
|
form = NewCompensationActionModalForm(request.POST or None, instance=acc, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request,
|
request,
|
||||||
msg_success=COMPENSATION_ACTION_ADDED,
|
msg_success=COMPENSATION_ACTION_ADDED,
|
||||||
|
@ -6,12 +6,11 @@ Created on: 09.08.21
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.http import HttpRequest
|
from django.http import HttpRequest
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
|
|
||||||
from compensation.forms.modalForms import NewPaymentForm, RemovePaymentModalForm, EditPaymentModalForm
|
from compensation.forms.modals.payment import NewPaymentForm, RemovePaymentModalForm, EditPaymentModalForm
|
||||||
from compensation.models import Payment
|
from compensation.models import Payment
|
||||||
from intervention.models import Intervention
|
from intervention.models import Intervention
|
||||||
from konova.decorators import default_group_required, shared_access_required
|
from konova.decorators import default_group_required, shared_access_required
|
||||||
|
@ -10,8 +10,8 @@ from django.db import transaction
|
|||||||
from django.urls import reverse, reverse_lazy
|
from django.urls import reverse, reverse_lazy
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from compensation.forms.forms import AbstractCompensationForm, CompensationResponsibleFormMixin, \
|
from compensation.forms.mixins import CompensationResponsibleFormMixin, PikCompensationFormMixin
|
||||||
PikCompensationFormMixin
|
from compensation.forms.compensation import AbstractCompensationForm
|
||||||
from ema.models import Ema, EmaDocument
|
from ema.models import Ema, EmaDocument
|
||||||
from intervention.models import Responsibility, Handler
|
from intervention.models import Responsibility, Handler
|
||||||
from konova.forms import SimpleGeomForm
|
from konova.forms import SimpleGeomForm
|
||||||
|
12
ema/views.py
12
ema/views.py
@ -6,9 +6,11 @@ from django.shortcuts import render, get_object_or_404, redirect
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm, \
|
from compensation.forms.modals.compensation_action import NewCompensationActionModalForm, \
|
||||||
RemoveCompensationActionModalForm, RemoveCompensationStateModalForm, EditCompensationStateModalForm, \
|
EditCompensationActionModalForm, RemoveCompensationActionModalForm
|
||||||
EditCompensationActionModalForm, EditDeadlineModalForm
|
from compensation.forms.modals.deadline import NewDeadlineModalForm, EditDeadlineModalForm
|
||||||
|
from compensation.forms.modals.state import NewCompensationStateModalForm, RemoveCompensationStateModalForm, \
|
||||||
|
EditCompensationStateModalForm
|
||||||
from compensation.models import CompensationAction, CompensationState
|
from compensation.models import CompensationAction, CompensationState
|
||||||
from ema.forms import NewEmaForm, EditEmaForm, NewEmaDocumentModalForm
|
from ema.forms import NewEmaForm, EditEmaForm, NewEmaDocumentModalForm
|
||||||
from ema.tables import EmaTable
|
from ema.tables import EmaTable
|
||||||
@ -303,7 +305,7 @@ def state_new_view(request: HttpRequest, id: str):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
ema = get_object_or_404(Ema, id=id)
|
ema = get_object_or_404(Ema, id=id)
|
||||||
form = NewStateModalForm(request.POST or None, instance=ema, request=request)
|
form = NewCompensationStateModalForm(request.POST or None, instance=ema, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request,
|
request,
|
||||||
msg_success=COMPENSATION_STATE_ADDED,
|
msg_success=COMPENSATION_STATE_ADDED,
|
||||||
@ -325,7 +327,7 @@ def action_new_view(request: HttpRequest, id: str):
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
ema = get_object_or_404(Ema, id=id)
|
ema = get_object_or_404(Ema, id=id)
|
||||||
form = NewActionModalForm(request.POST or None, instance=ema, request=request)
|
form = NewCompensationActionModalForm(request.POST or None, instance=ema, request=request)
|
||||||
return form.process_request(
|
return form.process_request(
|
||||||
request,
|
request,
|
||||||
msg_success=COMPENSATION_ACTION_ADDED,
|
msg_success=COMPENSATION_ACTION_ADDED,
|
||||||
|
Loading…
Reference in New Issue
Block a user