diff --git a/compensation/forms/forms.py b/compensation/forms/forms.py
index 7c922f19..000cea2b 100644
--- a/compensation/forms/forms.py
+++ b/compensation/forms/forms.py
@@ -85,10 +85,61 @@ class AbstractCompensationForm(BaseForm):
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 = forms.CharField(
+ label=_("Eco-account handler"),
+ label_suffix="",
+ max_length=255,
+ required=False,
+ help_text=_("Who handles the eco-account"),
+ widget=forms.TextInput(
+ attrs={
+ "placeholder": _("Company Mustermann"),
+ "class": "form-control",
+ }
+ )
+ )
+
+
class NewCompensationForm(AbstractCompensationForm):
""" 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(
@@ -172,6 +223,9 @@ class NewCompensationForm(AbstractCompensationForm):
class EditCompensationForm(NewCompensationForm):
+ """ Form for editing compensations
+
+ """
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.form_title = _("Edit compensation")
@@ -224,48 +278,12 @@ class EditCompensationForm(NewCompensationForm):
return self.instance
-class NewEcoAccountForm(AbstractCompensationForm):
- 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 = forms.CharField(
- label=_("Eco-account handler"),
- label_suffix="",
- max_length=255,
- required=False,
- help_text=_("Who handles the eco-account"),
- widget=forms.TextInput(
- attrs={
- "placeholder": _("Company Mustermann"),
- "class": "form-control",
- }
- )
- )
+class NewEcoAccountForm(AbstractCompensationForm, CompensationResponsibleFormMixin):
+ """ Form for creating eco accounts
+
+ Inherits from basic AbstractCompensationForm and further form fields from CompensationResponsibleFormMixin
+
+ """
field_order = [
"identifier",
"title",
@@ -333,6 +351,9 @@ class NewEcoAccountForm(AbstractCompensationForm):
class EditEcoAccountForm(NewEcoAccountForm):
+ """ Form for editing eco accounts
+
+ """
surface = forms.DecimalField(
min_value=0.00,
decimal_places=2,
diff --git a/compensation/templates/compensation/new/view.html b/compensation/templates/compensation/form/view.html
similarity index 100%
rename from compensation/templates/compensation/new/view.html
rename to compensation/templates/compensation/form/view.html
diff --git a/compensation/views/compensation_views.py b/compensation/views/compensation_views.py
index 4778e6d0..0d56d817 100644
--- a/compensation/views/compensation_views.py
+++ b/compensation/views/compensation_views.py
@@ -58,7 +58,7 @@ def new_view(request: HttpRequest, intervention_id: str = None):
Returns:
"""
- template = "compensation/new/view.html"
+ template = "compensation/form/view.html"
data_form = NewCompensationForm(request.POST or None, intervention_id=intervention_id)
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
if request.method == "POST":
@@ -83,7 +83,6 @@ def new_view(request: HttpRequest, intervention_id: str = None):
context = {
"form": data_form,
"geom_form": geom_form,
- "url": reverse("compensation:new-id")
}
context = BaseContext(request, context).context
return render(request, template, context)
@@ -119,7 +118,7 @@ def edit_view(request: HttpRequest, id: str):
Returns:
"""
- template = "compensation/new/view.html"
+ template = "compensation/form/view.html"
# Get object from db
comp = get_object_or_404(Compensation, id=id)
# Create forms, initialize with values from db/from POST request
diff --git a/compensation/views/eco_account_views.py b/compensation/views/eco_account_views.py
index c0cbc781..476bd977 100644
--- a/compensation/views/eco_account_views.py
+++ b/compensation/views/eco_account_views.py
@@ -68,7 +68,7 @@ def new_view(request: HttpRequest):
Returns:
"""
- template = "compensation/new/view.html"
+ template = "compensation/form/view.html"
data_form = NewEcoAccountForm(request.POST or None)
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
if request.method == "POST":
@@ -93,7 +93,6 @@ def new_view(request: HttpRequest):
context = {
"form": data_form,
"geom_form": geom_form,
- "url": reverse("compensation:acc-new-id")
}
context = BaseContext(request, context).context
return render(request, template, context)
@@ -129,7 +128,7 @@ def edit_view(request: HttpRequest, id: str):
Returns:
"""
- template = "compensation/new/view.html"
+ template = "compensation/form/view.html"
# Get object from db
acc = get_object_or_404(EcoAccount, id=id)
# Create forms, initialize with values from db/from POST request
diff --git a/ema/forms.py b/ema/forms.py
new file mode 100644
index 00000000..d516259a
--- /dev/null
+++ b/ema/forms.py
@@ -0,0 +1,159 @@
+"""
+Author: Michel Peltriaux
+Organization: Struktur- und Genehmigungsdirektion Nord, Rhineland-Palatinate, Germany
+Contact: michel.peltriaux@sgdnord.rlp.de
+Created on: 06.10.21
+
+"""
+from django.contrib.auth.models import User
+from django.db import transaction
+from django.urls import reverse, reverse_lazy
+from django.utils.translation import gettext_lazy as _
+from compensation.forms.forms import AbstractCompensationForm, CompensationResponsibleFormMixin
+from ema.models import Ema
+from intervention.models import ResponsibilityData
+from konova.forms import SimpleGeomForm
+from user.models import UserActionLogEntry, UserAction
+
+
+class NewEmaForm(AbstractCompensationForm, CompensationResponsibleFormMixin):
+ """ Form for creating new EMA objects.
+
+ Inherits basic form fields from AbstractCompensationForm and additional from CompensationResponsibleFormMixin.
+ Second holds self.instance.response related fields
+
+ """
+ field_order = [
+ "identifier",
+ "title",
+ "conservation_office",
+ "conservation_file_number",
+ "handler",
+ "fundings",
+ "comment",
+ ]
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.form_title = _("New EMA")
+
+ self.action_url = reverse("ema:new")
+ self.cancel_redirect = reverse("ema:index")
+
+ tmp = Ema()
+ identifier = tmp.generate_new_identifier()
+ self.initialize_form_field("identifier", identifier)
+ self.fields["identifier"].widget.attrs["url"] = reverse_lazy("ema:new-id")
+ self.fields["title"].widget.attrs["placeholder"] = _("Compensation 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)
+ fundings = self.cleaned_data.get("fundings", None)
+ handler = self.cleaned_data.get("handler", 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)
+
+ # Create log entry
+ action = UserActionLogEntry.objects.create(
+ user=user,
+ action=UserAction.CREATED,
+ )
+ # Process the geometry form
+ geometry = geom_form.save(action)
+
+ responsible = ResponsibilityData.objects.create(
+ handler=handler,
+ conservation_file_number=conservation_file_number,
+ conservation_office=conservation_office,
+ )
+
+ # Finally create main object
+ acc = Ema.objects.create(
+ identifier=identifier,
+ title=title,
+ responsible=responsible,
+ created=action,
+ geometry=geometry,
+ comment=comment,
+ )
+ acc.fundings.set(fundings)
+
+ # Add the creating user to the list of shared users
+ acc.users.add(user)
+
+ # Add the log entry to the main objects log list
+ acc.log.add(action)
+ return acc
+
+
+class EditEmaForm(NewEmaForm):
+ """ Form for editing EMAs
+
+ """
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+ self.form_title = _("Edit EMA")
+
+ self.action_url = reverse("ema:edit", args=(self.instance.id,))
+ self.cancel_redirect = reverse("ema:open", args=(self.instance.id,))
+
+ self.fields["identifier"].widget.attrs["url"] = reverse_lazy("ema:new-id")
+ self.fields["title"].widget.attrs["placeholder"] = _("Compensation XY; Location ABC")
+
+ # Initialize form data
+ form_data = {
+ "identifier": self.instance.identifier,
+ "title": self.instance.title,
+ "handler": self.instance.responsible.handler,
+ "conservation_office": self.instance.responsible.conservation_office,
+ "conservation_file_number": self.instance.responsible.conservation_file_number,
+ "fundings": self.instance.fundings.all(),
+ "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)
+ fundings = self.cleaned_data.get("fundings", None)
+ handler = self.cleaned_data.get("handler", 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)
+
+ # Create log entry
+ action = UserActionLogEntry.objects.create(
+ user=user,
+ action=UserAction.EDITED,
+ )
+ # Process the geometry form
+ geometry = geom_form.save(action)
+
+ # Update responsible data
+ self.instance.responsible.handler = handler
+ self.instance.responsible.conservation_office = conservation_office
+ self.instance.responsible.conservation_file_number = conservation_file_number
+ self.instance.responsible.save()
+
+ # Update main oject data
+ self.instance.identifier = identifier
+ self.instance.title = title
+ self.instance.geometry = geometry
+ self.instance.comment = comment
+ self.instance.modified = action
+ self.instance.save()
+ self.instance.fundings.set(fundings)
+
+ # Add the log entry to the main objects log list
+ self.instance.log.add(action)
+ return self.instance
diff --git a/ema/templates/ema/detail/includes/controls.html b/ema/templates/ema/detail/includes/controls.html
index 9dc960fa..8b24f66e 100644
--- a/ema/templates/ema/detail/includes/controls.html
+++ b/ema/templates/ema/detail/includes/controls.html
@@ -24,7 +24,7 @@
{% endif %}
{% endif %}
{% if is_default_member %}
-
+
diff --git a/intervention/templates/intervention/new/view.html b/ema/templates/ema/form/view.html
similarity index 100%
rename from intervention/templates/intervention/new/view.html
rename to ema/templates/ema/form/view.html
diff --git a/ema/urls.py b/ema/urls.py
index 860d863b..404cdf53 100644
--- a/ema/urls.py
+++ b/ema/urls.py
@@ -12,6 +12,7 @@ app_name = "ema"
urlpatterns = [
path("", index_view, name="index"),
path("new/", new_view, name="new"),
+ path("new/id", new_id_view, name="new-id"),
path("", open_view, name="open"),
path('/log', log_view, name='log'),
path('/edit', edit_view, name='edit'),
diff --git a/ema/views.py b/ema/views.py
index 914c4129..e479c17b 100644
--- a/ema/views.py
+++ b/ema/views.py
@@ -1,12 +1,14 @@
+from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.db.models import Sum
-from django.http import HttpRequest
-from django.shortcuts import render, get_object_or_404
+from django.http import HttpRequest, JsonResponse
+from django.shortcuts import render, get_object_or_404, redirect
from django.urls import reverse
from django.utils.translation import gettext_lazy as _
import compensation
from compensation.forms.modalForms import NewStateModalForm, NewActionModalForm, NewDeadlineModalForm
+from ema.forms import NewEmaForm, EditEmaForm
from ema.tables import EmaTable
from konova.contexts import BaseContext
from konova.decorators import conservation_office_group_required
@@ -14,6 +16,7 @@ from ema.models import Ema, EmaDocument
from konova.forms import RemoveModalForm, NewDocumentForm, SimpleGeomForm, RecordModalForm
from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP
from konova.utils.documents import get_document, remove_document
+from konova.utils.message_templates import IDENTIFIER_REPLACED, FORM_INVALID
from konova.utils.user_checks import in_group
@@ -47,7 +50,8 @@ def index_view(request: HttpRequest):
@login_required
@conservation_office_group_required
def new_view(request: HttpRequest):
- """ Renders the form for a new EMA
+ """
+ Renders a view for a new eco account creation
Args:
request (HttpRequest): The incoming request
@@ -55,12 +59,54 @@ def new_view(request: HttpRequest):
Returns:
"""
- template = "generic_index.html"
- context = {}
+ template = "ema/form/view.html"
+ data_form = NewEmaForm(request.POST or None)
+ geom_form = SimpleGeomForm(request.POST or None, read_only=False)
+ if request.method == "POST":
+ if data_form.is_valid() and geom_form.is_valid():
+ generated_identifier = data_form.cleaned_data.get("identifier", None)
+ ema = data_form.save(request.user, geom_form)
+ if generated_identifier != ema.identifier:
+ messages.info(
+ request,
+ IDENTIFIER_REPLACED.format(
+ generated_identifier,
+ ema.identifier
+ )
+ )
+ messages.success(request, _("EMA {} added").format(ema.identifier))
+ return redirect("ema:open", id=ema.id)
+ else:
+ messages.error(request, FORM_INVALID)
+ else:
+ # For clarification: nothing in this case
+ pass
+ context = {
+ "form": data_form,
+ "geom_form": geom_form,
+ }
context = BaseContext(request, context).context
return render(request, template, context)
+@login_required
+def new_id_view(request: HttpRequest):
+ """ JSON endpoint
+
+ Provides fetching of free identifiers for e.g. AJAX calls
+
+ """
+ tmp = Ema()
+ identifier = tmp.generate_new_identifier()
+ while Ema.objects.filter(identifier=identifier).exists():
+ identifier = tmp.generate_new_identifier()
+ return JsonResponse(
+ data={
+ "identifier": identifier
+ }
+ )
+
+
@login_required
def open_view(request: HttpRequest, id: str):
""" Renders the detail view of an EMA
@@ -133,7 +179,38 @@ def log_view(request: HttpRequest, id: str):
@login_required
def edit_view(request: HttpRequest, id: str):
- get_object_or_404(Ema, id=id)
+ """
+ Renders a view for editing compensations
+
+ Args:
+ request (HttpRequest): The incoming request
+
+ Returns:
+
+ """
+ template = "compensation/form/view.html"
+ # Get object from db
+ ema = get_object_or_404(Ema, id=id)
+ # Create forms, initialize with values from db/from POST request
+ data_form = EditEmaForm(request.POST or None, instance=ema)
+ geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=ema)
+ if request.method == "POST":
+ if data_form.is_valid() and geom_form.is_valid():
+ # The data form takes the geom form for processing, as well as the performing user
+ ema = data_form.save(request.user, geom_form)
+ messages.success(request, _("EMA {} edited").format(ema.identifier))
+ return redirect("ema:open", id=ema.id)
+ else:
+ messages.error(request, FORM_INVALID)
+ else:
+ # For clarification: nothing in this case
+ pass
+ context = {
+ "form": data_form,
+ "geom_form": geom_form,
+ }
+ context = BaseContext(request, context).context
+ return render(request, template, context)
@login_required
diff --git a/intervention/templates/intervention/form/view.html b/intervention/templates/intervention/form/view.html
new file mode 100644
index 00000000..eb37e6b7
--- /dev/null
+++ b/intervention/templates/intervention/form/view.html
@@ -0,0 +1,6 @@
+{% extends 'base.html' %}
+{% load i18n l10n %}
+
+{% block body %}
+ {% include 'form/main_data_collapse_form.html' %}
+{% endblock %}
\ No newline at end of file
diff --git a/intervention/views.py b/intervention/views.py
index 5ef88eb0..8c9679f1 100644
--- a/intervention/views.py
+++ b/intervention/views.py
@@ -58,7 +58,7 @@ def new_view(request: HttpRequest):
Returns:
"""
- template = "intervention/new/view.html"
+ template = "intervention/form/view.html"
data_form = NewInterventionForm(request.POST or None)
geom_form = SimpleGeomForm(request.POST or None, read_only=False)
if request.method == "POST":
@@ -83,7 +83,6 @@ def new_view(request: HttpRequest):
context = {
"form": data_form,
"geom_form": geom_form,
- "url": reverse("intervention:new-id")
}
context = BaseContext(request, context).context
return render(request, template, context)
@@ -242,7 +241,7 @@ def edit_view(request: HttpRequest, id: str):
Returns:
"""
- template = "intervention/new/view.html"
+ template = "intervention/form/view.html"
# Get object from db
intervention = get_object_or_404(Intervention, id=id)
# Create forms, initialize with values from db/from POST request