From 72914bab9dd05c0d8af6b612d698b8ec9e5a6218 Mon Sep 17 00:00:00 2001 From: mpeltriaux Date: Sun, 14 Dec 2025 16:11:50 +0100 Subject: [PATCH] # Detail View * refactors detail view methods into classes * introduces AbstractDetailView --- compensation/urls/compensation.py | 5 +- compensation/urls/eco_account.py | 5 +- .../views/compensation/compensation.py | 79 ------------ compensation/views/compensation/detail.py | 97 ++++++++++++++ compensation/views/eco_account/detail.py | 97 ++++++++++++++ ema/urls.py | 5 +- ema/views/detail.py | 76 +++++++++++ ema/views/ema.py | 60 --------- intervention/urls.py | 6 +- intervention/views/intervention.py | 121 ++++++++---------- konova/views/detail.py | 23 ++++ konova/views/index.py | 2 - 12 files changed, 360 insertions(+), 216 deletions(-) create mode 100644 compensation/views/compensation/detail.py create mode 100644 compensation/views/eco_account/detail.py create mode 100644 ema/views/detail.py create mode 100644 konova/views/detail.py diff --git a/compensation/urls/compensation.py b/compensation/urls/compensation.py index c5c664cf..ca6029b5 100644 --- a/compensation/urls/compensation.py +++ b/compensation/urls/compensation.py @@ -7,6 +7,7 @@ Created on: 24.08.21 """ from django.urls import path +from compensation.views.compensation.detail import DetailCompensationView from compensation.views.compensation.document import EditCompensationDocumentView, NewCompensationDocumentView, \ GetCompensationDocumentView, RemoveCompensationDocumentView from compensation.views.compensation.resubmission import CompensationResubmissionView @@ -17,7 +18,7 @@ from compensation.views.compensation.action import NewCompensationActionView, Ed RemoveCompensationActionView from compensation.views.compensation.state import NewCompensationStateView, EditCompensationStateView, \ RemoveCompensationStateView -from compensation.views.compensation.compensation import new_view, new_id_view, detail_view, edit_view, \ +from compensation.views.compensation.compensation import new_view, new_id_view, edit_view, \ remove_view, IndexCompensationView from compensation.views.compensation.log import CompensationLogView @@ -27,7 +28,7 @@ urlpatterns = [ path('new/id', new_id_view, name='new-id'), path('new/', new_view, name='new'), path('new', new_view, name='new'), - path('', detail_view, name='detail'), + path('', DetailCompensationView.as_view(), name='detail'), path('/log', CompensationLogView.as_view(), name='log'), path('/edit', edit_view, name='edit'), path('/remove', remove_view, name='remove'), diff --git a/compensation/urls/eco_account.py b/compensation/urls/eco_account.py index e7fc85b2..8c8a27fd 100644 --- a/compensation/urls/eco_account.py +++ b/compensation/urls/eco_account.py @@ -8,8 +8,9 @@ Created on: 24.08.21 from django.urls import path from compensation.autocomplete.eco_account import EcoAccountAutocomplete +from compensation.views.eco_account.detail import DetailEcoAccountView from compensation.views.eco_account.eco_account import new_view, new_id_view, edit_view, remove_view, \ - detail_view, IndexEcoAccountView + IndexEcoAccountView from compensation.views.eco_account.log import EcoAccountLogView from compensation.views.eco_account.record import EcoAccountRecordView from compensation.views.eco_account.report import report_view @@ -31,7 +32,7 @@ urlpatterns = [ path("", IndexEcoAccountView.as_view(), name="index"), path('new/', new_view, name='new'), path('new/id', new_id_view, name='new-id'), - path('', detail_view, name='detail'), + path('', DetailEcoAccountView.as_view(), name='detail'), path('/log', EcoAccountLogView.as_view(), name='log'), path('/record', EcoAccountRecordView.as_view(), name='record'), path('/report', report_view, name='report'), diff --git a/compensation/views/compensation/compensation.py b/compensation/views/compensation/compensation.py index 8cc050cd..bd669672 100644 --- a/compensation/views/compensation/compensation.py +++ b/compensation/views/compensation/compensation.py @@ -211,85 +211,6 @@ def edit_view(request: HttpRequest, id: str): context = BaseContext(request, context).context return render(request, template, context) - -@login_required -@any_group_check -@uuid_required -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.objects.select_related( - "modified", - "created", - "geometry" - ), - id=id, - deleted=None, - intervention__deleted=None, - ) - 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 = comp.get_surface_before_states() - sum_after_states = comp.get_surface_after_states() - diff_states = abs(sum_before_states - sum_after_states) - - request = comp.set_status_messages(request) - - last_checked = comp.intervention.get_last_checked_action() - last_checked_tooltip = "" - if last_checked: - last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format(last_checked.get_timestamp_str_formatted(), last_checked.user) - - requesting_user_is_only_shared_user = comp.is_only_shared_with(_user) - if requesting_user_is_only_shared_user: - messages.info( - request, - DO_NOT_FORGET_TO_SHARE - ) - - context = { - "obj": comp, - "last_checked": last_checked, - "last_checked_tooltip": last_checked_tooltip, - "geom_form": geom_form, - "parcels": parcels, - "is_entry_shared": 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": _user.in_group(DEFAULT_GROUP), - "is_zb_member": _user.in_group(ZB_GROUP), - "is_ets_member": _user.in_group(ETS_GROUP), - "LANIS_LINK": comp.get_LANIS_link(), - TAB_TITLE_IDENTIFIER: f"{comp.identifier} - {comp.title}", - "has_finished_deadlines": comp.get_finished_deadlines().exists(), - } - context = BaseContext(request, context).context - return render(request, template, context) - - @login_required_modal @login_required @default_group_required diff --git a/compensation/views/compensation/detail.py b/compensation/views/compensation/detail.py new file mode 100644 index 00000000..6b342119 --- /dev/null +++ b/compensation/views/compensation/detail.py @@ -0,0 +1,97 @@ +""" +Author: Michel Peltriaux +Created on: 14.12.25 + +""" +from django.contrib import messages +from django.http import HttpRequest, HttpResponse +from django.shortcuts import render, get_object_or_404 + +from compensation.models import Compensation +from konova.contexts import BaseContext +from konova.forms import SimpleGeomForm +from konova.settings import ETS_GROUP, ZB_GROUP, DEFAULT_GROUP +from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER +from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE, DATA_CHECKED_PREVIOUSLY_TEMPLATE +from konova.views.detail import AbstractDetailView + + +class DetailCompensationView(AbstractDetailView): + _TEMPLATE = "compensation/detail/compensation/view.html" + + def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse: + + """ Renders a detail view for a compensation + + Args: + request (HttpRequest): The incoming request + id (str): The compensation's id + + Returns: + + """ + comp = get_object_or_404( + Compensation.objects.select_related( + "modified", + "created", + "geometry" + ), + id=id, + deleted=None, + intervention__deleted=None, + ) + 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 = comp.get_surface_before_states() + sum_after_states = comp.get_surface_after_states() + diff_states = abs(sum_before_states - sum_after_states) + + request = comp.set_status_messages(request) + + last_checked = comp.intervention.get_last_checked_action() + last_checked_tooltip = "" + if last_checked: + last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format( + last_checked.get_timestamp_str_formatted(), + last_checked.user + ) + + requesting_user_is_only_shared_user = comp.is_only_shared_with(_user) + if requesting_user_is_only_shared_user: + messages.info( + request, + DO_NOT_FORGET_TO_SHARE + ) + + context = { + "obj": comp, + "last_checked": last_checked, + "last_checked_tooltip": last_checked_tooltip, + "geom_form": geom_form, + "parcels": parcels, + "is_entry_shared": 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": _user.in_group(DEFAULT_GROUP), + "is_zb_member": _user.in_group(ZB_GROUP), + "is_ets_member": _user.in_group(ETS_GROUP), + "LANIS_LINK": comp.get_LANIS_link(), + TAB_TITLE_IDENTIFIER: f"{comp.identifier} - {comp.title}", + "has_finished_deadlines": comp.get_finished_deadlines().exists(), + } + context = BaseContext(request, context).context + return render(request, self._TEMPLATE, context) \ No newline at end of file diff --git a/compensation/views/eco_account/detail.py b/compensation/views/eco_account/detail.py new file mode 100644 index 00000000..500940a9 --- /dev/null +++ b/compensation/views/eco_account/detail.py @@ -0,0 +1,97 @@ +""" +Author: Michel Peltriaux +Created on: 14.12.25 + +""" +from django.contrib import messages +from django.http import HttpRequest, HttpResponse +from django.shortcuts import render, get_object_or_404 + +from compensation.models import EcoAccount +from konova.contexts import BaseContext +from konova.forms import SimpleGeomForm +from konova.settings import ETS_GROUP, ZB_GROUP, DEFAULT_GROUP +from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER +from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE +from konova.views.detail import AbstractDetailView + + +class DetailEcoAccountView(AbstractDetailView): + _TEMPLATE = "compensation/detail/eco_account/view.html" + + def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse: + """ Renders a detail view for a compensation + + Args: + request (HttpRequest): The incoming request + id (str): The compensation's id + + Returns: + + """ + acc = get_object_or_404( + EcoAccount.objects.prefetch_related( + "deadlines", + ).select_related( + 'geometry', + 'responsible', + ), + id=id, + deleted=None, + ) + geom_form = SimpleGeomForm(instance=acc) + parcels = acc.get_underlying_parcels() + _user = request.user + is_data_shared = acc.is_shared_with(_user) + + # Order states according to surface + before_states = acc.before_states.order_by("-surface") + after_states = acc.after_states.order_by("-surface") + + # 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 = acc.get_surface_before_states() + sum_after_states = acc.get_surface_after_states() + diff_states = abs(sum_before_states - sum_after_states) + # Calculate rest of available surface for deductions + available_total = acc.deductable_rest + available_relative = acc.get_deductable_rest_relative() + + # Prefetch related data to decrease the amount of db connections + deductions = acc.deductions.filter( + intervention__deleted=None, + ) + actions = acc.actions.all() + + request = acc.set_status_messages(request) + + requesting_user_is_only_shared_user = acc.is_only_shared_with(_user) + if requesting_user_is_only_shared_user: + messages.info( + request, + DO_NOT_FORGET_TO_SHARE + ) + + context = { + "obj": acc, + "geom_form": geom_form, + "parcels": parcels, + "is_entry_shared": is_data_shared, + "before_states": before_states, + "after_states": after_states, + "sum_before_states": sum_before_states, + "sum_after_states": sum_after_states, + "diff_states": diff_states, + "available": available_relative, + "available_total": available_total, + "is_default_member": _user.in_group(DEFAULT_GROUP), + "is_zb_member": _user.in_group(ZB_GROUP), + "is_ets_member": _user.in_group(ETS_GROUP), + "LANIS_LINK": acc.get_LANIS_link(), + "deductions": deductions, + "actions": actions, + TAB_TITLE_IDENTIFIER: f"{acc.identifier} - {acc.title}", + "has_finished_deadlines": acc.get_finished_deadlines().exists(), + } + context = BaseContext(request, context).context + return render(request, self._TEMPLATE, context) \ No newline at end of file diff --git a/ema/urls.py b/ema/urls.py index 52cac31a..0c4308b5 100644 --- a/ema/urls.py +++ b/ema/urls.py @@ -9,8 +9,9 @@ from django.urls import path from ema.views.action import NewEmaActionView, EditEmaActionView, RemoveEmaActionView from ema.views.deadline import NewEmaDeadlineView, EditEmaDeadlineView, RemoveEmaDeadlineView +from ema.views.detail import DetailEmaView from ema.views.document import NewEmaDocumentView, EditEmaDocumentView, RemoveEmaDocumentView, GetEmaDocumentView -from ema.views.ema import new_view, new_id_view, detail_view, edit_view, remove_view, IndexEmaView +from ema.views.ema import new_view, new_id_view, edit_view, remove_view, IndexEmaView from ema.views.log import EmaLogView from ema.views.record import EmaRecordView from ema.views.report import report_view @@ -23,7 +24,7 @@ urlpatterns = [ path("", IndexEmaView.as_view(), name="index"), path("new/", new_view, name="new"), path("new/id", new_id_view, name="new-id"), - path("", detail_view, name="detail"), + path("", DetailEmaView.as_view(), name="detail"), path('/log', EmaLogView.as_view(), name='log'), path('/edit', edit_view, name='edit'), path('/remove', remove_view, name='remove'), diff --git a/ema/views/detail.py b/ema/views/detail.py new file mode 100644 index 00000000..16d10125 --- /dev/null +++ b/ema/views/detail.py @@ -0,0 +1,76 @@ +""" +Author: Michel Peltriaux +Created on: 14.12.25 + +""" +from django.contrib import messages +from django.http import HttpResponse, HttpRequest +from django.shortcuts import get_object_or_404, render + +from ema.models import Ema +from konova.contexts import BaseContext +from konova.forms import SimpleGeomForm +from konova.settings import DEFAULT_GROUP, ZB_GROUP, ETS_GROUP +from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER +from konova.utils.message_templates import DO_NOT_FORGET_TO_SHARE +from konova.views.detail import AbstractDetailView + + +class DetailEmaView(AbstractDetailView): + _TEMPLATE = "ema/detail/view.html" + + def get(self, request: HttpRequest, id: str, *args, **kwargs) -> HttpResponse: + """ Renders the detail view of an EMA + + Args: + request (HttpRequest): The incoming request + id (str): The EMA id + + Returns: + + """ + ema = get_object_or_404(Ema, id=id, deleted=None) + + geom_form = SimpleGeomForm(instance=ema) + parcels = ema.get_underlying_parcels() + _user = request.user + is_entry_shared = ema.is_shared_with(_user) + + # Order states according to surface + before_states = ema.before_states.all().order_by("-surface") + after_states = ema.after_states.all().order_by("-surface") + + # 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 = ema.get_surface_before_states() + sum_after_states = ema.get_surface_after_states() + diff_states = abs(sum_before_states - sum_after_states) + + ema.set_status_messages(request) + + requesting_user_is_only_shared_user = ema.is_only_shared_with(_user) + if requesting_user_is_only_shared_user: + messages.info( + request, + DO_NOT_FORGET_TO_SHARE + ) + + context = { + "obj": ema, + "geom_form": geom_form, + "parcels": parcels, + "is_entry_shared": is_entry_shared, + "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": _user.in_group(DEFAULT_GROUP), + "is_zb_member": _user.in_group(ZB_GROUP), + "is_ets_member": _user.in_group(ETS_GROUP), + "LANIS_LINK": ema.get_LANIS_link(), + TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}", + "has_finished_deadlines": ema.get_finished_deadlines().exists(), + } + context = BaseContext(request, context).context + return render(request, self._TEMPLATE, context) diff --git a/ema/views/ema.py b/ema/views/ema.py index cfcd0f6f..1ea59120 100644 --- a/ema/views/ema.py +++ b/ema/views/ema.py @@ -129,66 +129,6 @@ def new_id_view(request: HttpRequest): ) -@login_required -@uuid_required -def detail_view(request: HttpRequest, id: str): - """ Renders the detail view of an EMA - - Args: - request (HttpRequest): The incoming request - id (str): The EMA id - - Returns: - - """ - template = "ema/detail/view.html" - ema = get_object_or_404(Ema, id=id, deleted=None) - - geom_form = SimpleGeomForm(instance=ema) - parcels = ema.get_underlying_parcels() - _user = request.user - is_entry_shared = ema.is_shared_with(_user) - - # Order states according to surface - before_states = ema.before_states.all().order_by("-surface") - after_states = ema.after_states.all().order_by("-surface") - - # 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 = ema.get_surface_before_states() - sum_after_states = ema.get_surface_after_states() - diff_states = abs(sum_before_states - sum_after_states) - - ema.set_status_messages(request) - - requesting_user_is_only_shared_user = ema.is_only_shared_with(_user) - if requesting_user_is_only_shared_user: - messages.info( - request, - DO_NOT_FORGET_TO_SHARE - ) - - context = { - "obj": ema, - "geom_form": geom_form, - "parcels": parcels, - "is_entry_shared": is_entry_shared, - "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": _user.in_group(DEFAULT_GROUP), - "is_zb_member": _user.in_group(ZB_GROUP), - "is_ets_member": _user.in_group(ETS_GROUP), - "LANIS_LINK": ema.get_LANIS_link(), - TAB_TITLE_IDENTIFIER: f"{ema.identifier} - {ema.title}", - "has_finished_deadlines": ema.get_finished_deadlines().exists(), - } - context = BaseContext(request, context).context - return render(request, template, context) - - @login_required @conservation_office_group_required @shared_access_required(Ema, "id") diff --git a/intervention/urls.py b/intervention/urls.py index 27f13fb9..136057dc 100644 --- a/intervention/urls.py +++ b/intervention/urls.py @@ -14,8 +14,8 @@ from intervention.views.deduction import NewInterventionDeductionView, EditInter RemoveInterventionDeductionView from intervention.views.document import NewInterventionDocumentView, GetInterventionDocumentView, \ RemoveInterventionDocumentView, EditInterventionDocumentView -from intervention.views.intervention import new_view, new_id_view, detail_view, edit_view, remove_view, \ - IndexInterventionView +from intervention.views.intervention import new_view, new_id_view, edit_view, remove_view, \ + IndexInterventionView, DetailInterventionView from intervention.views.log import InterventionLogView from intervention.views.record import InterventionRecordView from intervention.views.report import report_view @@ -29,7 +29,7 @@ urlpatterns = [ path("", IndexInterventionView.as_view(), name="index"), path('new/', new_view, name='new'), path('new/id', new_id_view, name='new-id'), - path('', detail_view, name='detail'), + path('', DetailInterventionView.as_view(), name='detail'), path('/log', InterventionLogView.as_view(), name='log'), path('/edit', edit_view, name='edit'), path('/remove', remove_view, name='remove'), diff --git a/intervention/views/intervention.py b/intervention/views/intervention.py index 4cd2b019..4d8e44ce 100644 --- a/intervention/views/intervention.py +++ b/intervention/views/intervention.py @@ -25,6 +25,7 @@ from konova.sub_settings.context_settings import TAB_TITLE_IDENTIFIER from konova.utils.message_templates import DATA_CHECKED_PREVIOUSLY_TEMPLATE, RECORDED_BLOCKS_EDIT, \ CHECK_STATE_RESET, FORM_INVALID, IDENTIFIER_REPLACED, DO_NOT_FORGET_TO_SHARE, GEOMETRY_SIMPLIFIED, \ GEOMETRIES_IGNORED_TEMPLATE +from konova.views.detail import AbstractDetailView from konova.views.index import AbstractIndexView @@ -134,79 +135,67 @@ def new_id_view(request: HttpRequest): ) -@login_required -@any_group_check -@uuid_required -def detail_view(request: HttpRequest, id: str): - """ Renders a detail view for viewing an intervention's data +class DetailInterventionView(AbstractDetailView): + _TEMPLATE = "intervention/detail/view.html" - Args: - request (HttpRequest): The incoming request - id (str): The intervention's id - - Returns: - - """ - template = "intervention/detail/view.html" - - # Fetch data, filter out deleted related data - intervention = get_object_or_404( - Intervention.objects.select_related( - "geometry", - "legal", - "responsible", - ).prefetch_related( - "legal__revocations", - ), - id=id, - deleted=None - ) - compensations = intervention.compensations.filter( - deleted=None, - ) - _user = request.user - is_data_shared = intervention.is_shared_with(user=_user) - - geom_form = SimpleGeomForm( - instance=intervention, - ) - last_checked = intervention.get_last_checked_action() - last_checked_tooltip = "" - if last_checked: - last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format( - last_checked.get_timestamp_str_formatted(), - last_checked.user + def get(self, request, id: str, *args, **kwargs) -> HttpResponse: + # Fetch data, filter out deleted related data + intervention = get_object_or_404( + Intervention.objects.select_related( + "geometry", + "legal", + "responsible", + ).prefetch_related( + "legal__revocations", + ), + id=id, + deleted=None ) - - has_payment_without_document = intervention.payments.exists() and not intervention.get_documents()[1].exists() - - requesting_user_is_only_shared_user = intervention.is_only_shared_with(_user) - if requesting_user_is_only_shared_user: - messages.info( - request, - DO_NOT_FORGET_TO_SHARE + compensations = intervention.compensations.filter( + deleted=None, ) + _user = request.user + is_data_shared = intervention.is_shared_with(user=_user) - context = { - "obj": intervention, - "last_checked": last_checked, - "last_checked_tooltip": last_checked_tooltip, - "compensations": compensations, - "is_entry_shared": is_data_shared, - "geom_form": geom_form, - "is_default_member": _user.in_group(DEFAULT_GROUP), - "is_zb_member": _user.in_group(ZB_GROUP), - "is_ets_member": _user.in_group(ETS_GROUP), - "LANIS_LINK": intervention.get_LANIS_link(), - "has_payment_without_document": has_payment_without_document, - TAB_TITLE_IDENTIFIER: f"{intervention.identifier} - {intervention.title}", - } + geom_form = SimpleGeomForm( + instance=intervention, + ) + last_checked = intervention.get_last_checked_action() + last_checked_tooltip = "" + if last_checked: + last_checked_tooltip = DATA_CHECKED_PREVIOUSLY_TEMPLATE.format( + last_checked.get_timestamp_str_formatted(), + last_checked.user + ) - request = intervention.set_status_messages(request) + has_payment_without_document = intervention.payments.exists() and not intervention.get_documents()[1].exists() - context = BaseContext(request, context).context - return render(request, template, context) + requesting_user_is_only_shared_user = intervention.is_only_shared_with(_user) + if requesting_user_is_only_shared_user: + messages.info( + request, + DO_NOT_FORGET_TO_SHARE + ) + context = { + "obj": intervention, + "last_checked": last_checked, + "last_checked_tooltip": last_checked_tooltip, + "compensations": compensations, + "is_entry_shared": is_data_shared, + "geom_form": geom_form, + "is_default_member": _user.in_group(DEFAULT_GROUP), + "is_zb_member": _user.in_group(ZB_GROUP), + "is_ets_member": _user.in_group(ETS_GROUP), + "LANIS_LINK": intervention.get_LANIS_link(), + "has_payment_without_document": has_payment_without_document, + TAB_TITLE_IDENTIFIER: f"{intervention.identifier} - {intervention.title}", + } + + request = intervention.set_status_messages(request) + + context = BaseContext(request, context).context + return render(request, self._TEMPLATE, context) @login_required @default_group_required diff --git a/konova/views/detail.py b/konova/views/detail.py new file mode 100644 index 00000000..3207680f --- /dev/null +++ b/konova/views/detail.py @@ -0,0 +1,23 @@ +""" +Author: Michel Peltriaux +Created on: 14.12.25 + +""" +from django.contrib.auth.mixins import LoginRequiredMixin +from django.utils.decorators import method_decorator +from django.views import View + +from konova.decorators import uuid_required, any_group_check + + +class AbstractDetailView(LoginRequiredMixin, View): + _TEMPLATE = None + + class Meta: + abstract = True + + @method_decorator(uuid_required) + @method_decorator(any_group_check) + def dispatch(self, request, *args, **kwargs): + return super().dispatch(request, *args, **kwargs) + diff --git a/konova/views/index.py b/konova/views/index.py index cafaeff9..7c1298fd 100644 --- a/konova/views/index.py +++ b/konova/views/index.py @@ -3,7 +3,6 @@ Author: Michel Peltriaux Created on: 14.12.25 """ -from django.contrib.auth.decorators import login_required from django.contrib.auth.mixins import LoginRequiredMixin from django.utils.decorators import method_decorator from django.views import View @@ -17,7 +16,6 @@ class AbstractIndexView(LoginRequiredMixin, View): class Meta: abstract = True - @method_decorator(login_required) @method_decorator(any_group_check) def dispatch(self, request, *args, **kwargs): return super().dispatch(request, *args, **kwargs)