Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Split single tier types #707

Merged
merged 4 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 25 additions & 14 deletions caps/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,20 +480,10 @@ def current_emissions_breakdown(self, year: int) -> pd.DataFrame:
return df

def get_scoring_group(self):
if self.country == self.NORTHERN_IRELAND:
group = "northern-ireland"
elif self.authority_type in ("CC", "LBO", "MD", "UA"):
group = "single"
elif self.authority_type == "NMD":
group = "district"
elif self.authority_type == "CTY":
group = "county"
elif self.authority_type in ["COMB", "SRA"]:
group = "combined"
else:
group = "single"

return self.SCORING_GROUPS[group]
for slug, group in self.SCORING_GROUPS.items():
if self.authority_type in group["types"]:
return group
return self.SCORING_GROUPS["single"]

@property
def powers(self):
Expand Down Expand Up @@ -631,6 +621,19 @@ def authority_type_code(cls, authority_type):
)
return descriptions_to_codes.get(authority_type.lower().strip())

@classmethod
def authority_type_desc(cls, authority_type_code):
"""
Return an authority type description given a code, or None if the code
isn't in the authority type choices
"""
if pd.isnull(authority_type_code):
return None
codes_to_descriptions = dict(
(code, type) for code, type in Council.AUTHORITY_TYPE_CHOICES
)
return codes_to_descriptions.get(authority_type_code)

@classmethod
def percent_with_plan(cls):
"""
Expand Down Expand Up @@ -676,6 +679,14 @@ def region_filter_choices(cls):
("English Counties", (counties)),
)

@classmethod
def get_authority_type_choices_for_scoring_group(cls, scoring_group_slug):
return [
choice
for choice in cls.AUTHORITY_TYPE_CHOICES
if choice[0] in cls.SCORING_GROUPS["single"]["types"]
]


class OverwriteStorage(FileSystemStorage):
"""
Expand Down
20 changes: 4 additions & 16 deletions caps/templates/caps/council_cards/scorecard.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,23 +49,14 @@
{{ council.name }} was a <strong>top performer</strong>
{% if scoring_accolades.overall %}
amongst

{% include 'caps/includes/authority_type.html' with group=scoring_group %}

councils.
{% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=True %}.
{% elif scoring_accolades.num_sections == 1 %}
amongst

{% include 'caps/includes/authority_type.html' with group=scoring_group %}

councils,
{% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=True %},
in the <strong>{{ scoring_accolades.example_section }}</strong> section.
{% else %}
amongst

{% include 'caps/includes/authority_type.html' with group=scoring_group %}

councils,
{% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=True %},
in {{ scoring_accolades.num_sections|apnumber }} sections
including <strong>{{ scoring_accolades.example_section }}</strong>.
{% endif %}
Expand All @@ -89,10 +80,7 @@
</th>
<th class="border-0" scope="col">
Average

{% include 'caps/includes/authority_type.html' with group=scoring_group %}

council
{% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=False %}
</th>
</tr>
</thead>
Expand Down
1 change: 0 additions & 1 deletion caps/templates/caps/includes/authority_type.html

This file was deleted.

5 changes: 5 additions & 0 deletions scoring/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,11 @@ class PlanScoreFilter(django_filters.FilterSet):
choices=Council.get_county_choices(),
)

authority_type = django_filters.ChoiceFilter(
field_name="council__authority_type",
choices=Council.get_authority_type_choices_for_scoring_group("single"),
)

class Meta:
model = PlanScore
fields = []
Expand Down
28 changes: 15 additions & 13 deletions scoring/mixins.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from caps.models import Council
from django.conf import settings
from django.contrib.auth.mixins import AccessMixin
from django.shortcuts import redirect

from caps.models import Council
from scoring.models import PlanScore


Expand All @@ -18,34 +18,33 @@ def dispatch(self, request, *args, **kwargs):


class AdvancedFilterMixin:
def setup_filter_context(self, context, filter, authority_type):
def setup_filter_context(self, context, filter, scoring_group):
if getattr(filter.form, "cleaned_data", None) is not None:
params = filter.form.cleaned_data
descs = []
if (
params.get("population", None) is not None
and params["population"] != ""
):
descs.append(params.get("population", None) is not None)
descs.append(params.get("population", None))
if params.get("control", None) is not None and params["control"] != "":
descs.append(params.get("control", None) is not None)
descs.append(params.get("control", None))
if (
params.get("ruc_cluster", None) is not None
and params["ruc_cluster"] != ""
):
descs.append(
PlanScore.ruc_cluster_description(
params.get("ruc_cluster", None) is not None
)
PlanScore.ruc_cluster_description(params.get("ruc_cluster", None))
)
if params.get("imdq", None) is not None and params["imdq"] != "":
descs.append(
"deprivation quintile {}".format(
params.get("imdq", None) is not None
)
)
descs.append("deprivation quintile {}".format(params.get("imdq", None)))
if params.get("country", None) is not None and params["country"] != "":
descs.append(Council.country_description(params["country"]))
if (
params.get("authority_type", None) is not None
and params["authority_type"] != ""
):
descs.append(Council.authority_type_desc(params["authority_type"]))
if params.get("region", None) is not None and params["region"] != "":
descs.append(params["region"])
if params.get("county", None) is not None and params["county"] != "":
Expand All @@ -56,9 +55,12 @@ def setup_filter_context(self, context, filter, authority_type):

