From aa4b0ee56b76db61788619647ac2900dd8697012 Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 12:47:07 +0100 Subject: [PATCH 01/10] fix none in snomed drugs --- .../templatetags/epilepsy12_template_tags.py | 139 ++++++++++-------- .../antiepilepsy_medicine_list.html | 4 +- .../partials/page_elements/select_model.html | 2 +- 3 files changed, 82 insertions(+), 63 deletions(-) diff --git a/epilepsy12/templatetags/epilepsy12_template_tags.py b/epilepsy12/templatetags/epilepsy12_template_tags.py index 57776f75..6ee7404c 100644 --- a/epilepsy12/templatetags/epilepsy12_template_tags.py +++ b/epilepsy12/templatetags/epilepsy12_template_tags.py @@ -34,10 +34,10 @@ def date_string(date): @register.simple_tag def characters_left(description): - length = 2000-len(description) - colour = 'black' - if (length < 100): - colour = 'red' + length = 2000 - len(description) + colour = "black" + if length < 100: + colour = "red" safe_text = f'{length}' return mark_safe(safe_text) @@ -45,70 +45,73 @@ def characters_left(description): @register.simple_tag def percentage_of_total(numerator, denominator): if numerator and denominator: - if (int(denominator) > 0): - return round(int(numerator)/int(denominator)*100) + if int(denominator) > 0: + return round(int(numerator) / int(denominator) * 100) @register.simple_tag def kpi_for_kpi_name(aggregated_kpi, kpi_name, color=False): - # guard clause check if color should be returned if color: - return aggregated_kpi['color'] - if aggregated_kpi['aggregated_kpis'][kpi_name] is None: + return aggregated_kpi["color"] + if aggregated_kpi["aggregated_kpis"][kpi_name] is None: return -1 else: - pct = 100*aggregated_kpi['aggregated_kpis'][kpi_name] / aggregated_kpi['aggregated_kpis']['total_number_of_cases'] + pct = ( + 100 + * aggregated_kpi["aggregated_kpis"][kpi_name] + / aggregated_kpi["aggregated_kpis"]["total_number_of_cases"] + ) return pct @register.simple_tag def kpi_average_for_kpi_name(aggregated_kpi, kpi_name): - if aggregated_kpi['aggregated_kpis'][kpi_name] is None: + if aggregated_kpi["aggregated_kpis"][kpi_name] is None: return 0 else: - return aggregated_kpi['aggregated_kpis'][f'{kpi_name}_average'] + return aggregated_kpi["aggregated_kpis"][f"{kpi_name}_average"] @register.simple_tag def formatlabel(label): if label is None: - return 'Unclassified' + return "Unclassified" else: - nhs_icb_string = re.search( - r'(NHS\s)(.+)(\sINTEGRATED CARE BOARD)', label) + nhs_icb_string = re.search(r"(NHS\s)(.+)(\sINTEGRATED CARE BOARD)", label) if nhs_icb_string: # \u002D fixes hyphen render for 'Stoke-on-trent' - return nhs_icb_string.group(2).replace(r'\u002D','-').title() + return nhs_icb_string.group(2).replace(r"\u002D", "-").title() return label @register.filter def custom_filter(text, color): safe_text = '{text}'.format( - color=color, text=text) + color=color, text=text + ) return mark_safe(safe_text) @register.simple_tag def permission_text(add_permission, change_permission, delete_permission, model_name): - return_string = 'You do not have permission to' + return_string = "You do not have permission to" if add_permission: if change_permission and not delete_permission: - return_string += f' delete {model_name}.' + return_string += f" delete {model_name}." elif not change_permission and delete_permission: - return_string += f' edit {model_name}.' + return_string += f" edit {model_name}." elif not change_permission and not delete_permission: - return_string += f' edit or delete {model_name}.' + return_string += f" edit or delete {model_name}." else: return_string = "" else: if change_permission and not delete_permission: - return_string += f' add or delete {model_name}.' + return_string += f" add or delete {model_name}." elif not change_permission and not delete_permission: - return_string += f' add, edit or delete {model_name}.' + return_string += f" add, edit or delete {model_name}." elif change_permission and delete_permission: - return_string += f' add {model_name}.' + return_string += f" add {model_name}." else: return_string = "" @@ -130,7 +133,7 @@ def snomed_concept(concept_id): if concept_id is None: return concept = fetch_concept(concept_id) - return concept['preferredDescription']['term'] + return concept["preferredDescription"]["term"] @register.filter @@ -142,7 +145,7 @@ def is_in(url_name, args): """ if args is None: return None - arg_list = [arg.strip() for arg in args.split(',')] + arg_list = [arg.strip() for arg in args.split(",")] if url_name in arg_list: return True else: @@ -158,11 +161,20 @@ def match_two_values(val1, val2): @register.simple_tag -def value_for_field_name(model, field_name): +def value_for_field_name(model, field_name, in_parentheses): """ Returns the field value for a given field name in a model + If in_parentheses is true, return the value in parentheses. """ - return getattr(model, field_name, None) + return_val = getattr(model, field_name, None) + if in_parentheses: + return_string = f"({return_val})" + else: + return_string = f"{return_val}" + + if return_val is not None: + return return_string + return "" @register.filter @@ -170,18 +182,22 @@ def record_complete(model): # helper largely for medicines table to report if complete or not minimum_requirement_met = False - if hasattr(model, 'medicine_entity'): + if hasattr(model, "medicine_entity"): if model.medicine_entity is not None: minimum_requirement_met = ( - model.antiepilepsy_medicine_start_date is not None and - model.antiepilepsy_medicine_risk_discussed is not None and - model.medicine_entity.medicine_name is not None + model.antiepilepsy_medicine_start_date is not None + and model.antiepilepsy_medicine_risk_discussed is not None + and model.medicine_entity.medicine_name is not None ) - if model.management.registration.case.sex == 2 and model.medicine_entity.medicine_name == 'Sodium valproate': + if ( + model.management.registration.case.sex == 2 + and model.medicine_entity.medicine_name == "Sodium valproate" + ): return minimum_requirement_met and ( - model.is_a_pregnancy_prevention_programme_needed is not None and - model.has_a_valproate_annual_risk_acknowledgement_form_been_completed is not None and - model.is_a_pregnancy_prevention_programme_in_place is not None + model.is_a_pregnancy_prevention_programme_needed is not None + and model.has_a_valproate_annual_risk_acknowledgement_form_been_completed + is not None + and model.is_a_pregnancy_prevention_programme_in_place is not None ) return minimum_requirement_met @@ -190,33 +206,33 @@ def record_complete(model): @register.filter def to_class_name(value): if value.__class__.__name__ == "Registration": - return 'Verification/Registration' + return "Verification/Registration" elif value.__class__.__name__ == "FirstPaediatricAssessment": - return 'First Paediatric Assessment' + return "First Paediatric Assessment" elif value.__class__.__name__ == "EpilepsyContext": - return 'Epilepsy Context' + return "Epilepsy Context" elif value.__class__.__name__ == "MultiaxialDiagnosis": - return 'Multiaxial Diagnosis' + return "Multiaxial Diagnosis" elif value.__class__.__name__ == "Assessment": - return 'Milestones' + return "Milestones" elif value.__class__.__name__ == "Investigations": - return 'Investigations' + return "Investigations" elif value.__class__.__name__ == "Management": - return 'Management' + return "Management" elif value.__class__.__name__ == "Site": - return 'Site' + return "Site" elif value.__class__.__name__ == "Episode": - return 'Episode' + return "Episode" elif value.__class__.__name__ == "Syndrome": - return 'Syndrome' + return "Syndrome" elif value.__class__.__name__ == "Comorbidity": - return 'Comorbidity' + return "Comorbidity" elif value.__class__.__name__ == "Epilepsy12User": - return 'Epilepsy12 User' + return "Epilepsy12 User" elif value.__class__.__name__ == "Antiepilepsy Medicine": - return 'Antiepilepsy Medicine' + return "Antiepilepsy Medicine" else: - return 'Error' + return "Error" @register.filter @@ -244,22 +260,22 @@ def return_case(value): elif value.__class__.__name__ == "Comorbidity": return value.multiaxial_diagnosis.registration.case elif value.__class__.__name__ == "Epilepsy12User": - return 'Epilepsy12 User' + return "Epilepsy12 User" elif value.__class__.__name__ == "Antiepilepsy Medicine": return value.management.registration.case else: - return 'Error' + return "Error" -@register.filter('has_group') +@register.filter("has_group") def has_group(user, group_names_string): # thanks to Lucas Simon for this efficiency # https://stackoverflow.com/questions/1052531/get-user-group-in-a-template """ Check if user has permission """ - result = [x.strip() for x in group_names_string.split(',')] - groups = user.groups.all().values_list('name', flat=True) + result = [x.strip() for x in group_names_string.split(",")] + groups = user.groups.all().values_list("name", flat=True) match = False for group in groups: if group in result: @@ -280,10 +296,10 @@ def none_percentage(field): if field is None: return "No data" else: - return f'{field} %' + return f"{field} %" -@register.filter(name='icon_for_score') +@register.filter(name="icon_for_score") def icon_for_score(score): if score is None: return @@ -296,7 +312,8 @@ def icon_for_score(score): data-position="top right" _="init js $('.rcpch_light_blue.exclamation.triangle.icon').popup(); end" > - """) + """ + ) elif score > 1: return mark_safe( """ - """) + """ + ) else: return mark_safe( """ - """) + """ + ) diff --git a/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine_list.html b/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine_list.html index cd777ee7..bec9e5f2 100644 --- a/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine_list.html +++ b/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine_list.html @@ -23,9 +23,9 @@ {% if medicine.antiepilepsy_medicine_start_date %} {{ medicine.antiepilepsy_medicine_start_date }} {% else %} - + None {% endif %} diff --git a/templates/epilepsy12/partials/page_elements/select_model.html b/templates/epilepsy12/partials/page_elements/select_model.html index 068ce18f..27523d7a 100644 --- a/templates/epilepsy12/partials/page_elements/select_model.html +++ b/templates/epilepsy12/partials/page_elements/select_model.html @@ -62,7 +62,7 @@
{{hx_default_text}}
From 6a16c8bb5882fb3b505c7fc6c490ca5cb1a7d4ec Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 13:17:34 +0100 Subject: [PATCH 02/10] fix kpis table region names if none --- templates/epilepsy12/partials/kpis/kpis.html | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/templates/epilepsy12/partials/kpis/kpis.html b/templates/epilepsy12/partials/kpis/kpis.html index 200fc702..a9045441 100644 --- a/templates/epilepsy12/partials/kpis/kpis.html +++ b/templates/epilepsy12/partials/kpis/kpis.html @@ -37,7 +37,7 @@

Clinical Team

class="info circle icon" id='totals_organisation' data-title='Epilepsy12 totals' - data-content="Number of children registered in this organisation." + data-content="Number of children registered in this organisation" {% if organisation.OrganisationName is not None %} + "{({{organisation.OrganisationName}})" {% endif %} data-position='top right' _="init js $('#totals_organisation').popup(); end" >({{organisation_kpis.total_number_of_cases}})

@@ -49,51 +49,51 @@

Clinical Team

class="info circle icon" id='totals_trust' data-title='Epilepsy12 totals' - data-content="Number of children registered in this Trust." + data-content="Number of children registered in this Trust" {% if organisation.ParentOrganisation_OrganisationName is not None %} + "{({{organisation.ParentOrganisation_OrganisationName}})" {% endif %} data-position='top right' _="init js $('#totals_trust').popup(); end" >({{trust_kpis.total_number_of_cases}})

-

Integrated Care Board ({{organisation.ICBName}})

+

Integrated Care Board

({{icb_kpis.total_number_of_cases}})

-

NHS Region ({{organisation.NHSEnglandRegion}})

+

NHS Region

({{nhs_kpis.total_number_of_cases}})

-

OPEN UK Region ({{organisation.OPENUKNetworkName}})

+

OPEN UK Region

({{open_uk_kpis.total_number_of_cases}})

-

Country ({{organisation.ons_region.ons_country.Country_ONS_Name}})

+

Country

({{country_kpis.total_number_of_cases}})

