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 from analysis.utils.report import TimespanReport from codelist.models import KonovaCode from konova.contexts import BaseContext from konova.decorators import conservation_office_group_required from konova.utils.message_templates import FORM_INVALID, PARAMS_INVALID @login_required @conservation_office_group_required def index_reports_view(request: HttpRequest): """ Args: request (HttpRequest): The incoming request Returns: """ template = "analysis/reports/index.html" form = TimespanReportForm(request.POST or None) if request.method == "POST": 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 ReportIndexView(LoginRequiredMixin, View): @method_decorator(conservation_office_group_required) def get(self, request: HttpRequest) -> HttpResponse: """ Args: request (HttpRequest): The incoming request Returns: """ 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 ) # 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) 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": office, "report": report, } context = BaseContext(request, context).context return render(request, template, context) 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={office.long_name}_{df}_{dt}.xlsx' return response