From 36e2b10f3860da3c0345033848e3e239b13b2269 Mon Sep 17 00:00:00 2001 From: Will Clarke Date: Thu, 21 Nov 2024 16:35:08 +0000 Subject: [PATCH 1/7] add test for redirect to category specific url update behaviour for invalid codes to redirect to generic search update single search page to have some content add new category single search page --- fala/apps/adviser/utils.py | 25 +++++ fala/apps/adviser/views.py | 33 +++++++ .../adviser/single_category_search.html | 93 +++++++++++++++++++ fala/urls.py | 8 +- 4 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 fala/apps/adviser/utils.py create mode 100644 fala/templates/adviser/single_category_search.html diff --git a/fala/apps/adviser/utils.py b/fala/apps/adviser/utils.py new file mode 100644 index 00000000..3a675b9a --- /dev/null +++ b/fala/apps/adviser/utils.py @@ -0,0 +1,25 @@ +# utils.py + +CATEGORY_TRANSLATIONS = { + "aap": "claims-against-public-authorities", + "med": "clinical-negligence", + "com": "community-care", + "crm": "crime", + "deb": "debt", + "disc": "discrimination", + "edu": "education", + "mat": "family", + "fmed": "family-mediation", + "hou": "housing", + "hlpas": "hlpas", + "immas": "immigration-asylum", + "mhe": "mental-health", + "mosl": "modern-slavery", + "pl": "prison-law", + "pub": "public-law", + "wb": "welfare-benefits", +} + + +def get_category_display_name(category_code): + return CATEGORY_TRANSLATIONS.get(category_code) diff --git a/fala/apps/adviser/views.py b/fala/apps/adviser/views.py index f85ac01d..94b69f76 100644 --- a/fala/apps/adviser/views.py +++ b/fala/apps/adviser/views.py @@ -11,6 +11,8 @@ from .forms import AdviserSearchForm, AdviserRootForm from .laa_laa_paginator import LaaLaaPaginator from .regions import Region +from django.shortcuts import redirect +from .utils import get_category_display_name class RobotsTxtView(View): @@ -50,8 +52,39 @@ def get_context_data(self, **kwargs): } ) return context +from django.shortcuts import redirect +from .utils import get_category_display_name +class SingleCategorySearchView(CommonContextMixin, TemplateView): + template_name = "adviser/single_category_search.html" + def get(self, request, *args, **kwargs): + category_code = request.GET.get("categories") + if category_code: + category_slug = get_category_display_name(category_code) + if category_slug: + return redirect('single_category_search', category=category_slug) + else: + return redirect('search') + + category_slug = kwargs.get("category") + if not category_slug: + return redirect('search') + + context = self.get_context_data(**kwargs) + form = AdviserRootForm(data=request.GET or None) + + context.update( + { + "form": form, + "category_slug": category_slug, + "category_display_name": category_slug.replace("-", " ").title(), + "current_url": request.path, + "CHECK_LEGAL_AID_URL": settings.CHECK_LEGAL_AID_URL, + } + ) + + return self.render_to_response(context) class AdviserView(CommonContextMixin, TemplateView): template_name = "adviser/search.html" diff --git a/fala/templates/adviser/single_category_search.html b/fala/templates/adviser/single_category_search.html new file mode 100644 index 00000000..fe6cef18 --- /dev/null +++ b/fala/templates/adviser/single_category_search.html @@ -0,0 +1,93 @@ +{% extends 'adviser/adviser_base.html' %} + +{% block pageTitle %}Find a Legal Aid Adviser or Family Mediator{% endblock %} + +{% import "macros/element.html" as Element %} +{% import "macros/forms.html" as Form %} + +{%- from 'govuk_frontend_jinja/components/error-summary/macro.html' import govukErrorSummary %} +{%- from 'govuk_frontend_jinja/components/checkboxes/macro.html' import govukCheckboxes %} +{%- from "govuk_frontend_jinja/components/input/macro.html" import govukInput %} + +{% block content %} +
+
+ {% if form.errors %} + {{ govukErrorSummary({ + "titleText": "There is a problem", + "errorList": errorList + }) }} + {% endif %} +

Find a legal aid adviser or family mediator

+

You need to provide information about your finances to find out if you qualify for legal aid.

+

Check if you qualify for legal aid (opens in a new tab)

+
+ + {% block search_form %} +
+
+ +
+ {% set errorMessage = {'err': ""} %} + + {% if form.errors %} + {% call Element.errorText() %} + {% for k, error in form.errors.items() %} + {% if errorMessage.update({'err': error | striptags}) %}{% endif %} + {% endfor %} + {% endcall %} + {% endif %} + + {% if 'postcode' in form.errors or form.errors['__all__'] %} + {{ govukInput({ + 'label': { + 'text': "Postcode", + 'classes': 'govuk-label--s', + }, + 'value': form.postcode.value(), + 'errorMessage': { 'text': form.errors['postcode'][0] }, + 'hint': { + 'text' : "For example, NE31 1SF", + }, + 'attributes': { + 'maxLength': 30, + }, + 'id': 'id_postcode', + 'classes': 'govuk-input--width-10', + 'name': "postcode" + }) }} + {% else %} + {{ govukInput({ + 'label': { + 'text': "Postcode", + 'classes': 'govuk-label--s', + }, + 'value': form.postcode.value(), + 'hint': { + 'text' : "For example, NE31 1SF", + }, + 'attributes': { + 'maxLength': 30, + }, + 'id': 'id_postcode', + 'classes': 'govuk-input--width-10', + 'name': "postcode" + }) }} + {% endif %} + + {{ govukButton({ + 'text': "Search", + 'type': "submit", + 'classes': "govuk-!-margin-bottom-2", + 'id': "searchButton", + 'name': "search" + }) }} +
+
+
+ {% endblock %} + +
+

If you are a provider and your details are incorrect, please contact your contract manager.