From 08890fe5ddc3e37d8714818abfd481d5ea2534c3 Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 14:11:54 +0100 Subject: [PATCH 03/10] add remove discontinue date button add to urls and views add padding to button --- epilepsy12/urls.py | 5 ++ epilepsy12/view_folder/management_views.py | 45 ++++++++++++- static/styles/style.css | 4 ++ .../antiepilepsy_medicine.html | 63 ++++++++++++++----- 4 files changed, 100 insertions(+), 17 deletions(-) diff --git a/epilepsy12/urls.py b/epilepsy12/urls.py index 0eeec847..23814e4f 100644 --- a/epilepsy12/urls.py +++ b/epilepsy12/urls.py @@ -822,6 +822,11 @@ views.antiepilepsy_medicine_add_stop_date, name="antiepilepsy_medicine_add_stop_date", ), + path( + "antiepilepsy_medicine//antiepilepsy_medicine_remove_stop_date", + views.antiepilepsy_medicine_remove_stop_date, + name="antiepilepsy_medicine_remove_stop_date", + ), path( "antiepilepsy_medicine//antiepilepsy_medicine_stop_date", views.antiepilepsy_medicine_stop_date, diff --git a/epilepsy12/view_folder/management_views.py b/epilepsy12/view_folder/management_views.py index 98fdec9c..933e42f4 100644 --- a/epilepsy12/view_folder/management_views.py +++ b/epilepsy12/view_folder/management_views.py @@ -251,9 +251,6 @@ def edit_antiepilepsy_medicine(request, antiepilepsy_medicine_id): is_rescue=antiepilepsy_medicine.is_rescue_medicine ).order_by("medicine_name") - for medicine in MedicineEntity.objects.all(): - print(medicine) - if antiepilepsy_medicine.antiepilepsy_medicine_stop_date: show_end_date = True else: @@ -516,6 +513,48 @@ def antiepilepsy_medicine_add_stop_date(request, antiepilepsy_medicine_id): return response +@login_required +@user_may_view_this_child() +@permission_required("epilepsy12.change_antiepilepsymedicine", raise_exception=True) +def antiepilepsy_medicine_remove_stop_date(request, antiepilepsy_medicine_id): + """ + POST callback from antiepilepsy_medicine.html partial to toggle closed antiepilepsy_medicine_end_date + """ + + error_message = "" + + antiepilepsy_medicine = AntiEpilepsyMedicine.objects.get( + pk=antiepilepsy_medicine_id + ) + + # set antiepilepsy_medicine_stop_date to None and save + antiepilepsy_medicine.antiepilepsy_medicine_stop_date = None + antiepilepsy_medicine.save() + + choices = MedicineEntity.objects.filter( + is_rescue=antiepilepsy_medicine.is_rescue_medicine + ).order_by("medicine_name") + + context = { + "choices": choices, + "antiepilepsy_medicine": antiepilepsy_medicine, + "is_rescue_medicine": antiepilepsy_medicine.is_rescue_medicine, + "show_end_date": False, + } + + template_name = "epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine.html" + + response = recalculate_form_generate_response( + model_instance=antiepilepsy_medicine.management, + request=request, + context=context, + template=template_name, + error_message=error_message, + ) + + return response + + @login_required @user_may_view_this_child() @permission_required("epilepsy12.change_antiepilepsymedicine", raise_exception=True) diff --git a/static/styles/style.css b/static/styles/style.css index d9e25321..e2ade3a3 100644 --- a/static/styles/style.css +++ b/static/styles/style.css @@ -1906,4 +1906,8 @@ div.sixteen.wide.column.search_field_wrapper > .ui.rcpch.icon.input { .case_create_buttons_wrapper { display: flex; +} + +.padded.field { + padding-top: 33px; } \ No newline at end of file diff --git a/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine.html b/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine.html index 46094b73..5707aed8 100644 --- a/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine.html +++ b/templates/epilepsy12/partials/management/antiepilepsy_medicines/antiepilepsy_medicine.html @@ -10,9 +10,9 @@
-
+
-
+
{% url 'antiepilepsy_medicine_start_date' antiepilepsy_medicine_id=antiepilepsy_medicine.pk as hx_post %} {% if is_rescue_medicine %} {% include 'epilepsy12/partials/page_elements/date_field.html' with choices=choices hx_post=hx_post hx_target='#rescue_medicine_list' hx_trigger='change delay:1s' hx_swap='innerHTML' input_date_field_name='antiepilepsy_medicine_start_date' date_value=antiepilepsy_medicine.antiepilepsy_medicine_start_date label=antiepilepsy_medicine.get_antiepilepsy_medicine_start_date_help_label_text reference=antiepilepsy_medicine.get_antiepilepsy_medicine_start_date_help_reference_text hx_default_text='enter date' data_position='top left' error_message=error_message enabled=perms.epilepsy12.change_antiepilepsymedicine has_permission=perms.epilepsy12.change_antiepilepsymedicine %} @@ -21,39 +21,74 @@
{% endif %}
-
- {% if show_end_date %} + {% if show_end_date %} +
{% url 'antiepilepsy_medicine_stop_date' antiepilepsy_medicine_id=antiepilepsy_medicine.pk as hx_post %} {% if is_rescue_medicine %} {% include 'epilepsy12/partials/page_elements/date_field.html' with choices=choices hx_post=hx_post hx_target='#rescue_medicine_list' hx_trigger='change delay:1s' hx_swap='innerHTML' input_date_field_name='antiepilepsy_medicine_stop_date' date_value=antiepilepsy_medicine.antiepilepsy_medicine_stop_date label=antiepilepsy_medicine.get_antiepilepsy_medicine_stop_date_help_label_text reference=antiepilepsy_medicine.get_antiepilepsy_medicine_stop_date_help_reference_text hx_default_text='enter date' data_position='top left' error_message=error_message enabled=perms.epilepsy12.change_antiepilepsymedicine has_permission=perms.epilepsy12.change_antiepilepsymedicine %} {% else %} {% include 'epilepsy12/partials/page_elements/date_field.html' with choices=choices hx_post=hx_post hx_target='#antiepilepsy_medicine_list' hx_trigger='change delay:1s' hx_swap='innerHTML' input_date_field_name='antiepilepsy_medicine_stop_date' date_value=antiepilepsy_medicine.antiepilepsy_medicine_stop_date label=antiepilepsy_medicine.get_antiepilepsy_medicine_stop_date_help_label_text reference=antiepilepsy_medicine.get_antiepilepsy_medicine_stop_date_help_reference_text hx_default_text='enter date' data_position='top left' error_message=error_message enabled=perms.epilepsy12.change_antiepilepsymedicine has_permission=perms.epilepsy12.change_antiepilepsymedicine %} - {% endif %} + {% endif %} +
+ {% endif %} + + {% if show_end_date %} + {% url 'antiepilepsy_medicine_remove_stop_date' antiepilepsy_medicine_id=antiepilepsy_medicine.pk as hx_post %} +
+ + {% if is_rescue_medicine %} + +
Remove discontinued date
{% else %} - {% url 'antiepilepsy_medicine_add_stop_date' antiepilepsy_medicine_id=antiepilepsy_medicine.pk as hx_post %} + +
Remove discontinued date
+ {% endif %} + +
+ + {% else %} + {% url 'antiepilepsy_medicine_add_stop_date' antiepilepsy_medicine_id=antiepilepsy_medicine.pk as hx_post %} +
+ {% if is_rescue_medicine %} -
Add End Date
+ >Add discontinued date
{% else %} -
Add End Date
+ >Add discontinued date
{% endif %} - {% endif %} -
+ +
+ + {% endif %} + +
{% if error_message %}
From b495c19af6176627099a937b34704898b9b9fa5c Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 14:22:05 +0100 Subject: [PATCH 04/10] sudep refactor in management form --- epilepsy12/models_folder/management.py | 68 +++++++++++++------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/epilepsy12/models_folder/management.py b/epilepsy12/models_folder/management.py index 2e66d91c..fde2fd00 100644 --- a/epilepsy12/models_folder/management.py +++ b/epilepsy12/models_folder/management.py @@ -1,7 +1,9 @@ # django from django.contrib.gis.db import models + # 3rd party from simple_history.models import HistoricalRecords + # rcpch from .help_text_mixin import HelpTextMixin from .time_and_user_abstract_base_classes import * @@ -20,17 +22,17 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex has_an_aed_been_given = models.BooleanField( help_text={ - 'label': "Has an antiseizure medicine been given?", - 'reference': "Has an antiseizure medicine been given?", + "label": "Has an antiseizure medicine been given?", + "reference": "Has an antiseizure medicine been given?", }, default=None, null=True, - blank=True + blank=True, ) has_rescue_medication_been_prescribed = models.BooleanField( help_text={ - 'label': "Has a rescue medicine been prescribed?", - 'reference': "Has a rescue medicine been prescribed?", + "label": "Has a rescue medicine been prescribed?", + "reference": "Has a rescue medicine been prescribed?", }, default=None, null=True, @@ -38,8 +40,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_in_place = models.BooleanField( help_text={ - 'label': 'Has care planning (either an individualised epilepsy document or copy clinic letter including care planning information) commenced?', - 'reference': 'Has care planning (either an individualised epilepsy document or copy clinic letter including care planning information) commenced?', + "label": "Has care planning (either an individualised epilepsy document or copy clinic letter including care planning information) commenced?", + "reference": "Has care planning (either an individualised epilepsy document or copy clinic letter including care planning information) commenced?", }, default=None, null=True, @@ -47,8 +49,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_date = models.DateField( help_text={ - 'label': "On what date was the individualised care plan put in place?", - 'reference': "On what date was the individualised care plan put in place?", + "label": "On what date was the individualised care plan put in place?", + "reference": "On what date was the individualised care plan put in place?", }, default=None, null=True, @@ -56,8 +58,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_has_parent_carer_child_agreement = models.BooleanField( help_text={ - 'label': "Parent or carer and child agreement", - 'reference': "Has the parent or carer and child agreement to an individualised care plan been documented?", + "label": "Parent or carer and child agreement", + "reference": "Has the parent or carer and child agreement to an individualised care plan been documented?", }, default=None, null=True, @@ -65,8 +67,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_includes_service_contact_details = models.BooleanField( help_text={ - 'label': 'Service contact details', - 'reference': "Does the individualised care plan include service contact details?", + "label": "Service contact details", + "reference": "Does the individualised care plan include service contact details?", }, default=None, null=True, @@ -74,8 +76,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_include_first_aid = models.BooleanField( help_text={ - 'label': 'First aid advice', - 'reference': "Does the individualised care plan include first aid advice?", + "label": "First aid advice", + "reference": "Does the individualised care plan include first aid advice?", }, default=None, null=True, @@ -83,8 +85,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_parental_prolonged_seizure_care = models.BooleanField( help_text={ - 'label': 'Parental advice on managing prolonged seizures', - 'reference': "Does the individualised care plan include parental advice on managing prolonged seizures?", + "label": "Parental advice on managing prolonged seizures", + "reference": "Does the individualised care plan include parental advice on managing prolonged seizures?", }, default=None, null=True, @@ -92,8 +94,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_includes_general_participation_risk = models.BooleanField( help_text={ - 'label': 'General participation and risk assessment', - 'reference': "Does the individualised care plan include general participation and risk assessment?", + "label": "General participation and risk assessment", + "reference": "Does the individualised care plan include general participation and risk assessment?", }, default=None, null=True, @@ -101,8 +103,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_addresses_water_safety = models.BooleanField( help_text={ - 'label': 'Water safety', - 'reference': "Does the individualised care plan address water safety?", + "label": "Water safety", + "reference": "Does the individualised care plan address water safety?", }, default=None, null=True, @@ -110,8 +112,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_addresses_sudep = models.BooleanField( help_text={ - 'label': 'Sudden unexplained death in epilepsy (SUDEP)', - 'reference': "Does the individualised care plan address sudden unexplained death in epilepsy?", + "label": "Sudden unexpected death in epilepsy (SUDEP)", + "reference": "Does the individualised care plan address sudden unexpected death in epilepsy?", }, default=None, null=True, @@ -119,8 +121,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) individualised_care_plan_includes_ehcp = models.BooleanField( help_text={ - 'label': 'An educational health care plan (EHCP)', - 'reference': "Does the individualised care plan include an educational health care plan (EHCP)?", + "label": "An educational health care plan (EHCP)", + "reference": "Does the individualised care plan include an educational health care plan (EHCP)?", }, default=None, null=True, @@ -128,8 +130,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex ) has_individualised_care_plan_been_updated_in_the_last_year = models.BooleanField( help_text={ - 'label': 'Being updated as necessary', - 'reference': "Has the individualised care plan been updated in the last year?", + "label": "Being updated as necessary", + "reference": "Has the individualised care plan been updated in the last year?", }, default=None, null=True, @@ -138,8 +140,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex has_been_referred_for_mental_health_support = models.BooleanField( help_text={ - 'label': 'Has a referral for mental health support been made?', - 'reference': "Has the child been referred for support with their mental health?", + "label": "Has a referral for mental health support been made?", + "reference": "Has the child been referred for support with their mental health?", }, default=None, null=True, @@ -148,8 +150,8 @@ class Management(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTex has_support_for_mental_health_support = models.BooleanField( help_text={ - 'label': 'Is mental health support in place?', - 'reference': "Is there evidence of the child receiving support for their mental health?", + "label": "Is mental health support in place?", + "reference": "Is there evidence of the child receiving support for their mental health?", }, default=None, null=True, @@ -167,9 +169,9 @@ def _history_user(self, value): self.updated_by = value registration = models.OneToOneField( - 'epilepsy12.Registration', + "epilepsy12.Registration", on_delete=models.CASCADE, - verbose_name="related registration" + verbose_name="related registration", ) class Meta: From cddc6d6224b456d85034b724597ce1f62ddaa77c Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 15:45:14 +0100 Subject: [PATCH 05/10] add eeg_declined button to form update urls and views to allow toggle persist 15/4/1915 as declined date --- .../validate_form_update_model.py | 98 +++++++++++-------- epilepsy12/models_folder/investigations.py | 71 ++++++++------ epilepsy12/urls.py | 5 + epilepsy12/view_folder/investigation_views.py | 74 +++++++++++++- static/styles/style.css | 8 ++ .../epilepsy12/forms/investigations_form.html | 2 +- .../investigations/eeg_information.html | 61 ++++++++++-- 7 files changed, 232 insertions(+), 87 deletions(-) diff --git a/epilepsy12/common_view_functions/validate_form_update_model.py b/epilepsy12/common_view_functions/validate_form_update_model.py index f05f9d05..7d0dad5d 100644 --- a/epilepsy12/common_view_functions/validate_form_update_model.py +++ b/epilepsy12/common_view_functions/validate_form_update_model.py @@ -7,13 +7,13 @@ def validate_and_update_model( - request, - model_id, - model, - field_name, - page_element, - comparison_date_field_name=None, - is_earliest_date=None + request, + model_id, + model, + field_name, + page_element, + comparison_date_field_name=None, + is_earliest_date=None, ): """ This is called from the view to update the model or return an error @@ -26,53 +26,61 @@ def validate_and_update_model( comparison_date_field_name: string corresponding to field name for date in model is_earliest_date: boolean - It replaces the decorator @update_model as decorators can only redirect the request, + It replaces the decorator @update_model as decorators can only redirect the request, they cannot pass parameters to the function they wrap. This means that errors raised in updating the model cannot be passed back to the template so the logic has been added to this function instead. - It is important that this function is called early on in the view function and that an updated instance of + It is important that this function is called early on in the view function and that an updated instance of the model AFTER UPDATE is put in the context that is passed back to the template. """ - if page_element == 'toggle_button': + if page_element == "toggle_button": # toggle button # the trigger_name of the element here corresponds to whether true or false has been selected - if request.htmx.trigger_name == 'button-true': + if request.htmx.trigger_name == "button-true": field_value = True - elif request.htmx.trigger_name == 'button-false': + elif request.htmx.trigger_name == "button-false": field_value = False else: # an error has occurred - print('Error has occurred') + print("Error has occurred") - elif page_element == 'multiple_choice_multiple_toggle_button' or page_element == 'single_choice_multiple_toggle_button': + elif ( + page_element == "multiple_choice_multiple_toggle_button" + or page_element == "single_choice_multiple_toggle_button" + ): # multiple_choice_multiple_toggle_button field_value = request.htmx.trigger_name - elif page_element == 'date_field': - field_value = datetime.strptime(request.POST.get( - request.htmx.trigger_name), "%Y-%m-%d").date() + elif page_element == "date_field": + field_value = datetime.strptime( + request.POST.get(request.htmx.trigger_name), "%Y-%m-%d" + ).date() - elif page_element == 'select' or page_element == 'snomed_select': - if request.htmx.trigger_name == 'syndrome_name': + elif page_element == "select" or page_element == "snomed_select": + if request.htmx.trigger_name == "syndrome_name": syndrome_entity = SyndromeEntity.objects.get( - pk=request.POST.get(request.htmx.trigger_name)) + pk=request.POST.get(request.htmx.trigger_name) + ) field_value = syndrome_entity # note field name here is syndrome - elif request.htmx.trigger_name == 'epilepsy_cause': + elif request.htmx.trigger_name == "epilepsy_cause": epilepsy_cause_entity = EpilepsyCauseEntity.objects.get( - pk=request.POST.get(request.htmx.trigger_name)) - field_value = epilepsy_cause_entity # note field name here is epilepsy_cause - elif request.htmx.trigger_name == 'medicine_id': + pk=request.POST.get(request.htmx.trigger_name) + ) + field_value = ( + epilepsy_cause_entity # note field name here is epilepsy_cause + ) + elif request.htmx.trigger_name == "medicine_id": medicine_entity = MedicineEntity.objects.get( pk=request.POST.get(request.htmx.trigger_name) ) field_value = medicine_entity - field_name = 'medicine_entity' + field_name = "medicine_entity" else: field_value = request.POST.get(request.htmx.trigger_name) # validate - if page_element == 'date_field': + if page_element == "date_field": # date tests a bit involved # No date can be before the date of birth # If a comparison date field is supplied, the date itself might not yet have been set. @@ -83,30 +91,37 @@ def validate_and_update_model( if comparison_date_field_name: instance = model.objects.get(pk=model_id) - comparison_date = getattr( - instance, comparison_date_field_name) + comparison_date = getattr(instance, comparison_date_field_name) if is_earliest_date: if comparison_date: - date_valid = field_value <= comparison_date and field_value <= date.today() - date_error = f'The date you chose ({field_value}) cannot not be after {comparison_date} or in the future.' + date_valid = ( + field_value <= comparison_date and field_value <= date.today() + ) + date_error = f"The date you chose ({field_value}) cannot not be after {comparison_date} or in the future." else: date_valid = field_value <= date.today() - date_error = f'The date you chose ({field_value}) cannot not be in the future.' + date_error = f"The date you chose ({field_value}) cannot not be in the future." if not date_valid: errors = date_error else: if comparison_date: - date_valid = field_value >= comparison_date - date_error = f'The date you chose ({field_value}) cannot not be before {comparison_date}' + date_valid = ( + field_value >= comparison_date and field_value <= date.today() + ) + date_error = f"The date you chose ({field_value}) cannot not be before {comparison_date} or in the future." else: # no other date supplied yet date_valid = True if not date_valid: errors = date_error - elif field_value > date.today() and (is_earliest_date is None or is_earliest_date): + elif field_value > date.today() and ( + is_earliest_date is None or is_earliest_date + ): # dates cannot be in the future unless they are the second of 2 dates - date_error = f'The date you chose ({field_value}) cannot not be in the future.' + date_error = ( + f"The date you chose ({field_value}) cannot not be in the future." + ) errors = date_error date_valid = False else: @@ -122,8 +137,7 @@ def validate_and_update_model( # if saving a registration_date, this has to trigger the save() method to generate a cohort # so update() cannot be used # This feels like a bit of a hack so very open to suggestions on more Django way of doing this - if field_name == 'registration_date': - + if field_name == "registration_date": # registration_date cannot be before date of birth registration = Registration.objects.get(pk=model_id) if field_value < registration.case.date_of_birth: @@ -133,7 +147,8 @@ def validate_and_update_model( # the registration date cannot be before the current cohort current_cohort_end_date = first_tuesday_in_january( - current_cohort_start_date().year+2)+relativedelta(days=7) + current_cohort_start_date().year + 2 + ) + relativedelta(days=7) if field_value < current_cohort_start_date(): date_valid = False errors = f'The date you entered cannot be before the current cohort start date ({current_cohort_start_date().strftime("%d %B %Y")})' @@ -152,12 +167,11 @@ def validate_and_update_model( else: updated_field = { field_name: field_value, - 'updated_at': timezone.now(), - 'updated_by': request.user + "updated_at": timezone.now(), + "updated_by": request.user, } try: - model.objects.filter( - pk=model_id).update(**updated_field) + model.objects.filter(pk=model_id).update(**updated_field) except DatabaseError as error: raise Exception(error) diff --git a/epilepsy12/models_folder/investigations.py b/epilepsy12/models_folder/investigations.py index 99956dd1..ebd46b76 100644 --- a/epilepsy12/models_folder/investigations.py +++ b/epilepsy12/models_folder/investigations.py @@ -1,92 +1,95 @@ # django from django.contrib.gis.db import models + # 3rd party from simple_history.models import HistoricalRecords + # rcpch from .help_text_mixin import HelpTextMixin from ..general_functions import calculate_time_elapsed from .time_and_user_abstract_base_classes import * -class Investigations(TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTextMixin): - +class Investigations( + TimeStampAbstractBaseClass, UserStampAbstractBaseClass, HelpTextMixin +): eeg_indicated = models.BooleanField( help_text={ - 'label': "Has a first EEG been requested?", - 'reference': "All children with Epilepsy should have an EEG", + "label": "Has a first EEG been requested?", + "reference": "All children with Epilepsy should have an EEG", }, default=None, null=True, - blank=True + blank=True, ) eeg_request_date = models.DateField( help_text={ - 'label': "Date EEG requested", - 'reference': "Date EEG requested", + "label": "Date EEG requested", + "reference": "Date EEG requested. Even if the EEG was not performed, a request date is still required.", }, default=None, null=True, - blank=True + blank=True, ) eeg_performed_date = models.DateField( help_text={ - 'label': "Date EEG performed", - 'reference': "Date EEG performed", + "label": "Date EEG performed", + "reference": "Date EEG performed", }, default=None, null=True, - blank=True + blank=True, ) twelve_lead_ecg_status = models.BooleanField( help_text={ - 'label': "Has a 12-Lead ECG been performed?", - 'reference': "The Epilepsy12 standard is that all children with an convulsive episode should have a 12 lead ECG", + "label": "Has a 12-Lead ECG been performed?", + "reference": "The Epilepsy12 standard is that all children with an convulsive episode should have a 12 lead ECG", }, default=None, null=True, - blank=True + blank=True, ) ct_head_scan_status = models.BooleanField( help_text={ - 'label': "Has a CT head been performed?", - 'reference': "NICE states if MRI is contraindicated, consider a CT scan for children, young people and adults with epilepsy.", + "label": "Has a CT head been performed?", + "reference": "NICE states if MRI is contraindicated, consider a CT scan for children, young people and adults with epilepsy.", }, default=None, null=True, - blank=True + blank=True, ) mri_indicated = models.BooleanField( help_text={ - 'label': "Has a brain MRI been requested?", - 'reference': "NICE recommends that an MRI scan should be offered to children, young people and adults diagnosed with epilepsy, unless they have idiopathic generalised epilepsy or self-limited epilepsy with centrotemporal spikes. The MRI should be carried out within 6 weeks of the MRI referral.", + "label": "Has a brain MRI been requested?", + "reference": "NICE recommends that an MRI scan should be offered to children, young people and adults diagnosed with epilepsy, unless they have idiopathic generalised epilepsy or self-limited epilepsy with centrotemporal spikes. The MRI should be carried out within 6 weeks of the MRI referral.", }, default=None, null=True, - blank=True + blank=True, ) mri_brain_requested_date = models.DateField( help_text={ - 'label': "MRI brain requested date", - 'reference': "MRI brain requested date", + "label": "MRI brain requested date", + "reference": "MRI brain requested date", }, default=None, null=True, - blank=True + blank=True, ) mri_brain_reported_date = models.DateField( help_text={ - 'label': "Date MRI brain reported", - 'reference': "Date MRI brain reported", + "label": "Date MRI brain reported", + "reference": "Date MRI brain reported", }, default=None, null=True, - blank=True + blank=True, ) history = HistoricalRecords() @@ -104,26 +107,30 @@ def mri_wait(self): Calculated field. Returns time elapsed between date EEG requested and performed as a string. """ if self.mri_brain_reported_date and self.mri_brain_requested_date: - return calculate_time_elapsed(self.mri_brain_requested_date, self.mri_brain_reported_date) + return calculate_time_elapsed( + self.mri_brain_requested_date, self.mri_brain_reported_date + ) def eeg_wait(self): """ Calculated field. Returns time elapsed between date EEG requested and performed as a string. """ if self.eeg_performed_date and self.eeg_request_date: - return calculate_time_elapsed(self.eeg_request_date, self.eeg_performed_date) + return calculate_time_elapsed( + self.eeg_request_date, self.eeg_performed_date + ) # relationships registration = models.OneToOneField( - 'epilepsy12.Registration', + "epilepsy12.Registration", on_delete=models.CASCADE, verbose_name="Related Registration", - null=True + null=True, ) class Meta: - verbose_name = 'Investigations' - verbose_name_plural = 'Investigations' + verbose_name = "Investigations" + verbose_name_plural = "Investigations" def __str__(self) -> str: return f"Investigations for {self.registration.case}" diff --git a/epilepsy12/urls.py b/epilepsy12/urls.py index 23814e4f..2d9c30ff 100644 --- a/epilepsy12/urls.py +++ b/epilepsy12/urls.py @@ -750,6 +750,11 @@ views.eeg_performed_date, name="eeg_performed_date", ), + path( + "investigations//eeg_declined/", + views.eeg_declined, + name="eeg_declined", + ), path( "investigations//twelve_lead_ecg_status", views.twelve_lead_ecg_status, diff --git a/epilepsy12/view_folder/investigation_views.py b/epilepsy12/view_folder/investigation_views.py index f39ba791..e2df46c8 100644 --- a/epilepsy12/view_folder/investigation_views.py +++ b/epilepsy12/view_folder/investigation_views.py @@ -1,3 +1,4 @@ +from datetime import date from django.utils import timezone from django.contrib.auth.decorators import login_required, permission_required from epilepsy12.models import Investigations, Registration, Site @@ -25,6 +26,11 @@ def investigations(request, case_id): ).get() organisation_id = site.organisation.pk + if investigations.eeg_performed_date == date(year=1915, month=4, day=15): + eeg_declined = True + else: + eeg_declined = False + context = { "case_id": case_id, "registration": registration, @@ -32,6 +38,7 @@ def investigations(request, case_id): "audit_progress": registration.audit_progress, "active_template": "investigations", "organisation_id": organisation_id, + "eeg_declined": eeg_declined, } template_name = "epilepsy12/investigations.html" @@ -80,7 +87,12 @@ def eeg_indicated(request, investigations_id): investigations.updated_by = request.user investigations.save() - context = {"investigations": investigations} + if investigations.eeg_performed_date == date(year=1915, month=4, day=15): + eeg_declined = True + else: + eeg_declined = False + + context = {"investigations": investigations, "eeg_declined": eeg_declined} template_name = "epilepsy12/partials/investigations/eeg_information.html" @@ -126,9 +138,12 @@ def eeg_request_date(request, investigations_id): template_name = "epilepsy12/partials/investigations/eeg_information.html" - context = { - "investigations": investigations, - } + if investigations.eeg_performed_date == date(year=1915, month=4, day=15): + eeg_declined = True + else: + eeg_declined = False + + context = {"investigations": investigations, "eeg_declined": eeg_declined} response = recalculate_form_generate_response( model_instance=investigations, @@ -170,7 +185,56 @@ def eeg_performed_date(request, investigations_id): investigations = Investigations.objects.get(pk=investigations_id) - context = {"investigations": investigations} + if investigations.eeg_performed_date == date(year=1915, month=4, day=15): + eeg_declined = True + else: + eeg_declined = False + + context = {"investigations": investigations, "eeg_declined": eeg_declined} + + template_name = "epilepsy12/partials/investigations/eeg_information.html" + + response = recalculate_form_generate_response( + model_instance=investigations, + request=request, + context=context, + template=template_name, + error_message=error_message, + ) + + return response + + +@login_required +@user_may_view_this_child() +@permission_required("epilepsy12.change_investigations", raise_exception=True) +def eeg_declined(request, investigations_id, confirm): + """ + This is an HTMX callback from the ecg_information.html partial template + which contains fields on eeg_indicated, eeg_request_date and eeg_performed_date. + It also contains a calculated field showing time to EEG from request. + It is triggered by a toggle in the partial generating a post request on click in the eeg_declined button. + EEGs might be declined if the child is not cooperative or practical/technical issues relating to the EEG test. + Failure to provide a completion date of the EEG however results in a fail for this measure. + To denote failure, the completion date is persisted as 15/4/1915, the date of birth of Jean Henri Gestaut + This updates the model and returns the same partial. + """ + + error_message = None + + investigations = Investigations.objects.get(pk=investigations_id) + if confirm == "decline": + investigations.eeg_performed_date = date(year=1915, month=4, day=15) + eeg_declined = True + elif confirm == "edit": + investigations.eeg_performed_date = None + eeg_declined = False + else: + raise ValueError("No confirm parameter passed to eeg_decline path.") + + investigations.save() + + context = {"investigations": investigations, "eeg_declined": eeg_declined} template_name = "epilepsy12/partials/investigations/eeg_information.html" diff --git a/static/styles/style.css b/static/styles/style.css index e2ade3a3..c8c6c880 100644 --- a/static/styles/style.css +++ b/static/styles/style.css @@ -1910,4 +1910,12 @@ div.sixteen.wide.column.search_field_wrapper > .ui.rcpch.icon.input { .padded.field { padding-top: 33px; +} + +.padded_form { + margin-top: 13px !important; +} + +.padded_field { + padding-top: 20px; } \ No newline at end of file diff --git a/templates/epilepsy12/forms/investigations_form.html b/templates/epilepsy12/forms/investigations_form.html index 85278cbd..348a5a5c 100644 --- a/templates/epilepsy12/forms/investigations_form.html +++ b/templates/epilepsy12/forms/investigations_form.html @@ -1,6 +1,6 @@
- {% include 'epilepsy12/partials/investigations/eeg_information.html' with investigations_id=investigations.pk %} + {% include 'epilepsy12/partials/investigations/eeg_information.html' with investigations_id=investigations.pk eeg_declined=eeg_declined %}
diff --git a/templates/epilepsy12/partials/investigations/eeg_information.html b/templates/epilepsy12/partials/investigations/eeg_information.html index aacd14df..f7297dbd 100644 --- a/templates/epilepsy12/partials/investigations/eeg_information.html +++ b/templates/epilepsy12/partials/investigations/eeg_information.html @@ -15,15 +15,62 @@
{% url 'eeg_request_date' investigations_id=investigations.pk as hx_post %} - {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_request_date label=investigations.get_eeg_request_date_help_label_text reference=investigations.get_eeg_request_date_help_reference_text data_position="top left" input_date_field_name='eeg_request_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} + {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_request_date label=investigations.get_eeg_request_date_help_label_text reference=investigations.get_eeg_request_date_help_reference_text data_position="top left" input_date_field_name='eeg_request_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} + + {% if eeg_declined %} +
+ +
DECLINED
+
+
+ {% url 'eeg_declined' investigations_id=investigations.pk confirm='edit' as hx_post %} +
Edit date
+
+ + {% else %} + + {% url 'eeg_performed_date' investigations_id=investigations.pk as hx_post %} + {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_performed_date label=investigations.get_eeg_performed_date_help_label_text reference=investigations.get_eeg_performed_date_help_reference_text data_position="top left" input_date_field_name='eeg_performed_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} - {% url 'eeg_performed_date' investigations_id=investigations.pk as hx_post %} - {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_performed_date label=investigations.get_eeg_performed_date_help_label_text reference=investigations.get_eeg_performed_date_help_reference_text data_position="top left" input_date_field_name='eeg_performed_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} + {% if investigations.eeg_request_date and investigations.eeg_performed_date %} +
+ + +
+ {% endif %} + +
+ {% url 'eeg_declined' investigations_id=investigations.pk confirm='decline' as hx_post %} +
EEG declined
+
+ + {% endif %} -
- - -
From 87e79aea775ab66d17193edcb64cbe3593dc7f1a Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 16:21:29 +0100 Subject: [PATCH 06/10] implement MRI declined fields/views/url --- epilepsy12/urls.py | 5 + epilepsy12/view_folder/investigation_views.py | 89 ++++++++++++++++- .../epilepsy12/forms/investigations_form.html | 2 +- .../investigations/eeg_information.html | 31 +++--- .../investigations/mri_brain_information.html | 96 +++++++++++++++---- 5 files changed, 190 insertions(+), 33 deletions(-) diff --git a/epilepsy12/urls.py b/epilepsy12/urls.py index 2d9c30ff..5ba21be8 100644 --- a/epilepsy12/urls.py +++ b/epilepsy12/urls.py @@ -780,6 +780,11 @@ views.mri_brain_reported_date, name="mri_brain_reported_date", ), + path( + "investigations//mri_brain_declined/", + views.mri_brain_declined, + name="mri_brain_declined", + ), # management path( "management//has_an_aed_been_given", diff --git a/epilepsy12/view_folder/investigation_views.py b/epilepsy12/view_folder/investigation_views.py index e2df46c8..f07a2b32 100644 --- a/epilepsy12/view_folder/investigation_views.py +++ b/epilepsy12/view_folder/investigation_views.py @@ -31,6 +31,11 @@ def investigations(request, case_id): else: eeg_declined = False + if investigations.mri_brain_reported_date == date(year=1915, month=4, day=15): + mri_brain_declined = True + else: + mri_brain_declined = False + context = { "case_id": case_id, "registration": registration, @@ -39,6 +44,7 @@ def investigations(request, case_id): "active_template": "investigations", "organisation_id": organisation_id, "eeg_declined": eeg_declined, + "mri_brain_declined": mri_brain_declined, } template_name = "epilepsy12/investigations.html" @@ -217,6 +223,7 @@ def eeg_declined(request, investigations_id, confirm): EEGs might be declined if the child is not cooperative or practical/technical issues relating to the EEG test. Failure to provide a completion date of the EEG however results in a fail for this measure. To denote failure, the completion date is persisted as 15/4/1915, the date of birth of Jean Henri Gestaut + The confirm flag can either be set to 'decline' or 'edit' reflecting the toggle state in the template This updates the model and returns the same partial. """ @@ -365,7 +372,15 @@ def mri_indicated(request, investigations_id): investigations.updated_by = request.user investigations.save() - context = {"investigations": investigations} + if investigations.mri_brain_reported_date == date(year=1915, month=4, day=15): + mri_brain_declined = True + else: + mri_brain_declined = False + + context = { + "investigations": investigations, + "mri_brain_declined": mri_brain_declined, + } template_name = "epilepsy12/partials/investigations/mri_brain_information.html" @@ -407,7 +422,15 @@ def mri_brain_requested_date(request, investigations_id): investigations = Investigations.objects.get(pk=investigations_id) - context = {"investigations": investigations} + if investigations.mri_brain_reported_date == date(year=1915, month=4, day=15): + mri_brain_declined = True + else: + mri_brain_declined = False + + context = { + "investigations": investigations, + "mri_brain_declined": mri_brain_declined, + } template_name = "epilepsy12/partials/investigations/mri_brain_information.html" @@ -449,7 +472,67 @@ def mri_brain_reported_date(request, investigations_id): investigations = Investigations.objects.get(pk=investigations_id) - context = {"investigations": investigations} + if investigations.mri_brain_reported_date == date(year=1915, month=4, day=15): + mri_brain_declined = True + else: + mri_brain_declined = False + + context = { + "investigations": investigations, + "mri_brain_declined": mri_brain_declined, + } + + template_name = "epilepsy12/partials/investigations/mri_brain_information.html" + + response = recalculate_form_generate_response( + model_instance=investigations, + request=request, + context=context, + template=template_name, + error_message=error_message, + ) + + return response + + +@login_required +@user_may_view_this_child() +@permission_required("epilepsy12.change_investigations", raise_exception=True) +def mri_brain_declined(request, investigations_id, confirm): + """ + This is an HTMX callback from the mri_brain_information.html partial template + which contains fields on mri_indicated, mri_request_date and mri_performed_date. + It also contains a calculated field showing time to MRI from request. + It is triggered by a toggle in the partial generating a post request on click in the eeg_declined button. + MRIs might be declined if the child is not cooperative or practical/technical issues relating to the MRI test. + Failure to provide a completion date of the MRI however results in a fail for this measure. + To denote failure, the completion date is persisted as 15/4/1915, the date of birth of Jean Henri Gestaut + The confirm flag can either be set to 'decline' or 'edit' reflecting the toggle state in the template + This updates the model and returns the same partial. + """ + + error_message = None + + investigations = Investigations.objects.get(pk=investigations_id) + + if confirm == "decline": + investigations.mri_brain_reported_date = date(year=1915, month=4, day=15) + mri_brain_declined = True + elif confirm == "edit": + investigations.mri_brain_reported_date = None + mri_brain_declined = False + else: + raise ValueError("No confirm parameter passed to eeg_decline path.") + + if investigations.mri_brain_reported_date == date(year=1915, month=4, day=15): + mri_brain_declined = True + else: + mri_brain_declined = False + + context = { + "investigations": investigations, + "mri_brain_declined": mri_brain_declined, + } template_name = "epilepsy12/partials/investigations/mri_brain_information.html" diff --git a/templates/epilepsy12/forms/investigations_form.html b/templates/epilepsy12/forms/investigations_form.html index 348a5a5c..6e08cfbe 100644 --- a/templates/epilepsy12/forms/investigations_form.html +++ b/templates/epilepsy12/forms/investigations_form.html @@ -12,6 +12,6 @@
- {% include 'epilepsy12/partials/investigations/mri_brain_information.html' with investigations_id=investigations.pk %} + {% include 'epilepsy12/partials/investigations/mri_brain_information.html' with investigations_id=investigations.pk mri_brain_declined=mri_brain_declined %}
\ No newline at end of file diff --git a/templates/epilepsy12/partials/investigations/eeg_information.html b/templates/epilepsy12/partials/investigations/eeg_information.html index f7297dbd..8767fcd8 100644 --- a/templates/epilepsy12/partials/investigations/eeg_information.html +++ b/templates/epilepsy12/partials/investigations/eeg_information.html @@ -56,18 +56,27 @@
{% endif %} + + {% if investigations.eeg_performed_date is None %} + + {% comment %} + Only show the EEG declined button if the eeg_performed date has neither been declined already + nor has already been set + {% endcomment %} -
- {% url 'eeg_declined' investigations_id=investigations.pk confirm='decline' as hx_post %} -
EEG declined
-
+
+ {% url 'eeg_declined' investigations_id=investigations.pk confirm='decline' as hx_post %} +
EEG declined
+
+ + {% endif %} {% endif %} diff --git a/templates/epilepsy12/partials/investigations/mri_brain_information.html b/templates/epilepsy12/partials/investigations/mri_brain_information.html index 4bd2c452..9850aa77 100644 --- a/templates/epilepsy12/partials/investigations/mri_brain_information.html +++ b/templates/epilepsy12/partials/investigations/mri_brain_information.html @@ -1,35 +1,95 @@ - {% load epilepsy12_template_tags %}
- +
- {% url 'mri_indicated' investigations_id=investigations.pk as hx_post %} - {% include 'epilepsy12/partials/page_elements/toggle_button.html' with hx_post=hx_post hx_target="#mri_brain_information" hx_trigger="click" hx_swap="innerHTML" test_positive=investigations.mri_indicated tooltip_id='mri_brain_information_tooltip' label=investigations.get_mri_indicated_help_label_text reference=investigations.get_mri_indicated_help_reference_text data_position="top left" enabled=perms.epilepsy12.change_investigations %} +
+ + {% url 'mri_indicated' investigations_id=investigations.pk as hx_post %} + {% include 'epilepsy12/partials/page_elements/toggle_button.html' with hx_post=hx_post hx_target="#mri_brain_information" hx_trigger="click" hx_swap="innerHTML" test_positive=investigations.mri_indicated tooltip_id='mri_indicated_tooltip' label=investigations.get_mri_indicated_help_label_text reference=investigations.get_mri_indicated_help_reference_text data_position="top left" enabled=perms.epilepsy12.change_investigations %} + +
{% if investigations.mri_indicated %} -
+
- {% url 'mri_brain_requested_date' investigations_id=investigations.pk as hx_post %} - {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#mri_brain_information" hx_trigger="change delay:1s" label=investigations.get_mri_brain_requested_date_help_label_text reference=investigations.get_mri_brain_requested_date_help_reference_text date_value=investigations.mri_brain_requested_date data_position='top left' input_date_field_name='mri_brain_requested_date' error_message=error_message enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} - - {% url 'mri_brain_reported_date' investigations_id=investigations.pk as hx_post %} - {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#mri_brain_information" hx_trigger="change delay:1s" label=investigations.get_mri_brain_reported_date_help_label_text reference=investigations.get_mri_brain_reported_date_help_reference_text date_value=investigations.mri_brain_reported_date data_position='top left' input_date_field_name='mri_brain_reported_date' error_message=error_message enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} + {% url 'mri_brain_requested_date' investigations_id=investigations.pk as hx_post %} + {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#mri_brain_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.mri_brain_requested_date label=investigations.get_mri_brain_requested_date_help_label_text reference=investigations.get_mri_brain_requested_date_help_reference_text data_position="top left" input_date_field_name='mri_brain_requested_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} -
- - + {% if mri_brain_declined %} +
+ +
DECLINED
+
+
+ {% url 'mri_brain_declined' investigations_id=investigations.pk confirm='edit' as hx_post %} +
Edit date
+ + {% else %} + + {% url 'mri_brain_reported_date' investigations_id=investigations.pk as hx_post %} + {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#mri_brain_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.mri_brain_reported_date label=investigations.get_mri_brain_reported_date_help_label_text reference=investigations.get_mri_brain_reported_date_help_reference_text data_position="top left" input_date_field_name='mri_brain_reported_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} -
+ {% if investigations.mri_brain_requested_date and investigations.mri_brain_reported_date %} +
+ + +
+ {% endif %} + + {% if investigations.mri_brain_reported_date is None %} + + {% comment %} + Only show the MRI declined button if the mri_brain_reported date has neither been declined already + nor has already been set + {% endcomment %} + +
+ {% url 'mri_brain_declined' investigations_id=investigations.pk confirm='decline' as hx_post %} +
MRI Brain declined
+
+ + + {% endif %} - {% if error_message %} -
- {{ error_message }} -
{% endif %} + +
+ + {% if error_message %} +
+ {{ error_message }} +
+ {% endif %} + {% endif %}
From 8396ce15aea93ce07c997b3b2dbff70e87cd0195 Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 18:25:48 +0100 Subject: [PATCH 07/10] refactor validate_form_update_model to accept minimum date --- .../validate_form_update_model.py | 32 ++++++++++++++----- epilepsy12/view_folder/assessment_views.py | 16 ++++++++++ epilepsy12/view_folder/investigation_views.py | 9 +++++- epilepsy12/view_folder/management_views.py | 10 ++++++ .../view_folder/multiaxial_diagnosis_views.py | 4 +++ epilepsy12/view_folder/registration_views.py | 6 +++- epilepsy12/view_folder/syndrome_views.py | 2 ++ 7 files changed, 69 insertions(+), 10 deletions(-) diff --git a/epilepsy12/common_view_functions/validate_form_update_model.py b/epilepsy12/common_view_functions/validate_form_update_model.py index 7d0dad5d..14366445 100644 --- a/epilepsy12/common_view_functions/validate_form_update_model.py +++ b/epilepsy12/common_view_functions/validate_form_update_model.py @@ -14,6 +14,7 @@ def validate_and_update_model( page_element, comparison_date_field_name=None, is_earliest_date=None, + earliest_allowable_date=None, ): """ This is called from the view to update the model or return an error @@ -25,6 +26,7 @@ def validate_and_update_model( page_element: string one of 'date_field', 'toggle_button', 'multiple_choice_single_toggle_button', 'multiple_choic_multiple_toggle_button', 'select', 'snomed_select', 'organisation_select' comparison_date_field_name: string corresponding to field name for date in model is_earliest_date: boolean + first_paediatric_assessment_date: date - used to validate It replaces the decorator @update_model as decorators can only redirect the request, they cannot pass parameters to the function they wrap. This means that errors raised in updating the model @@ -89,24 +91,40 @@ def validate_and_update_model( # If there is no comparison date (eg registration_date) the only stipulation is that it not be in the future. date_valid = None + if earliest_allowable_date: + if field_value < earliest_allowable_date: + # dates cannot be before the earliest allowable date (usually the first paediatric assessment or the cohort start date) + date_error = f"The date you chose ({field_value}) cannot not be before {earliest_allowable_date}." + errors = date_error + date_valid = False + if comparison_date_field_name: instance = model.objects.get(pk=model_id) comparison_date = getattr(instance, comparison_date_field_name) if is_earliest_date: if comparison_date: date_valid = ( - field_value <= comparison_date and field_value <= date.today() + field_value <= comparison_date + and field_value <= date.today() + and date_valid is None ) - date_error = f"The date you chose ({field_value}) cannot not be after {comparison_date} or in the future." + if field_value > comparison_date: + date_error = f"The date you chose ({field_value}) cannot not be after {comparison_date}." + if field_value > date.today(): + date_error = f"You cannot choose a date in the future." + else: - date_valid = field_value <= date.today() + date_valid = field_value <= date.today() and date_valid is None date_error = f"The date you chose ({field_value}) cannot not be in the future." + if not date_valid: errors = date_error else: if comparison_date: date_valid = ( - field_value >= comparison_date and field_value <= date.today() + field_value >= comparison_date + and field_value <= date.today() + and date_valid is None ) date_error = f"The date you chose ({field_value}) cannot not be before {comparison_date} or in the future." else: @@ -115,9 +133,7 @@ def validate_and_update_model( if not date_valid: errors = date_error - elif field_value > date.today() and ( - is_earliest_date is None or is_earliest_date - ): + elif field_value > date.today(): # dates cannot be in the future unless they are the second of 2 dates date_error = ( f"The date you chose ({field_value}) cannot not be in the future." @@ -125,7 +141,7 @@ def validate_and_update_model( errors = date_error date_valid = False else: - date_valid = True + print("date valid now") if date_valid: pass diff --git a/epilepsy12/view_folder/assessment_views.py b/epilepsy12/view_folder/assessment_views.py index 79459727..4449d2e9 100644 --- a/epilepsy12/view_folder/assessment_views.py +++ b/epilepsy12/view_folder/assessment_views.py @@ -89,6 +89,7 @@ def consultant_paediatrician_referral_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -98,6 +99,7 @@ def consultant_paediatrician_referral_date(request, assessment_id): page_element="date_field", comparison_date_field_name="consultant_paediatrician_input_date", is_earliest_date=True, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error @@ -143,6 +145,7 @@ def consultant_paediatrician_input_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -152,6 +155,7 @@ def consultant_paediatrician_input_date(request, assessment_id): page_element="date_field", comparison_date_field_name="consultant_paediatrician_referral_date", is_earliest_date=False, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error @@ -533,6 +537,7 @@ def paediatric_neurologist_referral_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -542,6 +547,7 @@ def paediatric_neurologist_referral_date(request, assessment_id): page_element="date_field", comparison_date_field_name="paediatric_neurologist_input_date", is_earliest_date=True, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error @@ -590,6 +596,7 @@ def paediatric_neurologist_input_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -599,6 +606,7 @@ def paediatric_neurologist_input_date(request, assessment_id): page_element="date_field", comparison_date_field_name="paediatric_neurologist_referral_date", is_earliest_date=False, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error @@ -1014,6 +1022,7 @@ def childrens_epilepsy_surgical_service_referral_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -1023,6 +1032,7 @@ def childrens_epilepsy_surgical_service_referral_date(request, assessment_id): page_element="date_field", comparison_date_field_name="childrens_epilepsy_surgical_service_input_date", is_earliest_date=True, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error @@ -1068,6 +1078,7 @@ def childrens_epilepsy_surgical_service_input_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -1077,6 +1088,7 @@ def childrens_epilepsy_surgical_service_input_date(request, assessment_id): page_element="date_field", comparison_date_field_name="childrens_epilepsy_surgical_service_referral_date", is_earliest_date=False, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error @@ -1422,6 +1434,7 @@ def epilepsy_specialist_nurse_referral_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -1431,6 +1444,7 @@ def epilepsy_specialist_nurse_referral_date(request, assessment_id): page_element="date_field", comparison_date_field_name="epilepsy_specialist_nurse_input_date", is_earliest_date=True, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error @@ -1463,6 +1477,7 @@ def epilepsy_specialist_nurse_input_date(request, assessment_id): """ try: + assessment = Assessment.objects.get(pk=assessment_id) error_message = None validate_and_update_model( request=request, @@ -1472,6 +1487,7 @@ def epilepsy_specialist_nurse_input_date(request, assessment_id): page_element="date_field", comparison_date_field_name="epilepsy_specialist_nurse_referral_date", is_earliest_date=False, + earliest_allowable_date=assessment.registration.registration_date, ) except ValueError as error: error_message = error diff --git a/epilepsy12/view_folder/investigation_views.py b/epilepsy12/view_folder/investigation_views.py index f07a2b32..ccd0139c 100644 --- a/epilepsy12/view_folder/investigation_views.py +++ b/epilepsy12/view_folder/investigation_views.py @@ -124,8 +124,8 @@ def eeg_request_date(request, investigations_id): It is triggered by a toggle in the partial generating a post request on change in the date field. This updates the model and returns the same partial. """ - try: + investigations = Investigations.objects.get(pk=investigations_id) error_message = None validate_and_update_model( request, @@ -135,6 +135,7 @@ def eeg_request_date(request, investigations_id): page_element="date_field", comparison_date_field_name="eeg_performed_date", is_earliest_date=True, + earliest_allowable_date=investigations.registration.registration_date, ) except ValueError as error: @@ -175,6 +176,7 @@ def eeg_performed_date(request, investigations_id): """ try: + investigations = Investigations.objects.get(pk=investigations_id) error_message = None validate_and_update_model( request, @@ -184,6 +186,7 @@ def eeg_performed_date(request, investigations_id): page_element="date_field", comparison_date_field_name="eeg_request_date", is_earliest_date=False, + earliest_allowable_date=investigations.registration.registration_date, ) except ValueError as errors: @@ -406,6 +409,7 @@ def mri_brain_requested_date(request, investigations_id): """ try: + investigations = Investigations.objects.get(pk=investigations_id) error_message = None validate_and_update_model( request, @@ -415,6 +419,7 @@ def mri_brain_requested_date(request, investigations_id): page_element="date_field", comparison_date_field_name="mri_brain_reported_date", is_earliest_date=True, + earliest_allowable_date=investigations.registration.registration_date, ) except ValueError as errors: @@ -456,6 +461,7 @@ def mri_brain_reported_date(request, investigations_id): """ try: + investigations = Investigations.objects.get(pk=investigations_id) error_message = None validate_and_update_model( request, @@ -465,6 +471,7 @@ def mri_brain_reported_date(request, investigations_id): page_element="date_field", comparison_date_field_name="mri_brain_requested_date", is_earliest_date=False, + earliest_allowable_date=investigations.registration.registration_date, ) except ValueError as errors: diff --git a/epilepsy12/view_folder/management_views.py b/epilepsy12/view_folder/management_views.py index 933e42f4..9810600b 100644 --- a/epilepsy12/view_folder/management_views.py +++ b/epilepsy12/view_folder/management_views.py @@ -429,6 +429,9 @@ def antiepilepsy_medicine_start_date(request, antiepilepsy_medicine_id): """ try: + antiepilepsy_medicine = AntiEpilepsyMedicine.objects.get( + pk=antiepilepsy_medicine_id + ) error_message = None validate_and_update_model( request=request, @@ -438,6 +441,7 @@ def antiepilepsy_medicine_start_date(request, antiepilepsy_medicine_id): page_element="date_field", comparison_date_field_name="antiepilepsy_medicine_stop_date", is_earliest_date=True, + earliest_allowable_date=antiepilepsy_medicine.management.registration.registration_date, ) except ValueError as error: error_message = error @@ -564,6 +568,9 @@ def antiepilepsy_medicine_stop_date(request, antiepilepsy_medicine_id): """ try: + antiepilepsy_medicine = AntiEpilepsyMedicine.objects.get( + pk=antiepilepsy_medicine_id + ) error_message = None validate_and_update_model( request=request, @@ -573,6 +580,7 @@ def antiepilepsy_medicine_stop_date(request, antiepilepsy_medicine_id): page_element="date_field", comparison_date_field_name="antiepilepsy_medicine_start_date", is_earliest_date=False, + earliest_allowable_date=antiepilepsy_medicine.management.registration.registration_date, ) except ValueError as error: error_message = error @@ -903,6 +911,7 @@ def individualised_care_plan_date(request, management_id): """ try: + management = Management.objects.get(pk=management_id) error_message = None validate_and_update_model( request=request, @@ -910,6 +919,7 @@ def individualised_care_plan_date(request, management_id): model_id=management_id, field_name="individualised_care_plan_date", page_element="date_field", + earliest_allowable_date=management.registration.registration_date, ) except ValueError as error: error_message = error diff --git a/epilepsy12/view_folder/multiaxial_diagnosis_views.py b/epilepsy12/view_folder/multiaxial_diagnosis_views.py index 5d9fbc32..5d0dad7e 100644 --- a/epilepsy12/view_folder/multiaxial_diagnosis_views.py +++ b/epilepsy12/view_folder/multiaxial_diagnosis_views.py @@ -372,6 +372,7 @@ def seizure_onset_date(request, episode_id): """ try: + episode = Episode.objects.get(pk=episode_id) error_message = None validate_and_update_model( request=request, @@ -379,6 +380,7 @@ def seizure_onset_date(request, episode_id): model_id=episode_id, field_name="seizure_onset_date", page_element="date_field", + earliest_allowable_date=None, # episodes may precede the first assessment date or cohort date ) except ValueError as error: error_message = error @@ -1645,6 +1647,7 @@ def comorbidity_diagnosis_date(request, comorbidity_id): """ try: + comorbidity = Comorbidity.objects.get(pk=comorbidity_id) error_message = None validate_and_update_model( request=request, @@ -1652,6 +1655,7 @@ def comorbidity_diagnosis_date(request, comorbidity_id): model_id=comorbidity_id, field_name="comorbidity_diagnosis_date", page_element="date_field", + earliest_allowable_date=comorbidity.multiaxial_diagnosis.registration.registration_date, ) except ValueError as error: error_message = error diff --git a/epilepsy12/view_folder/registration_views.py b/epilepsy12/view_folder/registration_views.py index 70381e51..cc697f4f 100644 --- a/epilepsy12/view_folder/registration_views.py +++ b/epilepsy12/view_folder/registration_views.py @@ -28,7 +28,10 @@ recalculate_form_generate_response, ) from ..decorator import user_may_view_this_child -from ..general_functions import construct_transfer_epilepsy12_site_email +from ..general_functions import ( + construct_transfer_epilepsy12_site_email, + get_current_cohort_data, +) @login_required @@ -615,6 +618,7 @@ def registration_date(request, case_id): Registration, field_name="registration_date", page_element="date_field", + earliest_allowable_date=get_current_cohort_data()["cohort_start_date"], ) except ValueError as error: diff --git a/epilepsy12/view_folder/syndrome_views.py b/epilepsy12/view_folder/syndrome_views.py index 35ecf20c..7d14f4ec 100644 --- a/epilepsy12/view_folder/syndrome_views.py +++ b/epilepsy12/view_folder/syndrome_views.py @@ -19,6 +19,7 @@ def syndrome_diagnosis_date(request, syndrome_id): """ try: + syndrome = Syndrome.objects.get(pk=syndrome_id) error_message = None validate_and_update_model( request=request, @@ -26,6 +27,7 @@ def syndrome_diagnosis_date(request, syndrome_id): model_id=syndrome_id, field_name="syndrome_diagnosis_date", page_element="date_field", + earliest_allowable_date=syndrome.multiaxial_diagnosis.registration.registration_date, ) except ValueError as error: error_message = error From f354f9c6f707a4d05fe2fe77a11cb2120edfb65f Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sat, 6 May 2023 21:12:57 +0100 Subject: [PATCH 08/10] fix seed dates update error messaging for dates --- .../validate_form_update_model.py | 41 +- .../general_functions/random_generator.py | 14 +- .../management/commands/create_e12_records.py | 496 +++++++++++------- epilepsy12/management/commands/seed.py | 12 +- .../investigations/eeg_information.html | 4 +- .../partials/page_elements/toggle_button.html | 4 +- 6 files changed, 339 insertions(+), 232 deletions(-) diff --git a/epilepsy12/common_view_functions/validate_form_update_model.py b/epilepsy12/common_view_functions/validate_form_update_model.py index 14366445..858c0686 100644 --- a/epilepsy12/common_view_functions/validate_form_update_model.py +++ b/epilepsy12/common_view_functions/validate_form_update_model.py @@ -90,63 +90,56 @@ def validate_and_update_model( # The later of the two dates CAN be in the future but cannot be earlier than the first if supplied. # If there is no comparison date (eg registration_date) the only stipulation is that it not be in the future. date_valid = None + date_error = "" if earliest_allowable_date: if field_value < earliest_allowable_date: # dates cannot be before the earliest allowable date (usually the first paediatric assessment or the cohort start date) date_error = f"The date you chose ({field_value}) cannot not be before {earliest_allowable_date}." - errors = date_error date_valid = False - if comparison_date_field_name: + if comparison_date_field_name and date_valid is None: instance = model.objects.get(pk=model_id) comparison_date = getattr(instance, comparison_date_field_name) if is_earliest_date: if comparison_date: date_valid = ( - field_value <= comparison_date - and field_value <= date.today() - and date_valid is None + field_value <= comparison_date and field_value <= date.today() ) if field_value > comparison_date: - date_error = f"The date you chose ({field_value}) cannot not be after {comparison_date}." + date_error = f"The date you chose ({field_value}) cannot be after {comparison_date}." if field_value > date.today(): date_error = f"You cannot choose a date in the future." - else: - date_valid = field_value <= date.today() and date_valid is None - date_error = f"The date you chose ({field_value}) cannot not be in the future." + date_valid = field_value <= date.today() + if not date_valid: + date_error = f"The date you chose ({field_value}) cannot be in the future." - if not date_valid: - errors = date_error else: if comparison_date: date_valid = ( - field_value >= comparison_date - and field_value <= date.today() - and date_valid is None + field_value >= comparison_date and field_value <= date.today() ) - date_error = f"The date you chose ({field_value}) cannot not be before {comparison_date} or in the future." + if field_value < comparison_date: + date_error = f"The date you chose ({field_value}) cannot be before {comparison_date}." + if field_value > date.today(): + date_error = ( + f"The date you chose ({field_value}) is in the future." + ) + print(f"{field_value} and {comparison_date}") else: # no other date supplied yet date_valid = True - if not date_valid: - errors = date_error elif field_value > date.today(): # dates cannot be in the future unless they are the second of 2 dates - date_error = ( - f"The date you chose ({field_value}) cannot not be in the future." - ) - errors = date_error + date_error = f"The date you chose ({field_value}) cannot be in the future." date_valid = False - else: - print("date valid now") if date_valid: pass else: - raise ValueError(errors) + raise ValueError(date_error) # update the model diff --git a/epilepsy12/general_functions/random_generator.py b/epilepsy12/general_functions/random_generator.py index a2047fdc..100c4221 100644 --- a/epilepsy12/general_functions/random_generator.py +++ b/epilepsy12/general_functions/random_generator.py @@ -1,14 +1,8 @@ from random import randrange -from datetime import timedelta +from datetime import timedelta, date -def random_date(start, end): - """ - This function will return a random datetime between two datetime - objects. - Thanks to Boris Verkihovsky (https://stackoverflow.com/questions/553303/generate-a-random-date-between-two-other-dates) - """ +def random_date(start: date, end: date): delta = end - start - int_delta = (delta.days * 24 * 60 * 60) + delta.seconds - random_second = randrange(int_delta) - return start + timedelta(seconds=random_second) + random_days = randrange(0, delta.days) + return start + timedelta(days=random_days) diff --git a/epilepsy12/management/commands/create_e12_records.py b/epilepsy12/management/commands/create_e12_records.py index 284faf2c..bee61c00 100644 --- a/epilepsy12/management/commands/create_e12_records.py +++ b/epilepsy12/management/commands/create_e12_records.py @@ -1,11 +1,64 @@ # python dependencies from random import randint, getrandbits from dateutil.relativedelta import relativedelta +from datetime import date # epilepsy12 dependencies -from ...models import FirstPaediatricAssessment, EpilepsyContext, MultiaxialDiagnosis, Syndrome, Episode, Keyword, Comorbidity, Assessment, Site, Organisation, Management, AntiEpilepsyMedicine, Case, AuditProgress, Registration, KPI, Investigations, SyndromeEntity, EpilepsyCauseEntity, ComorbidityEntity, MedicineEntity -from ...constants import OPT_OUT_UNCERTAIN, SYNDROMES, EPILEPSY_CAUSES, NEUROPSYCHIATRIC, DATE_ACCURACY, EPISODE_DEFINITION, EPILEPSY_DIAGNOSIS_STATUS, EPILEPSY_SEIZURE_TYPE, FOCAL_EPILEPSY_MOTOR_MANIFESTATIONS, FOCAL_EPILEPSY_NONMOTOR_MANIFESTATIONS, FOCAL_EPILEPSY_EEG_MANIFESTATIONS, LATERALITY, GENERALISED_SEIZURE_TYPE, NON_EPILEPSY_SEIZURE_ONSET, NON_EPILEPSY_SEIZURE_TYPE, NON_EPILEPSY_BEHAVIOURAL_ARREST_SYMPTOMS, MIGRAINES, EPIS_MISC, NON_EPILEPSY_SLEEP_RELATED_SYMPTOMS, NON_EPILEPTIC_SYNCOPES, NON_EPILEPSY_PAROXYSMS, ANTIEPILEPSY_MEDICINES, BENZODIAZEPINE_TYPES -from ...general_functions import random_date, current_cohort_start_date, first_tuesday_in_january, fetch_ecl, fetch_paediatric_neurodisability_outpatient_diagnosis_simple_reference_set +from ...models import ( + FirstPaediatricAssessment, + EpilepsyContext, + MultiaxialDiagnosis, + Syndrome, + Episode, + Keyword, + Comorbidity, + Assessment, + Site, + Organisation, + Management, + AntiEpilepsyMedicine, + Case, + AuditProgress, + Registration, + KPI, + Investigations, + SyndromeEntity, + EpilepsyCauseEntity, + ComorbidityEntity, + MedicineEntity, +) +from ...constants import ( + OPT_OUT_UNCERTAIN, + SYNDROMES, + EPILEPSY_CAUSES, + NEUROPSYCHIATRIC, + DATE_ACCURACY, + EPISODE_DEFINITION, + EPILEPSY_DIAGNOSIS_STATUS, + EPILEPSY_SEIZURE_TYPE, + FOCAL_EPILEPSY_MOTOR_MANIFESTATIONS, + FOCAL_EPILEPSY_NONMOTOR_MANIFESTATIONS, + FOCAL_EPILEPSY_EEG_MANIFESTATIONS, + LATERALITY, + GENERALISED_SEIZURE_TYPE, + NON_EPILEPSY_SEIZURE_ONSET, + NON_EPILEPSY_SEIZURE_TYPE, + NON_EPILEPSY_BEHAVIOURAL_ARREST_SYMPTOMS, + MIGRAINES, + EPIS_MISC, + NON_EPILEPSY_SLEEP_RELATED_SYMPTOMS, + NON_EPILEPTIC_SYNCOPES, + NON_EPILEPSY_PAROXYSMS, + ANTIEPILEPSY_MEDICINES, + BENZODIAZEPINE_TYPES, +) +from ...general_functions import ( + random_date, + current_cohort_start_date, + first_tuesday_in_january, + fetch_ecl, + fetch_paediatric_neurodisability_outpatient_diagnosis_simple_reference_set, +) from ...common_view_functions import test_fields_update_audit_progress, calculate_kpis @@ -14,7 +67,7 @@ def create_registrations(): run through all newly created cases and create registrations """ for case in Case.objects.all(): - if not hasattr(case, 'registration'): + if not hasattr(case, "registration"): # create a registration audit_progress = AuditProgress.objects.create( registration_complete=False, @@ -42,7 +95,7 @@ def create_registrations(): lead_organisation = Site.objects.filter( case=case, site_is_primary_centre_of_epilepsy_care=True, - site_is_actively_involved_in_epilepsy_care=True + site_is_actively_involved_in_epilepsy_care=True, ).get() kpi = KPI.objects.create( organisation=lead_organisation.organisation, @@ -67,12 +120,10 @@ def create_registrations(): general_participation_and_risk=0, service_contact_details=0, sudep=0, - school_individual_healthcare_plan=0 + school_individual_healthcare_plan=0, ) Registration.objects.create( - case=case, - audit_progress=audit_progress, - kpi=kpi + case=case, audit_progress=audit_progress, kpi=kpi ) else: print(f"{case} is registered already. Skipping") @@ -84,23 +135,24 @@ def create_epilepsy12_record(registration_instance): Creates a full randomised record for a given registration instance. """ # score registration_instance - test_fields_update_audit_progress( - model_instance=registration_instance) + test_fields_update_audit_progress(model_instance=registration_instance) # create random first paediatric assessment first_paediatric_assessment = create_first_paediatric_assessment( - registration_instance=registration_instance) - test_fields_update_audit_progress( - model_instance=first_paediatric_assessment) + registration_instance=registration_instance + ) + test_fields_update_audit_progress(model_instance=first_paediatric_assessment) # create random EpilepsyContext epilepsy_context = create_epilepsy_context( - registration_instance=registration_instance) + registration_instance=registration_instance + ) test_fields_update_audit_progress(model_instance=epilepsy_context) # create random Multiaxial Diagnosis multiaxial_diagnosis = create_multiaxial_diagnosis( - registration_instance=registration_instance) + registration_instance=registration_instance + ) test_fields_update_audit_progress(model_instance=multiaxial_diagnosis) # create random Assessment @@ -108,8 +160,7 @@ def create_epilepsy12_record(registration_instance): test_fields_update_audit_progress(model_instance=assessment) # create random Investigations - assessment = create_investigations( - registration_instance=registration_instance) + assessment = create_investigations(registration_instance=registration_instance) test_fields_update_audit_progress(model_instance=assessment) # create random Management @@ -124,21 +175,22 @@ def create_first_paediatric_assessment(registration_instance): """ Complete the first paediatric assessment aspect of the audit """ - if not hasattr(registration_instance, 'firstpaediatricassessment'): + if not hasattr(registration_instance, "firstpaediatricassessment"): return FirstPaediatricAssessment.objects.create( first_paediatric_assessment_in_acute_or_nonacute_setting=bool( - getrandbits(1)), - has_number_of_episodes_since_the_first_been_documented=bool( - getrandbits(1)), + getrandbits(1) + ), + has_number_of_episodes_since_the_first_been_documented=bool(getrandbits(1)), general_examination_performed=bool(getrandbits(1)), neurological_examination_performed=bool(getrandbits(1)), developmental_learning_or_schooling_problems=bool(getrandbits(1)), behavioural_or_emotional_problems=bool(getrandbits(1)), - registration=registration_instance + registration=registration_instance, ) else: print( - f'First Paediatric assessment exists for {registration_instance.case}. Skipping...') + f"First Paediatric assessment exists for {registration_instance.case}. Skipping..." + ) return registration_instance.firstpaediatricassessment @@ -146,182 +198,222 @@ def create_epilepsy_context(registration_instance): """ Complete the epilepsy_context aspect of the audit """ - if not hasattr(registration_instance, 'epilepsycontext'): + if not hasattr(registration_instance, "epilepsycontext"): return EpilepsyContext.objects.create( previous_febrile_seizure=OPT_OUT_UNCERTAIN[randint(0, 2)][0], - previous_acute_symptomatic_seizure=OPT_OUT_UNCERTAIN[randint( - 0, 2)][0], - is_there_a_family_history_of_epilepsy=OPT_OUT_UNCERTAIN[randint( - 0, 2)][0], + previous_acute_symptomatic_seizure=OPT_OUT_UNCERTAIN[randint(0, 2)][0], + is_there_a_family_history_of_epilepsy=OPT_OUT_UNCERTAIN[randint(0, 2)][0], previous_neonatal_seizures=OPT_OUT_UNCERTAIN[randint(0, 2)][0], diagnosis_of_epilepsy_withdrawn=bool(getrandbits(1)), were_any_of_the_epileptic_seizures_convulsive=bool(getrandbits(1)), - experienced_prolonged_generalized_convulsive_seizures=OPT_OUT_UNCERTAIN[randint( - 0, 2)][0], - experienced_prolonged_focal_seizures=OPT_OUT_UNCERTAIN[randint( - 0, 2)][0], - registration=registration_instance + experienced_prolonged_generalized_convulsive_seizures=OPT_OUT_UNCERTAIN[ + randint(0, 2) + ][0], + experienced_prolonged_focal_seizures=OPT_OUT_UNCERTAIN[randint(0, 2)][0], + registration=registration_instance, ) else: - print( - f'Epilepsy context exists for {registration_instance.case}. Skipping...') + print(f"Epilepsy context exists for {registration_instance.case}. Skipping...") return registration_instance.epilepsycontext def create_multiaxial_diagnosis(registration_instance): """ - Complete the multiaxial diagnosis aspect of the audit, including episodes, + Complete the multiaxial diagnosis aspect of the audit, including episodes, syndromes, causes and comorbidities """ - if not hasattr(registration_instance, 'multiaxialdiagnosis'): + if not hasattr(registration_instance, "multiaxialdiagnosis"): multiaxial_diagnosis = MultiaxialDiagnosis.objects.create( syndrome_present=bool(getrandbits(1)), epilepsy_cause_known=bool(getrandbits(1)), relevant_impairments_behavioural_educational=bool(getrandbits(1)), mental_health_screen=bool(getrandbits(1)), mental_health_issue_identified=bool(getrandbits(1)), - registration=registration_instance + registration=registration_instance, ) if multiaxial_diagnosis.syndrome_present: # create a related syndrome syndrome_entity = SyndromeEntity.objects.filter( - syndrome_name=SYNDROMES[randint(0, len(SYNDROMES) - 1)][1]).get() + syndrome_name=SYNDROMES[randint(0, len(SYNDROMES) - 1)][1] + ).get() Syndrome.objects.create( syndrome_diagnosis_date=random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date), + start=registration_instance.registration_date, end=date.today() + ), syndrome=syndrome_entity, - multiaxial_diagnosis=multiaxial_diagnosis + multiaxial_diagnosis=multiaxial_diagnosis, ) if multiaxial_diagnosis.epilepsy_cause_known: - ecl = '<< 363235000' + ecl = "<< 363235000" epilepsy_causes = fetch_ecl(ecl) random_cause = EpilepsyCauseEntity.objects.filter( - conceptId=epilepsy_causes[randint(0, len(epilepsy_causes) - 1)]['conceptId']).first() + conceptId=epilepsy_causes[randint(0, len(epilepsy_causes) - 1)][ + "conceptId" + ] + ).first() multiaxial_diagnosis.epilepsy_cause = random_cause total_cause_choices = len(EPILEPSY_CAUSES) random_number_of_choices = randint(1, total_cause_choices) choices = [] for choice in range(0, random_number_of_choices): - choices.append(EPILEPSY_CAUSES - [randint(0, len(EPILEPSY_CAUSES) - 1)][0]) + choices.append(EPILEPSY_CAUSES[randint(0, len(EPILEPSY_CAUSES) - 1)][0]) multiaxial_diagnosis.epilepsy_cause_categories = choices if multiaxial_diagnosis.mental_health_issue_identified: - multiaxial_diagnosis.mental_health_issue = NEUROPSYCHIATRIC[randint( - 0, len(NEUROPSYCHIATRIC) - 1)][0] + multiaxial_diagnosis.mental_health_issue = NEUROPSYCHIATRIC[ + randint(0, len(NEUROPSYCHIATRIC) - 1) + ][0] if multiaxial_diagnosis.relevant_impairments_behavioural_educational: # add upto 5 comorbidities for count_item in range(1, randint(1, 5)): - comorbidity_choices = fetch_paediatric_neurodisability_outpatient_diagnosis_simple_reference_set() - random_comorbidities = comorbidity_choices[randint( - 0, len(comorbidity_choices) - 1)] + comorbidity_choices = ( + fetch_paediatric_neurodisability_outpatient_diagnosis_simple_reference_set() + ) + random_comorbidities = comorbidity_choices[ + randint(0, len(comorbidity_choices) - 1) + ] random_comorbidity = ComorbidityEntity.objects.filter( - conceptId=random_comorbidities['conceptId']).first() + conceptId=random_comorbidities["conceptId"] + ).first() try: Comorbidity.objects.create( multiaxial_diagnosis=multiaxial_diagnosis, comorbidity_diagnosis_date=random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date), - comorbidityentity=random_comorbidity + start=registration_instance.registration_date, + end=date.today(), + ), + comorbidityentity=random_comorbidity, ) except Exception as e: - print( - f'Failed to create Comorbidity with {random_comorbidity}:{e=}') + f"Failed to create Comorbidity with {random_comorbidity}:{e=}" + ) # create a random number of episodes to a maximum of 5 for count_item in range(1, randint(1, 5)): current_cohort_end_date = first_tuesday_in_january( - current_cohort_start_date().year + 2) + relativedelta(days=7) + current_cohort_start_date().year + 2 + ) + relativedelta(days=7) episode = Episode.objects.create( multiaxial_diagnosis=multiaxial_diagnosis, seizure_onset_date=random_date( - start=registration_instance.registration_date, end=current_cohort_end_date), - seizure_onset_date_confidence=DATE_ACCURACY[randint( - 0, len(DATE_ACCURACY) - 1)][0], - episode_definition=EPISODE_DEFINITION[randint( - 0, len(EPISODE_DEFINITION) - 1)][0] + start=registration_instance.registration_date + - relativedelta(months=6), + end=date.today(), + ), + seizure_onset_date_confidence=DATE_ACCURACY[ + randint(0, len(DATE_ACCURACY) - 1) + ][0], + episode_definition=EPISODE_DEFINITION[ + randint(0, len(EPISODE_DEFINITION) - 1) + ][0], ) if count_item == 1: # the first episode must be epileptic, subsequent ones are random - episode.epilepsy_or_nonepilepsy_status = 'E' + episode.epilepsy_or_nonepilepsy_status = "E" else: - episode.epilepsy_or_nonepilepsy_status = EPILEPSY_DIAGNOSIS_STATUS[randint( - 0, len(EPILEPSY_DIAGNOSIS_STATUS) - 1)][0] + episode.epilepsy_or_nonepilepsy_status = EPILEPSY_DIAGNOSIS_STATUS[ + randint(0, len(EPILEPSY_DIAGNOSIS_STATUS) - 1) + ][0] episode.has_description_of_the_episode_or_episodes_been_gathered = bool( - getrandbits(1)) + getrandbits(1) + ) if episode.has_description_of_the_episode_or_episodes_been_gathered: keyword_array = [] activity_choices = ( - 'running', 'sleeping', 'on their way to school', 'watching YouTube', 'gaming') - description_string = f'{registration_instance.case} was ' + "running", + "sleeping", + "on their way to school", + "watching YouTube", + "gaming", + ) + description_string = f"{registration_instance.case} was " for random_number in range(randint(1, 5)): - random_keyword = Keyword.objects.order_by('?').first() + random_keyword = Keyword.objects.order_by("?").first() keyword_array.append(random_keyword) - description_string += f'{activity_choices[random_number]} when they developed ' + description_string += ( + f"{activity_choices[random_number]} when they developed " + ) for index, semiology_keyword in enumerate(keyword_array): if index == len(keyword_array) - 1: - description_string += f'and {semiology_keyword}.' + description_string += f"and {semiology_keyword}." else: - description_string += f'{semiology_keyword}, ' + description_string += f"{semiology_keyword}, " episode.description = description_string episode.description_keywords = keyword_array - if episode.epilepsy_or_nonepilepsy_status == 'E': - episode.epileptic_seizure_onset_type = EPILEPSY_SEIZURE_TYPE[randint( - 0, len(EPILEPSY_SEIZURE_TYPE) - 1)][0] + if episode.epilepsy_or_nonepilepsy_status == "E": + episode.epileptic_seizure_onset_type = EPILEPSY_SEIZURE_TYPE[ + randint(0, len(EPILEPSY_SEIZURE_TYPE) - 1) + ][0] - if episode.epileptic_seizure_onset_type == 'FO': + if episode.epileptic_seizure_onset_type == "FO": laterality = LATERALITY[randint(0, len(LATERALITY) - 1)] - motor_manifestation = FOCAL_EPILEPSY_MOTOR_MANIFESTATIONS[randint( - 0, len(FOCAL_EPILEPSY_MOTOR_MANIFESTATIONS) - 1)] - nonmotor_manifestation = FOCAL_EPILEPSY_NONMOTOR_MANIFESTATIONS[randint( - 0, len(FOCAL_EPILEPSY_NONMOTOR_MANIFESTATIONS) - 1)] - eeg_manifestations = FOCAL_EPILEPSY_EEG_MANIFESTATIONS[randint( - 0, len(FOCAL_EPILEPSY_EEG_MANIFESTATIONS) - 1)] - setattr(episode, laterality['name'], True) - setattr(episode, motor_manifestation['name'], True) - setattr(episode, nonmotor_manifestation['name'], True) - setattr(episode, eeg_manifestations['name'], True) - - elif episode.epileptic_seizure_onset_type == 'GO': - episode.epileptic_generalised_onset = GENERALISED_SEIZURE_TYPE[randint( - 0, len(GENERALISED_SEIZURE_TYPE) - 1)][0] - - elif episode.epilepsy_or_nonepilepsy_status == 'NE': - episode.nonepileptic_seizure_unknown_onset = NON_EPILEPSY_SEIZURE_ONSET[randint( - 0, len(NON_EPILEPSY_SEIZURE_ONSET) - 1)][0] - episode.nonepileptic_seizure_type = NON_EPILEPSY_SEIZURE_TYPE[randint( - 0, len(NON_EPILEPSY_SEIZURE_TYPE) - 1)][0] - - if episode.nonepileptic_seizure_type == 'BPP': - episode.nonepileptic_seizure_behavioural = NON_EPILEPSY_BEHAVIOURAL_ARREST_SYMPTOMS[len( - NON_EPILEPSY_BEHAVIOURAL_ARREST_SYMPTOMS) - 1][0] - elif episode.nonepileptic_seizure_type == 'MAD': - episode.nonepileptic_seizure_migraine = MIGRAINES[len( - MIGRAINES) - 1][0] - elif episode.nonepileptic_seizure_type == 'ME': - episode.nonepileptic_seizure_miscellaneous = EPIS_MISC[len( - EPIS_MISC) - 1][0] - elif episode.nonepileptic_seizure_type == 'SRC': - episode.nonepileptic_seizure_sleep = NON_EPILEPSY_SLEEP_RELATED_SYMPTOMS[len( - NON_EPILEPSY_SLEEP_RELATED_SYMPTOMS) - 1][0] - elif episode.nonepileptic_seizure_type == 'SAS': - episode.nonepileptic_seizure_syncope = NON_EPILEPTIC_SYNCOPES[len( - NON_EPILEPTIC_SYNCOPES) - 1][0] - elif episode.nonepileptic_seizure_type == 'PMD': - episode.nonepileptic_seizure_paroxysmal = NON_EPILEPSY_PAROXYSMS[len( - NON_EPILEPSY_PAROXYSMS) - 1][0] + motor_manifestation = FOCAL_EPILEPSY_MOTOR_MANIFESTATIONS[ + randint(0, len(FOCAL_EPILEPSY_MOTOR_MANIFESTATIONS) - 1) + ] + nonmotor_manifestation = FOCAL_EPILEPSY_NONMOTOR_MANIFESTATIONS[ + randint(0, len(FOCAL_EPILEPSY_NONMOTOR_MANIFESTATIONS) - 1) + ] + eeg_manifestations = FOCAL_EPILEPSY_EEG_MANIFESTATIONS[ + randint(0, len(FOCAL_EPILEPSY_EEG_MANIFESTATIONS) - 1) + ] + setattr(episode, laterality["name"], True) + setattr(episode, motor_manifestation["name"], True) + setattr(episode, nonmotor_manifestation["name"], True) + setattr(episode, eeg_manifestations["name"], True) + + elif episode.epileptic_seizure_onset_type == "GO": + episode.epileptic_generalised_onset = GENERALISED_SEIZURE_TYPE[ + randint(0, len(GENERALISED_SEIZURE_TYPE) - 1) + ][0] + + elif episode.epilepsy_or_nonepilepsy_status == "NE": + episode.nonepileptic_seizure_unknown_onset = NON_EPILEPSY_SEIZURE_ONSET[ + randint(0, len(NON_EPILEPSY_SEIZURE_ONSET) - 1) + ][0] + episode.nonepileptic_seizure_type = NON_EPILEPSY_SEIZURE_TYPE[ + randint(0, len(NON_EPILEPSY_SEIZURE_TYPE) - 1) + ][0] + + if episode.nonepileptic_seizure_type == "BPP": + episode.nonepileptic_seizure_behavioural = ( + NON_EPILEPSY_BEHAVIOURAL_ARREST_SYMPTOMS[ + len(NON_EPILEPSY_BEHAVIOURAL_ARREST_SYMPTOMS) - 1 + ][0] + ) + elif episode.nonepileptic_seizure_type == "MAD": + episode.nonepileptic_seizure_migraine = MIGRAINES[ + len(MIGRAINES) - 1 + ][0] + elif episode.nonepileptic_seizure_type == "ME": + episode.nonepileptic_seizure_miscellaneous = EPIS_MISC[ + len(EPIS_MISC) - 1 + ][0] + elif episode.nonepileptic_seizure_type == "SRC": + episode.nonepileptic_seizure_sleep = ( + NON_EPILEPSY_SLEEP_RELATED_SYMPTOMS[ + len(NON_EPILEPSY_SLEEP_RELATED_SYMPTOMS) - 1 + ][0] + ) + elif episode.nonepileptic_seizure_type == "SAS": + episode.nonepileptic_seizure_syncope = NON_EPILEPTIC_SYNCOPES[ + len(NON_EPILEPTIC_SYNCOPES) - 1 + ][0] + elif episode.nonepileptic_seizure_type == "PMD": + episode.nonepileptic_seizure_paroxysmal = NON_EPILEPSY_PAROXYSMS[ + len(NON_EPILEPSY_PAROXYSMS) - 1 + ][0] else: pass @@ -331,41 +423,45 @@ def create_multiaxial_diagnosis(registration_instance): return multiaxial_diagnosis else: print( - f'Multiaxial diagnosis exists for {registration_instance.case}. Skipping...') + f"Multiaxial diagnosis exists for {registration_instance.case}. Skipping..." + ) return registration_instance.multiaxialdiagnosis def create_assessment(registration_instance): """ - Complete the assessment aspect of the audit, including specialist sites, + Complete the assessment aspect of the audit, including specialist sites, """ - if not hasattr(registration_instance, 'assessment'): + if not hasattr(registration_instance, "assessment"): assessment = Assessment.objects.create( childrens_epilepsy_surgical_service_referral_criteria_met=bool( - getrandbits(1)), + getrandbits(1) + ), consultant_paediatrician_referral_made=bool(getrandbits(1)), paediatric_neurologist_referral_made=bool(getrandbits(1)), - childrens_epilepsy_surgical_service_referral_made=bool( - getrandbits(1)), + childrens_epilepsy_surgical_service_referral_made=bool(getrandbits(1)), epilepsy_specialist_nurse_referral_made=bool(getrandbits(1)), - registration=registration_instance + registration=registration_instance, ) if assessment.consultant_paediatrician_referral_made: assessment.consultant_paediatrician_referral_date = random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date) - assessment.consultant_paediatrician_input_date = assessment.consultant_paediatrician_referral_date + \ - relativedelta(weeks=randint(1, 5)) + start=registration_instance.registration_date, end=date.today() + ) + assessment.consultant_paediatrician_input_date = ( + assessment.consultant_paediatrician_referral_date + + relativedelta(weeks=randint(1, 5)) + ) random_organisation = Organisation.objects.order_by("?").first() if Site.objects.filter( site_is_actively_involved_in_epilepsy_care=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ).exists(): site = Site.objects.filter( site_is_actively_involved_in_epilepsy_care=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ).get() site.site_is_general_paediatric_centre = True site.save() @@ -374,24 +470,27 @@ def create_assessment(registration_instance): site_is_actively_involved_in_epilepsy_care=True, site_is_general_paediatric_centre=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ) if assessment.paediatric_neurologist_referral_made: assessment.paediatric_neurologist_referral_date = random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date) - assessment.paediatric_neurologist_input_date = assessment.paediatric_neurologist_referral_date + \ - relativedelta(weeks=randint(1, 5)) + start=registration_instance.registration_date, end=date.today() + ) + assessment.paediatric_neurologist_input_date = ( + assessment.paediatric_neurologist_referral_date + + relativedelta(weeks=randint(1, 5)) + ) random_organisation = Organisation.objects.order_by("?").first() if Site.objects.filter( site_is_actively_involved_in_epilepsy_care=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ).exists(): site = Site.objects.filter( site_is_actively_involved_in_epilepsy_care=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ).get() site.site_is_general_paediatric_centre = True site.save() @@ -400,24 +499,27 @@ def create_assessment(registration_instance): site_is_actively_involved_in_epilepsy_care=True, site_is_paediatric_neurology_centre=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ) if assessment.childrens_epilepsy_surgical_service_referral_made: assessment.childrens_epilepsy_surgical_service_referral_date = random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date) - assessment.childrens_epilepsy_surgical_service_input_date = assessment.childrens_epilepsy_surgical_service_referral_date + \ - relativedelta(weeks=randint(1, 5)) + start=registration_instance.registration_date, end=date.today() + ) + assessment.childrens_epilepsy_surgical_service_input_date = ( + assessment.childrens_epilepsy_surgical_service_referral_date + + relativedelta(weeks=randint(1, 5)) + ) random_organisation = Organisation.objects.order_by("?").first() if Site.objects.filter( site_is_actively_involved_in_epilepsy_care=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ).exists(): site = Site.objects.filter( site_is_actively_involved_in_epilepsy_care=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ).get() site.site_is_general_paediatric_centre = True site.save() @@ -426,20 +528,22 @@ def create_assessment(registration_instance): site_is_actively_involved_in_epilepsy_care=True, site_is_childrens_epilepsy_surgery_centre=True, case=registration_instance.case, - organisation=random_organisation + organisation=random_organisation, ) if assessment.epilepsy_specialist_nurse_referral_made: assessment.epilepsy_specialist_nurse_referral_date = random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date) - assessment.epilepsy_specialist_nurse_input_date = assessment.epilepsy_specialist_nurse_referral_date + \ - relativedelta(weeks=randint(1, 12)) + start=registration_instance.registration_date, end=date.today() + ) + assessment.epilepsy_specialist_nurse_input_date = ( + assessment.epilepsy_specialist_nurse_referral_date + + relativedelta(weeks=randint(1, 12)) + ) assessment.save() return assessment else: - print( - f'Assessment exists for {registration_instance.case}. Skipping...') + print(f"Assessment exists for {registration_instance.case}. Skipping...") return registration_instance.assessment @@ -447,29 +551,33 @@ def create_investigations(registration_instance): """ Complete the investigations aspect of the audit, including medications """ - if not hasattr(registration_instance, 'investigations'): + if not hasattr(registration_instance, "investigations"): investigations = Investigations.objects.create( eeg_indicated=bool(getrandbits(1)), twelve_lead_ecg_status=bool(getrandbits(1)), ct_head_scan_status=bool(getrandbits(1)), mri_indicated=bool(getrandbits(1)), - registration=registration_instance + registration=registration_instance, ) if investigations.eeg_indicated: investigations.eeg_request_date = random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date) - investigations.eeg_performed_date = investigations.eeg_request_date + \ - relativedelta(weeks=randint(1, 5)) + start=registration_instance.registration_date, end=date.today() + ) + investigations.eeg_performed_date = ( + investigations.eeg_request_date + relativedelta(weeks=randint(1, 5)) + ) if investigations.mri_indicated: investigations.mri_brain_requested_date = random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date) - investigations.mri_brain_reported_date = investigations.mri_brain_requested_date + \ - relativedelta(weeks=randint(1, 5)) + start=registration_instance.registration_date, end=date.today() + ) + investigations.mri_brain_reported_date = ( + investigations.mri_brain_requested_date + + relativedelta(weeks=randint(1, 5)) + ) investigations.save() return investigations else: - print( - f'Investigations exist for {registration_instance.case}. Skipping...') + print(f"Investigations exist for {registration_instance.case}. Skipping...") return registration_instance.investigations @@ -477,7 +585,7 @@ def create_management(registration_instance): """ Complete the management aspect of the audit, including medications """ - if not hasattr(registration_instance, 'management'): + if not hasattr(registration_instance, "management"): management = Management.objects.create( registration=registration_instance, has_an_aed_been_given=bool(getrandbits(1)), @@ -488,67 +596,83 @@ def create_management(registration_instance): if management.has_an_aed_been_given: for count_item in range(1, randint(1, 3)): # add a random number of medicines up to a total of 3 - random_medicine = MedicineEntity.objects.filter( - is_rescue=False).order_by("?").first() + random_medicine = ( + MedicineEntity.objects.filter(is_rescue=False).order_by("?").first() + ) antiepilepsy_medicine = AntiEpilepsyMedicine.objects.create( management=management, is_rescue_medicine=False, antiepilepsy_medicine_start_date=random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date), + start=registration_instance.registration_date, end=date.today() + ), antiepilepsy_medicine_risk_discussed=bool(getrandbits(1)), - medicine_entity=random_medicine + medicine_entity=random_medicine, ) - if registration_instance.case.sex == 2 and hasattr(antiepilepsy_medicine, 'medicine_entity'): - if hasattr(antiepilepsy_medicine, 'medicine_entity') and antiepilepsy_medicine.medicine_entity is not None: - if antiepilepsy_medicine.medicine_entity.medicine_name == "Sodium valproate": + if registration_instance.case.sex == 2 and hasattr( + antiepilepsy_medicine, "medicine_entity" + ): + if ( + hasattr(antiepilepsy_medicine, "medicine_entity") + and antiepilepsy_medicine.medicine_entity is not None + ): + if ( + antiepilepsy_medicine.medicine_entity.medicine_name + == "Sodium valproate" + ): antiepilepsy_medicine.is_a_pregnancy_prevention_programme_needed = bool( - getrandbits(1)) + getrandbits(1) + ) antiepilepsy_medicine.has_a_valproate_annual_risk_acknowledgement_form_been_completed antiepilepsy_medicine.is_a_pregnancy_prevention_programme_in_place = bool( - getrandbits(1)) + getrandbits(1) + ) antiepilepsy_medicine.save() if management.has_rescue_medication_been_prescribed: for count_item in range(1, randint(1, 3)): # add a random number of medicines up to a total of 3 - random_medicine = MedicineEntity.objects.filter( - is_rescue=True).order_by("?").first() + random_medicine = ( + MedicineEntity.objects.filter(is_rescue=True).order_by("?").first() + ) AntiEpilepsyMedicine.objects.create( management=management, is_rescue_medicine=True, antiepilepsy_medicine_start_date=random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date), + start=registration_instance.registration_date, end=date.today() + ), antiepilepsy_medicine_risk_discussed=bool(getrandbits(1)), - medicine_entity=random_medicine + medicine_entity=random_medicine, ) else: - print( - f'Management exists for {registration_instance.case}. Skipping...') + print(f"Management exists for {registration_instance.case}. Skipping...") return registration_instance.management if management.individualised_care_plan_in_place: management.individualised_care_plan_date = random_date( - start=registration_instance.registration_date, end=registration_instance.registration_close_date) + start=registration_instance.registration_date, end=date.today() + ) management.individualised_care_plan_has_parent_carer_child_agreement = bool( - getrandbits(1)) + getrandbits(1) + ) management.individualised_care_plan_includes_service_contact_details = bool( - getrandbits(1)) - management.individualised_care_plan_include_first_aid = bool( - getrandbits(1)) + getrandbits(1) + ) + management.individualised_care_plan_include_first_aid = bool(getrandbits(1)) management.individualised_care_plan_parental_prolonged_seizure_care = bool( - getrandbits(1)) + getrandbits(1) + ) management.individualised_care_plan_includes_general_participation_risk = bool( - getrandbits(1)) + getrandbits(1) + ) management.individualised_care_plan_addresses_water_safety = bool( - getrandbits(1)) - management.individualised_care_plan_addresses_sudep = bool( - getrandbits(1)) - management.individualised_care_plan_includes_ehcp = bool( - getrandbits(1)) + getrandbits(1) + ) + management.individualised_care_plan_addresses_sudep = bool(getrandbits(1)) + management.individualised_care_plan_includes_ehcp = bool(getrandbits(1)) management.has_individualised_care_plan_been_updated_in_the_last_year = bool( - getrandbits(1)) - management.has_been_referred_for_mental_health_support = bool( - getrandbits(1)) + getrandbits(1) + ) + management.has_been_referred_for_mental_health_support = bool(getrandbits(1)) management.has_support_for_mental_health_support = bool(getrandbits(1)) management.save() diff --git a/epilepsy12/management/commands/seed.py b/epilepsy12/management/commands/seed.py index 75b70dae..e2422243 100644 --- a/epilepsy12/management/commands/seed.py +++ b/epilepsy12/management/commands/seed.py @@ -1,12 +1,10 @@ # python -from operator import itemgetter from random import randint, choice -from datetime import datetime, date +from datetime import date from dateutil.relativedelta import relativedelta from random import randint -from django.utils import timezone from django.core.management.base import BaseCommand -from django.contrib.gis.geos import Point +from ...general_functions import get_current_cohort_data from ...constants import ( @@ -200,12 +198,10 @@ def complete_registrations(): "Completing all the Epilepsy12 fields for the fictional cases...", "\033[33m", ) + current_cohort = get_current_cohort_data() for registration in Registration.objects.all(): - current_cohort_end_date = first_tuesday_in_january( - current_cohort_start_date().year + 2 - ) + relativedelta(days=7) registration.registration_date = random_date( - start=current_cohort_start_date(), end=current_cohort_end_date + start=current_cohort["cohort_start_date"], end=date.today() ) registration.eligibility_criteria_met = True registration.save() diff --git a/templates/epilepsy12/partials/investigations/eeg_information.html b/templates/epilepsy12/partials/investigations/eeg_information.html index 8767fcd8..90f51da4 100644 --- a/templates/epilepsy12/partials/investigations/eeg_information.html +++ b/templates/epilepsy12/partials/investigations/eeg_information.html @@ -15,7 +15,7 @@
{% url 'eeg_request_date' investigations_id=investigations.pk as hx_post %} - {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_request_date label=investigations.get_eeg_request_date_help_label_text reference=investigations.get_eeg_request_date_help_reference_text data_position="top left" input_date_field_name='eeg_request_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} + {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_request_date label=investigations.get_eeg_request_date_help_label_text reference=investigations.get_eeg_request_date_help_reference_text data_position="top left" input_date_field_name='eeg_request_date' enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} {% if eeg_declined %}
@@ -48,7 +48,7 @@ {% else %} {% url 'eeg_performed_date' investigations_id=investigations.pk as hx_post %} - {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_performed_date label=investigations.get_eeg_performed_date_help_label_text reference=investigations.get_eeg_performed_date_help_reference_text data_position="top left" input_date_field_name='eeg_performed_date' error_messages=error_messages enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} + {% include 'epilepsy12/partials/page_elements/date_field.html' with hx_post=hx_post hx_target="#eeg_information" hx_trigger="change delay:1s" hx_swap="innerHTML" date_value=investigations.eeg_performed_date label=investigations.get_eeg_performed_date_help_label_text reference=investigations.get_eeg_performed_date_help_reference_text data_position="top left" input_date_field_name='eeg_performed_date' enabled=perms.epilepsy12.change_investigations has_permission=perms.epilepsy12.change_investigations %} {% if investigations.eeg_request_date and investigations.eeg_performed_date %}
diff --git a/templates/epilepsy12/partials/page_elements/toggle_button.html b/templates/epilepsy12/partials/page_elements/toggle_button.html index 0b6ea05b..693a365e 100644 --- a/templates/epilepsy12/partials/page_elements/toggle_button.html +++ b/templates/epilepsy12/partials/page_elements/toggle_button.html @@ -139,11 +139,11 @@
{% endif %} - {% if error_message %} +
{% if not enabled %} You do not have permission to update this field From 17d9b9a9d0cef1f7de824e352144a0a4e9538b17 Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sun, 7 May 2023 12:37:01 +0100 Subject: [PATCH 09/10] Public facing kpi charts Fixes #462 --- epilepsy12/urls.py | 11 ++- epilepsy12/view_folder/organisation_views.py | 96 +++++++++++++++++++- epilepsy12/views.py | 38 +++++++- templates/epilepsy12/epilepsy12index.html | 3 +- templates/epilepsy12/nav.html | 4 +- templates/epilepsy12/open_access.html | 24 +++++ templates/epilepsy12/patient.html | 7 -- 7 files changed, 164 insertions(+), 19 deletions(-) create mode 100644 templates/epilepsy12/open_access.html delete mode 100644 templates/epilepsy12/patient.html diff --git a/epilepsy12/urls.py b/epilepsy12/urls.py index 5ba21be8..6b5fe3ad 100644 --- a/epilepsy12/urls.py +++ b/epilepsy12/urls.py @@ -102,6 +102,11 @@ views.selected_trust_kpis, name="selected_trust_kpis", ), + path( + "selected_trust//kpis/open", + views.selected_trust_kpis_open, + name="selected_trust_kpis_open", + ), path( "selected_trust_kpis//select_kpi", views.selected_trust_select_kpi, @@ -131,7 +136,11 @@ path("epilepsy_context/", epilepsy_context, name="epilepsy_context"), path("management/", management, name="management"), path("docs", views.documentation, name="docs"), - path("patient", views.patient, name="patient"), + path( + "organisation//open_access", + views.open_access, + name="open_access", + ), path("investigations/", investigations, name="investigations"), path( "organisation//epilepsy12_user_list/", diff --git a/epilepsy12/view_folder/organisation_views.py b/epilepsy12/view_folder/organisation_views.py index ae8c456e..4326fa81 100644 --- a/epilepsy12/view_folder/organisation_views.py +++ b/epilepsy12/view_folder/organisation_views.py @@ -111,8 +111,8 @@ def organisation_reports(request): ) else: total_percent_trust = 0 - - org_list=Organisation.objects.order_by('OrganisationName').all() + + org_list = Organisation.objects.order_by("OrganisationName").all() return render( request=request, @@ -240,8 +240,6 @@ def selected_organisation_summary(request): ) else: total_percent_trust = 0 - - return render( request=request, @@ -372,6 +370,96 @@ def selected_trust_kpis(request, organisation_id): return response +def selected_trust_kpis_open(request, organisation_id): + """ + Open access endpoint for KPIs table + """ + + # + organisation = Organisation.objects.get(pk=organisation_id) + cohort_data = get_current_cohort_data() + organisation_level = all_registered_cases_for_cohort_and_abstraction_level( + organisation_instance=organisation, + cohort=cohort_data["cohort"], + case_complete=True, + abstraction_level="organisation", + ) + trust_level = all_registered_cases_for_cohort_and_abstraction_level( + organisation_instance=organisation, + cohort=cohort_data["cohort"], + case_complete=True, + abstraction_level="trust", + ) + icb_level = all_registered_cases_for_cohort_and_abstraction_level( + organisation_instance=organisation, + cohort=cohort_data["cohort"], + case_complete=True, + abstraction_level="icb", + ) + nhs_level = all_registered_cases_for_cohort_and_abstraction_level( + organisation_instance=organisation, + cohort=cohort_data["cohort"], + case_complete=True, + abstraction_level="nhs_region", + ) + open_uk_level = all_registered_cases_for_cohort_and_abstraction_level( + organisation_instance=organisation, + cohort=cohort_data["cohort"], + case_complete=True, + abstraction_level="open_uk", + ) + country_level = all_registered_cases_for_cohort_and_abstraction_level( + organisation_instance=organisation, + cohort=cohort_data["cohort"], + case_complete=True, + abstraction_level="country", + ) + national_level = all_registered_cases_for_cohort_and_abstraction_level( + organisation_instance=organisation, + cohort=cohort_data["cohort"], + case_complete=True, + abstraction_level="national", + ) + + # aggregate at each level of abstraction + organisation_kpis = aggregate_all_eligible_kpi_fields(organisation_level) + trust_kpis = aggregate_all_eligible_kpi_fields(trust_level) + icb_kpis = aggregate_all_eligible_kpi_fields(icb_level) + nhs_kpis = aggregate_all_eligible_kpi_fields(nhs_level) + open_uk_kpis = aggregate_all_eligible_kpi_fields(open_uk_level) + country_kpis = aggregate_all_eligible_kpi_fields(country_level) + national_kpis = aggregate_all_eligible_kpi_fields(national_level) + + # create an empty instance of KPI model to access the labels - this is a bit of a hack but works and + # and has very little overhead + organisation = Organisation.objects.get(pk=organisation_id) + kpis = KPI.objects.create( + organisation=organisation, + parent_trust=organisation.ParentOrganisation_OrganisationName, + ) + + template_name = "epilepsy12/partials/kpis/kpis.html" + context = { + "organisation": organisation, + "organisation_kpis": organisation_kpis, + "trust_kpis": trust_kpis, + "icb_kpis": icb_kpis, + "nhs_kpis": nhs_kpis, + "open_uk_kpis": open_uk_kpis, + "country_kpis": country_kpis, + "national_kpis": national_kpis, + "kpis": kpis, + "organisation_list": Organisation.objects.all().order_by("OrganisationName"), + } + + # remove the temporary instance as otherwise would contribute to totals + kpis.delete() + + response = render(request=request, template_name=template_name, context=context) + + return response + + @login_required @user_may_view_this_organisation() def child_organisation_select(request, organisation_id, template_name): diff --git a/epilepsy12/views.py b/epilepsy12/views.py index bbd3e4f8..853971b6 100644 --- a/epilepsy12/views.py +++ b/epilepsy12/views.py @@ -36,6 +36,9 @@ def epilepsy12_login(request): + """ + Callback from the login form + """ if request.method == "POST": form = Epilepsy12LoginForm(request, data=request.POST) @@ -87,8 +90,15 @@ def epilepsy12_login(request): def index(request): + """ + This is the landing page for all site visitors. Any navigation on from here requires the user to login, + except the children and families page which requires an organisation id to filter against. An organisation is chosen + here at random, but in future might be chosen based on the location of the visitor's ISP. + """ + random_organisation = Organisation.objects.order_by("?").first() template_name = "epilepsy12/epilepsy12index.html" - return render(request, template_name, {}) + context = {"organisation": random_organisation} + return render(request=request, template_name=template_name, context=context) def database(request): @@ -136,12 +146,24 @@ def log_list(request, organisation_id, epilepsy12_user_id): return render(request=request, template_name=template_name, context=context) -def patient(request): - template_name = "epilepsy12/patient.html" - return render(request, template_name, {}) +def open_access(request, organisation_id): + """ + Landing page for children and families - takes an organisation_id to present + the KPI table for that organisation, as well as load the dropdown with all organisations. + """ + template_name = "epilepsy12/open_access.html" + organisation = Organisation.objects.get(pk=organisation_id) + context = { + "organisation": organisation, + "organisation_list": Organisation.objects.all().order_by("OrganisationName"), + } + return render(request, template_name, context=context) def documentation(request): + """ + Deprecated - docs are now hosted elsewhere + """ template_name = "epilepsy12/docs.html" return render(request, template_name, {}) @@ -474,6 +496,10 @@ def download(request, model_name): def return_choice_for_instance_and_value(model, field, choice_value): + """ + Helper function when cleaning the data for downloadable csv files of the different models, + accessed via the Frida button. + """ query_object = {field: choice_value} temp_instance = model(**query_object) choice = getattr(temp_instance, "get_{}_display".format(field))() @@ -503,19 +529,21 @@ def rcpch_403(request, exception): def redirect_403(request): - # return the custom 403 template. There is not context to add. + # return the custom 403 template. There is no context to add. return render( request, template_name="epilepsy12/error_pages/rcpch_403.html", context={} ) def rcpch_404(request, exception): + # return the custom 404 template. There is no context to add. return render( request, template_name="epilepsy12/error_pages/rcpch_404.html", context={} ) def rcpch_500(request): + # return the custom 500 template. There is no context to add. return render( request, template_name="epilepsy12/error_pages/rcpch_500.html", status=500 ) diff --git a/templates/epilepsy12/epilepsy12index.html b/templates/epilepsy12/epilepsy12index.html index d8ae4979..a00b5778 100644 --- a/templates/epilepsy12/epilepsy12index.html +++ b/templates/epilepsy12/epilepsy12index.html @@ -69,7 +69,8 @@

Patient access

THIS WILL BE ACCESS FOR PUBLIC FACING REPORTS

- Select diff --git a/templates/epilepsy12/nav.html b/templates/epilepsy12/nav.html index 26523ff2..1daf11f0 100644 --- a/templates/epilepsy12/nav.html +++ b/templates/epilepsy12/nav.html @@ -46,7 +46,9 @@

Epilepsy12 audit platform

{% if request.user|has_group:"patient_access" %} + + href="{% url 'open_access' %}" + > Patient access {% endif %} diff --git a/templates/epilepsy12/open_access.html b/templates/epilepsy12/open_access.html new file mode 100644 index 00000000..2e01407d --- /dev/null +++ b/templates/epilepsy12/open_access.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} +{% load static %} +{% block content %} +
+ + {% url 'open_access' organisation_id=organisation.pk as hx_post %} + {% include 'epilepsy12/partials/page_elements/rcpch_organisations_select.html' with organisation_list=organisation_list test_positive=organisation.pk hx_post=hx_post hx_name="selected_trust_kpis_open" hx_target="#organisation_summary" %} + +
+ This represents all the Key Performance Indicators for the selected hospital +
+ + +
+ +
+
+{% endblock %} \ No newline at end of file diff --git a/templates/epilepsy12/patient.html b/templates/epilepsy12/patient.html deleted file mode 100644 index ea4a585d..00000000 --- a/templates/epilepsy12/patient.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "base.html" %} -{% load static %} -{% block content %} -
-

Patient route

-
-{% endblock %} \ No newline at end of file From 92afd205177c534a319ca20e758597d7e6d858ea Mon Sep 17 00:00:00 2001 From: Simon Chapman Date: Sun, 7 May 2023 13:04:57 +0100 Subject: [PATCH 10/10] fix report_queries to for ICBs in Wales return no filter add trust name to complete returns progress dial remove refresh button for open_access KPIs --- .../common_view_functions/report_queries.py | 42 ++++++++++++------- epilepsy12/view_folder/organisation_views.py | 4 +- templates/epilepsy12/partials/kpis/kpis.html | 9 +++- .../selected_organisation_summary.html | 2 +- 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/epilepsy12/common_view_functions/report_queries.py b/epilepsy12/common_view_functions/report_queries.py index 315a72d5..c5ca980d 100644 --- a/epilepsy12/common_view_functions/report_queries.py +++ b/epilepsy12/common_view_functions/report_queries.py @@ -71,24 +71,36 @@ def all_registered_cases_for_cohort_and_abstraction_level( & Q(site__site_is_primary_centre_of_epilepsy_care=True) ) elif abstraction_level == "icb": - q_filter = ( - Q( - site__organisation__integrated_care_board__ODS_ICB_Code=organisation_instance.integrated_care_board.ODS_ICB_Code + if organisation_instance.integrated_care_board is not None: + """ + Wales has no ICBs + """ + q_filter = ( + Q( + site__organisation__integrated_care_board__ODS_ICB_Code=organisation_instance.integrated_care_board.ODS_ICB_Code + ) + & Q(site__site_is_actively_involved_in_epilepsy_care=True) + & Q(site__site_is_primary_centre_of_epilepsy_care=True) ) - & Q(site__site_is_actively_involved_in_epilepsy_care=True) - & Q(site__site_is_primary_centre_of_epilepsy_care=True) - ) + else: + return all_cases_for_cohort elif abstraction_level == "nhs_region": - q_filter = ( - Q( - site__organisation__nhs_region__NHS_Region_Code=organisation_instance.nhs_region.NHS_Region_Code - ) - & Q( - site__organisation__ons_region__ons_country__Country_ONS_Name=organisation_instance.ons_region.ons_country.Country_ONS_Name + """ + Wales has no NHS regions + """ + if organisation_instance.nhs_region is not None: + q_filter = ( + Q( + site__organisation__nhs_region__NHS_Region_Code=organisation_instance.nhs_region.NHS_Region_Code + ) + & Q( + site__organisation__ons_region__ons_country__Country_ONS_Name=organisation_instance.ons_region.ons_country.Country_ONS_Name + ) + & Q(site__site_is_actively_involved_in_epilepsy_care=True) + & Q(site__site_is_primary_centre_of_epilepsy_care=True) ) - & Q(site__site_is_actively_involved_in_epilepsy_care=True) - & Q(site__site_is_primary_centre_of_epilepsy_care=True) - ) + else: + return all_cases_for_cohort elif abstraction_level == "open_uk": q_filter = ( Q( diff --git a/epilepsy12/view_folder/organisation_views.py b/epilepsy12/view_folder/organisation_views.py index 4326fa81..ad6a15a2 100644 --- a/epilepsy12/view_folder/organisation_views.py +++ b/epilepsy12/view_folder/organisation_views.py @@ -112,8 +112,6 @@ def organisation_reports(request): else: total_percent_trust = 0 - org_list = Organisation.objects.order_by("OrganisationName").all() - return render( request=request, template_name=template_name, @@ -356,6 +354,7 @@ def selected_trust_kpis(request, organisation_id): "country_kpis": country_kpis, "national_kpis": national_kpis, "kpis": kpis, + "open_access": False, } # remove the temporary instance as otherwise would contribute to totals @@ -450,6 +449,7 @@ def selected_trust_kpis_open(request, organisation_id): "national_kpis": national_kpis, "kpis": kpis, "organisation_list": Organisation.objects.all().order_by("OrganisationName"), + "open_access": True, } # remove the temporary instance as otherwise would contribute to totals diff --git a/templates/epilepsy12/partials/kpis/kpis.html b/templates/epilepsy12/partials/kpis/kpis.html index a9045441..e90c3bae 100644 --- a/templates/epilepsy12/partials/kpis/kpis.html +++ b/templates/epilepsy12/partials/kpis/kpis.html @@ -1,5 +1,10 @@ {% load epilepsy12_template_tags %} - +{% comment %} +This template is the kpis table and is called from selected_trust_kpis and selected_trust_kpis_open, that latter for +open access. The open_access flag passed in from both endpoints denotes this. +Currently the aggregation queries are run with every page load, but in future, the open_access results +will be persisted and run as a cron job once a day. +{% endcomment %}
@@ -10,6 +15,7 @@

{{organisation.OrganisationName}} ({{ organisation.ParentOrganisation_OrganisationName }})

+ {% if not open_access %} + {% endif %}
diff --git a/templates/epilepsy12/partials/selected_organisation_summary.html b/templates/epilepsy12/partials/selected_organisation_summary.html index 304cb6f9..f89b143f 100644 --- a/templates/epilepsy12/partials/selected_organisation_summary.html +++ b/templates/epilepsy12/partials/selected_organisation_summary.html @@ -143,7 +143,7 @@

Completed Patient Records

{% include 'epilepsy12/partials/charts/progress.html' with percentage=percent_completed_trust numerator=count_of_current_cohort_registered_completed_cases_in_this_organisation denominator=count_of_current_cohort_registered_cases_in_this_organisation title="Completed Patient Records - Trust" pie_size='med' %}
-

{{selected_organisation.ParentName}}

+

{{selected_organisation.ParentOrganisation_OrganisationName}}