mpeltriaux
4e57ca4954
* adds fake-inherited is_ready_for_publish() method to compensation model (not derived from RecordableObjectMixin) to equalize usage of is_ready_for_publish() usage for all data types (compensation can be checked the same way as intervention, ecoaccount or ema)
494 lines
16 KiB
Python
494 lines
16 KiB
Python
from django.contrib.auth.decorators import login_required
|
|
from django.db.models import Sum
|
|
from django.http import HttpRequest, JsonResponse
|
|
from django.shortcuts import render
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
from compensation.forms.forms import NewCompensationForm, EditCompensationForm
|
|
from compensation.forms.modalForms import NewStateModalForm, NewDeadlineModalForm, NewActionModalForm, \
|
|
NewCompensationDocumentForm
|
|
from compensation.models import Compensation, CompensationState, CompensationAction, CompensationDocument
|
|
from compensation.tables import CompensationTable
|
|
from intervention.models import Intervention
|
|
from konova.contexts import BaseContext
|
|
from konova.decorators import *
|
|
from konova.forms import RemoveModalForm, SimpleGeomForm
|
|
from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER
|
|
from konova.utils.documents import get_document, remove_document
|
|
from konova.utils.generators import generate_qr_code
|
|
from konova.utils.message_templates import FORM_INVALID, IDENTIFIER_REPLACED, DATA_UNSHARED_EXPLANATION, \
|
|
CHECKED_RECORDED_RESET
|
|
from konova.utils.user_checks import in_group
|
|
|
|
|
|
@login_required
|
|
@any_group_check
|
|
def index_view(request: HttpRequest):
|
|
"""
|
|
Renders the index view for compensation
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
|
|
Returns:
|
|
A rendered view
|
|
"""
|
|
template = "generic_index.html"
|
|
compensations = Compensation.objects.filter(
|
|
deleted=None, # only show those which are not deleted individually
|
|
intervention__deleted=None, # and don't show the ones whose intervention has been deleted
|
|
)
|
|
table = CompensationTable(
|
|
request=request,
|
|
queryset=compensations
|
|
)
|
|
context = {
|
|
"table": table,
|
|
TAB_TITLE_IDENTIFIER: _("Compensations - Overview"),
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, template, context)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Intervention, "intervention_id")
|
|
def new_view(request: HttpRequest, intervention_id: str = None):
|
|
"""
|
|
Renders a view for a new compensation creation
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
|
|
Returns:
|
|
|
|
"""
|
|
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":
|
|
if data_form.is_valid() and geom_form.is_valid():
|
|
generated_identifier = data_form.cleaned_data.get("identifier", None)
|
|
comp = data_form.save(request.user, geom_form)
|
|
if generated_identifier != comp.identifier:
|
|
messages.info(
|
|
request,
|
|
IDENTIFIER_REPLACED.format(
|
|
generated_identifier,
|
|
comp.identifier
|
|
)
|
|
)
|
|
messages.success(request, _("Compensation {} added").format(comp.identifier))
|
|
return redirect("compensation:detail", id=comp.id)
|
|
else:
|
|
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
|
else:
|
|
# For clarification: nothing in this case
|
|
pass
|
|
context = {
|
|
"form": data_form,
|
|
"geom_form": geom_form,
|
|
TAB_TITLE_IDENTIFIER: _("New compensation"),
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, template, context)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
def new_id_view(request: HttpRequest):
|
|
""" JSON endpoint
|
|
|
|
Provides fetching of free identifiers for e.g. AJAX calls
|
|
|
|
"""
|
|
tmp = Compensation()
|
|
identifier = tmp.generate_new_identifier()
|
|
while Compensation.objects.filter(identifier=identifier).exists():
|
|
identifier = tmp.generate_new_identifier()
|
|
return JsonResponse(
|
|
data={
|
|
"identifier": identifier
|
|
}
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def edit_view(request: HttpRequest, id: str):
|
|
"""
|
|
Renders a view for editing compensations
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
|
|
Returns:
|
|
|
|
"""
|
|
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
|
|
data_form = EditCompensationForm(request.POST or None, instance=comp)
|
|
geom_form = SimpleGeomForm(request.POST or None, read_only=False, instance=comp)
|
|
if request.method == "POST":
|
|
if data_form.is_valid() and geom_form.is_valid():
|
|
# Preserve state of intervention recorded/checked to determine whether the user must be informed or not
|
|
# about a change of the recorded/checked state
|
|
intervention_recorded = comp.intervention.recorded is not None
|
|
intervention_checked = comp.intervention.checked is not None
|
|
|
|
# The data form takes the geom form for processing, as well as the performing user
|
|
comp = data_form.save(request.user, geom_form)
|
|
if intervention_recorded or intervention_checked:
|
|
messages.info(request, CHECKED_RECORDED_RESET)
|
|
messages.success(request, _("Compensation {} edited").format(comp.identifier))
|
|
return redirect("compensation:detail", id=comp.id)
|
|
else:
|
|
messages.error(request, FORM_INVALID, extra_tags="danger",)
|
|
else:
|
|
# For clarification: nothing in this case
|
|
pass
|
|
context = {
|
|
"form": data_form,
|
|
"geom_form": geom_form,
|
|
TAB_TITLE_IDENTIFIER: _("Edit {}").format(comp.identifier),
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, template, context)
|
|
|
|
|
|
@login_required
|
|
@any_group_check
|
|
def detail_view(request: HttpRequest, id: str):
|
|
""" Renders a detail view for a compensation
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id
|
|
|
|
Returns:
|
|
|
|
"""
|
|
template = "compensation/detail/compensation/view.html"
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
geom_form = SimpleGeomForm(instance=comp)
|
|
parcels = comp.get_underlying_parcels()
|
|
_user = request.user
|
|
is_data_shared = comp.intervention.is_shared_with(_user)
|
|
|
|
# Order states according to surface
|
|
before_states = comp.before_states.all().prefetch_related("biotope_type").order_by("-surface")
|
|
after_states = comp.after_states.all().prefetch_related("biotope_type").order_by("-surface")
|
|
actions = comp.actions.all().prefetch_related("action_type")
|
|
|
|
# Precalculate logical errors between before- and after-states
|
|
# Sum() returns None in case of no states, so we catch that and replace it with 0 for easier handling
|
|
sum_before_states = before_states.aggregate(Sum("surface"))["surface__sum"] or 0
|
|
sum_after_states = after_states.aggregate(Sum("surface"))["surface__sum"] or 0
|
|
diff_states = abs(sum_before_states - sum_after_states)
|
|
|
|
request = comp.set_status_messages(request)
|
|
|
|
context = {
|
|
"obj": comp,
|
|
"geom_form": geom_form,
|
|
"parcels": parcels,
|
|
"has_access": is_data_shared,
|
|
"actions": actions,
|
|
"before_states": before_states,
|
|
"after_states": after_states,
|
|
"sum_before_states": sum_before_states,
|
|
"sum_after_states": sum_after_states,
|
|
"diff_states": diff_states,
|
|
"is_default_member": in_group(_user, DEFAULT_GROUP),
|
|
"is_zb_member": in_group(_user, ZB_GROUP),
|
|
"is_ets_member": in_group(_user, ETS_GROUP),
|
|
"LANIS_LINK": comp.get_LANIS_link(),
|
|
TAB_TITLE_IDENTIFIER: f"{comp.identifier} - {comp.title}",
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, template, context)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def log_view(request: HttpRequest, id: str):
|
|
""" Renders a log view using modal
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id
|
|
|
|
Returns:
|
|
|
|
"""
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
template = "modal/modal_generic.html"
|
|
body_template = "log.html"
|
|
|
|
context = {
|
|
"modal_body_template": body_template,
|
|
"log": comp.log.all(),
|
|
"modal_title": _("Log"),
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, template, context)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def remove_view(request: HttpRequest, id: str):
|
|
""" Renders a modal view for removing the compensation
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id
|
|
|
|
Returns:
|
|
|
|
"""
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
form = RemoveModalForm(request.POST or None, instance=comp, request=request)
|
|
return form.process_request(
|
|
request=request,
|
|
msg_success=_("Compensation removed"),
|
|
redirect_url=reverse("compensation:index"),
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def new_document_view(request: HttpRequest, id: str):
|
|
""" Renders a form for uploading new documents
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id to which the new document will be related
|
|
Returns:
|
|
|
|
"""
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
form = NewCompensationDocumentForm(request.POST or None, request.FILES or None, instance=comp, request=request)
|
|
return form.process_request(
|
|
request,
|
|
msg_success=_("Document added")
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
def get_document_view(request: HttpRequest, doc_id: str):
|
|
""" Returns the document as downloadable file
|
|
|
|
Wraps the generic document fetcher function from konova.utils.
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
doc_id (str): The document id
|
|
|
|
Returns:
|
|
|
|
"""
|
|
doc = get_object_or_404(CompensationDocument, id=doc_id)
|
|
user = request.user
|
|
instance = doc.instance
|
|
# File download only possible if related instance is shared with user
|
|
if not instance.users.filter(id=user.id):
|
|
messages.info(
|
|
request,
|
|
DATA_UNSHARED
|
|
)
|
|
return redirect("compensation:detail", id=instance.id)
|
|
return get_document(doc)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
def remove_document_view(request: HttpRequest, doc_id: str):
|
|
""" Removes the document from the database and file system
|
|
|
|
Wraps the generic functionality from konova.utils.
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
doc_id (str): The document id
|
|
|
|
Returns:
|
|
|
|
"""
|
|
doc = get_object_or_404(CompensationDocument, id=doc_id)
|
|
return remove_document(
|
|
request,
|
|
doc
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def state_new_view(request: HttpRequest, id: str):
|
|
""" Renders a form for adding new states for a compensation
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id to which the new state will be related
|
|
|
|
Returns:
|
|
|
|
"""
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
form = NewStateModalForm(request.POST or None, instance=comp, request=request)
|
|
return form.process_request(
|
|
request,
|
|
msg_success=_("State added")
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def action_new_view(request: HttpRequest, id: str):
|
|
""" Renders a form for adding new actions for a compensation
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id to which the new state will be related
|
|
|
|
Returns:
|
|
|
|
"""
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
form = NewActionModalForm(request.POST or None, instance=comp, request=request)
|
|
return form.process_request(
|
|
request,
|
|
msg_success=_("Action added")
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def deadline_new_view(request: HttpRequest, id: str):
|
|
""" Renders a form for adding new states for a compensation
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id to which the new state will be related
|
|
|
|
Returns:
|
|
|
|
"""
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
form = NewDeadlineModalForm(request.POST or None, instance=comp, request=request)
|
|
return form.process_request(
|
|
request,
|
|
msg_success=_("Deadline added")
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def state_remove_view(request: HttpRequest, id: str, state_id: str):
|
|
""" Renders a form for removing a compensation state
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id
|
|
state_id (str): The state's id
|
|
|
|
Returns:
|
|
|
|
"""
|
|
state = get_object_or_404(CompensationState, id=state_id)
|
|
form = RemoveModalForm(request.POST or None, instance=state, request=request)
|
|
return form.process_request(
|
|
request,
|
|
msg_success=_("State removed")
|
|
)
|
|
|
|
|
|
@login_required
|
|
@default_group_required
|
|
@shared_access_required(Compensation, "id")
|
|
def action_remove_view(request: HttpRequest, id: str, action_id: str):
|
|
""" Renders a form for removing a compensation action
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The compensation's id
|
|
id (str): The action's id
|
|
|
|
Returns:
|
|
|
|
"""
|
|
action = get_object_or_404(CompensationAction, id=action_id)
|
|
form = RemoveModalForm(request.POST or None, instance=action, request=request)
|
|
return form.process_request(
|
|
request,
|
|
msg_success=_("Action removed")
|
|
)
|
|
|
|
|
|
def report_view(request: HttpRequest, id: str):
|
|
""" Renders the public report view
|
|
|
|
Args:
|
|
request (HttpRequest): The incoming request
|
|
id (str): The id of the intervention
|
|
|
|
Returns:
|
|
|
|
"""
|
|
# Reuse the compensation report template since compensations are structurally identical
|
|
template = "compensation/report/compensation/report.html"
|
|
comp = get_object_or_404(Compensation, id=id)
|
|
|
|
tab_title = _("Report {}").format(comp.identifier)
|
|
# If intervention is not recorded (yet or currently) we need to render another template without any data
|
|
if not comp.is_ready_for_publish():
|
|
template = "report/unavailable.html"
|
|
context = {
|
|
TAB_TITLE_IDENTIFIER: tab_title,
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, template, context)
|
|
|
|
# Prepare data for map viewer
|
|
geom_form = SimpleGeomForm(
|
|
instance=comp
|
|
)
|
|
parcels = comp.get_underlying_parcels()
|
|
qrcode_img = generate_qr_code(
|
|
request.build_absolute_uri(reverse("compensation:report", args=(id,))),
|
|
10
|
|
)
|
|
qrcode_img_lanis = generate_qr_code(
|
|
comp.get_LANIS_link(),
|
|
7
|
|
)
|
|
# Order states by surface
|
|
before_states = comp.before_states.all().order_by("-surface").prefetch_related("biotope_type")
|
|
after_states = comp.after_states.all().order_by("-surface").prefetch_related("biotope_type")
|
|
actions = comp.actions.all().prefetch_related("action_type")
|
|
|
|
context = {
|
|
"obj": comp,
|
|
"qrcode": qrcode_img,
|
|
"qrcode_lanis": qrcode_img_lanis,
|
|
"has_access": False, # disables action buttons during rendering
|
|
"before_states": before_states,
|
|
"after_states": after_states,
|
|
"geom_form": geom_form,
|
|
"parcels": parcels,
|
|
"actions": actions,
|
|
TAB_TITLE_IDENTIFIER: tab_title,
|
|
}
|
|
context = BaseContext(request, context).context
|
|
return render(request, template, context)
|