Compensation detail view

* adds compensation detail view (WIP)
* adds includes dir for related objects, similar to interventions
* adds functionality for
   * adding/removing before_states
   * adding/removing after_states
   * adding/removing deadlines
   * adding/removing documents
* refactors usage of BaseModalForm
   * holds now process_request() in base class for generic usage anywhere
* adds __str__() method for some models
* compensation__action is blank=True now
* renamed tooltips
* adds new routes for state/deadline/document handling inside of compensation/urls.py
* adds precalculation of before/after_states for detail view, so users will see directly if there are missing states
* removes unnecessary link for intervention detail payment
* adds missing tooltips for check and record icon on detail views
* refactors DeadlineTypeEnum into DeadlineType in konova/models.py, just as the django 3.x documentation suggests for model enumerations
* UuidModel id field is not editable anymore in the admin interface
* adds/updates translations
This commit is contained in:
mipel
2021-08-03 13:13:01 +02:00
parent a06b532108
commit 881edaeba6
22 changed files with 1010 additions and 236 deletions

View File

@@ -56,10 +56,4 @@ class UserActionLogEntryEnum(BaseEnum):
CHECKED = "Checked"
RECORDED = "Recorded"
CREATED = "Created"
DELETED = "Deleted"
class DeadlineTypeEnum(BaseEnum):
MAINTAIN = "Maintain"
CONTROL = "Control"
OTHER = "Other"
DELETED = "Deleted"

View File

@@ -132,6 +132,45 @@ class BaseModalForm(BaseForm, BSModalForm):
"""
is_modal_form = True
render_submit = True
template = "modal/modal_form.html"
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
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():
self.save()
messages.success(
request,
msg_success
)
return redirect(redirect_url)
else:
messages.info(
request,
msg_error
)
return redirect(redirect_url)
elif request.method == "GET":
context = {
"form": self,
}
context = BaseContext(request, context).context
return render(request, template, context)
else:
raise NotImplementedError
class SimpleGeomForm(BaseForm):
@@ -200,44 +239,6 @@ class RemoveModalForm(BaseModalForm):
# If the class does not provide restorable delete functionality, we must delete the entry finally
self.instance.delete()
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
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():
self.save()
messages.success(
request,
msg_success
)
return redirect(redirect_url)
else:
messages.info(
request,
msg_error
)
return redirect(redirect_url)
elif request.method == "GET":
context = {
"form": self,
}
context = BaseContext(request, context).context
return render(request, template, context)
else:
raise NotImplementedError
class NewDocumentForm(BaseModalForm):
""" Modal form for new documents
@@ -306,4 +307,4 @@ class NewDocumentForm(BaseModalForm):
date_of_creation=self.cleaned_data["creation_date"],
)
self.instance.documents.add(doc)
return doc
return doc

View File

@@ -8,10 +8,10 @@ Created on: 17.11.20
import os
import uuid
from django.utils.translation import gettext_lazy as _
from django.contrib.gis.db.models import MultiPolygonField
from django.db import models
from konova.enums import DeadlineTypeEnum
from konova.settings import DEFAULT_SRID
from user.models import UserActionLogEntry
@@ -23,6 +23,7 @@ class UuidModel(models.Model):
id = models.UUIDField(
primary_key=True,
default=uuid.uuid4,
editable=False,
)
class Meta:
@@ -54,17 +55,43 @@ class BaseObject(BaseResource):
abstract = True
class DeadlineType(models.TextChoices):
"""
Django 3.x way of handling enums for models
"""
FINISHED = "finished", _("Finished")
MAINTAIN = "maintain", _("Maintain")
CONTROL = "control", _("Control")
OTHER = "other", _("Other")
class Deadline(BaseResource):
"""
Defines a deadline, which can be used to define dates with a semantic meaning
"""
type = models.CharField(max_length=255, null=True, blank=True, choices=DeadlineTypeEnum.as_choices(drop_empty_choice=True))
type = models.CharField(max_length=255, null=True, blank=True, choices=DeadlineType.choices)
date = models.DateField(null=True, blank=True)
comment = models.CharField(max_length=1000, null=True, blank=True)
def __str__(self):
return self.type
@property
def type_humanized(self):
""" Returns humanized version of enum
Used for template rendering
Returns:
"""
choices = DeadlineType.choices
for choice in choices:
if choice[0] == self.type:
return choice[1]
return None
class Document(BaseResource):
"""

View File

@@ -20,7 +20,7 @@ from simple_sso.sso_client.client import Client
from konova.autocompletes import OrganisationAutocomplete, NonOfficialOrganisationAutocomplete
from konova.settings import SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY, DEBUG
from konova.views import logout_view, home_view, get_document_view, remove_document_view
from konova.views import logout_view, home_view, get_document_view, remove_document_view, remove_deadline_view
sso_client = Client(SSO_SERVER, SSO_PUBLIC_KEY, SSO_PRIVATE_KEY)
urlpatterns = [
@@ -39,6 +39,9 @@ urlpatterns = [
path('document/<id>', get_document_view, name="doc-open"),
path('document/<id>/remove', remove_document_view, name="doc-remove"),
# Generic deadline routes
path('deadline/<id>/remove', remove_deadline_view, name="deadline-remove"),
# Autocomplete paths
path("atcmplt/orgs", OrganisationAutocomplete.as_view(), name="orgs-autocomplete"),
path("atcmplt/orgs/other", NonOfficialOrganisationAutocomplete.as_view(), name="other-orgs-autocomplete"),

View File

@@ -18,7 +18,7 @@ from intervention.models import Intervention
from konova.contexts import BaseContext
from konova.decorators import any_group_check
from konova.forms import RemoveModalForm
from konova.models import Document
from konova.models import Document, Deadline
from news.models import ServerMessage
from konova.settings import SSO_SERVER_BASE
@@ -141,3 +141,22 @@ def remove_document_view(request: HttpRequest, id: str):
request=request,
msg_success=_("Document '{}' deleted").format(title)
)
@login_required
def remove_deadline_view(request: HttpRequest, id:str):
""" Renders a modal form for removing a deadline object
Args:
request (HttpRequest): The incoming request
id (str): The deadline id
Returns:
"""
deadline = get_object_or_404(Deadline, id=id)
form = RemoveModalForm(request.POST or None, instance=deadline, user=request.user)
return form.process_request(
request,
msg_success=_("Deadline removed")
)