import itertools from typing import Any, Dict, List, Set from django.contrib.auth.mixins import PermissionRequiredMixin from django.db import transaction from django.db.models import Q from django.http import HttpResponseRedirect from django.shortcuts import get_object_or_404, render from django.urls import reverse, reverse_lazy from django.views.generic import CreateView, DetailView, FormView, ListView from ctrack.caf.models import CAF, EssentialService from ctrack.register.models import EngagementEvent from .forms import AddressInlineFormSet, IncidentReportForm, OrganisationCreateForm from .models import IncidentReport, Organisation, Person, Submode from .utils import filter_private_events # TODO - needs a permission on this view def essential_service_detail(request, pk): es = EssentialService.objects.get(pk=pk) org = es.organisation cafs = CAF.objects.filter(organisation=org.pk) asses = es.systems.all() # es = get_object_or_404(EssentialService, organisation__pk=org_pk) context = {"es": es, "asses": asses, "cafs": cafs} return render(request, "organisations/essential_service_detail.html", context) class PersonListView(PermissionRequiredMixin, ListView): model = Person template_name = "organisations/person_list.html" permission_required = "organisations.view_person" def person_detail(request, person_id): p = get_object_or_404(Person, pk=person_id) return render(request, "organisations/person_detail.html", {"person": p}) class OrganisationCreate(PermissionRequiredMixin, CreateView): model = Organisation template_name = "organisations/org_create_formset.html" form_class = OrganisationCreateForm permission_required = "organisations.add_organisation" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) if self.request.POST: context["addresses"] = AddressInlineFormSet(self.request.POST) else: context["addresses"] = AddressInlineFormSet() return context def form_valid(self, form): context = self.get_context_data() addresses = context["addresses"] with transaction.atomic(): # form.instance.updated_by = self.request.user REMOVED updated_by self.object = form.save() if addresses.is_valid(): addresses.instance = self.object addresses.save() return super().form_valid(form) def get_success_url(self): return reverse_lazy("organisations:detail", kwargs={"slug": self.object.slug}) class OrganisationListView(PermissionRequiredMixin, ListView): model = Organisation permission_required = "organisations.view_organisation" def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) context["organisation_list"] = Organisation.objects.all().order_by("name") return context class OrganisationDetailView(PermissionRequiredMixin, DetailView): model = Organisation permission_required = "organisations.view_organisation" def get_context_data(self, **kwargs: Any): context = super().get_context_data() org = kwargs["object"] peoples = org.person_set.all() cafs = org.caf_set.all() # simple datetime events for org _sdes = [ filter_private_events( person.get_single_datetime_events(), self.request.user ) for person in peoples ] flat_sdes = sorted( list(itertools.chain.from_iterable(_sdes)), key=lambda e: e.datetime, reverse=True, ) # Some events will not involve a participant, which is what ties an event to an organisation. # Because we want to list events to an organisation here we must related it via the CAF object too... engagement_events = EngagementEvent.objects.filter( Q(participants__in=peoples) | Q(related_caf__in=cafs) ).order_by("-date") essential_services = EssentialService.objects.filter(organisation=org) no_addr = org.addresses.count() if no_addr > 1: context["no_addr"] = no_addr addr = org.addresses.all() context["addr"] = addr else: context["no_addr"] = 1 addr = org.addresses.first() context["addr"] = addr people = org.person_set.all() context["people"] = people applicable_systems = org.applicable_systems() context["applicable_systems"] = applicable_systems context["engagement_events"] = engagement_events context["essential_services"] = essential_services context["cafs"] = cafs context["single_datetime_events"] = flat_sdes return context class IncidentReportCreateView(FormView): model = IncidentReport form_class = IncidentReportForm template_name = "organisations/incidentreport_form.html" success_url = reverse_lazy("core:home") def get_form_kwargs(self): kwargs = super().get_form_kwargs() kwargs["org"] = self.request.user.stakeholder.person.organisation kwargs["reporting_person"] = self.request.user.stakeholder.person return kwargs def form_valid(self, form): form.save() return HttpResponseRedirect(reverse("core:home")) def inspectors_for_each_mode(lead_type="lead_inspector") -> Dict[str, Set[str]]: """ We want to be able to group lead inspectors by submode. """ if lead_type not in ["lead_inspector", "deputy_lead_inspector"]: raise ValueError("Can only query for lead_inspector and deputy_lead_inspector attributes.") submodes = Submode.objects.all() out = {} for sm in submodes: insp = set() orgs = sm.organisation_set.all() for org in orgs: insp.add(getattr(org, lead_type)) out[sm.descriptor] = insp del insp return out