context["urbanisation_filter"] = PlanScore.RUC_TYPES
context["population_filter"] = PlanScore.POPULATION_FILTER_CHOICES.get(
authority_type["slug"]
scoring_group["slug"]
)
context["county_filter"] = Council.get_county_choices()
context["authority_type_filter"] = (
Council.get_authority_type_choices_for_scoring_group("single")
)

return context

Expand Down
33 changes: 12 additions & 21 deletions scoring/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,19 +235,18 @@ def section_codes(cls, year=settings.PLAN_YEAR):

@classmethod
def get_average_scores(
cls, council_group=None, filter=None, year=settings.PLAN_YEAR
cls, scoring_group=None, filter=None, year=settings.PLAN_YEAR
):
"""
This excludes plans with zero score as it's assumed that if they have 0 then they
were not marked, or the council has no plan, and hence including them would artificially
reduce the average.
"""
has_score = PlanScore.objects.filter(total__gt=0, year=year)
if council_group is not None:
group = Council.SCORING_GROUPS[council_group]
if scoring_group is not None:
has_score = has_score.filter(
council__authority_type__in=group["types"],
council__country__in=group["countries"],
council__authority_type__in=scoring_group["types"],
council__country__in=scoring_group["countries"],
)

if filter is not None:
Expand Down Expand Up @@ -433,6 +432,11 @@ def get_all_section_top_mark_counts(cls, council_group=None, plan_year=None):


class PlanQuestionGroup(models.Model):
"""
Typically referred to as "scoring_group" elsewhere in the code.
"""

# This is the scoring_group’s slug, eg: "single-tier"
description = models.TextField(max_length=200)

def __str__(self):
Expand Down Expand Up @@ -543,27 +547,14 @@ def evidence_links_cleaned(self):
def is_negatively_marked(self):
return self.question_type == "negative"

@classmethod
def get_average_scores(cls, section=None, council_group=None):
qs = PlanQuestionScore.objects.all()
if section is not None:
qs = qs.filter(plan_question__section=section)
# XXX fix this when relevant code is merged
# if council_group is not None:
# qs = qs.filter(question__=section)

qs = qs.values("plan_question__code").annotate(average=Avg("score"))

return qs

def get_scores_breakdown(self, year=None, council_group=None):
def get_scores_breakdown(self, year=None, scoring_group=None):
filters = {
"plan_question": self,
}
if year is not None:
filters["plan_score__year"] = year
if council_group is not None:
filters["plan_score__council__authority_type__in"] = council_group["types"]
if scoring_group is not None:
filters["plan_score__council__authority_type__in"] = scoring_group["types"]

