# Analysis, API and Payment views

* refactors payment creation, editing and removing into class based views
* refactors analysis report methods into class based views
* drops unused method view on api app (token generating has been de facto moved into users app long time ago)
This commit is contained in:
2026-01-13 10:35:09 +01:00
parent 88058d7caf
commit 3f33de3626
6 changed files with 182 additions and 134 deletions

View File

@@ -10,6 +10,6 @@ from analysis.views import *
app_name = "analysis"
urlpatterns = [
path("reports/", index_reports_view, name="reports"),
path("reports/<id>", detail_report_view, name="report-detail"),
path("reports/", ReportIndexView.as_view(), name="reports"),
path("reports/<id>", ReportDetailView.as_view(), name="report-detail"),
]

View File

@@ -1,8 +1,12 @@
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpRequest, HttpResponse
from django.shortcuts import render, redirect, get_object_or_404
from django.utils import timezone
from django.utils.decorators import method_decorator
from django.views import View
from django.views.generic import DetailView
from analysis.forms import TimespanReportForm
from analysis.utils.excel.excel import TempExcelFile
@@ -42,57 +46,112 @@ def index_reports_view(request: HttpRequest):
context = BaseContext(request, context).context
return render(request, template, context)
class ReportIndexView(LoginRequiredMixin, View):
@method_decorator(conservation_office_group_required)
def get(self, request: HttpRequest) -> HttpResponse:
@login_required
@conservation_office_group_required
def detail_report_view(request: HttpRequest, id: str):
""" Renders the detailed report for a conservation office
"""
Args:
request (HttpRequest): The incoming request
id (str): The conservation_office KonovaCode id
Args:
request (HttpRequest): The incoming request
Returns:
Returns:
"""
# Try to resolve the requested office id
cons_office = get_object_or_404(
KonovaCode,
id=id
)
# Try to resolve the date parameters into Date objects -> redirect if this fails
try:
df = request.GET.get("df", None)
dt = request.GET.get("dt", None)
date_from = timezone.make_aware(timezone.datetime.fromisoformat(df))
date_to = timezone.make_aware(timezone.datetime.fromisoformat(dt))
except ValueError:
messages.error(
request,
PARAMS_INVALID,
extra_tags="danger",
"""
template = "analysis/reports/index.html"
form = TimespanReportForm(None)
context = {
"form": form
}
context = BaseContext(request, context).context
return render(request, template, context)
@method_decorator(conservation_office_group_required)
def post(self, request: HttpRequest) -> HttpResponse:
"""
Args:
request (HttpRequest): The incoming request
Returns:
"""
template = "analysis/reports/index.html"
form = TimespanReportForm(request.POST or None)
if form.is_valid():
redirect_url = form.save()
return redirect(redirect_url)
else:
messages.error(
request,
FORM_INVALID,
extra_tags="danger",
)
context = {
"form": form
}
context = BaseContext(request, context).context
return render(request, template, context)
class ReportDetailView(LoginRequiredMixin, DetailView):
@method_decorator(conservation_office_group_required)
def get(self, request: HttpRequest, id: str):
""" Renders the detailed report for a conservation office
Args:
request (HttpRequest): The incoming request
id (str): The conservation_office KonovaCode id
Returns:
"""
# Try to resolve the requested office id
cons_office = get_object_or_404(
KonovaCode,
id=id
)
return redirect("analysis:reports")
# Try to resolve the date parameters into Date objects -> redirect if this fails
try:
df = request.GET.get("df", None)
dt = request.GET.get("dt", None)
date_from = timezone.make_aware(timezone.datetime.fromisoformat(df))
date_to = timezone.make_aware(timezone.datetime.fromisoformat(dt))
except ValueError:
messages.error(
request,
PARAMS_INVALID,
extra_tags="danger",
)
return redirect("analysis:reports")
# Check whether the html default rendering is requested or an alternative
format_param = request.GET.get("format", "html")
report = TimespanReport(id, date_from, date_to)
# Check whether the html default rendering is requested or an alternative
format_param = request.GET.get("format", "html")
report = TimespanReport(id, date_from, date_to)
if format_param == "html":
if format_param == "html":
return self.__handle_html_format(request, report, cons_office)
elif format_param == "excel":
return self.__handle_excel_format(report, cons_office, df, dt)
else:
raise NotImplementedError
def __handle_html_format(self, request, report: TimespanReport, office: KonovaCode):
template = "analysis/reports/detail.html"
context = {
"office": cons_office,
"office": office,
"report": report,
}
context = BaseContext(request, context).context
return render(request, template, context)
elif format_param == "excel":
def __handle_excel_format(self, report: TimespanReport, office: KonovaCode, df: str, dt: str):
file = TempExcelFile(report.excel_template_path, report.excel_map)
response = HttpResponse(
content=file.stream,
content_type="application/ms-excel",
)
response['Content-Disposition'] = f'attachment; filename={cons_office.long_name}_{df}_{dt}.xlsx'
response['Content-Disposition'] = f'attachment; filename={office.long_name}_{df}_{dt}.xlsx'
return response
else:
raise NotImplementedError