+
+{% endblock %} \ No newline at end of file diff --git a/fala/urls.py b/fala/urls.py index 33efc983..e07c8dea 100644 --- a/fala/urls.py +++ b/fala/urls.py @@ -1,5 +1,4 @@ -# coding=utf-8 -from django.conf import settings +# urls.py from django.urls import re_path from adviser.views import ( @@ -10,6 +9,7 @@ CookiesView, RobotsTxtView, SecurityTxtView, + SingleCategorySearchView, ) from django.views.static import serve @@ -21,4 +21,6 @@ re_path(r"^search$", SearchView.as_view(), name="search"), re_path(r"^robots\.txt$", RobotsTxtView.as_view(), name="robots_txt"), re_path(r"^security\.txt$", SecurityTxtView.as_view(), name="security_txt"), -] + [re_path(r"^static/(?P.*)$", serve, {"document_root": settings.STATIC_ROOT})] + re_path(r"^single-category-search/(?P[\w-]+)$", SingleCategorySearchView.as_view(), name="single_category_search"), + re_path(r"^single-category-search$", SingleCategorySearchView.as_view(), name="single_category_search_query"), +] + [re_path(r"^static/(?P.*)$", serve, {"document_root": settings.STATIC_ROOT})] \ No newline at end of file From a733c5c4687b53759504d5c9c405300a7102f184 Mon Sep 17 00:00:00 2001 From: Will Clarke Date: Thu, 21 Nov 2024 20:09:54 +0000 Subject: [PATCH 2/7] works for a certain definition of working display categry name in H1 handle custom content for some categories add custom styling for hlpas --- .gitignore | 3 +- fala/apps/adviser/views.py | 57 +++++-- .../adviser/single_category_search.html | 150 +++++++++++------- fala/urls.py | 12 +- 4 files changed, 145 insertions(+), 77 deletions(-) diff --git a/.gitignore b/.gitignore index 98ab9040..31c6ac66 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,5 @@ fala/static .python-version # VSCode -.vscode \ No newline at end of file +.vscode +fala/apps/adviser/fala.code-workspace \ No newline at end of file diff --git a/fala/apps/adviser/views.py b/fala/apps/adviser/views.py index 94b69f76..b389e352 100644 --- a/fala/apps/adviser/views.py +++ b/fala/apps/adviser/views.py @@ -52,39 +52,74 @@ def get_context_data(self, **kwargs): } ) return context -from django.shortcuts import redirect -from .utils import get_category_display_name + class SingleCategorySearchView(CommonContextMixin, TemplateView): template_name = "adviser/single_category_search.html" + CATEGORY_MESSAGES = { + "hlpas": "Tell the adviser your home is at risk and you want advice through the Housing Loss Prevention Advice Service.", + "welfare-benefits": """Legal aid for advice about welfare benefits is only available if you are appealing a decision made by the social security tribunal. This appeal must be in the Upper Tribunal, Court of Appeal or Supreme Court. + + For any other benefits issue, ask the legal adviser if you can get free legal advice or if you will have to pay for it.""", + "clinical-negligence": "Legal aid for advice about clinical negligence is usually only available if you have a child that suffered a brain injury during pregnancy, birth or the first 8 weeks of life.", + } + + CATEGORY_DISPLAY_NAMES = { + "hlpas": "Housing Loss Prevention Advice Service", + } + def get(self, request, *args, **kwargs): - category_code = request.GET.get("categories") - if category_code: + + category_code = request.GET.get("categories") # Extract `categories` from query parameters + if category_code: # Redirect to the correct category-based URL category_slug = get_category_display_name(category_code) if category_slug: - return redirect('single_category_search', category=category_slug) + return redirect("single_category_search", category=category_slug) else: - return redirect('search') - + return redirect("search") + category_slug = kwargs.get("category") if not category_slug: - return redirect('search') + return redirect("search") context = self.get_context_data(**kwargs) form = AdviserRootForm(data=request.GET or None) + category_message = self.CATEGORY_MESSAGES.get(category_slug, "") + category_display_name = self.CATEGORY_DISPLAY_NAMES.get(category_slug, category_slug.replace("-", " ").title()) context.update( { "form": form, "category_slug": category_slug, - "category_display_name": category_slug.replace("-", " ").title(), - "current_url": request.path, - "CHECK_LEGAL_AID_URL": settings.CHECK_LEGAL_AID_URL, + "category_display_name": category_display_name, + "category_message": category_message, } ) + if form.is_valid(): + postcode = form.cleaned_data.get("postcode") + if postcode: + # Perform the search using the postcode and category_slug + results = self.perform_search(postcode, category_slug) + context.update({"results": results}) + return self.render_to_response(context) + + def perform_search(self, postcode, category): + try: + data = laalaa.find( + postcode=postcode, + categories=[category], + page=1, # Assuming you want the first page of results + ) + return data.get("results", []) + except laalaa.LaaLaaError: + return [] + + + + class AdviserView(CommonContextMixin, TemplateView): template_name = "adviser/search.html" diff --git a/fala/templates/adviser/single_category_search.html b/fala/templates/adviser/single_category_search.html index fe6cef18..e500fc81 100644 --- a/fala/templates/adviser/single_category_search.html +++ b/fala/templates/adviser/single_category_search.html @@ -18,76 +18,104 @@ "errorList": errorList }) }} {% endif %} -

Find a legal aid adviser or family mediator

-

You need to provide information about your finances to find out if you qualify for legal aid.

-

Check if you qualify for legal aid (opens in a new tab)

+

Find a legal aid adviser for + {% if category_slug == 'hlpas' %} + {{ category_display_name }} + {% else %} + {{ category_display_name | lower }} + {% endif %} +

+

Search for official legal aid advisers in England and Wales.

+ {% if category_message %} +

{{ category_message |linebreaks }}

+ {% endif %} {% block search_form %} -
-
+
-
- {% set errorMessage = {'err': ""} %} + + {% set errorMessage = {'err': ""} %} - {% if form.errors %} - {% call Element.errorText() %} - {% for k, error in form.errors.items() %} - {% if errorMessage.update({'err': error | striptags}) %}{% endif %} - {% endfor %} - {% endcall %} - {% endif %} + {% if form.errors %} + {% call Element.errorText() %} + {% for k, error in form.errors.items() %} + {% if errorMessage.update({'err': error | striptags}) %}{% endif %} + {% endfor %} + {% endcall %} + {% endif %} - {% if 'postcode' in form.errors or form.errors['__all__'] %} - {{ govukInput({ - 'label': { - 'text': "Postcode", - 'classes': 'govuk-label--s', - }, - 'value': form.postcode.value(), - 'errorMessage': { 'text': form.errors['postcode'][0] }, - 'hint': { - 'text' : "For example, NE31 1SF", - }, - 'attributes': { - 'maxLength': 30, - }, - 'id': 'id_postcode', - 'classes': 'govuk-input--width-10', - 'name': "postcode" - }) }} - {% else %} - {{ govukInput({ - 'label': { - 'text': "Postcode", - 'classes': 'govuk-label--s', - }, - 'value': form.postcode.value(), - 'hint': { - 'text' : "For example, NE31 1SF", - }, - 'attributes': { - 'maxLength': 30, - }, - 'id': 'id_postcode', - 'classes': 'govuk-input--width-10', - 'name': "postcode" - }) }} - {% endif %} +

Next steps

+
    +
  1. We'll show you a list of legal advisers.
  2. +
  3. When you contact the adviser they'll ask about your problem and finances to work out if you can get legal aid.
  4. +
