work/views.py
File not formatted according to black style guidefrom typing import AnyFile not formatted according to black style guide File not formatted according to black style guidefrom django.db import connectionFile not formatted according to black style guidefrom django.db.models import SumFile not formatted according to black style guidefrom django.utils.translation import gettext as _File not formatted according to black style guidefrom django.views.generic import TemplateViewFile not formatted according to black style guidefrom django.views.generic.edit import FormViewFile not formatted according to black style guide File not formatted according to black style guideimport plotly.express as pxFile not formatted according to black style guide File not formatted according to black style guidefrom core.constants import DAY_MILLISECONDSFile not formatted according to black style guide File not formatted according to black style guidefrom .forms import WorkFormFile not formatted according to black style guidefrom .models import WorkFile not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef dictfetchall(cursor):File not formatted according to black style guide """Return a list of dictionaries containing all rows from a databaseFile not formatted according to black style guide cursor."""File not formatted according to black style guide columns = [col[0] for col in cursor.description]File not formatted according to black style guide return [dict(zip(columns, row)) for row in cursor.fetchall()]File not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef get_daily_total_hours_by_role_and_work_type_with_percent():File not formatted according to black style guide query = """File not formatted according to black style guide with daily_work_totals_by_type as (File not formatted according to black style guide selectFile not formatted according to black style guide date,File not formatted according to black style guide caregiver_role.name as role_name,File not formatted according to black style guide work_type.name as work_type,File not formatted according to black style guide sum(duration_hours) as daily_total_hoursFile not formatted according to black style guide from workFile not formatted according to black style guide left join work_type on type_id = work_type.idFile not formatted according to black style guide left join caregiver_role on caregiver_role_id = caregiver_role.idFile not formatted according to black style guide group by date, role_name, work_typeFile not formatted according to black style guide ),File not formatted according to black style guide daily_work_totals_by_type_with_role_total_hours as (File not formatted according to black style guide selectFile not formatted according to black style guide *,File not formatted according to black style guide sum(daily_total_hours) over (partition by date, role_name) as daily_role_total_hoursFile not formatted according to black style guide from daily_work_totals_by_typeFile not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide selectFile not formatted according to black style guide *,File not formatted according to black style guide CAST(daily_total_hours as float) / CAST(daily_role_total_hours as float) as percent_of_daily_role_total_hoursFile not formatted according to black style guide from daily_work_totals_by_type_with_role_total_hours;File not formatted according to black style guide """File not formatted according to black style guide File not formatted according to black style guide with connection.cursor() as cursor:File not formatted according to black style guide cursor.execute(query)File not formatted according to black style guide File not formatted according to black style guide result = dictfetchall(cursor)File not formatted according to black style guide File not formatted according to black style guide return resultFile not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef get_total_hours_by_role_and_work_type_with_percent():File not formatted according to black style guide query = """File not formatted according to black style guide with work_totals_by_type as (File not formatted according to black style guide selectFile not formatted according to black style guide caregiver_role.name as role_name,File not formatted according to black style guide work_type.name as work_type,File not formatted according to black style guide sum(duration_hours) as total_hoursFile not formatted according to black style guide from workFile not formatted according to black style guide left join work_type on type_id = work_type.idFile not formatted according to black style guide left join caregiver_role on caregiver_role_id = caregiver_role.idFile not formatted according to black style guide group by role_name, work_typeFile not formatted according to black style guide ),File not formatted according to black style guide work_totals_by_type_with_role_total_hours as (File not formatted according to black style guide selectFile not formatted according to black style guide *,File not formatted according to black style guide sum(total_hours) over (partition by role_name) as role_total_hoursFile not formatted according to black style guide from work_totals_by_typeFile not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide selectFile not formatted according to black style guide *,File not formatted according to black style guide CAST(total_hours as float) / CAST(role_total_hours as float) as percent_of_role_total_hoursFile not formatted according to black style guide from work_totals_by_type_with_role_total_hours;File not formatted according to black style guide """File not formatted according to black style guide File not formatted according to black style guide with connection.cursor() as cursor:File not formatted according to black style guide cursor.execute(query)File not formatted according to black style guide File not formatted according to black style guide result = dictfetchall(cursor)File not formatted according to black style guide File not formatted according to black style guide return resultFile not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef get_work_by_type_data():File not formatted according to black style guide work_by_type = (File not formatted according to black style guide Work.objects.values("type__name")File not formatted according to black style guide .order_by("type__name")File not formatted according to black style guide .annotate(total_hours=Sum("duration_hours"))File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide return list(work_by_type)File not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef prepare_work_by_type_chart(data):File not formatted according to black style guide work_by_type_chart = px.bar(File not formatted according to black style guide data,File not formatted according to black style guide x="type__name",File not formatted according to black style guide y="total_hours",File not formatted according to black style guide title=_("Work hours by work type"),File not formatted according to black style guide labels={File not formatted according to black style guide "type__name": _("Type of work"),File not formatted according to black style guide "total_hours": _("Total hours"),File not formatted according to black style guide },File not formatted according to black style guide ).to_html()File not formatted according to black style guide File not formatted according to black style guide return work_by_type_chartFile not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef get_work_by_caregiver_role_data():File not formatted according to black style guide work_by_caregiver_role_data = (File not formatted according to black style guide Work.objects.values("caregiver_role__name")File not formatted according to black style guide .order_by("caregiver_role__name")File not formatted according to black style guide .annotate(total_hours=Sum("duration_hours"))File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide return list(work_by_caregiver_role_data)File not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef prepare_work_by_caregiver_role_chart(data):File not formatted according to black style guide work_by_caregiver_role_chart = px.bar(File not formatted according to black style guide data,File not formatted according to black style guide x="caregiver_role__name",File not formatted according to black style guide y="total_hours",File not formatted according to black style guide title=_("Work hours by caregiver role"),File not formatted according to black style guide labels={File not formatted according to black style guide "caregiver_role__name": _("Caregiver role"),File not formatted according to black style guide "total_hours": _("Total hours"),File not formatted according to black style guide },File not formatted according to black style guide ).to_html()File not formatted according to black style guide File not formatted according to black style guide return work_by_caregiver_role_chartFile not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef prepare_daily_work_percent_by_caregiver_role_and_type_chart(data):File not formatted according to black style guide daily_work_percent_by_caregiver_role_and_type_chart = px.bar(File not formatted according to black style guide data,File not formatted according to black style guide x="date",File not formatted according to black style guide y="percent_of_daily_role_total_hours",File not formatted according to black style guide facet_row="role_name",File not formatted according to black style guide color="work_type",File not formatted according to black style guide title=_("Daily work percent by caregiver role and work type"),File not formatted according to black style guide labels={File not formatted according to black style guide "role_name": _("Caregiver role"),File not formatted according to black style guide "percent_of_daily_role_total_hours": _("Work percent"),File not formatted according to black style guide "work_type": _("Type of work"),File not formatted according to black style guide },File not formatted according to black style guide # Add numeric text on barsFile not formatted according to black style guide text_auto=True,File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide # Format y-axis as percentagesFile not formatted according to black style guide daily_work_percent_by_caregiver_role_and_type_chart.update_yaxes(tickformat=",.0%")File not formatted according to black style guide File not formatted according to black style guide # Remove facet prefix from facet row labelsFile not formatted according to black style guide daily_work_percent_by_caregiver_role_and_type_chart.for_each_annotation(File not formatted according to black style guide lambda a: a.update(text=a.text.split("=")[-1]),File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide # Ensure that all bar widths are one day (where units are in milliseconds)File not formatted according to black style guide daily_work_percent_by_caregiver_role_and_type_chart.update_traces(File not formatted according to black style guide width=DAY_MILLISECONDS,File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide return daily_work_percent_by_caregiver_role_and_type_chart.to_html()File not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef prepare_work_percent_by_caregiver_role_and_type_chart(data):File not formatted according to black style guide work_percent_by_caregiver_role_and_type_chart = px.bar(File not formatted according to black style guide data,File not formatted according to black style guide x="role_name",File not formatted according to black style guide y="percent_of_role_total_hours",File not formatted according to black style guide color="work_type",File not formatted according to black style guide title=_("Work percent by caregiver role and work type"),File not formatted according to black style guide labels={File not formatted according to black style guide "role_name": _("Caregiver role"),File not formatted according to black style guide "percent_of_role_total_hours": _("Work percent"),File not formatted according to black style guide "work_type": _("Type of work"),File not formatted according to black style guide },File not formatted according to black style guide text_auto=True,File not formatted according to black style guide )File not formatted according to black style guide work_percent_by_caregiver_role_and_type_chart.layout.yaxis.tickformat = ",.0%"File not formatted according to black style guide File not formatted according to black style guide return work_percent_by_caregiver_role_and_type_chart.to_html()File not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guidedef prepare_work_by_caregiver_role_and_type_chart(data):File not formatted according to black style guide work_by_caregiver_role_and_type_chart = px.bar(File not formatted according to black style guide data,File not formatted according to black style guide x="role_name",File not formatted according to black style guide y="total_hours",File not formatted according to black style guide color="work_type",File not formatted according to black style guide title=_("Work hours by caregiver role and work type"),File not formatted according to black style guide labels={File not formatted according to black style guide "role_name": _("Caregiver role"),File not formatted according to black style guide "total_hours": _("Total hours"),File not formatted according to black style guide "work_type": _("Type of work"),File not formatted according to black style guide },File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide return work_by_caregiver_role_and_type_chart.to_html()File not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guideclass WorkReportView(TemplateView):File not formatted according to black style guide template_name = "work/report.html"File not formatted according to black style guide File not formatted according to black style guide def prepare_charts(self, context):File not formatted according to black style guide """Prepare data/charts and add them to the template context."""File not formatted according to black style guide context["work_by_type_chart"] = prepare_work_by_type_chart(File not formatted according to black style guide get_work_by_type_data(),File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide context["work_by_caregiver_role_chart"] = prepare_work_by_caregiver_role_chart(File not formatted according to black style guide get_work_by_caregiver_role_data(),File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide context["daily_work_percent_by_caregiver_role_and_type_chart"] = (File not formatted according to black style guide prepare_daily_work_percent_by_caregiver_role_and_type_chart(File not formatted according to black style guide get_daily_total_hours_by_role_and_work_type_with_percent(),File not formatted according to black style guide )File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide work_by_caregiver_role_and_type_with_percent = (File not formatted according to black style guide get_total_hours_by_role_and_work_type_with_percent()File not formatted according to black style guide )File not formatted according to black style guide context["work_percent_by_caregiver_role_and_type_chart"] = (File not formatted according to black style guide prepare_work_percent_by_caregiver_role_and_type_chart(File not formatted according to black style guide work_by_caregiver_role_and_type_with_percent,File not formatted according to black style guide )File not formatted according to black style guide )File not formatted according to black style guide context["work_by_caregiver_role_and_type_chart"] = (File not formatted according to black style guide prepare_work_by_caregiver_role_and_type_chart(File not formatted according to black style guide work_by_caregiver_role_and_type_with_percent,File not formatted according to black style guide )File not formatted according to black style guide )File not formatted according to black style guide File not formatted according to black style guide return contextFile not formatted according to black style guide File not formatted according to black style guide def get_context_data(self, **kwargs: Any) -> dict[str, Any]:File not formatted according to black style guide context = super().get_context_data(**kwargs)File not formatted according to black style guide File not formatted according to black style guide # Check if work has been recordedFile not formatted according to black style guide # by selecting one recordFile not formatted according to black style guide context["work_has_been_recorded"] = Work.objects.all()[:1].exists()File not formatted according to black style guide File not formatted according to black style guide # Only prepare charts if work has been recordedFile not formatted according to black style guide if context["work_has_been_recorded"]:File not formatted according to black style guide context = self.prepare_charts(context)File not formatted according to black style guide File not formatted according to black style guide return contextFile not formatted according to black style guide File not formatted according to black style guide File not formatted according to black style guideclass WorkFormView(FormView):File not formatted according to black style guide template_name = "work/form.html"File not formatted according to black style guide form_class = WorkFormFile not formatted according to black style guide success_url = "/"File not formatted according to black style guide File not formatted according to black style guide def form_valid(self, form):File not formatted according to black style guide # save the form before redirecting to success URLFile not formatted according to black style guide # Note: this may be unnecessary,File not formatted according to black style guide # but the form wasn't saving previouslyFile not formatted according to black style guide form.save()File not formatted according to black style guide File not formatted according to black style guide return super().form_valid(form)