counts = (
PlanQuestionScore.objects.filter(**filters)
Expand Down
2 changes: 1 addition & 1 deletion scoring/templates/scoring/council-preview.html
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ <h1 class="text-shadow js-count">
{% if plan_score.top_performer %}
<span class="mb-5 me-auto fw-bold subtitle text-shadow text-yellow-300 mt-2">
{% include 'caps/icons/scorecards-star.html' with classes='me-1 align-text-top' width='1.2em' height='auto' role='presentation' %}
High scoring council &mdash; {% include 'caps/includes/authority_type.html' with group=authority_type %}
High scoring {% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=False %}
</span>
{% endif %}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{% block content %}
<div class="mb-5 me-auto fw-bold text-shadow text-yellow-300 d-flex align-items-center" style="font-size: 3rem; line-height: 1.2;">
{% include 'caps/icons/scorecards-star.html' with classes='me-4 align-text-top' width='1.2em' height='auto' role='presentation' %}
<span>High scorer &mdash; {% include 'caps/includes/authority_type.html' with group=authority_type %} councils</span>
<span>High scorer &mdash; {% include 'scoring/includes/scoring-group-name.html' with group=scoring_group.slug plural=True %}</span>
</div>
<div class="open-graph-preview__grid">
<div class="grid__name">
Expand Down
10 changes: 5 additions & 5 deletions scoring/templates/scoring/council.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ <h1 class="mt-4">{{ council.name }}</h1>
{% if plan_score.top_performer %}
<div class="d-flex align-items-center">
{% include 'caps/icons/scorecards-star.html' with classes='me-2' width='1rem' height='1rem' role='presentation' %}
This council is one of the highest scoring {% include 'caps/includes/authority_type.html' with group=authority_type %} councils.
This council is one of the highest scoring {% include 'scoring/includes/scoring-group-name.html' with group=council.get_scoring_group.slug plural=True %}.
</div>
{% endif %}
<dl class="mt-4 mb-0 council-stats-grid">
Expand Down Expand Up @@ -306,15 +306,15 @@ <h3 class="exclamation text-white">Visit us again on a bigger screen</h3>
{% endfor %}

<td class="d-none d-md-table-cell top-tier-score border-bottom border-end">
<a href="{% url 'scoring:question' answer.code %}?type={{ authority_type.slug }}" class="mx-auto" style="text-transform: none">
<a href="{% url 'scoring:question' answer.code %}?type={{ council.get_scoring_group.slug }}" class="mx-auto" style="text-transform: none">
{{ answer.council_count }} out of {{ council_count }}
</a>
<span class="fs-8 mt-1 me-0 ms-auto d-block">
{% include 'caps/includes/authority_type.html' with group=authority_type %}
{% include 'scoring/includes/scoring-group-name.html' with group=council.get_scoring_group.slug plural=True %}
{% if answer.type == "negative" %}
councils got <strong>no penalty marks</strong> for this question.
got <strong>no penalty marks</strong> for this question.
{% else %}
councils got full marks for this question.
got full marks for this question.
{% endif %}
</span>
</td>
Expand Down
6 changes: 3 additions & 3 deletions scoring/templates/scoring/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ <h3 class="fs-6 mb-0">Check a council&rsquo;s Scorecard</h3>
<div class="table-header mb-4 d-md-flex align-items-end">
<div class="me-md-auto">
<h3 class="d-inline-block">
<span>{{ authority_type_label }}</span>
<span>{{ scoring_group.name }}</span>
{% if filter_descs %}
<span>·</span>
{% if filter_descs|length > 1 %}
Expand Down Expand Up @@ -133,7 +133,7 @@ <h3 class="d-inline-block">
</tr>
<tr class="second-row position-sticky z-index-4">
<th scope="col" style="min-width:250px" class="bg-primary-100 position-sticky z-index-4">
<span class="ms-4 fs-6 fw-bold d-block">{{ authority_type_label }} average</span>
<span class="ms-4 fs-6 fw-bold d-block">{{ scoring_group.name }} average</span>
</th>
<th scope="col" class="bg-primary-100 total-score position-sticky z-index-4 bg-green-l2">
{% include 'scoring/includes/score-bar.html' with percentage=averages.total.percentage average=1 %}
Expand Down Expand Up @@ -235,7 +235,7 @@ <h3 class="d-inline-block">
</th>
<tr class="second-row position-sticky z-index-4">
<th class="bg-white" scope="col" style="min-width:250px">
<span class="ms-4 fs-6 fw-bold d-block" style="white-space: break-spaces;">{{ authority_type_label }} average</span>
<span class="ms-4 fs-6 fw-bold d-block" style="white-space: break-spaces;">{{ scoring_group.name }} average</span>
</th>
<th scope="col" class="total-score position-sticky z-index-4">
{% include 'scoring/includes/score-bar.html' with percentage=averages.total.percentage average=1 %}
Expand Down
4 changes: 2 additions & 2 deletions scoring/templates/scoring/home_combined.html
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
</tr>
<tr class="second-row position-sticky z-index-4">
<th scope="col" style="min-width:250px" class="bg-primary-100 position-sticky z-index-4">
<span class="ms-4 fs-6 fw-bold d-block">{{ authority_type_label }} average</span>
<span class="ms-4 fs-6 fw-bold d-block">{{ scoring_group.name }} average</span>
</th>
<th scope="col" class="bg-primary-100 total-score position-sticky z-index-4 bg-green-l2">
{% include 'scoring/includes/score-bar.html' with percentage=averages.total.percentage average=1 %}
Expand Down Expand Up @@ -139,7 +139,7 @@
</th>
<tr class="second-row position-sticky z-index-4">
<th class="bg-white" scope="col" style="min-width:250px">
<span class="ms-4 fs-6 fw-bold d-block" style="white-space: break-spaces;">{{ authority_type_label }} average</span>
<span class="ms-4 fs-6 fw-bold d-block" style="white-space: break-spaces;">{{ scoring_group.name }} average</span>
</th>
<th scope="col" class="total-score position-sticky z-index-4">
{% include 'scoring/includes/score-bar.html' with percentage=averages.total.percentage average=1 %}
Expand Down
Loading
Loading