- {{ govukButton({ - 'text': "Search", - 'type': "submit", - 'classes': "govuk-!-margin-bottom-2", - 'id': "searchButton", - 'name': "search" + {% if 'postcode' in form.errors or form.errors['__all__'] %} + {{ govukInput({ + 'label': { + 'text': "What is your postcode?", + 'classes': 'govuk-label--s', + }, + 'value': form.postcode.value(), + 'errorMessage': { 'text': form.errors['postcode'][0] }, + 'hint': { + 'text' : "For example, SW1H 9AJ", + }, + 'attributes': { + 'maxLength': 30, + }, + 'id': 'id_postcode', + 'classes': 'govuk-input--width-10', + 'name': "postcode" + }) }} + {% else %} + {{ govukInput({ + 'label': { + 'text': "What is your postcode?", + 'classes': 'govuk-label--s', + }, + 'value': form.postcode.value(), + 'hint': { + 'text' : "For example, SW1H 9AJ", + }, + 'attributes': { + 'maxLength': 30, + }, + 'id': 'id_postcode', + 'classes': 'govuk-input--width-10', + 'name': "postcode" }) }} -
-
+ {% endif %} + + {{ govukButton({ + 'text': "Search", + 'type': "submit", + 'classes': "govuk-!-margin-bottom-2", + 'id': "searchButton", + 'name': "search" + }) }} +
{% endblock %} -
-

If you are a provider and your details are incorrect, please contact your contract manager.

-
+ {% if results %} +

Results

+
    + {% for item in results %} +
  • +

    {{ item.organisation.name }}

    +

    {{ item.location.address }}, {{ item.location.city }}, {{ item.location.postcode }}

    +

    Phone: {{ item.telephone }}

    + {% if item.distance %} +

    {{ item.distance|round(1) }} miles away

    + {% endif %} +
  • + {% endfor %} +
+{% else %} +

No results found for the given postcode and category.

+{% endif %} + + {% endblock %} \ No newline at end of file diff --git a/fala/urls.py b/fala/urls.py index e07c8dea..31ce610d 100644 --- a/fala/urls.py +++ b/fala/urls.py @@ -1,5 +1,5 @@ -# urls.py - +# coding=utf-8 +from django.conf import settings from django.urls import re_path from adviser.views import ( AccessibilityView, @@ -21,6 +21,10 @@ re_path(r"^search$", SearchView.as_view(), name="search"), re_path(r"^robots\.txt$", RobotsTxtView.as_view(), name="robots_txt"), re_path(r"^security\.txt$", SecurityTxtView.as_view(), name="security_txt"), - re_path(r"^single-category-search/(?P[\w-]+)$", SingleCategorySearchView.as_view(), name="single_category_search"), + re_path( + r"^single-category-search/(?P[\w-]+)$", + SingleCategorySearchView.as_view(), + name="single_category_search", + ), re_path(r"^single-category-search$", SingleCategorySearchView.as_view(), name="single_category_search_query"), -] + [re_path(r"^static/(?P.*)$", serve, {"document_root": settings.STATIC_ROOT})] \ No newline at end of file +] + [re_path(r"^static/(?P.*)$", serve, {"document_root": settings.STATIC_ROOT})] From 9ae00833bf95840c9c9f8a21664cafb6fbcb881a Mon Sep 17 00:00:00 2001 From: Will Clarke Date: Thu, 28 Nov 2024 13:16:12 +0000 Subject: [PATCH 3/7] make regions reuseable extract dictionaries to utils.py --- fala/apps/adviser/forms.py | 59 ++++- fala/apps/adviser/models.py | 146 +++++++++++ fala/apps/adviser/utils.py | 21 ++ fala/apps/adviser/views.py | 232 +++--------------- .../adviser/single_category_search.html | 7 +- fala/urls.py | 1 + 6 files changed, 269 insertions(+), 197 deletions(-) diff --git a/fala/apps/adviser/forms.py b/fala/apps/adviser/forms.py index 3dcf7b12..287cdb68 100644 --- a/fala/apps/adviser/forms.py +++ b/fala/apps/adviser/forms.py @@ -4,7 +4,6 @@ from django.utils.translation import gettext_lazy as _ from django.utils.safestring import mark_safe from django.conf import settings - import laalaa.api as laalaa import requests from requests.adapters import HTTPAdapter @@ -193,3 +192,61 @@ def search(self): return {} else: return {} + + +class SingleCategorySearchForm(forms.Form): + postcode = CapitalisedPostcodeField( + label=_("Postcode"), + max_length=30, + required=True, # Postcode is required in this form + widget=FalaTextInput(attrs={"class": "govuk-input govuk-!-width-two-thirds"}), + ) + + def __init__(self, categories=None, *args, **kwargs): + super().__init__(*args, **kwargs) + # Ensure categories is a list and assign it to self.categories + self.categories = categories if categories is not None else [] + + def clean_postcode(self): + postcode = self.cleaned_data.get("postcode") + if not postcode: + raise forms.ValidationError(_("Enter a valid postcode")) + return postcode + + def clean(self): + cleaned_data = super().clean() + categories = self.data.get("category") + if not categories: + self.add_error("categories", "Category is required.") + else: + self.categories = [categories] + return cleaned_data + + # this is required if i want to rename category to categories in the single_category_search.html file + # however this then breaks the search as it just reloads the page + + def search(self): + if self.is_valid(): + try: + postcode = self.cleaned_data.get("postcode") + if not postcode: + self.add_error("postcode", _("Enter a valid postcode")) + return {} + + # Use `self.categories` for the search (ensure it is passed as a list) + data = laalaa.find( + postcode=postcode, + categories=self.categories, # Pass the list of categories + page=1, # Always default to the first page for simplicity + ) + + if "error" in data: + self.add_error("postcode", data["error"]) + return {} + return data + + except laalaa.LaaLaaError: + self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) + return {} + + return {} diff --git a/fala/apps/adviser/models.py b/fala/apps/adviser/models.py index 7745b70c..2c8a8d5f 100644 --- a/fala/apps/adviser/models.py +++ b/fala/apps/adviser/models.py @@ -1,5 +1,9 @@ from django.db import models from django.utils import timezone +from .regions import Region +from .laa_laa_paginator import LaaLaaPaginator +import urllib +from django.conf import settings class SatisfactionFeedback(models.Model): @@ -10,3 +14,145 @@ class SatisfactionFeedback(models.Model): def __str__(self): return f"Feedback {self.id}" + + +class EnglandOrWalesState(object): + def __init__(self, form): + self._form = form + self._data = form.search() + + @property + def template_name(self): + return "results.html" + + def get_queryset(self): + return self._data.get("results", None) + + def get_context_data(self): + pages = LaaLaaPaginator(self._data["count"], 10, 3, self._form.current_page) + current_page = pages.current_page() + params = { + "postcode": self._form.cleaned_data["postcode"], + "name": self._form.cleaned_data["name"], + } + categories = self._form.cleaned_data["categories"] + + # create list of tuples which can be passed to urlencode for pagination links + category_tuples = [("categories", c) for c in categories] + + def item_for(page_num): + if len(categories) > 0: + page_params = {"page": page_num} + href = ( + "/search?" + + urllib.parse.urlencode({**page_params, **params}) + + "&" + + urllib.parse.urlencode(category_tuples) + ) + else: + page_params = {"page": page_num} + href = "/search?" + urllib.parse.urlencode({**page_params, **params}) + + return {"number": page_num, "current": self._form.current_page == page_num, "href": href} + + pagination = {"items": [item_for(page_num) for page_num in pages.page_range]} + + if current_page.has_previous(): + if len(categories) > 0: + page_params = {"page": current_page.previous_page_number()} + prev_link = ( + "/search?" + + urllib.parse.urlencode({**page_params, **params}) + + "&" + + urllib.parse.urlencode(category_tuples) + ) + else: + page_params = {"page": current_page.previous_page_number()} + prev_link = "/search?" + urllib.parse.urlencode({**page_params, **params}) + pagination["previous"] = {"href": prev_link} + + if current_page.has_next(): + if len(categories) > 0: + page_params = {"page": current_page.next_page_number()} + href = ( + "/search?" + + urllib.parse.urlencode({**page_params, **params}) + + "&" + + urllib.parse.urlencode(category_tuples) + ) + else: + page_params = {"page": current_page.next_page_number()} + href = "/search?" + urllib.parse.urlencode({**page_params, **params}) + pagination["next"] = {"href": href} + + return { + "form": self._form, + "data": self._data, + "params": params, + "FEATURE_FLAG_SURVEY_MONKEY": settings.FEATURE_FLAG_SURVEY_MONKEY, + "pagination": pagination, + } + + +class OtherJurisdictionState(object): + REGION_TO_LINK = { + Region.NI: { + "link": "https://www.nidirect.gov.uk/articles/legal-aid-schemes", + "region": "Northern Ireland", + }, + Region.IOM: { + "link": "https://www.gov.im/categories/benefits-and-financial-support/legal-aid/", + "region": "the Isle of Man", + }, + Region.JERSEY: { + "link": "https://www.legalaid.je/", + "region": "Jersey", + }, + Region.GUERNSEY: { + "link": "https://www.gov.gg/legalaid", + "region": "Guernsey", + }, + } + + def __init__(self, region, postcode): + self._region = region + self._postcode = postcode + + def get_queryset(self): + return [] + + @property + def template_name(self): + return "other_region.html" + + def get_context_data(self): + region_data = self.REGION_TO_LINK[self._region] + return { + "postcode": self._postcode, + "link": region_data["link"], + "region": region_data["region"], + } + + +class ErrorState(object): + def __init__(self, form): + self._form = form + + @property + def template_name(self): + return "search.html" + + def get_queryset(self): + return [] + + def get_context_data(self): + errorList = [] + for field, error in self._form.errors.items(): + # choose the first field is the error in form-wide + if field == "__all__": + item = {"text": error[0], "href": "#id_postcode"} + else: + item = {"text": error[0], "href": f"#id_{field}"} + errorList.append(item) + + return {"form": self._form, "data": {}, "errorList": errorList} diff --git a/fala/apps/adviser/utils.py b/fala/apps/adviser/utils.py index 3a675b9a..3368f382 100644 --- a/fala/apps/adviser/utils.py +++ b/fala/apps/adviser/utils.py @@ -20,6 +20,27 @@ "wb": "welfare-benefits", } +SLUG_TO_CODE = {v: k for k, v in CATEGORY_TRANSLATIONS.items()} + + +def get_category_code_from_slug(slug): + return SLUG_TO_CODE.get(slug) + def get_category_display_name(category_code): return CATEGORY_TRANSLATIONS.get(category_code) + + +CATEGORY_MESSAGES = { + "hlpas": "Tell the adviser your home is at risk and you want advice through the Housing Loss Prevention Advice Service.", + "welfare-benefits": ( + "Legal aid for advice about welfare benefits is only available if you are appealing a decision made by the social security tribunal. " + "This appeal must be in the Upper Tribunal, Court of Appeal or Supreme Court.\n\n" + "For any other benefits issue, ask the legal adviser if you can get free legal advice or if you will have to pay for it." + ), + "clinical-negligence": "Legal aid for advice about clinical negligence is usually only available if you have a child that suffered a brain injury during pregnancy, birth or the first 8 weeks of life.", +} + +CATEGORY_DISPLAY_NAMES = { + "hlpas": "Housing Loss Prevention Advice Service", +} diff --git a/fala/apps/adviser/views.py b/fala/apps/adviser/views.py index b389e352..983ffc85 100644 --- a/fala/apps/adviser/views.py +++ b/fala/apps/adviser/views.py @@ -1,18 +1,16 @@ # coding=utf-8 -import urllib - from django.conf import settings from django.urls import resolve, reverse from django.views.generic import TemplateView, ListView from django.http import HttpResponse import os from django.views import View - from .forms import AdviserSearchForm, AdviserRootForm -from .laa_laa_paginator import LaaLaaPaginator from .regions import Region -from django.shortcuts import redirect -from .utils import get_category_display_name +from django.shortcuts import redirect, render +from .models import EnglandOrWalesState, ErrorState, OtherJurisdictionState +from .forms import SingleCategorySearchForm +from .utils import CATEGORY_MESSAGES, CATEGORY_DISPLAY_NAMES, get_category_display_name, get_category_code_from_slug class RobotsTxtView(View): @@ -54,70 +52,53 @@ def get_context_data(self, **kwargs): return context -class SingleCategorySearchView(CommonContextMixin, TemplateView): +class SingleCategorySearchView(TemplateView): template_name = "adviser/single_category_search.html" - CATEGORY_MESSAGES = { - "hlpas": "Tell the adviser your home is at risk and you want advice through the Housing Loss Prevention Advice Service.", - "welfare-benefits": """Legal aid for advice about welfare benefits is only available if you are appealing a decision made by the social security tribunal. This appeal must be in the Upper Tribunal, Court of Appeal or Supreme Court. - - For any other benefits issue, ask the legal adviser if you can get free legal advice or if you will have to pay for it.""", - "clinical-negligence": "Legal aid for advice about clinical negligence is usually only available if you have a child that suffered a brain injury during pregnancy, birth or the first 8 weeks of life.", - } - - CATEGORY_DISPLAY_NAMES = { - "hlpas": "Housing Loss Prevention Advice Service", - } - def get(self, request, *args, **kwargs): + category_code = request.GET.get("categories") - category_code = request.GET.get("categories") # Extract `categories` from query parameters - if category_code: # Redirect to the correct category-based URL + if category_code: category_slug = get_category_display_name(category_code) if category_slug: return redirect("single_category_search", category=category_slug) else: return redirect("search") - + category_slug = kwargs.get("category") if not category_slug: return redirect("search") - context = self.get_context_data(**kwargs) - form = AdviserRootForm(data=request.GET or None) - category_message = self.CATEGORY_MESSAGES.get(category_slug, "") - category_display_name = self.CATEGORY_DISPLAY_NAMES.get(category_slug, category_slug.replace("-", " ").title()) + if not category_code or category_code == "None": + category_code = get_category_code_from_slug(category_slug) - context.update( - { - "form": form, - "category_slug": category_slug, - "category_display_name": category_display_name, - "category_message": category_message, - } - ) + category_message = CATEGORY_MESSAGES.get(category_slug, "") + category_display_name = CATEGORY_DISPLAY_NAMES.get(category_slug, category_slug.replace("-", " ").title()) + form = SingleCategorySearchForm(categories=category_slug, data=request.GET or None) if form.is_valid(): - postcode = form.cleaned_data.get("postcode") - if postcode: - # Perform the search using the postcode and category_slug - results = self.perform_search(postcode, category_slug) - context.update({"results": results}) - - return self.render_to_response(context) - - def perform_search(self, postcode, category): - try: - data = laalaa.find( - postcode=postcode, - categories=[category], - page=1, # Assuming you want the first page of results - ) - return data.get("results", []) - except laalaa.LaaLaaError: - return [] + results = form.search() + else: + results = None + + search_url = reverse("single_category_search", kwargs={"category": category_slug}) + + context = { + "form": form, + "category_slug": category_slug, + "category_code": category_code, + "category_display_name": category_display_name, + "category_message": category_message, + "results": results, + "search_url": search_url, + } + return render(request, self.template_name, context) + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context["search_url"] = reverse("single_category_search", kwargs={"category": kwargs.get("category_slug")}) + return context class AdviserView(CommonContextMixin, TemplateView): @@ -154,157 +135,18 @@ class CookiesView(CommonContextMixin, TemplateView): template_name = "adviser/cookies.html" -class SearchView(CommonContextMixin, ListView): - class ErrorState(object): - def __init__(self, form): - self._form = form - - @property - def template_name(self): - return "search.html" - - def get_queryset(self): - return [] - - def get_context_data(self): - errorList = [] - for field, error in self._form.errors.items(): - # choose the first field is the error in form-wide - if field == "__all__": - item = {"text": error[0], "href": "#id_postcode"} - else: - item = {"text": error[0], "href": f"#id_{field}"} - errorList.append(item) - - return {"form": self._form, "data": {}, "errorList": errorList} - - class EnglandOrWalesState(object): - def __init__(self, form): - self._form = form - self._data = form.search() - - @property - def template_name(self): - return "results.html" - - def get_queryset(self): - return self._data.get("results", None) - - def get_context_data(self): - pages = LaaLaaPaginator(self._data["count"], 10, 3, self._form.current_page) - current_page = pages.current_page() - params = { - "postcode": self._form.cleaned_data["postcode"], - "name": self._form.cleaned_data["name"], - } - categories = self._form.cleaned_data["categories"] - - # create list of tuples which can be passed to urlencode for pagination links - category_tuples = [("categories", c) for c in categories] - - def item_for(page_num): - if len(categories) > 0: - page_params = {"page": page_num} - href = ( - "/search?" - + urllib.parse.urlencode({**page_params, **params}) - + "&" - + urllib.parse.urlencode(category_tuples) - ) - else: - page_params = {"page": page_num} - href = "/search?" + urllib.parse.urlencode({**page_params, **params}) - - return {"number": page_num, "current": self._form.current_page == page_num, "href": href} - - pagination = {"items": [item_for(page_num) for page_num in pages.page_range]} - - if current_page.has_previous(): - if len(categories) > 0: - page_params = {"page": current_page.previous_page_number()} - prev_link = ( - "/search?" - + urllib.parse.urlencode({**page_params, **params}) - + "&" - + urllib.parse.urlencode(category_tuples) - ) - else: - page_params = {"page": current_page.previous_page_number()} - prev_link = "/search?" + urllib.parse.urlencode({**page_params, **params}) - pagination["previous"] = {"href": prev_link} - - if current_page.has_next(): - if len(categories) > 0: - page_params = {"page": current_page.next_page_number()} - href = ( - "/search?" - + urllib.parse.urlencode({**page_params, **params}) - + "&" - + urllib.parse.urlencode(category_tuples) - ) - else: - page_params = {"page": current_page.next_page_number()} - href = "/search?" + urllib.parse.urlencode({**page_params, **params}) - pagination["next"] = {"href": href} - - return { - "form": self._form, - "data": self._data, - "params": params, - "FEATURE_FLAG_SURVEY_MONKEY": settings.FEATURE_FLAG_SURVEY_MONKEY, - "pagination": pagination, - } - - class OtherJurisdictionState(object): - REGION_TO_LINK = { - Region.NI: { - "link": "https://www.nidirect.gov.uk/articles/legal-aid-schemes", - "region": "Northern Ireland", - }, - Region.IOM: { - "link": "https://www.gov.im/categories/benefits-and-financial-support/legal-aid/", - "region": "the Isle of Man", - }, - Region.JERSEY: { - "link": "https://www.legalaid.je/", - "region": "Jersey", - }, - Region.GUERNSEY: { - "link": "https://www.gov.gg/legalaid", - "region": "Guernsey", - }, - } - - def __init__(self, region, postcode): - self._region = region - self._postcode = postcode - - def get_queryset(self): - return [] - - @property - def template_name(self): - return "other_region.html" - - def get_context_data(self): - region_data = self.REGION_TO_LINK[self._region] - return { - "postcode": self._postcode, - "link": region_data["link"], - "region": region_data["region"], - } - +class SearchView(CommonContextMixin, ListView, EnglandOrWalesState, OtherJurisdictionState): def get(self, request, *args, **kwargs): form = AdviserSearchForm(data=request.GET or None) if form.is_valid(): region = form.region if region == Region.ENGLAND_OR_WALES or region == Region.SCOTLAND: - self.state = self.EnglandOrWalesState(form) + self.state = EnglandOrWalesState(form) else: - self.state = self.OtherJurisdictionState(region, form.cleaned_data["postcode"]) + self.state = OtherJurisdictionState(region, form.cleaned_data["postcode"]) else: - self.state = self.ErrorState(form) + self.state = ErrorState(form) return super().get(self, request, *args, **kwargs) diff --git a/fala/templates/adviser/single_category_search.html b/fala/templates/adviser/single_category_search.html index e500fc81..21007589 100644 --- a/fala/templates/adviser/single_category_search.html +++ b/fala/templates/adviser/single_category_search.html @@ -34,7 +34,12 @@

Find a legal aid adviser for {% block search_form %}
-
+ + + +

DEBUG: Category slug: {{ category_slug }}

+

DEBUG: Category code: {{ category_code }}

+ {% set errorMessage = {'err': ""} %} {% if form.errors %} diff --git a/fala/urls.py b/fala/urls.py index 31ce610d..112229a3 100644 --- a/fala/urls.py +++ b/fala/urls.py @@ -1,6 +1,7 @@ # coding=utf-8 from django.conf import settings from django.urls import re_path + from adviser.views import ( AccessibilityView, AdviserView, From 6e0fee0b15a0c581a9e1397e0ab53407ceaf177c Mon Sep 17 00:00:00 2001 From: Will Clarke Date: Fri, 29 Nov 2024 16:18:53 +0000 Subject: [PATCH 4/7] display results but its ugly --- fala/apps/adviser/forms.py | 170 +++++++++++++++++++++++++++++++++---- fala/apps/adviser/views.py | 16 +++- fala/apps/laalaa/api.py | 4 +- 3 files changed, 168 insertions(+), 22 deletions(-) diff --git a/fala/apps/adviser/forms.py b/fala/apps/adviser/forms.py index 287cdb68..b0a85e5d 100644 --- a/fala/apps/adviser/forms.py +++ b/fala/apps/adviser/forms.py @@ -8,6 +8,7 @@ import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry +import logging from .regions import Region @@ -36,7 +37,7 @@ def to_python(self, value): # Capitalise the input value capitalised_value = value.upper() if value else value return super().to_python(capitalised_value) - +logger = logging.getLogger(__name__) # This is so that we can hit the front page with query parameters in url and not see form validation errors # In django, form validation happens when the data is cleaned, i.e. form validation, form errors, form cleaned @@ -206,6 +207,8 @@ def __init__(self, categories=None, *args, **kwargs): super().__init__(*args, **kwargs) # Ensure categories is a list and assign it to self.categories self.categories = categories if categories is not None else [] + self._region = None + self._country_from_valid_postcode = None def clean_postcode(self): postcode = self.cleaned_data.get("postcode") @@ -215,38 +218,171 @@ def clean_postcode(self): def clean(self): cleaned_data = super().clean() + postcode = cleaned_data.get("postcode") categories = self.data.get("category") + + logger.debug("343434Validating postcode and categories: %s, %s", postcode, categories) + + # Validate postcode and set `_country_from_valid_postcode` + if postcode: + valid_postcode = self.validate_postcode_and_return_country(postcode) + if not valid_postcode: + self.add_error("postcode", _("Enter a valid postcode")) + else: + self._country_from_valid_postcode = valid_postcode # This is used by the `region` property + logger.debug("67676767Valid postcode: %s", valid_postcode) + + # Check if categories are provided if not categories: - self.add_error("categories", "Category is required.") + self.add_error("categories", _("Category is required.")) else: self.categories = [categories] + return cleaned_data + # this is required if i want to rename category to categories in the single_category_search.html file # however this then breaks the search as it just reloads the page + # def search(self): + # if self.is_valid(): + # try: + # postcode = self.cleaned_data.get("postcode") + # if not postcode: + # self.add_error("postcode", _("Enter a valid postcode")) + # return {} + + # # Use `self.categories` for the search (ensure it is passed as a list) + # data = laalaa.find( + # postcode=postcode, + # categories=self.categories, # Pass the list of categories + # page=1, # Always default to the first page for simplicity + # ) + + # if "error" in data: + # self.add_error("postcode", data["error"]) + # return {} + # return data + + # except laalaa.LaaLaaError: + # self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) + # return {} + + # return {} + + @property + def region(self): + # Log the start of the method + logger.debug("Entering `region` property.") + # retrieve the api call variables + country_from_valid_postcode = getattr(self, "_country_from_valid_postcode", None) + logger.debug("Country from valid postcode: %s", country_from_valid_postcode) + + # Return `Region.ENGLAND_OR_WALES` from `clean` if set + if not country_from_valid_postcode: + region = getattr(self, "_region", None) + logger.debug("111111NOT Country from valid postcode: %s", country_from_valid_postcode) + logger.debug("Region from `_region` attribute: %s", region) + return region + + # for Guernsey & Jersey the country comes back as 'Channel Islands', we are using `nhs_ha` key to distinguish between them + country, nhs_ha = country_from_valid_postcode + logger.debug("Country: %s, NHS HA: %s", country, nhs_ha) + + if country == "Northern Ireland": + return Region.NI + elif country == "Isle of Man": + return Region.IOM + elif country == "Channel Islands" and nhs_ha == "Jersey Health Authority": + return Region.JERSEY + elif country == "Channel Islands" and nhs_ha == "Guernsey Health Authority": + return Region.GUERNSEY + elif country == "Scotland": + return Region.SCOTLAND + elif country in ["England", "Wales"]: + return Region.ENGLAND_OR_WALES + else: + logger.error("Invalid region: country=%s, nhs_ha=%s", country, nhs_ha) + self.add_error("postcode", _("This service is only available for England and Wales")) + return None + + @property + def current_page(self): + page = self.cleaned_data.get("page", 1) + logger.debug("Current page: %s", page) + return page + + def validate_postcode_and_return_country(self, postcode): + logger.debug("Validating postcode: %s", postcode) + try: + if not isinstance(postcode, str) or not postcode.strip(): + logger.warning("Invalid postcode input: %s", postcode) + return False + + session = requests.Session() + retry_strategy = Retry(total=5, backoff_factor=0.1) + adapter = HTTPAdapter(max_retries=retry_strategy) + session.mount("https://", adapter) + + url = settings.POSTCODE_IO_URL + f"{postcode}" + logger.debug("Requesting postcode data from URL: %s", url) + response = session.get(url, timeout=5) + + if response.status_code != 200: + logger.error("Failed to retrieve postcode data. Status code: %s", response.status_code) + return False + + data = response.json() + logger.debug("Postcode API response: %s", data) + + if not data.get("result"): + logger.warning("No results found for postcode: %s", postcode) + return False + + first_result_in_list = data["result"][0] + country = first_result_in_list.get("country") + nhs_ha = first_result_in_list.get("nhs_ha") + + if country and nhs_ha: + logger.info("Postcode validated. Country: %s, NHS HA: %s", country, nhs_ha) + return country, nhs_ha + else: + logger.warning("Country or NHS HA missing in response.") + return False + + except requests.RequestException as e: + logger.error("RequestException during postcode validation: %s", e) + self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) + return False + def search(self): + logger.debug("Initiating search.") if self.is_valid(): try: postcode = self.cleaned_data.get("postcode") - if not postcode: - self.add_error("postcode", _("Enter a valid postcode")) - return {} + categories = self.categories + logger.debug("Starting laalaa search with postcode: %s and categories: %s", postcode, categories) - # Use `self.categories` for the search (ensure it is passed as a list) - data = laalaa.find( - postcode=postcode, - categories=self.categories, # Pass the list of categories - page=1, # Always default to the first page for simplicity - ) + # Call the API + data = laalaa.find(postcode=postcode, categories=categories, page=1) + # Check for errors in the response if "error" in data: + logger.error("Error from laalaa search: %s", data["error"]) self.add_error("postcode", data["error"]) - return {} - return data - - except laalaa.LaaLaaError: + return [] + + # Extract only the 'results' key + results = data.get("results", []) + logger.info("Search completed successfully. Extracted results: %s", results) + return results + except laalaa.LaaLaaError as e: + logger.error("LaaLaaError during search: %s", e) self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) - return {} + return [] + + logger.warning("Search form is invalid.") + return [] + + - return {} diff --git a/fala/apps/adviser/views.py b/fala/apps/adviser/views.py index 983ffc85..2d353fb2 100644 --- a/fala/apps/adviser/views.py +++ b/fala/apps/adviser/views.py @@ -11,7 +11,7 @@ from .models import EnglandOrWalesState, ErrorState, OtherJurisdictionState from .forms import SingleCategorySearchForm from .utils import CATEGORY_MESSAGES, CATEGORY_DISPLAY_NAMES, get_category_display_name, get_category_code_from_slug - +import logging class RobotsTxtView(View): def get(self, request): @@ -51,7 +51,7 @@ def get_context_data(self, **kwargs): ) return context - +logger = logging.getLogger(__name__) class SingleCategorySearchView(TemplateView): template_name = "adviser/single_category_search.html" @@ -77,9 +77,17 @@ def get(self, request, *args, **kwargs): form = SingleCategorySearchForm(categories=category_slug, data=request.GET or None) if form.is_valid(): - results = form.search() + logger.debug("Form is valid. Determining region.") + region = form.region # Now `region` will be correctly determined + if region == Region.ENGLAND_OR_WALES: + logger.debug("Region is England or Wales.") + results = form.search() + else: + logger.warning("Region is outside of England or Wales. Results will be empty.") + results = [] else: - results = None + logger.error("Form is invalid: %s", form.errors) + results = [] search_url = reverse("single_category_search", kwargs={"category": category_slug}) diff --git a/fala/apps/laalaa/api.py b/fala/apps/laalaa/api.py index 2d3b3209..f4228c11 100644 --- a/fala/apps/laalaa/api.py +++ b/fala/apps/laalaa/api.py @@ -2,6 +2,7 @@ from urllib.parse import urlencode from collections import OrderedDict import requests +import logging from django.conf import settings from django.utils.translation import gettext_lazy as _ @@ -13,7 +14,7 @@ except NameError: basestring = str - +logger = logging.getLogger(__name__) def get_categories(): if settings.LAALAA_API_HOST: categories = LaalaaProviderCategoriesApiClient.singleton(settings.LAALAA_API_HOST, _).get_categories() @@ -66,5 +67,6 @@ def find(postcode=None, categories=None, page=1, organisation_types=None, organi ) data["results"] = list(map(decode_categories, data.get("results", []))) + logger.debug(f"find: processed results type={type(data['results'])}, processed results={data['results'][:3]}") # Log first 3 processed results return data From dae8ecfabf26d386b4ff9cbbe67b9724df8e881d Mon Sep 17 00:00:00 2001 From: Will Clarke Date: Fri, 29 Nov 2024 18:01:39 +0000 Subject: [PATCH 5/7] the correct template is now being called but the data does not match what the template is expecting --- fala/apps/adviser/forms.py | 2 +- fala/apps/adviser/models.py | 14 ++++++++++---- fala/apps/adviser/views.py | 22 +++++++++++++++------- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/fala/apps/adviser/forms.py b/fala/apps/adviser/forms.py index b0a85e5d..8b4d4451 100644 --- a/fala/apps/adviser/forms.py +++ b/fala/apps/adviser/forms.py @@ -287,7 +287,7 @@ def region(self): # for Guernsey & Jersey the country comes back as 'Channel Islands', we are using `nhs_ha` key to distinguish between them country, nhs_ha = country_from_valid_postcode - logger.debug("Country: %s, NHS HA: %s", country, nhs_ha) + logger.debug("fefvasefvbsefCountry: %s, NHS HA: %s", country, nhs_ha) if country == "Northern Ireland": return Region.NI diff --git a/fala/apps/adviser/models.py b/fala/apps/adviser/models.py index 2c8a8d5f..778636d7 100644 --- a/fala/apps/adviser/models.py +++ b/fala/apps/adviser/models.py @@ -4,6 +4,7 @@ from .laa_laa_paginator import LaaLaaPaginator import urllib from django.conf import settings +import logging class SatisfactionFeedback(models.Model): @@ -15,7 +16,7 @@ class SatisfactionFeedback(models.Model): def __str__(self): return f"Feedback {self.id}" - +logger = logging.getLogger(__name__) class EnglandOrWalesState(object): def __init__(self, form): self._form = form @@ -23,13 +24,18 @@ def __init__(self, form): @property def template_name(self): - return "results.html" + return "adviser/results.html" def get_queryset(self): - return self._data.get("results", None) + if isinstance(self._data, list): # Ensure it is a list before returning + return self._data + else: + logger.error("Unexpected data format: %s", self._data) + return [] # Return an empty list if data is not valid def get_context_data(self): pages = LaaLaaPaginator(self._data["count"], 10, 3, self._form.current_page) + logger.debug("343434Validating pages: %s", pages) current_page = pages.current_page() params = { "postcode": self._form.cleaned_data["postcode"], @@ -123,7 +129,7 @@ def get_queryset(self): @property def template_name(self): - return "other_region.html" + return "adviser/other_region.html" def get_context_data(self): region_data = self.REGION_TO_LINK[self._region] diff --git a/fala/apps/adviser/views.py b/fala/apps/adviser/views.py index 2d353fb2..0275fd75 100644 --- a/fala/apps/adviser/views.py +++ b/fala/apps/adviser/views.py @@ -76,18 +76,24 @@ def get(self, request, *args, **kwargs): category_display_name = CATEGORY_DISPLAY_NAMES.get(category_slug, category_slug.replace("-", " ").title()) form = SingleCategorySearchForm(categories=category_slug, data=request.GET or None) + + # Determine the state and results if form.is_valid(): logger.debug("Form is valid. Determining region.") region = form.region # Now `region` will be correctly determined - if region == Region.ENGLAND_OR_WALES: - logger.debug("Region is England or Wales.") - results = form.search() + if region in [Region.ENGLAND_OR_WALES, Region.SCOTLAND]: + logger.debug("Region is England or Wales or Scotland.") + state = EnglandOrWalesState(form) else: - logger.warning("Region is outside of England or Wales. Results will be empty.") - results = [] + logger.warning("Region is outside of England or Wales. Using OtherJurisdictionState.") + state = OtherJurisdictionState(region, form.cleaned_data["postcode"]) else: logger.error("Form is invalid: %s", form.errors) - results = [] + state = ErrorState(form) + + # Let the state handle the logic for results + results = state.get_queryset() + template_name = state.template_name search_url = reverse("single_category_search", kwargs={"category": category_slug}) @@ -98,10 +104,12 @@ def get(self, request, *args, **kwargs): "category_display_name": category_display_name, "category_message": category_message, "results": results, + "data": results, "search_url": search_url, } - return render(request, self.template_name, context) + return render(request, template_name, context) + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) From 777da7eaffe8e245c5438a925c62f622ac3c4995 Mon Sep 17 00:00:00 2001 From: Will Clarke Date: Fri, 29 Nov 2024 18:11:00 +0000 Subject: [PATCH 6/7] add comment on current issue --- fala/apps/adviser/forms.py | 66 +++---------------------------------- fala/apps/adviser/models.py | 3 ++ fala/apps/adviser/views.py | 10 ++++-- fala/apps/laalaa/api.py | 6 +++- 4 files changed, 20 insertions(+), 65 deletions(-) diff --git a/fala/apps/adviser/forms.py b/fala/apps/adviser/forms.py index 8b4d4451..f2ee9f3a 100644 --- a/fala/apps/adviser/forms.py +++ b/fala/apps/adviser/forms.py @@ -8,7 +8,6 @@ import requests from requests.adapters import HTTPAdapter from urllib3.util.retry import Retry -import logging from .regions import Region @@ -37,7 +36,7 @@ def to_python(self, value): # Capitalise the input value capitalised_value = value.upper() if value else value return super().to_python(capitalised_value) -logger = logging.getLogger(__name__) + # This is so that we can hit the front page with query parameters in url and not see form validation errors # In django, form validation happens when the data is cleaned, i.e. form validation, form errors, form cleaned @@ -221,8 +220,6 @@ def clean(self): postcode = cleaned_data.get("postcode") categories = self.data.get("category") - logger.debug("343434Validating postcode and categories: %s, %s", postcode, categories) - # Validate postcode and set `_country_from_valid_postcode` if postcode: valid_postcode = self.validate_postcode_and_return_country(postcode) @@ -230,7 +227,6 @@ def clean(self): self.add_error("postcode", _("Enter a valid postcode")) else: self._country_from_valid_postcode = valid_postcode # This is used by the `region` property - logger.debug("67676767Valid postcode: %s", valid_postcode) # Check if categories are provided if not categories: @@ -240,54 +236,18 @@ def clean(self): return cleaned_data - - # this is required if i want to rename category to categories in the single_category_search.html file - # however this then breaks the search as it just reloads the page - - # def search(self): - # if self.is_valid(): - # try: - # postcode = self.cleaned_data.get("postcode") - # if not postcode: - # self.add_error("postcode", _("Enter a valid postcode")) - # return {} - - # # Use `self.categories` for the search (ensure it is passed as a list) - # data = laalaa.find( - # postcode=postcode, - # categories=self.categories, # Pass the list of categories - # page=1, # Always default to the first page for simplicity - # ) - - # if "error" in data: - # self.add_error("postcode", data["error"]) - # return {} - # return data - - # except laalaa.LaaLaaError: - # self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) - # return {} - - # return {} - @property def region(self): - # Log the start of the method - logger.debug("Entering `region` property.") # retrieve the api call variables country_from_valid_postcode = getattr(self, "_country_from_valid_postcode", None) - logger.debug("Country from valid postcode: %s", country_from_valid_postcode) # Return `Region.ENGLAND_OR_WALES` from `clean` if set if not country_from_valid_postcode: region = getattr(self, "_region", None) - logger.debug("111111NOT Country from valid postcode: %s", country_from_valid_postcode) - logger.debug("Region from `_region` attribute: %s", region) return region # for Guernsey & Jersey the country comes back as 'Channel Islands', we are using `nhs_ha` key to distinguish between them country, nhs_ha = country_from_valid_postcode - logger.debug("fefvasefvbsefCountry: %s, NHS HA: %s", country, nhs_ha) if country == "Northern Ireland": return Region.NI @@ -302,21 +262,17 @@ def region(self): elif country in ["England", "Wales"]: return Region.ENGLAND_OR_WALES else: - logger.error("Invalid region: country=%s, nhs_ha=%s", country, nhs_ha) self.add_error("postcode", _("This service is only available for England and Wales")) return None @property def current_page(self): page = self.cleaned_data.get("page", 1) - logger.debug("Current page: %s", page) return page def validate_postcode_and_return_country(self, postcode): - logger.debug("Validating postcode: %s", postcode) try: if not isinstance(postcode, str) or not postcode.strip(): - logger.warning("Invalid postcode input: %s", postcode) return False session = requests.Session() @@ -325,18 +281,14 @@ def validate_postcode_and_return_country(self, postcode): session.mount("https://", adapter) url = settings.POSTCODE_IO_URL + f"{postcode}" - logger.debug("Requesting postcode data from URL: %s", url) response = session.get(url, timeout=5) if response.status_code != 200: - logger.error("Failed to retrieve postcode data. Status code: %s", response.status_code) return False data = response.json() - logger.debug("Postcode API response: %s", data) if not data.get("result"): - logger.warning("No results found for postcode: %s", postcode) return False first_result_in_list = data["result"][0] @@ -344,45 +296,35 @@ def validate_postcode_and_return_country(self, postcode): nhs_ha = first_result_in_list.get("nhs_ha") if country and nhs_ha: - logger.info("Postcode validated. Country: %s, NHS HA: %s", country, nhs_ha) return country, nhs_ha else: - logger.warning("Country or NHS HA missing in response.") return False except requests.RequestException as e: - logger.error("RequestException during postcode validation: %s", e) self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) return False def search(self): - logger.debug("Initiating search.") if self.is_valid(): try: postcode = self.cleaned_data.get("postcode") categories = self.categories - logger.debug("Starting laalaa search with postcode: %s and categories: %s", postcode, categories) # Call the API data = laalaa.find(postcode=postcode, categories=categories, page=1) # Check for errors in the response if "error" in data: - logger.error("Error from laalaa search: %s", data["error"]) self.add_error("postcode", data["error"]) return [] # Extract only the 'results' key + # this may be where the problem is with the display of the results + # i remove everythng but the results but I think the template wants a + # block called 'data' within which exists `results`` so data.results cntains the search results results = data.get("results", []) - logger.info("Search completed successfully. Extracted results: %s", results) return results except laalaa.LaaLaaError as e: - logger.error("LaaLaaError during search: %s", e) self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) return [] - - logger.warning("Search form is invalid.") return [] - - - diff --git a/fala/apps/adviser/models.py b/fala/apps/adviser/models.py index 778636d7..dfabf93c 100644 --- a/fala/apps/adviser/models.py +++ b/fala/apps/adviser/models.py @@ -16,7 +16,10 @@ class SatisfactionFeedback(models.Model): def __str__(self): return f"Feedback {self.id}" + logger = logging.getLogger(__name__) + + class EnglandOrWalesState(object): def __init__(self, form): self._form = form diff --git a/fala/apps/adviser/views.py b/fala/apps/adviser/views.py index 0275fd75..845172ed 100644 --- a/fala/apps/adviser/views.py +++ b/fala/apps/adviser/views.py @@ -13,6 +13,7 @@ from .utils import CATEGORY_MESSAGES, CATEGORY_DISPLAY_NAMES, get_category_display_name, get_category_code_from_slug import logging + class RobotsTxtView(View): def get(self, request): environment = os.getenv("ENVIRONMENT", "development").lower() @@ -51,7 +52,10 @@ def get_context_data(self, **kwargs): ) return context + logger = logging.getLogger(__name__) + + class SingleCategorySearchView(TemplateView): template_name = "adviser/single_category_search.html" @@ -108,8 +112,10 @@ def get(self, request, *args, **kwargs): "search_url": search_url, } - return render(request, template_name, context) - + return render(request, self.template_name, context) + # so to show the search page this must be self.template_name + # but when i want to show results it needs to be template_name + # so that it can take it from EnglandOrWalesState which uses results.html def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) diff --git a/fala/apps/laalaa/api.py b/fala/apps/laalaa/api.py index f4228c11..9cee919d 100644 --- a/fala/apps/laalaa/api.py +++ b/fala/apps/laalaa/api.py @@ -15,6 +15,8 @@ basestring = str logger = logging.getLogger(__name__) + + def get_categories(): if settings.LAALAA_API_HOST: categories = LaalaaProviderCategoriesApiClient.singleton(settings.LAALAA_API_HOST, _).get_categories() @@ -67,6 +69,8 @@ def find(postcode=None, categories=None, page=1, organisation_types=None, organi ) data["results"] = list(map(decode_categories, data.get("results", []))) - logger.debug(f"find: processed results type={type(data['results'])}, processed results={data['results'][:3]}") # Log first 3 processed results + logger.debug( + f"find: processed results type={type(data['results'])}, processed results={data['results'][:3]}" + ) # Log first 3 processed results return data From b0d34b96064093b7b52550aecfbe8d12c84002ba Mon Sep 17 00:00:00 2001 From: Will Clarke Date: Fri, 29 Nov 2024 18:24:28 +0000 Subject: [PATCH 7/7] linting --- fala/apps/adviser/forms.py | 4 ++-- fala/apps/adviser/views.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fala/apps/adviser/forms.py b/fala/apps/adviser/forms.py index f2ee9f3a..22f10a0f 100644 --- a/fala/apps/adviser/forms.py +++ b/fala/apps/adviser/forms.py @@ -300,7 +300,7 @@ def validate_postcode_and_return_country(self, postcode): else: return False - except requests.RequestException as e: + except requests.RequestException: self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) return False @@ -324,7 +324,7 @@ def search(self): # block called 'data' within which exists `results`` so data.results cntains the search results results = data.get("results", []) return results - except laalaa.LaaLaaError as e: + except laalaa.LaaLaaError: self.add_error("postcode", _("Error looking up legal advisers. Please try again later.")) return [] return [] diff --git a/fala/apps/adviser/views.py b/fala/apps/adviser/views.py index 845172ed..fb627a13 100644 --- a/fala/apps/adviser/views.py +++ b/fala/apps/adviser/views.py @@ -97,7 +97,7 @@ def get(self, request, *args, **kwargs): # Let the state handle the logic for results results = state.get_queryset() - template_name = state.template_name + # template_name = state.template_name search_url = reverse("single_category_search", kwargs={"category": category_slug})