From 14bcd4fdf77314c7b9b5f80bc15cc5d90845c7fe Mon Sep 17 00:00:00 2001
From: Carlos Vega <carlos.vega@lih.lu>
Date: Tue, 24 Oct 2023 15:24:37 +0200
Subject: [PATCH] solved other pylint issues, added ignore pragmas where
 considered, added two more to the list of globally ignored checks E1131 and
 E1131

---
 .pylintrc                                     |   2 +
 smash/web/api_views/subject.py                | 551 +++++++++++-------
 smash/web/forms/study_subject_forms.py        | 236 ++++----
 smash/web/forms/voucher_forms.py              | 103 ++--
 .../web/importer/csv_subject_import_reader.py |   2 +-
 smash/web/importer/importer_cron_job.py       |  75 ++-
 smash/web/migrations/0001_version-1-0-0.py    |   5 +-
 .../0032_configurationitem_email_items.py     |   4 +-
 .../migrations/0061_remove_subject_country.py |  16 +-
 .../web/migrations/0064_auto_20171127_0954.py |  12 +-
 smash/web/migrations/0066_subject.py          |   2 +-
 .../0082_studysubjectlist_visits.py           |   8 +-
 .../migrations/0086_unfinished_visit_list.py  |   2 +-
 .../0106_approaching_post_mail_list_update.py |   2 +-
 .../web/migrations/0114_auto_20180611_0950.py |   9 +-
 .../0158_configurationitem_email_items.py     |   4 +-
 ...onfigurationitem_email_items_for_redcap.py |   4 +-
 ...onfigurationitem_email_items_for_redcap.py |   4 +-
 .../0165_configurationitem_email_virus.py     |   4 +-
 .../web/migrations/0166_auto_20200423_1457.py |   4 +-
 .../migrations/0168_rename_radcap_field.py    |   4 +-
 .../0171_configurationitem_serology.py        |   4 +-
 .../web/migrations/0173_auto_20201105_1142.py |  20 +-
 .../web/migrations/0174_auto_20201105_1157.py |  12 +-
 .../web/migrations/0178_auto_20201116_1250.py |   1 +
 .../web/migrations/0183_auto_20201126_1154.py |  58 +-
 ...4_migrate_subject_type_to_new_structure.py |  68 ++-
 .../web/migrations/0212_auto_20231024_1238.py |  27 +-
 smash/web/officeAvailability.py               |   6 +-
 smash/web/templatetags/filters.py             |  24 +-
 smash/web/tests/models/test_study_subject.py  | 137 +++--
 smash/web/tests/view/test_privacy_notice.py   |  36 +-
 smash/web/views/subject.py                    |   2 +-
 smash/web/views/virus_mail.py                 |  71 ++-
 34 files changed, 871 insertions(+), 648 deletions(-)

diff --git a/.pylintrc b/.pylintrc
index 501b838b..003bd7d1 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -2,6 +2,8 @@
 load-plugins=pylint.extensions.no_self_use
 
 disable=
+    E1131, # unsupported-binary-operation
+    R1713, # consider-using-join
     C0114, # missing-module-docstring
     C0115, # missing-class-docstring
     C0116, # missing-function-docstring
diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index 27cfcaa7..808cf020 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -9,18 +9,53 @@ from django.db.models import Q
 from django.http import JsonResponse, HttpRequest, HttpResponseNotAllowed, HttpResponse
 from django.urls import reverse
 
-from web.api_views.serialization_utils import str_to_yes_no_null, bool_to_yes_no, flying_team_to_str, location_to_str, \
-    add_column, serialize_date, serialize_datetime, get_filters_for_data_table_request
-from web.models import ConfigurationItem, StudySubject, Visit, Appointment, Subject, SubjectColumns, StudyColumns, \
-    Study, ContactAttempt, SubjectType
-from web.models.constants import GLOBAL_STUDY_ID, VISIT_SHOW_VISIT_NUMBER_FROM_ZERO, \
-    CUSTOM_FIELD_TYPE_TEXT, CUSTOM_FIELD_TYPE_BOOLEAN, CUSTOM_FIELD_TYPE_INTEGER, CUSTOM_FIELD_TYPE_DOUBLE, \
-    CUSTOM_FIELD_TYPE_DATE, CUSTOM_FIELD_TYPE_SELECT_LIST, CUSTOM_FIELD_TYPE_FILE
+from web.api_views.serialization_utils import (
+    str_to_yes_no_null,
+    bool_to_yes_no,
+    flying_team_to_str,
+    location_to_str,
+    add_column,
+    serialize_date,
+    serialize_datetime,
+    get_filters_for_data_table_request,
+)
+from web.models import (
+    ConfigurationItem,
+    StudySubject,
+    Visit,
+    Appointment,
+    Subject,
+    SubjectColumns,
+    StudyColumns,
+    Study,
+    ContactAttempt,
+    SubjectType,
+)
+from web.models.constants import (
+    GLOBAL_STUDY_ID,
+    VISIT_SHOW_VISIT_NUMBER_FROM_ZERO,
+    CUSTOM_FIELD_TYPE_TEXT,
+    CUSTOM_FIELD_TYPE_BOOLEAN,
+    CUSTOM_FIELD_TYPE_INTEGER,
+    CUSTOM_FIELD_TYPE_DOUBLE,
+    CUSTOM_FIELD_TYPE_DATE,
+    CUSTOM_FIELD_TYPE_SELECT_LIST,
+    CUSTOM_FIELD_TYPE_FILE,
+)
 from web.models.custom_data.custom_study_subject_field import get_study_subject_field_id, CustomStudySubjectField
-from web.models.study_subject_list import SUBJECT_LIST_GENERIC, SUBJECT_LIST_NO_VISIT, SUBJECT_LIST_REQUIRE_CONTACT, \
-    StudySubjectList, SUBJECT_LIST_VOUCHER_EXPIRY
-from web.views.notifications import get_subjects_with_no_visit, get_subjects_with_reminder, get_today_midnight_date, \
-    get_subjects_with_almost_expired_vouchers
+from web.models.study_subject_list import (
+    SUBJECT_LIST_GENERIC,
+    SUBJECT_LIST_NO_VISIT,
+    SUBJECT_LIST_REQUIRE_CONTACT,
+    StudySubjectList,
+    SUBJECT_LIST_VOUCHER_EXPIRY,
+)
+from web.views.notifications import (
+    get_subjects_with_no_visit,
+    get_subjects_with_reminder,
+    get_today_midnight_date,
+    get_subjects_with_almost_expired_vouchers,
+)
 from web.views.view_utils import e500_error
 
 logger = logging.getLogger(__name__)
@@ -28,18 +63,14 @@ logger = logging.getLogger(__name__)
 
 # noinspection PyUnusedLocal
 def cities(request):
-    result_subjects = Subject.objects.filter(city__isnull=False).values_list('city').distinct()
-    return JsonResponse({
-        "cities": [x[0] for x in result_subjects]
-    })
+    result_subjects = Subject.objects.filter(city__isnull=False).values_list("city").distinct()
+    return JsonResponse({"cities": [x[0] for x in result_subjects]})
 
 
 # noinspection PyUnusedLocal
 def referrals(request):
-    result_subjects = StudySubject.objects.filter(referral__isnull=False).values_list('referral').distinct()
-    return JsonResponse({
-        "referrals": [x[0] for x in result_subjects]
-    })
+    result_subjects = StudySubject.objects.filter(referral__isnull=False).values_list("referral").distinct()
+    return JsonResponse({"referrals": [x[0] for x in result_subjects]})
 
 
 # noinspection PyUnusedLocal
@@ -69,15 +100,28 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
     add_column(result, "Contact on", "datetime_contact_reminder", study_subject_columns, None, study.columns)
     add_column(result, "Last contact attempt", "last_contact_attempt", study_subject_list, None)
     add_column(result, "Referred by", "referral", study_subject_columns, "string_filter", study.columns)
-    add_column(result, "Health partner name", "health_partner_first_name", None, "string_filter",
-               add_param=study.columns.health_partner,
-               visible_param=study_subject_columns.health_partner)
-    add_column(result, "Health partner last name", "health_partner_last_name", None, "string_filter",
-               add_param=study.columns.health_partner,
-               visible_param=study_subject_columns.health_partner)
+    add_column(
+        result,
+        "Health partner name",
+        "health_partner_first_name",
+        None,
+        "string_filter",
+        add_param=study.columns.health_partner,
+        visible_param=study_subject_columns.health_partner,
+    )
+    add_column(
+        result,
+        "Health partner last name",
+        "health_partner_last_name",
+        None,
+        "string_filter",
+        add_param=study.columns.health_partner,
+        visible_param=study_subject_columns.health_partner,
+    )
     add_column(result, "Location", "default_location", study_subject_columns, "location_filter", study.columns)
-    add_column(result, "Flying team location", "flying_team", study_subject_columns, "flying_team_filter",
-               study.columns)
+    add_column(
+        result, "Flying team location", "flying_team", study_subject_columns, "flying_team_filter", study.columns
+    )
     add_column(result, "Deceased", "dead", subject_columns, "yes_no_filter")
     add_column(result, "Resigned", "resigned", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Endpoint Reached", "endpoint_reached", study_subject_columns, "yes_no_filter", study.columns)
@@ -87,8 +131,13 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
     add_column(result, "Next of kin address", "next_of_kin_address", subject_columns, "string_filter")
     add_column(result, "Excluded", "excluded", study_subject_columns, "yes_no_filter", study.columns)
     add_column(result, "Info sent", "information_sent", study_subject_columns, "yes_no_filter", study.columns)
-    add_column(result, "Default Written Communication Language",
-               "default_written_communication_language", subject_columns, "language_filter")
+    add_column(
+        result,
+        "Default Written Communication Language",
+        "default_written_communication_language",
+        subject_columns,
+        "language_filter",
+    )
 
     visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
     # True values are y, yes, t, true, on and 1; false values are n, no, f, false, off and 0.
@@ -101,56 +150,70 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
     for custom_study_subject_field in study.customstudysubjectfield_set.all():
         visible = study_subject_columns.is_custom_field_visible(custom_study_subject_field)
         if custom_study_subject_field.type == CUSTOM_FIELD_TYPE_TEXT:
-            add_column(result,
-                       custom_study_subject_field.name,
-                       get_study_subject_field_id(custom_study_subject_field),
-                       study_subject_columns,
-                       "string_filter",
-                       visible_param=visible)
+            add_column(
+                result,
+                custom_study_subject_field.name,
+                get_study_subject_field_id(custom_study_subject_field),
+                study_subject_columns,
+                "string_filter",
+                visible_param=visible,
+            )
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_BOOLEAN:
-            add_column(result,
-                       custom_study_subject_field.name,
-                       get_study_subject_field_id(custom_study_subject_field),
-                       study_subject_columns,
-                       "yes_no_filter",
-                       visible_param=visible)
+            add_column(
+                result,
+                custom_study_subject_field.name,
+                get_study_subject_field_id(custom_study_subject_field),
+                study_subject_columns,
+                "yes_no_filter",
+                visible_param=visible,
+            )
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_INTEGER:
-            add_column(result,
-                       custom_study_subject_field.name,
-                       get_study_subject_field_id(custom_study_subject_field),
-                       study_subject_columns,
-                       None,
-                       sortable=False,
-                       visible_param=visible)
+            add_column(
+                result,
+                custom_study_subject_field.name,
+                get_study_subject_field_id(custom_study_subject_field),
+                study_subject_columns,
+                None,
+                sortable=False,
+                visible_param=visible,
+            )
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_DOUBLE:
-            add_column(result,
-                       custom_study_subject_field.name,
-                       get_study_subject_field_id(custom_study_subject_field),
-                       study_subject_columns,
-                       None,
-                       sortable=False,
-                       visible_param=visible)
+            add_column(
+                result,
+                custom_study_subject_field.name,
+                get_study_subject_field_id(custom_study_subject_field),
+                study_subject_columns,
+                None,
+                sortable=False,
+                visible_param=visible,
+            )
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_DATE:
-            add_column(result,
-                       custom_study_subject_field.name,
-                       get_study_subject_field_id(custom_study_subject_field),
-                       study_subject_columns,
-                       None,
-                       visible_param=visible)
+            add_column(
+                result,
+                custom_study_subject_field.name,
+                get_study_subject_field_id(custom_study_subject_field),
+                study_subject_columns,
+                None,
+                visible_param=visible,
+            )
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_SELECT_LIST:
-            add_column(result,
-                       custom_study_subject_field.name,
-                       get_study_subject_field_id(custom_study_subject_field),
-                       study_subject_columns,
-                       'select_filter:' + custom_study_subject_field.possible_values,
-                       visible_param=visible)
+            add_column(
+                result,
+                custom_study_subject_field.name,
+                get_study_subject_field_id(custom_study_subject_field),
+                study_subject_columns,
+                "select_filter:" + custom_study_subject_field.possible_values,
+                visible_param=visible,
+            )
         elif custom_study_subject_field.type == CUSTOM_FIELD_TYPE_FILE:
-            add_column(result,
-                       custom_study_subject_field.name,
-                       get_study_subject_field_id(custom_study_subject_field),
-                       study_subject_columns,
-                       'select_filter:N/A;Available',
-                       visible_param=visible)
+            add_column(
+                result,
+                custom_study_subject_field.name,
+                get_study_subject_field_id(custom_study_subject_field),
+                study_subject_columns,
+                "select_filter:N/A;Available",
+                visible_param=visible,
+            )
         else:
             raise NotImplementedError
 
@@ -158,8 +221,9 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
 
     for one_based_idx, visit_number in enumerate(visit_numbers, 1):
         visit_key = f"visit_{one_based_idx}"  # always starts in 1
-        add_column(result, f"Visit {visit_number}", visit_key, None,
-                   "visit_filter", visible_param=study_subject_list.visits)
+        add_column(
+            result, f"Visit {visit_number}", visit_key, None, "visit_filter", visible_param=study_subject_list.visits
+        )
 
     return JsonResponse({"columns": result})
 
@@ -179,8 +243,8 @@ def get_subjects(request, list_type):
 
 def order_by_visit(subjects_to_be_ordered, order_f, visit_number):
     return subjects_to_be_ordered.annotate(
-        sort_visit_date=Min(Case(When(visit__visit_number=visit_number,
-                                      then='visit__datetime_begin')))).order_by(order_f('sort_visit_date'))
+        sort_visit_date=Min(Case(When(visit__visit_number=visit_number, then="visit__datetime_begin")))
+    ).order_by(order_f("sort_visit_date"))
 
 
 def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_direction, column_filters=None):
@@ -188,88 +252,101 @@ def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_dir
         column_filters = {}
     result = subjects_to_be_ordered
     if order_direction == "asc":
+
         def order_f(x):
             return F(x).asc(nulls_first=True)
+
     else:
+
         def order_f(x):
             return F(x).desc(nulls_last=True)
+
     if order_column is None:
         logger.warning("Column cannot be null")
     elif order_column == "first_name":
-        result = subjects_to_be_ordered.order_by(order_f('subject__first_name'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__first_name"))
     elif order_column == "last_name":
-        result = subjects_to_be_ordered.order_by(order_f('subject__last_name'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__last_name"))
     elif order_column == "address":
-        result = subjects_to_be_ordered.order_by(order_f('subject__address'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__address"))
     elif order_column == "next_of_kin_name":
-        result = subjects_to_be_ordered.order_by(order_f('subject__next_of_kin_name'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__next_of_kin_name"))
     elif order_column == "next_of_kin_phone":
-        result = subjects_to_be_ordered.order_by(order_f('subject__next_of_kin_phone'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__next_of_kin_phone"))
     elif order_column == "next_of_kin_address":
-        result = subjects_to_be_ordered.order_by(order_f('subject__next_of_kin_address'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__next_of_kin_address"))
     elif order_column == "nd_number":
-        result = subjects_to_be_ordered.order_by(order_f('nd_number'))
+        result = subjects_to_be_ordered.order_by(order_f("nd_number"))
     elif order_column == "referral":
-        result = subjects_to_be_ordered.order_by(order_f('referral'))
+        result = subjects_to_be_ordered.order_by(order_f("referral"))
     elif order_column == "default_written_communication_language":
-        result = subjects_to_be_ordered.order_by(order_f('subject__default_written_communication_language__name'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__default_written_communication_language__name"))
     elif order_column == "phone_number":
-        result = subjects_to_be_ordered.order_by(order_f('subject__phone_number'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__phone_number"))
     elif order_column == "phone_number_2":
-        result = subjects_to_be_ordered.order_by(order_f('subject__phone_number_2'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__phone_number_2"))
     elif order_column == "phone_number_3":
-        result = subjects_to_be_ordered.order_by(order_f('subject__phone_number_3'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__phone_number_3"))
     elif order_column == "screening_number":
-        if 'screening_number' not in column_filters:
+        if "screening_number" not in column_filters:
             pattern = None
         else:
-            pattern = column_filters['screening_number']
+            pattern = column_filters["screening_number"]
         result = subjects_to_be_ordered.all()
-        result = sorted(result, key=lambda t: t.sort_matched_screening_first(pattern, reverse=order_direction != 'asc'),
-                        reverse=order_direction != 'asc')
+        result = sorted(
+            result,
+            key=lambda t: t.sort_matched_screening_first(pattern, reverse=order_direction != "asc"),
+            reverse=order_direction != "asc",
+        )
     elif order_column == "default_location":
-        result = subjects_to_be_ordered.order_by(order_f('default_location__name'))
+        result = subjects_to_be_ordered.order_by(order_f("default_location__name"))
     elif order_column == "flying_team":
-        result = subjects_to_be_ordered.order_by(order_f('flying_team'))
+        result = subjects_to_be_ordered.order_by(order_f("flying_team"))
     elif order_column == "dead":
-        result = subjects_to_be_ordered.order_by(order_f('subject__dead'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__dead"))
     elif order_column == "resigned":
-        result = subjects_to_be_ordered.order_by(order_f('resigned'))
+        result = subjects_to_be_ordered.order_by(order_f("resigned"))
     elif order_column == "endpoint_reached":
-        result = subjects_to_be_ordered.order_by(order_f('endpoint_reached'))
+        result = subjects_to_be_ordered.order_by(order_f("endpoint_reached"))
     elif order_column == "information_sent":
-        result = subjects_to_be_ordered.order_by(order_f('information_sent'))
+        result = subjects_to_be_ordered.order_by(order_f("information_sent"))
     elif order_column == "health_partner_first_name":
-        result = subjects_to_be_ordered.order_by(order_f('health_partner__first_name'))
+        result = subjects_to_be_ordered.order_by(order_f("health_partner__first_name"))
     elif order_column == "health_partner_last_name":
-        result = subjects_to_be_ordered.order_by(order_f('health_partner__last_name'))
+        result = subjects_to_be_ordered.order_by(order_f("health_partner__last_name"))
     elif order_column == "social_security_number":
-        result = subjects_to_be_ordered.order_by(order_f('subject__social_security_number'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__social_security_number"))
     elif order_column == "postponed":
-        result = subjects_to_be_ordered.order_by(order_f('postponed'))
+        result = subjects_to_be_ordered.order_by(order_f("postponed"))
     elif order_column == "excluded":
-        result = subjects_to_be_ordered.order_by(order_f('excluded'))
+        result = subjects_to_be_ordered.order_by(order_f("excluded"))
     elif order_column == "type":
-        result = subjects_to_be_ordered.order_by(order_f('type__name'))
+        result = subjects_to_be_ordered.order_by(order_f("type__name"))
     elif order_column == "id":
-        result = subjects_to_be_ordered.order_by(order_f('id'))
+        result = subjects_to_be_ordered.order_by(order_f("id"))
     elif order_column == "date_born":
-        result = subjects_to_be_ordered.order_by(order_f('subject__date_born'))
+        result = subjects_to_be_ordered.order_by(order_f("subject__date_born"))
     elif order_column == "datetime_contact_reminder":
-        result = subjects_to_be_ordered.order_by(order_f('datetime_contact_reminder'))
+        result = subjects_to_be_ordered.order_by(order_f("datetime_contact_reminder"))
     elif order_column == "last_contact_attempt":
         # noinspection SpellCheckingInspection
-        result = subjects_to_be_ordered.annotate(sort_contact_attempt=Max(
-            "contactattempt__datetime_when")).order_by(order_f('sort_contact_attempt'))
+        result = subjects_to_be_ordered.annotate(sort_contact_attempt=Max("contactattempt__datetime_when")).order_by(
+            order_f("sort_contact_attempt")
+        )
     elif str(order_column).startswith("visit_"):
         visit_number = get_visit_number_from_visit_x_string(order_column)
         result = order_by_visit(subjects_to_be_ordered, order_f, visit_number)
-    elif re.search(r'^custom_field-[0-9]+$', order_column):
+    elif re.search(r"^custom_field-[0-9]+$", order_column):
         field_id = int(order_column.replace("custom_field-", ""))
         result = subjects_to_be_ordered.annotate(
-            custom_field_value=Min(Case(When(customstudysubjectvalue__study_subject_field__id=field_id,
-                                             then='customstudysubjectvalue__value')))). \
-            order_by(order_f('custom_field_value'))
+            custom_field_value=Min(
+                Case(
+                    When(
+                        customstudysubjectvalue__study_subject_field__id=field_id, then="customstudysubjectvalue__value"
+                    )
+                )
+            )
+        ).order_by(order_f("custom_field_value"))
     else:
         logger.warning("Unknown sort column: %s", str(order_column))
     return result
@@ -282,58 +359,94 @@ def get_visit_number_from_visit_x_string(order_column):
 def filter_by_visit(result, visit_number, visit_type):
     # we need to give custom names for filtering params that contain visit_number in it
     # because we might want to filter by few visits  and they shouldn't collide
-    datetime_begin_filter = 'visit_' + str(visit_number) + '_datetime_begin'
-    datetime_end_filter = 'visit_' + str(visit_number) + '_datetime_end'
-    is_finished_filter = 'visit_' + str(visit_number) + '_is_finished'
-    finished_appointments_filter = 'visit_' + str(visit_number) + '_finished_appointments'
-    scheduled_appointments_filter = 'visit_' + str(visit_number) + '_scheduled_appointments'
+    datetime_begin_filter = "visit_" + str(visit_number) + "_datetime_begin"
+    datetime_end_filter = "visit_" + str(visit_number) + "_datetime_end"
+    is_finished_filter = "visit_" + str(visit_number) + "_is_finished"
+    finished_appointments_filter = "visit_" + str(visit_number) + "_finished_appointments"
+    scheduled_appointments_filter = "visit_" + str(visit_number) + "_scheduled_appointments"
 
     # this is hack... instead of providing True/False value this field contain 1/0 value, the problem is that we need
     # to provide aggregate function for the interacting parameter
     # If we try to assign it with pure Case(When...) (without Count/Min/Max/Avg) we obtain duplicates
     # of the results which are later on messing up with the subject list
-    result = result.annotate(**{
-        is_finished_filter: Count(Case(When(Q(visit__is_finished=True) & Q(visit__visit_number=visit_number), then=1)))
-    })
+    result = result.annotate(
+        **{
+            is_finished_filter: Count(
+                Case(When(Q(visit__is_finished=True) & Q(visit__visit_number=visit_number), then=1))
+            )
+        }
+    )
 
     # number of finished appointments
-    result = result.annotate(**{finished_appointments_filter: Count(Case(When(
-        Q(visit__appointment__status=Appointment.APPOINTMENT_STATUS_FINISHED) & Q(visit__visit_number=visit_number),
-        then=1)))})
+    result = result.annotate(
+        **{
+            finished_appointments_filter: Count(
+                Case(
+                    When(
+                        Q(visit__appointment__status=Appointment.APPOINTMENT_STATUS_FINISHED)
+                        & Q(visit__visit_number=visit_number),
+                        then=1,
+                    )
+                )
+            )
+        }
+    )
     # number of scheduled appointments
-    result = result.annotate(**{scheduled_appointments_filter: Count(Case(When(
-        Q(visit__appointment__status=Appointment.APPOINTMENT_STATUS_SCHEDULED) & Q(visit__visit_number=visit_number),
-        then=1)))})
+    result = result.annotate(
+        **{
+            scheduled_appointments_filter: Count(
+                Case(
+                    When(
+                        Q(visit__appointment__status=Appointment.APPOINTMENT_STATUS_SCHEDULED)
+                        & Q(visit__visit_number=visit_number),
+                        then=1,
+                    )
+                )
+            )
+        }
+    )
 
     # when visit starts
     result = result.annotate(
-        **{datetime_begin_filter: Min(Case(When(visit__visit_number=visit_number, then='visit__datetime_begin')))})
+        **{datetime_begin_filter: Min(Case(When(visit__visit_number=visit_number, then="visit__datetime_begin")))}
+    )
     # when visit finish
     result = result.annotate(
-        **{datetime_end_filter: Min(Case(When(visit__visit_number=visit_number, then='visit__datetime_end')))})
+        **{datetime_end_filter: Min(Case(When(visit__visit_number=visit_number, then="visit__datetime_end")))}
+    )
 
     if visit_type == "DONE":
-        result = result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()}). \
-            filter(**{is_finished_filter + "__gt": 0}). \
-            filter(**{finished_appointments_filter + "__gt": 0})
+        result = (
+            result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()})
+            .filter(**{is_finished_filter + "__gt": 0})
+            .filter(**{finished_appointments_filter + "__gt": 0})
+        )
     elif visit_type == "MISSED":
-        result = result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()}). \
-            filter(**{is_finished_filter + "__gt": 0}). \
-            filter(**{finished_appointments_filter: 0})
+        result = (
+            result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()})
+            .filter(**{is_finished_filter + "__gt": 0})
+            .filter(**{finished_appointments_filter: 0})
+        )
     elif visit_type == "EXCEED":
-        result = result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()}). \
-            filter(**{is_finished_filter: 0}). \
-            filter(**{scheduled_appointments_filter: 0}). \
-            filter(**{datetime_end_filter + "__lt": get_today_midnight_date()})
+        result = (
+            result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()})
+            .filter(**{is_finished_filter: 0})
+            .filter(**{scheduled_appointments_filter: 0})
+            .filter(**{datetime_end_filter + "__lt": get_today_midnight_date()})
+        )
     elif visit_type == "IN_PROGRESS":
-        result = result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()}). \
-            filter(**{is_finished_filter: 0}). \
-            filter(**{scheduled_appointments_filter + "__gt": 0})
+        result = (
+            result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()})
+            .filter(**{is_finished_filter: 0})
+            .filter(**{scheduled_appointments_filter + "__gt": 0})
+        )
     elif visit_type == "SHOULD_BE_IN_PROGRESS":
-        result = result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()}). \
-            filter(**{is_finished_filter: 0}). \
-            filter(**{datetime_end_filter + "__gt": get_today_midnight_date()}). \
-            filter(**{scheduled_appointments_filter: 0})
+        result = (
+            result.filter(**{datetime_begin_filter + "__lt": get_today_midnight_date()})
+            .filter(**{is_finished_filter: 0})
+            .filter(**{datetime_end_filter + "__gt": get_today_midnight_date()})
+            .filter(**{scheduled_appointments_filter: 0})
+        )
     elif visit_type == "UPCOMING":
         result = result.filter(**{datetime_begin_filter + "__gt": get_today_midnight_date()})
 
@@ -352,8 +465,12 @@ def get_subjects_filtered(subjects_to_be_filtered: QuerySet, filters) -> QuerySe
         elif column == "last_name":
             result = result.filter(subject__last_name__icontains=value)
         elif column == "address":
-            result = result.filter(Q(subject__address__icontains=value) | Q(subject__city__icontains=value) | Q(
-                subject__country__name__icontains=value))
+            # pylint: disable-next=E1131
+            result = result.filter(
+                Q(subject__address__icontains=value)
+                | Q(subject__city__icontains=value)
+                | Q(subject__country__name__icontains=value)
+            )
         elif column == "next_of_kin_name":
             result = result.filter(subject__next_of_kin_name__icontains=value)
         elif column == "next_of_kin_phone":
@@ -401,31 +518,41 @@ def get_subjects_filtered(subjects_to_be_filtered: QuerySet, filters) -> QuerySe
         elif str(column).startswith("visit_"):
             visit_number = get_visit_number_from_visit_x_string(column)
             result = filter_by_visit(result, visit_number, value)
-        elif re.search(r'^custom_field-[0-9]+$', column):
+        elif re.search(r"^custom_field-[0-9]+$", column):
             field_id = int(column.replace("custom_field-", ""))
             field = CustomStudySubjectField.objects.get(pk=field_id)
             if field.type == CUSTOM_FIELD_TYPE_TEXT:
-                result = result.filter(customstudysubjectvalue__study_subject_field__id=field_id,
-                                       customstudysubjectvalue__value__icontains=value)
+                result = result.filter(
+                    customstudysubjectvalue__study_subject_field__id=field_id,
+                    customstudysubjectvalue__value__icontains=value,
+                )
             elif field.type == CUSTOM_FIELD_TYPE_BOOLEAN:
-                if value.lower() == 'true' or value.lower() == 'false':
-                    result = result.filter(customstudysubjectvalue__study_subject_field__id=field_id,
-                                           customstudysubjectvalue__value__icontains=value)
+                if value.lower() == "true" or value.lower() == "false":
+                    result = result.filter(
+                        customstudysubjectvalue__study_subject_field__id=field_id,
+                        customstudysubjectvalue__value__icontains=value,
+                    )
                 else:
-                    result = result.filter(customstudysubjectvalue__study_subject_field__id=field_id,
-                                           customstudysubjectvalue__value='')
-            elif field.type == CUSTOM_FIELD_TYPE_INTEGER or field.type == CUSTOM_FIELD_TYPE_DOUBLE:
-                result = result.filter(customstudysubjectvalue__study_subject_field__id=field_id,
-                                       customstudysubjectvalue__value=value)
+                    result = result.filter(
+                        customstudysubjectvalue__study_subject_field__id=field_id, customstudysubjectvalue__value=""
+                    )
+            elif field.type in (CUSTOM_FIELD_TYPE_INTEGER, CUSTOM_FIELD_TYPE_DOUBLE):
+                result = result.filter(
+                    customstudysubjectvalue__study_subject_field__id=field_id, customstudysubjectvalue__value=value
+                )
             elif field.type == CUSTOM_FIELD_TYPE_DATE:
-                result = result.filter(customstudysubjectvalue__study_subject_field__id=field_id,
-                                       customstudysubjectvalue__value=value)
-            elif field.type == CUSTOM_FIELD_TYPE_INTEGER or field.type == CUSTOM_FIELD_TYPE_SELECT_LIST:
-                result = result.filter(customstudysubjectvalue__study_subject_field__id=field_id,
-                                       customstudysubjectvalue__value=value)
+                result = result.filter(
+                    customstudysubjectvalue__study_subject_field__id=field_id, customstudysubjectvalue__value=value
+                )
+            elif field.type in (CUSTOM_FIELD_TYPE_INTEGER, CUSTOM_FIELD_TYPE_SELECT_LIST):
+                result = result.filter(
+                    customstudysubjectvalue__study_subject_field__id=field_id, customstudysubjectvalue__value=value
+                )
             elif field.type == CUSTOM_FIELD_TYPE_FILE:
-                result = result.filter(customstudysubjectvalue__study_subject_field__id=field_id,
-                                       customstudysubjectvalue__value__isnull=(value == 'N/A'))
+                result = result.filter(
+                    customstudysubjectvalue__study_subject_field__id=field_id,
+                    customstudysubjectvalue__value__isnull=(value == "N/A"),
+                )
             else:
                 raise NotImplementedError
         elif column == "":
@@ -447,7 +574,7 @@ def subjects(request: WSGIRequest, subject_list_type: str) -> HttpResponse:
         elif request.method == "POST":
             request_data = request.POST
         else:
-            return HttpResponseNotAllowed(['GET', 'POST'])
+            return HttpResponseNotAllowed(["GET", "POST"])
 
         # id of the query from dataTable: https://datatables.net/manual/server-side
         draw = int(request_data.get("draw", "-1"))
@@ -469,7 +596,7 @@ def subjects(request: WSGIRequest, subject_list_type: str) -> HttpResponse:
         if length == -1:
             sliced_subjects = ordered_subjects
         else:
-            sliced_subjects = ordered_subjects[start:(start + length)]
+            sliced_subjects = ordered_subjects[start: (start + length)]
 
         result_subjects = sliced_subjects
 
@@ -479,12 +606,14 @@ def subjects(request: WSGIRequest, subject_list_type: str) -> HttpResponse:
         for subject in result_subjects:
             data.append(serialize_subject(subject))
 
-        return JsonResponse({
-            "draw": draw,
-            "recordsTotal": count,
-            "recordsFiltered": count_filtered,
-            "data": data,
-        })
+        return JsonResponse(
+            {
+                "draw": draw,
+                "recordsTotal": count,
+                "recordsFiltered": count_filtered,
+                "data": data,
+            }
+        )
     except Exception as e:
         logger.error(e, exc_info=True)
         return e500_error(request)
@@ -495,35 +624,36 @@ def types(request):
     data = []
     for subject_type in SubjectType.objects.all():
         data.append({"id": subject_type.id, "name": subject_type.name})
-    return JsonResponse({
-        "types": data
-    })
+    return JsonResponse({"types": data})
 
 
 def serialize_subject(study_subject: StudySubject):
     location = location_to_str(study_subject.default_location)
     flying_team = flying_team_to_str(study_subject.flying_team)
-    visits = Visit.objects.filter(subject=study_subject).order_by('visit_number')
+    visits = Visit.objects.filter(subject=study_subject).order_by("visit_number")
     serialized_visits = []
     for visit in visits:
         if visit.datetime_begin < get_today_midnight_date():
             if visit.is_finished:
                 finished_appointments_count = visit.appointment_set.filter(
-                    status=Appointment.APPOINTMENT_STATUS_FINISHED).count()
+                    status=Appointment.APPOINTMENT_STATUS_FINISHED
+                ).count()
                 if finished_appointments_count > 0:
                     status = "DONE"
                 else:
                     status = "MISSED"
             elif visit.datetime_end < get_today_midnight_date():
                 scheduled_appointments_count = visit.appointment_set.filter(
-                    status=Appointment.APPOINTMENT_STATUS_SCHEDULED).count()
+                    status=Appointment.APPOINTMENT_STATUS_SCHEDULED
+                ).count()
                 if scheduled_appointments_count > 0:
                     status = "IN_PROGRESS"
                 else:
                     status = "EXCEEDED"
             else:
                 scheduled_appointments_count = visit.appointment_set.filter(
-                    status=Appointment.APPOINTMENT_STATUS_SCHEDULED).count()
+                    status=Appointment.APPOINTMENT_STATUS_SCHEDULED
+                ).count()
                 if scheduled_appointments_count > 0:
                     status = "IN_PROGRESS"
                 else:
@@ -531,26 +661,34 @@ def serialize_subject(study_subject: StudySubject):
         else:
             status = "UPCOMING"
 
-        appointment_types = [f'{at.code} ({at.description})' for at in visit.appointment_types.all()]
+        appointment_types = [f"{at.code} ({at.description})" for at in visit.appointment_types.all()]
         if len(appointment_types) == 0:
-            appointment_types = ['No appointment types set.']
-
-        serialized_visits.append({
-            "status": status,
-            "appointment_types": appointment_types,
-            "edit_visit_url": reverse('web.views.visit_details', args=(visit.id,)),
-            "add_appointment_url": reverse('web.views.appointment_add', args=(visit.id,)),
-            "datetime_start": serialize_date(visit.datetime_begin),
-            "datetime_end": serialize_date(visit.datetime_end),
-            "is_finished": visit.is_finished
-        })
+            appointment_types = ["No appointment types set."]
+
+        serialized_visits.append(
+            {
+                "status": status,
+                "appointment_types": appointment_types,
+                "edit_visit_url": reverse("web.views.visit_details", args=(visit.id,)),
+                "add_appointment_url": reverse("web.views.appointment_add", args=(visit.id,)),
+                "datetime_start": serialize_date(visit.datetime_begin),
+                "datetime_end": serialize_date(visit.datetime_end),
+                "is_finished": visit.is_finished,
+            }
+        )
     contact_reminder = serialize_datetime(study_subject.datetime_contact_reminder)
     contact_attempts = ContactAttempt.objects.filter(subject=study_subject).order_by("-datetime_when")
     if len(contact_attempts) > 0:
         last_contact_attempt = contact_attempts[0]
-        last_contact_attempt_string = serialize_datetime(last_contact_attempt.datetime_when) + "<br/>" + str(
-            last_contact_attempt.worker) + "<br/> Success: " + bool_to_yes_no(
-            last_contact_attempt.success) + "<br/>" + last_contact_attempt.comment
+        last_contact_attempt_string = (
+            serialize_datetime(last_contact_attempt.datetime_when)
+            + "<br/>"
+            + str(last_contact_attempt.worker)
+            + "<br/> Success: "
+            + bool_to_yes_no(last_contact_attempt.success)
+            + "<br/>"
+            + last_contact_attempt.comment
+        )
 
     else:
         last_contact_attempt_string = ""
@@ -594,16 +732,18 @@ def serialize_subject(study_subject: StudySubject):
         "type": study_subject.type.name,
         "id": study_subject.id,
         "visits": serialized_visits,
-        "default_written_communication_language": default_written_communication_language
+        "default_written_communication_language": default_written_communication_language,
     }
 
     for field_value in study_subject.custom_data_values:
-        if field_value.study_subject_field.type == CUSTOM_FIELD_TYPE_TEXT \
-                or field_value.study_subject_field.type == CUSTOM_FIELD_TYPE_INTEGER \
-                or field_value.study_subject_field.type == CUSTOM_FIELD_TYPE_DOUBLE:
+        if field_value.study_subject_field.type in (
+            CUSTOM_FIELD_TYPE_TEXT,
+            CUSTOM_FIELD_TYPE_INTEGER,
+            CUSTOM_FIELD_TYPE_DOUBLE,
+        ):
             val = field_value.value
             if val is None:
-                val = ''
+                val = ""
             result[get_study_subject_field_id(field_value.study_subject_field)] = val
         elif field_value.study_subject_field.type == CUSTOM_FIELD_TYPE_BOOLEAN:
             result[get_study_subject_field_id(field_value.study_subject_field)] = str_to_yes_no_null(field_value.value)
@@ -613,10 +753,11 @@ def serialize_subject(study_subject: StudySubject):
             result[get_study_subject_field_id(field_value.study_subject_field)] = field_value.value
         elif field_value.study_subject_field.type == CUSTOM_FIELD_TYPE_FILE:
             if field_value.value is None:
-                result[get_study_subject_field_id(field_value.study_subject_field)] = ''
+                result[get_study_subject_field_id(field_value.study_subject_field)] = ""
             else:
-                result[get_study_subject_field_id(field_value.study_subject_field)] = reverse(
-                    'web.views.uploaded_files') + '?file=' + str(field_value.value)
+                result[get_study_subject_field_id(field_value.study_subject_field)] = (
+                    reverse("web.views.uploaded_files") + "?file=" + str(field_value.value)
+                )
         else:
             raise NotImplementedError
 
diff --git a/smash/web/forms/study_subject_forms.py b/smash/web/forms/study_subject_forms.py
index 8027773c..8a848792 100644
--- a/smash/web/forms/study_subject_forms.py
+++ b/smash/web/forms/study_subject_forms.py
@@ -7,9 +7,15 @@ from django.forms import ModelForm
 
 from web.forms.forms import DATETIMEPICKER_DATE_ATTRS, get_worker_from_args, DATEPICKER_DATE_ATTRS
 from web.models import StudySubject, Study, StudyColumns, VoucherType, Worker, Visit
-from web.models.constants import CUSTOM_FIELD_TYPE_TEXT, CUSTOM_FIELD_TYPE_BOOLEAN, \
-    CUSTOM_FIELD_TYPE_INTEGER, CUSTOM_FIELD_TYPE_DOUBLE, \
-    CUSTOM_FIELD_TYPE_DATE, CUSTOM_FIELD_TYPE_SELECT_LIST, CUSTOM_FIELD_TYPE_FILE
+from web.models.constants import (
+    CUSTOM_FIELD_TYPE_TEXT,
+    CUSTOM_FIELD_TYPE_BOOLEAN,
+    CUSTOM_FIELD_TYPE_INTEGER,
+    CUSTOM_FIELD_TYPE_DOUBLE,
+    CUSTOM_FIELD_TYPE_DATE,
+    CUSTOM_FIELD_TYPE_SELECT_LIST,
+    CUSTOM_FIELD_TYPE_FILE,
+)
 from web.models.custom_data import CustomStudySubjectField, CustomStudySubjectValue
 from web.models.custom_data.custom_study_subject_field import get_study_subject_field_id
 from web.models.worker_study_role import WORKER_HEALTH_PARTNER
@@ -19,61 +25,87 @@ logger = logging.getLogger(__name__)
 
 
 def get_custom_select_choices(possible_values):
-    result = list()
+    result = []
     index = 1
-    result.append(('0', '---'))
+    result.append(("0", "---"))
     for value in possible_values.split(";"):
         result.append((str(index), value))
         index += 1
     return result
 
 
-def create_field_for_custom_study_subject_field(study_subject_field: CustomStudySubjectField,
-                                                field_value: CustomStudySubjectValue = None) -> forms.Field:
+def create_field_for_custom_study_subject_field(
+    study_subject_field: CustomStudySubjectField, field_value: CustomStudySubjectValue = None
+) -> forms.Field:
     val = study_subject_field.default_value
     if field_value is not None:
         val = field_value.value
     if study_subject_field.type == CUSTOM_FIELD_TYPE_TEXT:
-        field = forms.CharField(label=study_subject_field.name, initial=val,
-                                required=study_subject_field.required, disabled=study_subject_field.readonly)
+        field = forms.CharField(
+            label=study_subject_field.name,
+            initial=val,
+            required=study_subject_field.required,
+            disabled=study_subject_field.readonly,
+        )
     elif study_subject_field.type == CUSTOM_FIELD_TYPE_BOOLEAN:
         initial = False
-        if val is not None and val.lower() == 'true':
+        if val is not None and val.lower() == "true":
             initial = True
-        field = forms.BooleanField(label=study_subject_field.name, initial=initial,
-                                   required=study_subject_field.required, disabled=study_subject_field.readonly)
+        field = forms.BooleanField(
+            label=study_subject_field.name,
+            initial=initial,
+            required=study_subject_field.required,
+            disabled=study_subject_field.readonly,
+        )
     elif study_subject_field.type == CUSTOM_FIELD_TYPE_INTEGER:
         initial = None
         if val is not None and re.match(r"[-+]?\d+$", val) is not None:
             initial = int(val)
-        field = forms.IntegerField(label=study_subject_field.name, initial=initial,
-                                   required=study_subject_field.required, disabled=study_subject_field.readonly)
+        field = forms.IntegerField(
+            label=study_subject_field.name,
+            initial=initial,
+            required=study_subject_field.required,
+            disabled=study_subject_field.readonly,
+        )
     elif study_subject_field.type == CUSTOM_FIELD_TYPE_DOUBLE:
         initial = None
         if val is not None and re.match(r"[-+]?\d+?\.\d+?$", val) is not None:
             initial = float(val)
-        field = forms.FloatField(label=study_subject_field.name, initial=initial,
-                                 required=study_subject_field.required, disabled=study_subject_field.readonly)
+        field = forms.FloatField(
+            label=study_subject_field.name,
+            initial=initial,
+            required=study_subject_field.required,
+            disabled=study_subject_field.readonly,
+        )
     elif study_subject_field.type == CUSTOM_FIELD_TYPE_DATE:
         initial = None
-        if val is not None and val != '':
-            initial = datetime.datetime.strptime(val, '%Y-%m-%d')
-        field = forms.DateTimeField(label=study_subject_field.name, initial=initial,
-                                    required=study_subject_field.required, disabled=study_subject_field.readonly,
-                                    widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"))
+        if val is not None and val != "":
+            initial = datetime.datetime.strptime(val, "%Y-%m-%d")
+        field = forms.DateTimeField(
+            label=study_subject_field.name,
+            initial=initial,
+            required=study_subject_field.required,
+            disabled=study_subject_field.readonly,
+            widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"),
+        )
     elif study_subject_field.type == CUSTOM_FIELD_TYPE_SELECT_LIST:
-        initial = '0'
+        initial = "0"
         for v, k in get_custom_select_choices(study_subject_field.possible_values):
             if k == val:
                 initial = v
-        field = forms.ChoiceField(label=study_subject_field.name, initial=initial,
-                                  required=study_subject_field.required, disabled=study_subject_field.readonly,
-                                  choices=get_custom_select_choices(study_subject_field.possible_values))
+        field = forms.ChoiceField(
+            label=study_subject_field.name,
+            initial=initial,
+            required=study_subject_field.required,
+            disabled=study_subject_field.readonly,
+            choices=get_custom_select_choices(study_subject_field.possible_values),
+        )
     elif study_subject_field.type == CUSTOM_FIELD_TYPE_FILE:
         initial = None
         if val is not None:
+
             class CustomFileField:
-                url = ''
+                url = ""
 
                 def __str__(self):
                     return f"{self.url}"
@@ -89,7 +121,7 @@ def create_field_for_custom_study_subject_field(study_subject_field: CustomStudy
             required=study_subject_field.required,
             disabled=study_subject_field.readonly,
             initial=initial,
-            widget=SecuredFileWidget()  # TODO: how to allow multiple files?
+            widget=SecuredFileWidget(),
         )
     else:
         raise NotImplementedError
@@ -97,18 +129,19 @@ def create_field_for_custom_study_subject_field(study_subject_field: CustomStudy
 
 
 class StudySubjectForm(ModelForm):
-    datetime_contact_reminder = forms.DateTimeField(label="Contact on",
-                                                    widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS),
-                                                    required=False)
-    referral_letter = forms.FileField(label='Referral letter', widget=SecuredFileWidget(), required=False)
-    voucher_types = forms.ModelMultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple,
-                                                   queryset=VoucherType.objects.all())
+    datetime_contact_reminder = forms.DateTimeField(
+        label="Contact on", widget=forms.DateTimeInput(DATETIMEPICKER_DATE_ATTRS), required=False
+    )
+    referral_letter = forms.FileField(label="Referral letter", widget=SecuredFileWidget(), required=False)
+    voucher_types = forms.ModelMultipleChoiceField(
+        required=False, widget=forms.CheckboxSelectMultiple, queryset=VoucherType.objects.all()
+    )
 
     study: Study
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        instance = kwargs.get('instance')
+        instance = kwargs.get("instance")
         if instance:
             for value in instance.custom_data_values:
                 field_id = get_study_subject_field_id(value.study_subject_field)
@@ -118,24 +151,27 @@ class StudySubjectForm(ModelForm):
                 field_id = get_study_subject_field_id(field_type)
                 self.fields[field_id] = create_field_for_custom_study_subject_field(field_type)
 
-        self.fields['health_partner'].queryset = Worker.get_workers_by_worker_type(
-            WORKER_HEALTH_PARTNER)
+        self.fields["health_partner"].queryset = Worker.get_workers_by_worker_type(WORKER_HEALTH_PARTNER)
 
     def clean(self):
         cleaned_data = super().clean()
         subject_id = -1
-        if getattr(self, 'instance', None) is not None:
-            subject_id = getattr(self, 'instance', None).id
+        if getattr(self, "instance", None) is not None:
+            subject_id = getattr(self, "instance", None).id
         for field_type in CustomStudySubjectField.objects.filter(study=self.study):
             if field_type.unique:
                 field_id = get_study_subject_field_id(field_type)
                 value = cleaned_data[field_id]
                 if value is not None and value != "":
-                    count = StudySubject.objects.filter(customstudysubjectvalue__study_subject_field=field_type,
-                                                        customstudysubjectvalue__value=value,
-                                                        study=self.study) \
-                        .exclude(id=subject_id) \
+                    count = (
+                        StudySubject.objects.filter(
+                            customstudysubjectvalue__study_subject_field=field_type,
+                            customstudysubjectvalue__value=value,
+                            study=self.study,
+                        )
+                        .exclude(id=subject_id)
                         .count()
+                    )
                     if count > 0:
                         self.add_error(field_id, "Value must be unique within the study")
         return cleaned_data
@@ -144,8 +180,8 @@ class StudySubjectForm(ModelForm):
 class StudySubjectAddForm(StudySubjectForm):
     class Meta:
         model = StudySubject
-        fields = '__all__'
-        exclude = ['resigned', 'resign_reason', 'endpoint_reached', 'endpoint_reached_reason']
+        fields = "__all__"
+        exclude = ["resigned", "resign_reason", "endpoint_reached", "endpoint_reached_reason"]
 
     def __init__(self, *args, **kwargs):
         self.user = get_worker_from_args(kwargs)
@@ -161,12 +197,13 @@ class StudySubjectAddForm(StudySubjectForm):
         # we can add custom values only after object exists in the database
         for field_type in CustomStudySubjectField.objects.filter(study=self.study):
             if not field_type.readonly:
-                self.instance.set_custom_data_value(field_type, get_study_subject_field_value(field_type, self[
-                    get_study_subject_field_id(field_type)]))
+                self.instance.set_custom_data_value(
+                    field_type, get_study_subject_field_value(field_type, self[get_study_subject_field_id(field_type)])
+                )
         return instance
 
     def build_screening_number(self, cleaned_data):
-        screening_number = cleaned_data.get('screening_number', None)
+        screening_number = cleaned_data.get("screening_number", None)
         if not screening_number:
             prefix_screening_number = self.get_prefix_screening_number()
             if prefix_screening_number is not None:
@@ -177,18 +214,18 @@ class StudySubjectAddForm(StudySubjectForm):
         cleaned_data = super().clean()
         screening_number = self.build_screening_number(cleaned_data)
         if screening_number is not None and self.study.columns.screening_number:
-            cleaned_data['screening_number'] = screening_number
+            cleaned_data["screening_number"] = screening_number
         validate_subject_screening_number(self, cleaned_data)
         validate_subject_nd_number(self, cleaned_data)
         return cleaned_data
 
     def get_prefix_screening_number(self):
-        default_location = self.cleaned_data.get('default_location', None)
+        default_location = self.cleaned_data.get("default_location", None)
         screening_number_prefix = None
         if default_location is not None and default_location.prefix:
             screening_number_prefix = default_location.prefix
         else:
-            subject_type = self.cleaned_data.get('type', None)
+            subject_type = self.cleaned_data.get("type", None)
             if subject_type is not None:
                 screening_number_prefix = subject_type.screening_number_prefix
         if screening_number_prefix is None:
@@ -217,11 +254,11 @@ def get_new_screening_number(screening_number_prefix):
 class StudySubjectDetailForm(StudySubjectForm):
     class Meta:
         model = StudySubject
-        fields = '__all__'
+        fields = "__all__"
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
-        instance = getattr(self, 'instance', None)
+        instance = getattr(self, "instance", None)
 
         self.study = get_study_from_study_subject_instance(instance)
 
@@ -253,8 +290,8 @@ def get_study_subject_field_value(field_type: CustomStudySubjectField, field: fo
             return None
         return field.value()
     elif field_type.type == CUSTOM_FIELD_TYPE_SELECT_LIST:
-        if field.value() == '0':
-            return ''
+        if field.value() == "0":
+            return ""
         if field.value() is None:
             return None
         for v, k in get_custom_select_choices(field_type.possible_values):
@@ -269,19 +306,18 @@ def get_study_subject_field_value(field_type: CustomStudySubjectField, field: fo
 
 
 class StudySubjectEditForm(StudySubjectForm):
-
     def __init__(self, *args, **kwargs):
-        was_resigned = kwargs.pop('was_resigned', False)
-        endpoint_was_reached = kwargs.pop('endpoint_was_reached', False)
+        was_resigned = kwargs.pop("was_resigned", False)
+        endpoint_was_reached = kwargs.pop("endpoint_was_reached", False)
         super().__init__(*args, **kwargs)
-        instance: StudySubject = getattr(self, 'instance', None)
+        instance: StudySubject = getattr(self, "instance", None)
         if instance and instance.id:
-            self.fields['screening_number'].widget.attrs['readonly'] = True
+            self.fields["screening_number"].widget.attrs["readonly"] = True
         self.study = get_study_from_study_subject_instance(instance)
         self.original_type = instance.type
 
-        self.fields['resigned'].disabled = was_resigned
-        self.fields['endpoint_reached'].disabled = endpoint_was_reached
+        self.fields["resigned"].disabled = was_resigned
+        self.fields["endpoint_reached"].disabled = endpoint_was_reached
 
         prepare_study_subject_fields(fields=self.fields, study=self.study)
 
@@ -294,22 +330,24 @@ class StudySubjectEditForm(StudySubjectForm):
     def save(self, commit=True) -> StudySubject:
         for field_type in CustomStudySubjectField.objects.filter(study=self.study):
             if not field_type.readonly:
-                self.instance.set_custom_data_value(field_type, get_study_subject_field_value(field_type, self[
-                    get_study_subject_field_id(field_type)]))
+                self.instance.set_custom_data_value(
+                    field_type, get_study_subject_field_value(field_type, self[get_study_subject_field_id(field_type)])
+                )
 
         if self.original_type != self.instance.type:
-            self.instance.visit_used_to_compute_followup_date = Visit.objects.filter(subject=self.instance).order_by(
-                '-visit_number').first()
+            self.instance.visit_used_to_compute_followup_date = (
+                Visit.objects.filter(subject=self.instance).order_by("-visit_number").first()
+            )
 
         return super().save(commit)
 
     class Meta:
         model = StudySubject
-        fields = '__all__'
+        fields = "__all__"
 
 
 def get_study_from_args(kwargs):
-    study = kwargs.pop('study', None)
+    study = kwargs.pop("study", None)
     if study is None:
         raise TypeError("Study not defined")
     return study
@@ -323,55 +361,55 @@ def prepare_field(fields, visible_columns: StudyColumns, field_name: str, requir
 
 
 def prepare_study_subject_fields(fields, study: Study):
-    prepare_field(fields, study.columns, 'default_location', required=True)
-    prepare_field(fields, study.columns, 'type', required=True)
-    prepare_field(fields, study.columns, 'screening_number')
-    prepare_field(fields, study.columns, 'nd_number')
-    prepare_field(fields, study.columns, 'datetime_contact_reminder')
-    prepare_field(fields, study.columns, 'postponed')
-    prepare_field(fields, study.columns, 'flying_team')
-    prepare_field(fields, study.columns, 'comments')
-    prepare_field(fields, study.columns, 'referral')
-    prepare_field(fields, study.columns, 'information_sent')
-    prepare_field(fields, study.columns, 'endpoint_reached')
-    prepare_field(fields, study.columns, 'endpoint_reached_reason')
-    prepare_field(fields, study.columns, 'excluded')
-    prepare_field(fields, study.columns, 'exclude_reason')
-    prepare_field(fields, study.columns, 'resigned')
-    prepare_field(fields, study.columns, 'resign_reason')
-    prepare_field(fields, study.columns, 'referral_letter')
-    prepare_field(fields, study.columns, 'health_partner')
-    prepare_field(fields, study.columns, 'health_partner_feedback_agreement')
+    prepare_field(fields, study.columns, "default_location", required=True)
+    prepare_field(fields, study.columns, "type", required=True)
+    prepare_field(fields, study.columns, "screening_number")
+    prepare_field(fields, study.columns, "nd_number")
+    prepare_field(fields, study.columns, "datetime_contact_reminder")
+    prepare_field(fields, study.columns, "postponed")
+    prepare_field(fields, study.columns, "flying_team")
+    prepare_field(fields, study.columns, "comments")
+    prepare_field(fields, study.columns, "referral")
+    prepare_field(fields, study.columns, "information_sent")
+    prepare_field(fields, study.columns, "endpoint_reached")
+    prepare_field(fields, study.columns, "endpoint_reached_reason")
+    prepare_field(fields, study.columns, "excluded")
+    prepare_field(fields, study.columns, "exclude_reason")
+    prepare_field(fields, study.columns, "resigned")
+    prepare_field(fields, study.columns, "resign_reason")
+    prepare_field(fields, study.columns, "referral_letter")
+    prepare_field(fields, study.columns, "health_partner")
+    prepare_field(fields, study.columns, "health_partner_feedback_agreement")
     if not study.columns.vouchers:
-        del fields['voucher_types']
+        del fields["voucher_types"]
 
 
 def validate_subject_screening_number(self, cleaned_data):
     if self.study.columns.resign_reason and self.study.columns.screening_number:
-        subjects_from_db = StudySubject.objects.filter(screening_number=cleaned_data["screening_number"],
-                                                       study=self.study)
+        subjects_from_db = StudySubject.objects.filter(
+            screening_number=cleaned_data["screening_number"], study=self.study
+        )
         if len(subjects_from_db) > 0:
-            self.add_error('screening_number', "Screening number already in use")
+            self.add_error("screening_number", "Screening number already in use")
 
 
 def validate_subject_nd_number(self, cleaned_data):
     if self.study.columns.nd_number:
-        nd_number = cleaned_data['nd_number']
+        nd_number = cleaned_data["nd_number"]
         if nd_number is None:
-            self.add_error('nd_number', "None ND number. ND number can be blank but not None.")
+            self.add_error("nd_number", "None ND number. ND number can be blank but not None.")
         elif nd_number:
             if not self.study.check_nd_number(nd_number):
-                self.add_error('nd_number', "Invalid ND number")
+                self.add_error("nd_number", "Invalid ND number")
             else:
-                subjects_from_db = StudySubject.objects.filter(
-                    nd_number=nd_number, study=self.study)
+                subjects_from_db = StudySubject.objects.filter(nd_number=nd_number, study=self.study)
                 if subjects_from_db:
-                    if subjects_from_db[0].screening_number != cleaned_data.get('screening_number', ''):
-                        self.add_error('nd_number', "Subject number already in use")
+                    if subjects_from_db[0].screening_number != cleaned_data.get("screening_number", ""):
+                        self.add_error("nd_number", "Subject number already in use")
         # else: #empty nd_number is valid
 
 
 def validate_subject_resign_reason(self, cleaned_data):
     if self.study.columns.resigned and self.study.columns.resign_reason:
-        if cleaned_data['resigned'] and cleaned_data['resign_reason'] == '':
-            self.add_error('resign_reason', "Resign reason cannot be empty")
+        if cleaned_data["resigned"] and cleaned_data["resign_reason"] == "":
+            self.add_error("resign_reason", "Resign reason cannot be empty")
diff --git a/smash/web/forms/voucher_forms.py b/smash/web/forms/voucher_forms.py
index 94ee92fc..bfd2de1b 100644
--- a/smash/web/forms/voucher_forms.py
+++ b/smash/web/forms/voucher_forms.py
@@ -18,100 +18,101 @@ logger = logging.getLogger(__name__)
 class VoucherTypeForm(ModelForm):
     class Meta:
         model = VoucherType
-        exclude = ['study']
+        exclude = ["study"]
 
 
 class VoucherTypePriceForm(ModelForm):
-    start_date = forms.DateField(label="Start date",
-                                 widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
-                                 )
-    end_date = forms.DateField(label="End date",
-                               widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d")
-                               )
+    start_date = forms.DateField(label="Start date", widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"))
+    end_date = forms.DateField(label="End date", widget=forms.DateInput(DATEPICKER_DATE_ATTRS, "%Y-%m-%d"))
 
     class Meta:
         model = VoucherTypePrice
-        exclude = ['voucher_type']
+        exclude = ["voucher_type"]
 
 
 class VoucherForm(ModelForm):
     class Meta:
         model = Voucher
-        fields = '__all__'
+        fields = "__all__"
 
     @staticmethod
     def _voucher_type_optgroup(subject_voucher_types, all_voucher_types):
         subject_voucher_types = {(vt.id, str(vt)) for vt in subject_voucher_types}
         all_voucher_types = {(vt.id, str(vt)) for vt in all_voucher_types}
         if subject_voucher_types == all_voucher_types:
-            return [(None, 'Please select an option')] + list(all_voucher_types)
+            return [(None, "Please select an option")] + list(all_voucher_types)
         elif len(subject_voucher_types) == 0:
-            return [(None, 'Please select an option')] + list(all_voucher_types)
+            return [(None, "Please select an option")] + list(all_voucher_types)
 
         rest_voucher_types = all_voucher_types - subject_voucher_types
         return (
-            (None, 'Please select an option'),
-            ('Subject Voucher Types', tuple(subject_voucher_types)),
-            ('Rest of Voucher Types', tuple(rest_voucher_types))
+            (None, "Please select an option"),
+            ("Subject Voucher Types", tuple(subject_voucher_types)),
+            ("Rest of Voucher Types", tuple(rest_voucher_types)),
         )
 
     def __init__(self, *args, **kwargs):
-        voucher_types = kwargs.pop('voucher_types', VoucherType.objects.all())
+        voucher_types = kwargs.pop("voucher_types", VoucherType.objects.all())
         super().__init__(*args, **kwargs)
 
-        self.fields['voucher_type'].choices = VoucherForm._voucher_type_optgroup(voucher_types,
-                                                                                 VoucherType.objects.all())
-        self.fields['voucher_type'].default = None
-        self.fields['usage_partner'].queryset = Worker.get_workers_by_worker_type(WORKER_VOUCHER_PARTNER)
+        self.fields["voucher_type"].choices = VoucherForm._voucher_type_optgroup(
+            voucher_types, VoucherType.objects.all()
+        )
+        self.fields["voucher_type"].default = None
+        self.fields["usage_partner"].queryset = Worker.get_workers_by_worker_type(WORKER_VOUCHER_PARTNER)
 
-        self.fields['number'].widget.attrs['readonly'] = True
-        self.fields['number'].required = False
-        self.fields['issue_worker'].widget.attrs['readonly'] = True
+        self.fields["number"].widget.attrs["readonly"] = True
+        self.fields["number"].required = False
+        self.fields["issue_worker"].widget.attrs["readonly"] = True
         # issue date
-        self.fields['issue_date'].input_formats = ('%Y-%m-%d',)
-        self.fields['issue_date'].required = False
-        self.fields['issue_date'].widget.attrs.update({'class': 'datepicker'})
-        self.fields['issue_date'].widget.attrs.update({'readonly': False})
-        self.fields['issue_date'].widget.attrs.update({'placeholder': 'yyyy-mm-dd (optional)'})
-        self.fields['issue_date'].widget.attrs.update({'pattern': '[0-9]{4}-[0-9]{2}-[0-9]{2}'})
-        self.fields['issue_date'].widget.attrs.update({'required': False})
-        self.fields['issue_date'].initial = timezone.now()
+        self.fields["issue_date"].input_formats = ("%Y-%m-%d",)
+        self.fields["issue_date"].required = False
+        self.fields["issue_date"].widget.attrs.update({"class": "datepicker"})
+        self.fields["issue_date"].widget.attrs.update({"readonly": False})
+        self.fields["issue_date"].widget.attrs.update({"placeholder": "yyyy-mm-dd (optional)"})
+        self.fields["issue_date"].widget.attrs.update({"pattern": "[0-9]{4}-[0-9]{2}-[0-9]{2}"})
+        self.fields["issue_date"].widget.attrs.update({"required": False})
+        self.fields["issue_date"].initial = timezone.now()
         # hours
-        self.fields['hours'].widget.attrs.update({'min': 0})
+        self.fields["hours"].widget.attrs.update({"min": 0})
         # expiry date
-        self.fields['expiry_date'].widget.attrs['readonly'] = True
-        self.fields['expiry_date'].required = False
-        instance = getattr(self, 'instance', None)
+        self.fields["expiry_date"].widget.attrs["readonly"] = True
+        self.fields["expiry_date"].required = False
+        instance = getattr(self, "instance", None)
         if instance and instance.pk:
-            self.fields['issue_date'].widget.attrs['readonly'] = True
-            self.fields['voucher_type'].widget.attrs['readonly'] = True
-            self.fields['hours'].widget.attrs['readonly'] = True
-            self.fields['activity_type'].widget.attrs['readonly'] = True
-            self.fields['usage_partner'].widget.attrs['readonly'] = True
+            self.fields["issue_date"].widget.attrs["readonly"] = True
+            self.fields["voucher_type"].widget.attrs["readonly"] = True
+            self.fields["hours"].widget.attrs["readonly"] = True
+            self.fields["activity_type"].widget.attrs["readonly"] = True
+            self.fields["usage_partner"].widget.attrs["readonly"] = True
 
             if instance.status in [VOUCHER_STATUS_USED, VOUCHER_STATUS_EXPIRED, VOUCHER_STATUS_REMOVED]:
-                self.fields['status'].widget.attrs['readonly'] = True
-                self.fields['feedback'].widget.attrs['readonly'] = True
+                self.fields["status"].widget.attrs["readonly"] = True
+                self.fields["feedback"].widget.attrs["readonly"] = True
 
     def clean(self):
         # if empty, add a datetime
-        if self.cleaned_data['issue_date'] is None:
-            self.cleaned_data['issue_date'] = timezone.now()
+        if self.cleaned_data["issue_date"] is None:
+            self.cleaned_data["issue_date"] = timezone.now()
 
     def save(self, commit=True):
         instance = super().save(commit=False)
         if not instance.id:
             instance.expiry_date = instance.issue_date + relativedelta(
-                months=+instance.study_subject.study.default_voucher_expiration_in_months)
+                months=+instance.study_subject.study.default_voucher_expiration_in_months
+            )
             max_id = str(1).zfill(5)
             if Voucher.objects.all().count() > 0:
-                max_id = str(Voucher.objects.latest('id').id + 1).zfill(4)
+                max_id = str(Voucher.objects.latest("id").id + 1).zfill(4)
             # number in format  {ND_NUMBER}-{DATE}-{VOUCHER_PARTNER_CODE}-{VOUCHER_TYPE}-{SEQ_NUMBER}{CHECKSUM}
-            instance.number = "{}-{}-{}-{}-{}{}".format(instance.study_subject.nd_number,
-                                                        datetime.datetime.now().strftime("%Y%m%d"),
-                                                        instance.usage_partner.voucher_partner_code,
-                                                        instance.voucher_type.code,
-                                                        max_id,
-                                                        VerhoeffAlgorithm.calculate_verhoeff_check_sum(max_id))
+            # pylint: disable-next=consider-using-f-string
+            instance.number = "{}-{}-{}-{}-{}{}".format(
+                instance.study_subject.nd_number,
+                datetime.datetime.now().strftime("%Y%m%d"),
+                instance.usage_partner.voucher_partner_code,
+                instance.voucher_type.code,
+                max_id,
+                VerhoeffAlgorithm.calculate_verhoeff_check_sum(max_id),
+            )
         if commit:
             instance.save()
diff --git a/smash/web/importer/csv_subject_import_reader.py b/smash/web/importer/csv_subject_import_reader.py
index 68c3276f..df587e77 100644
--- a/smash/web/importer/csv_subject_import_reader.py
+++ b/smash/web/importer/csv_subject_import_reader.py
@@ -45,7 +45,7 @@ class CsvSubjectImportReader(SubjectImportReader):
 
                 for header, value in zip(headers, row):
                     field = self.get_table_and_field(header)[1]
-                    if field is not None and (field.name == "nd_number" or field.name == "screening_number"):
+                    if field is not None and field.name in ("nd_number", "screening_number"):
                         self.add_data(study_subject, header, value)
                 if study_subject.nd_number is None or study_subject.nd_number == "":
                     study_subject.nd_number = study_subject.screening_number
diff --git a/smash/web/importer/importer_cron_job.py b/smash/web/importer/importer_cron_job.py
index 195152ba..19785538 100644
--- a/smash/web/importer/importer_cron_job.py
+++ b/smash/web/importer/importer_cron_job.py
@@ -24,11 +24,11 @@ class SubjectImporterCronJob(CronJobBase):
     try:
         item = SubjectImportData.objects.filter(study_id=GLOBAL_STUDY_ID).first()
         if item is not None:
-            RUN_AT_TIMES = item.run_at_times.split(';')
+            RUN_AT_TIMES = item.run_at_times.split(";")
     except (OperationalError, ProgrammingError):  # sqlite and postgres throw different errors here
-        logger.debug('Looks like db is not initialized')
+        logger.debug("Looks like db is not initialized")
     schedule = Schedule(run_at_times=RUN_AT_TIMES)
-    code = 'web.import_subjects_daily_job'  # a unique code
+    code = "web.import_subjects_daily_job"  # a unique code
 
     def __init__(self, study_id=GLOBAL_STUDY_ID):
         super().__init__()
@@ -40,36 +40,41 @@ class SubjectImporterCronJob(CronJobBase):
         email_recipients = ConfigurationItem.objects.get(type=DEFAULT_FROM_EMAIL).value
 
         for import_data in SubjectImportData.objects.filter(study=self.study).all():
-            if import_data.filename is None or import_data.filename == '':
+            if import_data.filename is None or import_data.filename == "":
                 logger.info("Importing subjects skipped. File not defined ")
                 return "import file not defined"
             filename = import_data.get_absolute_file_path()
             logger.info("Importing subjects from file: %s", filename)
             if not os.path.isfile(filename):
-                content = "<h3><font color='red'>File with imported data is not available in the system: " + \
-                          filename + "</font></h3>"
-                EmailSender.send_email(email_title,
-                                       content,
-                                       email_recipients)
+                content = (
+                    "<h3><font color='red'>File with imported data is not available in the system: "
+                    + filename
+                    + "</font></h3>"
+                )
+                EmailSender.send_email(email_title, content, email_recipients)
                 return "import file not found"
             # noinspection PyBroadException
             try:
                 importer = Importer(CsvSubjectImportReader(import_data))
                 importer.execute()
                 email_body = importer.get_summary()
-                EmailSender.send_email(email_title,
-                                       f"<h3>Data was successfully imported from file: {filename}</h3>{email_body}",
-                                       email_recipients)
+                EmailSender.send_email(
+                    email_title,
+                    f"<h3>Data was successfully imported from file: {filename}</h3>{email_body}",
+                    email_recipients,
+                )
                 backup_file(filename)
                 return "import is successful"
 
             except BaseException:
                 tb = traceback.format_exc()
-                EmailSender.send_email(email_title,
-                                       f"<h3><font color='red'>There was a problem with importing data from file: "
-                                       "{filename}</font></h3><pre>{tb}</pre>",
-                                       email_recipients)
-                logger.exception(f'There was a problem with importing data from file: {filename}')
+                EmailSender.send_email(
+                    email_title,
+                    f"<h3><font color='red'>There was a problem with importing data from file: "
+                    f"{filename}</font></h3><pre>{tb}</pre>",
+                    email_recipients,
+                )
+                logger.exception("There was a problem with importing data from file: %s", filename)
                 return "import crashed"
 
 
@@ -78,11 +83,11 @@ class VisitImporterCronJob(CronJobBase):
     try:
         item = VisitImportData.objects.filter(study_id=GLOBAL_STUDY_ID).first()
         if item is not None:
-            RUN_AT_TIMES = item.run_at_times.split(';')
+            RUN_AT_TIMES = item.run_at_times.split(";")
     except (OperationalError, ProgrammingError):  # sqlite and postgres throw different errors here
-        logger.debug('Looks like db is not initialized')
+        logger.debug("Looks like db is not initialized")
     schedule = Schedule(run_at_times=RUN_AT_TIMES)
-    code = 'web.import_visits_daily_job'  # a unique code
+    code = "web.import_visits_daily_job"  # a unique code
 
     def __init__(self, study_id=GLOBAL_STUDY_ID):
         super().__init__()
@@ -94,15 +99,17 @@ class VisitImporterCronJob(CronJobBase):
         email_recipients = ConfigurationItem.objects.get(type=DEFAULT_FROM_EMAIL).value
 
         for import_data in VisitImportData.objects.filter(study=self.study).all():
-
-            if import_data.filename is None or import_data.filename == '':
+            if import_data.filename is None or import_data.filename == "":
                 logger.info("Importing visits skipped. File not defined ")
                 return "import file not defined"
             filename = import_data.get_absolute_file_path()
             logger.info("Importing visits from file: %s", filename)
             if not import_data.file_available():
-                content = "<h3><font color='red'>File with imported data is not available in the system: " + \
-                          import_data.filename + "</font></h3>"
+                content = (
+                    "<h3><font color='red'>File with imported data is not available in the system: "
+                    + import_data.filename
+                    + "</font></h3>"
+                )
                 EmailSender.send_email(email_title, content, email_recipients)
                 return "import file not found"
 
@@ -111,19 +118,23 @@ class VisitImporterCronJob(CronJobBase):
                 importer = CsvVisitImportReader(import_data)
                 importer.load_data()
                 email_body = importer.get_summary()
-                EmailSender.send_email(email_title,
-                                       f"<h3>Data was successfully imported from file: {filename}</h3>{email_body}",
-                                       email_recipients)
+                EmailSender.send_email(
+                    email_title,
+                    f"<h3>Data was successfully imported from file: {filename}</h3>{email_body}",
+                    email_recipients,
+                )
                 backup_file(filename)
                 return "import is successful"
 
             except BaseException:
                 tb = traceback.format_exc()
-                EmailSender.send_email(email_title,
-                                       "<h3><font color='red'>There was a problem with importing data from file: "
-                                       f"{filename}</font></h3><pre>{tb}</pre>",
-                                       email_recipients)
-                logger.exception(f"There was a problem with importing data from file: {filename}")
+                EmailSender.send_email(
+                    email_title,
+                    "<h3><font color='red'>There was a problem with importing data from file: "
+                    f"{filename}</font></h3><pre>{tb}</pre>",
+                    email_recipients,
+                )
+                logger.exception("There was a problem with importing data from file: %s", filename)
                 return "import crashed"
 
 
diff --git a/smash/web/migrations/0001_version-1-0-0.py b/smash/web/migrations/0001_version-1-0-0.py
index f72b974c..251793ee 100644
--- a/smash/web/migrations/0001_version-1-0-0.py
+++ b/smash/web/migrations/0001_version-1-0-0.py
@@ -1,3 +1,4 @@
+# pylint: disable=too-many-lines
 # Generated by Django 3.1.4 on 2021-10-01 11:26
 
 import django.core.files.storage
@@ -70,12 +71,12 @@ def configuration_item_color_fields__0025(apps, schema_editor):  # pylint: disab
     cancelled_appointment_color.save()
 
 
-def create_item(apps, type, value, name, value_type: str = VALUE_TYPE_TEXT):
+def create_item(apps, _type, value, name, value_type: str = VALUE_TYPE_TEXT):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.value_type = value_type
diff --git a/smash/web/migrations/0032_configurationitem_email_items.py b/smash/web/migrations/0032_configurationitem_email_items.py
index 78b4deff..2145b322 100644
--- a/smash/web/migrations/0032_configurationitem_email_items.py
+++ b/smash/web/migrations/0032_configurationitem_email_items.py
@@ -11,12 +11,12 @@ from web.models.constants import (
 )
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0061_remove_subject_country.py b/smash/web/migrations/0061_remove_subject_country.py
index 23befcb7..e7657e16 100644
--- a/smash/web/migrations/0061_remove_subject_country.py
+++ b/smash/web/migrations/0061_remove_subject_country.py
@@ -2,23 +2,23 @@
 # Generated by Django 1.10.7 on 2017-10-31 09:15
 
 
-from django.db import migrations, models
+from django.db import migrations
 
 
 class Migration(migrations.Migration):
     dependencies = [
-        ('web', '0060_remove_subject_country'),
+        ("web", "0060_remove_subject_country"),
     ]
 
     operations = [
         migrations.RemoveField(
-            model_name='subject',
-            name='country',
+            model_name="subject",
+            name="country",
         ),
         migrations.RenameField(
-            model_name='subject',
-            old_name='country_2',
-            new_name='country',
+            model_name="subject",
+            old_name="country_2",
+            new_name="country",
         ),
-        migrations.RunSQL('update web_country set name=\'---\', "order"=0 where id=1;'),
+        migrations.RunSQL("update web_country set name='---', \"order\"=0 where id=1;"),
     ]
diff --git a/smash/web/migrations/0064_auto_20171127_0954.py b/smash/web/migrations/0064_auto_20171127_0954.py
index 55136985..712cded6 100644
--- a/smash/web/migrations/0064_auto_20171127_0954.py
+++ b/smash/web/migrations/0064_auto_20171127_0954.py
@@ -2,18 +2,14 @@
 # Generated by Django 1.10.7 on 2017-11-27 09:54
 
 
-import django.core.validators
-from django.db import migrations, models
-import django.db.models.deletion
+from django.db import migrations
 
 
 class Migration(migrations.Migration):
     atomic = False
-    
+
     dependencies = [
-        ('web', '0063_auto_20171120_1429'),
+        ("web", "0063_auto_20171120_1429"),
     ]
 
-    operations = [
-        migrations.RenameModel('Subject', 'StudySubject')
-    ]
+    operations = [migrations.RenameModel("Subject", "StudySubject")]
diff --git a/smash/web/migrations/0066_subject.py b/smash/web/migrations/0066_subject.py
index 4f92c9aa..7778b0b3 100644
--- a/smash/web/migrations/0066_subject.py
+++ b/smash/web/migrations/0066_subject.py
@@ -39,7 +39,7 @@ class Migration(migrations.Migration):
                 "web_studyubject_default_location_id_da83b714_fk_web_location_id;"
             ),
             migrations.RunSQL(
-                "alter table web_studysubject rename constraint" "web_subject_pkey to web_studysubject_pkey;"
+                "alter table web_studysubject rename constraint" + "web_subject_pkey to web_studysubject_pkey;"
             ),
             migrations.RunSQL(
                 "alter table web_studysubject_languages rename constraint"
diff --git a/smash/web/migrations/0082_studysubjectlist_visits.py b/smash/web/migrations/0082_studysubjectlist_visits.py
index 8cd76414..fc7ca077 100644
--- a/smash/web/migrations/0082_studysubjectlist_visits.py
+++ b/smash/web/migrations/0082_studysubjectlist_visits.py
@@ -2,14 +2,12 @@
 # Generated by Django 1.10.7 on 2017-12-04 16:47
 
 
-from django.db import migrations, models
+from django.db import migrations
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
-        ('web', '0081_studysubjectlist_last_contact_attempt'),
+        ("web", "0081_studysubjectlist_last_contact_attempt"),
     ]
 
-    operations = [
-    ]
+    operations = []
diff --git a/smash/web/migrations/0086_unfinished_visit_list.py b/smash/web/migrations/0086_unfinished_visit_list.py
index e6221b90..9f35dfae 100644
--- a/smash/web/migrations/0086_unfinished_visit_list.py
+++ b/smash/web/migrations/0086_unfinished_visit_list.py
@@ -2,7 +2,7 @@
 # Generated by Django 1.10.7 on 2017-12-05 16:50
 
 
-from django.db import migrations, models
+from django.db import migrations
 from ..migration_functions import is_sqlite_db
 
 
diff --git a/smash/web/migrations/0106_approaching_post_mail_list_update.py b/smash/web/migrations/0106_approaching_post_mail_list_update.py
index 2b45f359..f6d57a75 100644
--- a/smash/web/migrations/0106_approaching_post_mail_list_update.py
+++ b/smash/web/migrations/0106_approaching_post_mail_list_update.py
@@ -2,7 +2,7 @@
 # Generated by Django 1.10.7 on 2018-02-14 10:26
 
 
-from django.db import migrations, models
+from django.db import migrations
 
 from ..migration_functions import is_sqlite_db
 
diff --git a/smash/web/migrations/0114_auto_20180611_0950.py b/smash/web/migrations/0114_auto_20180611_0950.py
index 7bf9361e..b42ec0cf 100644
--- a/smash/web/migrations/0114_auto_20180611_0950.py
+++ b/smash/web/migrations/0114_auto_20180611_0950.py
@@ -2,16 +2,15 @@
 # Generated by Django 1.10.7 on 2018-06-11 09:50
 
 
-from django.db import migrations, models
-import django.db.models.deletion
+from django.db import migrations
 
 
 class Migration(migrations.Migration):
     dependencies = [
-        ('web', '0113_auto_20180608_1258'),
+        ("web", "0113_auto_20180608_1258"),
     ]
 
     operations = [
-        migrations.RunSQL('delete from web_voucherpartnersession;'),
-        migrations.RunSQL('delete from web_voucher;'),
+        migrations.RunSQL("delete from web_voucherpartnersession;"),
+        migrations.RunSQL("delete from web_voucher;"),
     ]
diff --git a/smash/web/migrations/0158_configurationitem_email_items.py b/smash/web/migrations/0158_configurationitem_email_items.py
index 9dd9143c..5bdd886e 100644
--- a/smash/web/migrations/0158_configurationitem_email_items.py
+++ b/smash/web/migrations/0158_configurationitem_email_items.py
@@ -7,12 +7,12 @@ from django.db import migrations
 from web.models.constants import KIT_DAILY_EMAIL_DAYS_PERIOD_TYPE, KIT_DAILY_EMAIL_TIME_FORMAT_TYPE
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0159_configurationitem_email_items_for_redcap.py b/smash/web/migrations/0159_configurationitem_email_items_for_redcap.py
index bde0d0ae..970ab382 100644
--- a/smash/web/migrations/0159_configurationitem_email_items_for_redcap.py
+++ b/smash/web/migrations/0159_configurationitem_email_items_for_redcap.py
@@ -18,12 +18,12 @@ from web.models.constants import (
 )
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0164_configurationitem_email_items_for_redcap.py b/smash/web/migrations/0164_configurationitem_email_items_for_redcap.py
index 40539225..b9a75fd4 100644
--- a/smash/web/migrations/0164_configurationitem_email_items_for_redcap.py
+++ b/smash/web/migrations/0164_configurationitem_email_items_for_redcap.py
@@ -7,12 +7,12 @@ from django.db import migrations
 from web.models.constants import RED_CAP_SAMPLE_DATE_FIELD_TYPE
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0165_configurationitem_email_virus.py b/smash/web/migrations/0165_configurationitem_email_virus.py
index 1e5c201c..5942ac67 100644
--- a/smash/web/migrations/0165_configurationitem_email_virus.py
+++ b/smash/web/migrations/0165_configurationitem_email_virus.py
@@ -7,12 +7,12 @@ from django.db import migrations
 from web.models.constants import VIRUS_EMAIL_HOUR_CONFIGURATION_TYPE
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0166_auto_20200423_1457.py b/smash/web/migrations/0166_auto_20200423_1457.py
index f2a541e1..31488847 100644
--- a/smash/web/migrations/0166_auto_20200423_1457.py
+++ b/smash/web/migrations/0166_auto_20200423_1457.py
@@ -6,12 +6,12 @@ from web.models.constants import VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
 from django.db import migrations
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0168_rename_radcap_field.py b/smash/web/migrations/0168_rename_radcap_field.py
index ab57c072..37be8307 100644
--- a/smash/web/migrations/0168_rename_radcap_field.py
+++ b/smash/web/migrations/0168_rename_radcap_field.py
@@ -6,12 +6,12 @@ from django.db import migrations
 from web.models.constants import RED_CAP_SAMPLE_DATE_FIELD_TYPE, RED_CAP_KIT_ID_FIELD_TYPE
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0171_configurationitem_serology.py b/smash/web/migrations/0171_configurationitem_serology.py
index f5abbea1..e9ea2ed4 100644
--- a/smash/web/migrations/0171_configurationitem_serology.py
+++ b/smash/web/migrations/0171_configurationitem_serology.py
@@ -7,12 +7,12 @@ from django.db import migrations
 from web.models.constants import RED_CAP_IGA_STATUS_FIELD_TYPE, RED_CAP_IGG_STATUS_FIELD_TYPE
 
 
-def create_item(apps, type, value, name):
+def create_item(apps, _type, value, name):
     # We can't import the ConfigurationItem model directly as it may be a newer
     # version than this migration expects. We use the historical version.
     ConfigurationItem = apps.get_model("web", "ConfigurationItem")
     item = ConfigurationItem.objects.create()
-    item.type = type
+    item.type = _type
     item.value = value
     item.name = name
     item.save()
diff --git a/smash/web/migrations/0173_auto_20201105_1142.py b/smash/web/migrations/0173_auto_20201105_1142.py
index 9332a188..74e66773 100644
--- a/smash/web/migrations/0173_auto_20201105_1142.py
+++ b/smash/web/migrations/0173_auto_20201105_1142.py
@@ -1,26 +1,22 @@
 # Generated by Django 2.0.13 on 2020-11-05 11:42
 
-import django.core.files.storage
-import django.core.validators
 from django.db import migrations, models
-import django.db.models.deletion
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
-        ('web', '0172_auto_20200525_1246'),
+        ("web", "0172_auto_20200525_1246"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='provenance',
-            name='modified_table',
-            field=models.CharField(max_length=1024, null=True, verbose_name='Modified table'),
+            model_name="provenance",
+            name="modified_table",
+            field=models.CharField(max_length=1024, null=True, verbose_name="Modified table"),
         ),
         migrations.AlterField(
-            model_name='provenance',
-            name='modified_table_id',
-            field=models.IntegerField(default=0, null=True, verbose_name='Modified table row'),
-        )
+            model_name="provenance",
+            name="modified_table_id",
+            field=models.IntegerField(default=0, null=True, verbose_name="Modified table row"),
+        ),
     ]
diff --git a/smash/web/migrations/0174_auto_20201105_1157.py b/smash/web/migrations/0174_auto_20201105_1157.py
index b6f2abbb..fdb995fe 100644
--- a/smash/web/migrations/0174_auto_20201105_1157.py
+++ b/smash/web/migrations/0174_auto_20201105_1157.py
@@ -1,21 +1,17 @@
 # Generated by Django 2.0.13 on 2020-11-05 11:57
 
-import django.core.files.storage
-import django.core.validators
 from django.db import migrations, models
-import django.db.models.deletion
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
-        ('web', '0173_auto_20201105_1142'),
+        ("web", "0173_auto_20201105_1142"),
     ]
 
     operations = [
         migrations.AddField(
-            model_name='provenance',
-            name='request_path',
-            field=models.CharField(blank=True, max_length=20480, null=True, verbose_name='Request Path'),
+            model_name="provenance",
+            name="request_path",
+            field=models.CharField(blank=True, max_length=20480, null=True, verbose_name="Request Path"),
         )
     ]
diff --git a/smash/web/migrations/0178_auto_20201116_1250.py b/smash/web/migrations/0178_auto_20201116_1250.py
index 1a8e45fe..91febe10 100644
--- a/smash/web/migrations/0178_auto_20201116_1250.py
+++ b/smash/web/migrations/0178_auto_20201116_1250.py
@@ -1,3 +1,4 @@
+# pylint: disable=too-many-lines
 # Generated by Django 2.0.13 on 2020-11-16 12:50
 
 import django.core.files.storage
diff --git a/smash/web/migrations/0183_auto_20201126_1154.py b/smash/web/migrations/0183_auto_20201126_1154.py
index 2e2670d0..1aeea749 100644
--- a/smash/web/migrations/0183_auto_20201126_1154.py
+++ b/smash/web/migrations/0183_auto_20201126_1154.py
@@ -1,59 +1,57 @@
 # Generated by Django 2.0.13 on 2020-11-26 11:54
 
-import django.core.files.storage
 from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
-        ('web', '0182_auto_20201126_1042'),
+        ("web", "0182_auto_20201126_1042"),
     ]
 
     operations = [
         migrations.RenameField(
-            model_name='subjectcolumns',
-            old_name='next_of_keen_address',
-            new_name='next_of_kin_address',
+            model_name="subjectcolumns",
+            old_name="next_of_keen_address",
+            new_name="next_of_kin_address",
         ),
         migrations.RenameField(
-            model_name='subjectcolumns',
-            old_name='next_of_keen_name',
-            new_name='next_of_kin_name',
+            model_name="subjectcolumns",
+            old_name="next_of_keen_name",
+            new_name="next_of_kin_name",
         ),
         migrations.RenameField(
-            model_name='subjectcolumns',
-            old_name='next_of_keen_phone',
-            new_name='next_of_kin_phone',
+            model_name="subjectcolumns",
+            old_name="next_of_keen_phone",
+            new_name="next_of_kin_phone",
         ),
         migrations.RenameField(
-            model_name='subject',
-            old_name='next_of_keen_address',
-            new_name='next_of_kin_address',
+            model_name="subject",
+            old_name="next_of_keen_address",
+            new_name="next_of_kin_address",
         ),
         migrations.RenameField(
-            model_name='subject',
-            old_name='next_of_keen_name',
-            new_name='next_of_kin_name',
+            model_name="subject",
+            old_name="next_of_keen_name",
+            new_name="next_of_kin_name",
         ),
         migrations.RenameField(
-            model_name='subject',
-            old_name='next_of_keen_phone',
-            new_name='next_of_kin_phone',
+            model_name="subject",
+            old_name="next_of_keen_phone",
+            new_name="next_of_kin_phone",
         ),
         migrations.AlterField(
-            model_name='subject',
-            name='next_of_kin_address',
-            field=models.TextField(blank=True, max_length=2000, verbose_name='Next of kin address'),
+            model_name="subject",
+            name="next_of_kin_address",
+            field=models.TextField(blank=True, max_length=2000, verbose_name="Next of kin address"),
         ),
         migrations.AlterField(
-            model_name='subject',
-            name='next_of_kin_name',
-            field=models.CharField(blank=True, max_length=255, verbose_name='Next of kin'),
+            model_name="subject",
+            name="next_of_kin_name",
+            field=models.CharField(blank=True, max_length=255, verbose_name="Next of kin"),
         ),
         migrations.AlterField(
-            model_name='subject',
-            name='next_of_kin_phone',
-            field=models.CharField(blank=True, max_length=50, verbose_name='Next of kin phone'),
+            model_name="subject",
+            name="next_of_kin_phone",
+            field=models.CharField(blank=True, max_length=50, verbose_name="Next of kin phone"),
         ),
     ]
diff --git a/smash/web/migrations/0194_migrate_subject_type_to_new_structure.py b/smash/web/migrations/0194_migrate_subject_type_to_new_structure.py
index d1da504c..231d01ed 100644
--- a/smash/web/migrations/0194_migrate_subject_type_to_new_structure.py
+++ b/smash/web/migrations/0194_migrate_subject_type_to_new_structure.py
@@ -2,43 +2,49 @@
 
 from django.db import migrations
 
-from web.models.constants import GLOBAL_STUDY_ID
-from web.models.study import FOLLOW_UP_INCREMENT_IN_YEARS
-from ..migration_functions import is_sqlite_db
+patient_prefix = "P"
 
-patient_prefix = 'P'
-
-control_prefix = 'L'
+control_prefix = "L"
 
 
 class Migration(migrations.Migration):
     dependencies = [
-        ('web', '0193_subjecttype'),
+        ("web", "0193_subjecttype"),
     ]
 
     operations = [
-        migrations.RunSQL("insert into web_subjecttype " +
-                          "(name, screening_number_prefix, follow_up_delta_time, follow_up_delta_units, "
-                          "auto_create_follow_up, study_id) " +
-                          "select 'PATIENT' , '" +
-                          patient_prefix + "', " +
-                          "default_delta_time_for_patient_follow_up," +
-                          "default_delta_time_for_follow_up_units," +
-                          "auto_create_follow_up," +
-                          "id from web_study"),
-        migrations.RunSQL("update web_studysubject " +
-                          " set new_type_id = (select max(id) from web_subjecttype) where type = 'P'"),
-        migrations.RunSQL("insert into web_subjecttype " +
-                          "(name, screening_number_prefix, follow_up_delta_time, follow_up_delta_units, "
-                          "auto_create_follow_up, study_id) " +
-                          "select 'CONTROL' , '" +
-                          control_prefix + "', " +
-                          "default_delta_time_for_control_follow_up," +
-                          "default_delta_time_for_follow_up_units," +
-                          "auto_create_follow_up," +
-                          "id from web_study"),
-        migrations.RunSQL("update web_studysubject " +
-                          " set new_type_id = (select max(id) from web_subjecttype) where type = 'C'"),
-        migrations.RunSQL("update web_studysubject " +
-                          " set new_type_id = (select max(id) from web_subjecttype) where new_type_id is null"),
+        migrations.RunSQL(
+            "insert into web_subjecttype "
+            + "(name, screening_number_prefix, follow_up_delta_time, follow_up_delta_units, "
+            "auto_create_follow_up, study_id) "
+            + "select 'PATIENT' , '"
+            + patient_prefix
+            + "', "
+            + "default_delta_time_for_patient_follow_up,"
+            + "default_delta_time_for_follow_up_units,"
+            + "auto_create_follow_up,"
+            + "id from web_study"
+        ),
+        migrations.RunSQL(
+            "update web_studysubject " + " set new_type_id = (select max(id) from web_subjecttype) where type = 'P'"
+        ),
+        migrations.RunSQL(
+            "insert into web_subjecttype "
+            + "(name, screening_number_prefix, follow_up_delta_time, follow_up_delta_units, "
+            "auto_create_follow_up, study_id) "
+            + "select 'CONTROL' , '"
+            + control_prefix
+            + "', "
+            + "default_delta_time_for_control_follow_up,"
+            + "default_delta_time_for_follow_up_units,"
+            + "auto_create_follow_up,"
+            + "id from web_study"
+        ),
+        migrations.RunSQL(
+            "update web_studysubject " + " set new_type_id = (select max(id) from web_subjecttype) where type = 'C'"
+        ),
+        migrations.RunSQL(
+            "update web_studysubject "
+            + " set new_type_id = (select max(id) from web_subjecttype) where new_type_id is null"
+        ),
     ]
diff --git a/smash/web/migrations/0212_auto_20231024_1238.py b/smash/web/migrations/0212_auto_20231024_1238.py
index b161ab2e..1fc38ff2 100644
--- a/smash/web/migrations/0212_auto_20231024_1238.py
+++ b/smash/web/migrations/0212_auto_20231024_1238.py
@@ -5,20 +5,31 @@ from django.db import migrations, models
 
 
 class Migration(migrations.Migration):
-
     dependencies = [
-        ('web', '0211_subjectexport_data'),
+        ("web", "0211_subjectexport_data"),
     ]
 
     operations = [
         migrations.AlterField(
-            model_name='study',
-            name='nd_number_study_subject_regex',
-            field=models.CharField(default='^ND\\d{4}$', help_text='Defines the regex to check the ID used for each study subject. Keep in mind that this regex should be valid for all previous study subjects in the database.', max_length=255, verbose_name='Study Subject ND Number Regex'),
+            model_name="study",
+            name="nd_number_study_subject_regex",
+            field=models.CharField(
+                default="^ND\\d{4}$",
+                help_text="Defines the regex to check the ID used for each study subject."
+                + " Keep in mind that this regex should be valid for all previous study subjects in the database.",
+                max_length=255,
+                verbose_name="Study Subject ND Number Regex",
+            ),
         ),
         migrations.AlterField(
-            model_name='studysubject',
-            name='referral_letter',
-            field=models.FileField(blank=True, null=True, storage=django.core.files.storage.FileSystemStorage(location='/tmp/upload'), upload_to='referral_letters', verbose_name='Referral letter'),
+            model_name="studysubject",
+            name="referral_letter",
+            field=models.FileField(
+                blank=True,
+                null=True,
+                storage=django.core.files.storage.FileSystemStorage(location="/tmp/upload"),
+                upload_to="referral_letters",
+                verbose_name="Referral letter",
+            ),
         ),
     ]
diff --git a/smash/web/officeAvailability.py b/smash/web/officeAvailability.py
index 51ed62c5..f7a15419 100644
--- a/smash/web/officeAvailability.py
+++ b/smash/web/officeAvailability.py
@@ -259,8 +259,10 @@ class OfficeAvailability:
         else:
             xticks = self.availability.asfreq(f"{n_ticks}H").index
 
-        title = f'Availability for {self.name} from {self.start.strftime("%Y/%m/%d %H:%M")}'
-        ' to {self.end.strftime("%Y/%m/%d %H:%M")}'
+        title = (
+            f'Availability for {self.name} from {self.start.strftime("%Y/%m/%d %H:%M")}'
+            + ' to {self.end.strftime("%Y/%m/%d %H:%M")}'
+        )
 
         axes = self.availability.plot(
             figsize=(16, 8),
diff --git a/smash/web/templatetags/filters.py b/smash/web/templatetags/filters.py
index 718e488e..339bd0e3 100644
--- a/smash/web/templatetags/filters.py
+++ b/smash/web/templatetags/filters.py
@@ -14,30 +14,30 @@ from web.models.constants import VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
 register = template.Library()
 
 
-@register.filter(name='add_class')
+@register.filter(name="add_class")
 def add_class(value, arg):
     # Get all the field's initial css-classes
     if isinstance(value.field.widget, CheckboxSelectMultiple):
         return value
     if isinstance(value.field.widget, CheckboxInput):
-        arg = 'checkbox'
-    css_classes = value.field.widget.attrs.get('class', ' ').split(' ')
+        arg = "checkbox"
+    css_classes = value.field.widget.attrs.get("class", " ").split(" ")
     # Filter out zero-length class names ('')
     css_classes = [x for x in css_classes if len(x) > 0]
     # Convert list to string
     css_classes = reduce(lambda a, x: f"{a} {x}", css_classes, "")
-    css_classes = f'{css_classes} {arg}'
+    css_classes = f"{css_classes} {arg}"
     # Return the widget with freshly crafted classes
-    return value.as_widget(attrs={'class': css_classes})
+    return value.as_widget(attrs={"class": css_classes})
 
 
-@register.filter(name='disable')
+@register.filter(name="disable")
 def disable(value):
-    value.field.widget.attrs['disabled'] = 'disabled'
+    value.field.widget.attrs["disabled"] = "disabled"
     return value
 
 
-@register.filter(name='is_checkbox')
+@register.filter(name="is_checkbox")
 def is_checkbox(value):
     return isinstance(value.field.widget, CheckboxSelectMultiple)
 
@@ -46,7 +46,7 @@ def is_checkbox(value):
 def render_appointments(statistics, appointment_type):
     html = ""
     for status_count in statistics.get(appointment_type, []):
-        html += f'<td>{status_count}</td>'
+        html += f"<td>{status_count}</td>"
     return mark_safe(html)
 
 
@@ -56,16 +56,16 @@ def timestamp(value):
     return (value.replace(tzinfo=None) - epoch).total_seconds()
 
 
-@register.filter(name='display_visit_number')
+@register.filter(name="display_visit_number")
 def display_visit_number(visit_number):
     visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
     # True values are y, yes, t, true, on and 1; false values are n, no, f, false, off and 0.
     if strtobool(visit_from_zero):
-        return (visit_number - 1)
+        return visit_number - 1
     else:
         return visit_number
 
 
-@register.filter(name='basename')
+@register.filter(name="basename")
 def basename(path):
     return os.path.basename(path)
diff --git a/smash/web/tests/models/test_study_subject.py b/smash/web/tests/models/test_study_subject.py
index 5bbd8a71..727366a4 100644
--- a/smash/web/tests/models/test_study_subject.py
+++ b/smash/web/tests/models/test_study_subject.py
@@ -4,12 +4,15 @@ from web.models import Appointment, Visit, StudySubject, Study
 from web.models.constants import CUSTOM_FIELD_TYPE_TEXT
 from web.models.custom_data import CustomStudySubjectField
 from web.tests.functions import create_visit, create_study
-from web.tests.functions import get_test_study, create_study_subject, create_appointment, \
-    create_study_subject_with_multiple_screening_numbers
+from web.tests.functions import (
+    get_test_study,
+    create_study_subject,
+    create_appointment,
+    create_study_subject_with_multiple_screening_numbers,
+)
 
 
 class SubjectModelTests(TestCase):
-
     def test_signal_mark_as_endpoint_reached(self):
         subject = create_study_subject()
         visit = create_visit(subject)
@@ -17,14 +20,12 @@ class SubjectModelTests(TestCase):
 
         subject.endpoint_reached = True
         subject.save()
-        appointment_status = Appointment.objects.filter(id=appointment.id)[
-            0].status
+        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
         visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
 
         self.assertTrue(subject.endpoint_reached)
         self.assertTrue(visit_finished)
-        self.assertEqual(
-            Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
+        self.assertEqual(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
 
     def test_mark_as_endpoint_reached(self):
         subject = create_study_subject()
@@ -32,14 +33,12 @@ class SubjectModelTests(TestCase):
         appointment = create_appointment(visit)
 
         subject.mark_as_endpoint_reached()
-        appointment_status = Appointment.objects.filter(id=appointment.id)[
-            0].status
+        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
         visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
 
         self.assertTrue(subject.endpoint_reached)
         self.assertTrue(visit_finished)
-        self.assertEqual(
-            Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
+        self.assertEqual(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
 
     def test_signal_mark_as_resigned(self):
         subject = create_study_subject()
@@ -48,14 +47,12 @@ class SubjectModelTests(TestCase):
 
         subject.resigned = True
         subject.save()
-        appointment_status = Appointment.objects.filter(id=appointment.id)[
-            0].status
+        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
         visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
 
         self.assertTrue(subject.resigned)
         self.assertTrue(visit_finished)
-        self.assertEqual(
-            Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
+        self.assertEqual(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
 
     def test_mark_as_resigned(self):
         subject = create_study_subject()
@@ -63,14 +60,12 @@ class SubjectModelTests(TestCase):
         appointment = create_appointment(visit)
 
         subject.mark_as_resigned()
-        appointment_status = Appointment.objects.filter(id=appointment.id)[
-            0].status
+        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
         visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
 
         self.assertTrue(subject.resigned)
         self.assertTrue(visit_finished)
-        self.assertEqual(
-            Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
+        self.assertEqual(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
 
     def test_signal_mark_as_excluded(self):
         subject = create_study_subject()
@@ -79,14 +74,12 @@ class SubjectModelTests(TestCase):
 
         subject.excluded = True
         subject.save()
-        appointment_status = Appointment.objects.filter(id=appointment.id)[
-            0].status
+        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
         visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
 
         self.assertTrue(subject.excluded)
         self.assertTrue(visit_finished)
-        self.assertEqual(
-            Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
+        self.assertEqual(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
 
     def test_mark_as_excluded(self):
         subject = create_study_subject()
@@ -94,14 +87,12 @@ class SubjectModelTests(TestCase):
         appointment = create_appointment(visit)
 
         subject.mark_as_excluded()
-        appointment_status = Appointment.objects.filter(id=appointment.id)[
-            0].status
+        appointment_status = Appointment.objects.filter(id=appointment.id)[0].status
         visit_finished = Visit.objects.filter(id=visit.id)[0].is_finished
 
         self.assertTrue(subject.excluded)
         self.assertTrue(visit_finished)
-        self.assertEqual(
-            Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
+        self.assertEqual(Appointment.APPOINTMENT_STATUS_CANCELLED, appointment_status)
 
     def test_check_nd_number_regex(self):
         study = get_test_study()
@@ -109,70 +100,83 @@ class SubjectModelTests(TestCase):
         # delete everything
         StudySubject.objects.all().delete()
         # get default regex
-        nd_number_study_subject_regex_default = Study._meta.get_field(
-            'nd_number_study_subject_regex').get_default()
+        nd_number_study_subject_regex_default = Study._meta.get_field("nd_number_study_subject_regex").get_default()
 
         self.assertTrue(StudySubject.check_nd_number_regex(nd_number_study_subject_regex_default, study))
         # this will add a studysubject with a NDnumber
-        create_study_subject(nd_number='ND0001')
+        create_study_subject(nd_number="ND0001")
 
         self.assertTrue(StudySubject.check_nd_number_regex(nd_number_study_subject_regex_default, study))
         # delete everything
         StudySubject.objects.all().delete()
         # this will add a studysubject with a NDnumber
-        create_study_subject(nd_number='ND00001')
+        create_study_subject(nd_number="ND00001")
         self.assertFalse(StudySubject.check_nd_number_regex(nd_number_study_subject_regex_default, study))
 
     def test_sort_matched_screening_first(self):
         def create_result(phrase, subject_id=1):
             phrase = phrase.format(subject_id=subject_id)
-            phrase = phrase.split(';')
+            phrase = phrase.split(";")
             for i, _ in enumerate(phrase):
-                letter, num = phrase[i].strip().split('-')
+                letter, num = _.strip().split("-")
                 phrase[i] = (letter, int(num))
             return phrase
 
-        subject = create_study_subject_with_multiple_screening_numbers(
-            subject_id=1)
-        self.assertEqual(subject.sort_matched_screening_first('L'), create_result(
-            'L-00{subject_id}; E-00{subject_id}', subject_id=1))
-        self.assertEqual(subject.sort_matched_screening_first(
-            'L-00'), create_result('L-00{subject_id}; E-00{subject_id}', subject_id=1))
-        self.assertEqual(subject.sort_matched_screening_first('E'), create_result(
-            'E-00{subject_id}; L-00{subject_id}', subject_id=1))
-        self.assertEqual(subject.sort_matched_screening_first(
-            '-'), create_result('E-00{subject_id}; L-00{subject_id}', subject_id=1))
-        self.assertEqual(subject.sort_matched_screening_first(''), create_result(
-            'E-00{subject_id}; L-00{subject_id}', subject_id=1))
-        self.assertEqual(subject.sort_matched_screening_first('001'), create_result(
-            'E-00{subject_id}; L-00{subject_id}', subject_id=1))
-        self.assertEqual(subject.sort_matched_screening_first('00'), create_result(
-            'E-00{subject_id}; L-00{subject_id}', subject_id=1))
-        self.assertEqual(subject.sort_matched_screening_first('potato'), create_result(
-            'E-00{subject_id}; L-00{subject_id}', subject_id=1))
+        subject = create_study_subject_with_multiple_screening_numbers(subject_id=1)
+        self.assertEqual(
+            subject.sort_matched_screening_first("L"), create_result("L-00{subject_id}; E-00{subject_id}", subject_id=1)
+        )
+        self.assertEqual(
+            subject.sort_matched_screening_first("L-00"),
+            create_result("L-00{subject_id}; E-00{subject_id}", subject_id=1),
+        )
+        self.assertEqual(
+            subject.sort_matched_screening_first("E"), create_result("E-00{subject_id}; L-00{subject_id}", subject_id=1)
+        )
+        self.assertEqual(
+            subject.sort_matched_screening_first("-"), create_result("E-00{subject_id}; L-00{subject_id}", subject_id=1)
+        )
+        self.assertEqual(
+            subject.sort_matched_screening_first(""), create_result("E-00{subject_id}; L-00{subject_id}", subject_id=1)
+        )
+        self.assertEqual(
+            subject.sort_matched_screening_first("001"),
+            create_result("E-00{subject_id}; L-00{subject_id}", subject_id=1),
+        )
+        self.assertEqual(
+            subject.sort_matched_screening_first("00"),
+            create_result("E-00{subject_id}; L-00{subject_id}", subject_id=1),
+        )
+        self.assertEqual(
+            subject.sort_matched_screening_first("potato"),
+            create_result("E-00{subject_id}; L-00{subject_id}", subject_id=1),
+        )
 
     def test_sort_matched_screening_first_bad_number(self):
         subject_id = 2
-        screening_number = f'L-0/0{subject_id}; E-00{subject_id}; F-0/1{subject_id}'
+        screening_number = f"L-0/0{subject_id}; E-00{subject_id}; F-0/1{subject_id}"
 
         subject = create_study_subject_with_multiple_screening_numbers(
-            subject_id=subject_id, screening_number=screening_number)
+            subject_id=subject_id, screening_number=screening_number
+        )
 
-        self.assertEqual(subject.sort_matched_screening_first('E-'), [('E', subject_id), ('F', '0/12'), ('L', '0/02')])
+        self.assertEqual(subject.sort_matched_screening_first("E-"), [("E", subject_id), ("F", "0/12"), ("L", "0/02")])
 
-        self.assertEqual(subject.sort_matched_screening_first('L-'), [('L', '0/02'), ('E', subject_id), ('F', '0/12')])
+        self.assertEqual(subject.sort_matched_screening_first("L-"), [("L", "0/02"), ("E", subject_id), ("F", "0/12")])
 
     def test_sort_matched_screening_first_bad_format(self):
-        screening_number = 'potato; tomato'
+        screening_number = "potato; tomato"
         subject_id = 3
         subject = create_study_subject_with_multiple_screening_numbers(
-            subject_id=subject_id, screening_number=screening_number)
+            subject_id=subject_id, screening_number=screening_number
+        )
 
-        self.assertEqual(subject.sort_matched_screening_first('L-'), [('potato', None), ('tomato', None)])
+        self.assertEqual(subject.sort_matched_screening_first("L-"), [("potato", None), ("tomato", None)])
 
     def test_subject_with_custom_field(self):
-        field = CustomStudySubjectField.objects.create(study=get_test_study(), default_value="xyz",
-                                                       type=CUSTOM_FIELD_TYPE_TEXT)
+        field = CustomStudySubjectField.objects.create(
+            study=get_test_study(), default_value="xyz", type=CUSTOM_FIELD_TYPE_TEXT
+        )
 
         subject = create_study_subject()
 
@@ -183,8 +187,9 @@ class SubjectModelTests(TestCase):
         self.assertEqual(field, value.study_subject_field)
 
     def test_subject_with_removed_custom_field(self):
-        field = CustomStudySubjectField.objects.create(study=get_test_study(), default_value="xyz",
-                                                       type=CUSTOM_FIELD_TYPE_TEXT)
+        field = CustomStudySubjectField.objects.create(
+            study=get_test_study(), default_value="xyz", type=CUSTOM_FIELD_TYPE_TEXT
+        )
 
         subject = create_study_subject()
         self.assertEqual(1, len(subject.custom_data_values))
@@ -193,7 +198,7 @@ class SubjectModelTests(TestCase):
         self.assertEqual(0, len(subject.custom_data_values))
 
     def test_subject_with_field_from_different_study(self):
-        field = CustomStudySubjectField.objects.create(study=create_study('bla'), type=CUSTOM_FIELD_TYPE_TEXT)
+        field = CustomStudySubjectField.objects.create(study=create_study("bla"), type=CUSTOM_FIELD_TYPE_TEXT)
 
         subject = create_study_subject()
         self.assertIsNone(subject.get_custom_data_value(field))
@@ -201,7 +206,11 @@ class SubjectModelTests(TestCase):
     def test_status(self):
         subject = create_study_subject()
         # noinspection PySetFunctionToLiteral
-        statuses = set([subject.status, ])
+        statuses = set(
+            [
+                subject.status,
+            ]
+        )
         subject.endpoint_reached = True
         statuses.add(subject.status)
         subject.excluded = True
diff --git a/smash/web/tests/view/test_privacy_notice.py b/smash/web/tests/view/test_privacy_notice.py
index abd22b6f..54ec848a 100644
--- a/smash/web/tests/view/test_privacy_notice.py
+++ b/smash/web/tests/view/test_privacy_notice.py
@@ -16,19 +16,14 @@ class PrivacyNoticeTests(LoggedInTestCase):
         self.assertEqual(0, PrivacyNotice.objects.count())
         self.login_as_admin()
 
-        form_data = dict(
-            name='example',
-            summary='example summary'
-        )
+        form_data = {"name": "example", "summary": "example summary"}
 
-        file_data = dict(
-            document=SimpleUploadedFile('file.txt', b"file_content")
-        )
+        file_data = {"document": SimpleUploadedFile("file.txt", b"file_content")}
 
         form = PrivacyNoticeForm(form_data, file_data)
         self.assertTrue(form.is_valid())
 
-        page = reverse('web.views.privacy_notice_add')
+        page = reverse("web.views.privacy_notice_add")
         response = self.client.post(page, data={**form_data, **file_data})
         self.assertEqual(response.status_code, 302)
         self.assertEqual(1, PrivacyNotice.objects.count())
@@ -42,28 +37,23 @@ class PrivacyNoticeTests(LoggedInTestCase):
     def test_edit_privacy_notice(self):
         self.assertEqual(1, PrivacyNotice.objects.count())
         pn = PrivacyNotice.objects.all()[0]
-        form_data = dict(
-            name='example2',
-            summary=pn.summary
-        )
+        form_data = {"name": "example2", "summary": pn.summary}
 
-        file_data = dict(
-            document=SimpleUploadedFile('file.txt', b"file_content")
-        )
+        file_data = {"document": SimpleUploadedFile("file.txt", b"file_content")}
 
         form = PrivacyNoticeForm(form_data, file_data, instance=pn)
         self.assertTrue(form.is_valid())
 
-        page = reverse('web.views.privacy_notice_edit', kwargs={'pk': pn.id})
+        page = reverse("web.views.privacy_notice_edit", kwargs={"pk": pn.id})
         response = self.client.post(page, data={**form_data, **file_data})
         self.assertEqual(response.status_code, 302)
         pn = PrivacyNotice.objects.all()[0]
-        self.assertEqual(pn.name, 'example2')
+        self.assertEqual(pn.name, "example2")
 
     def test_delete_privacy_notice(self):
         self.assertEqual(1, PrivacyNotice.objects.count())
         pn = PrivacyNotice.objects.all()[0]
-        page = reverse('web.views.privacy_notice_delete', kwargs={'pk': pn.id})
+        page = reverse("web.views.privacy_notice_delete", kwargs={"pk": pn.id})
         response = self.client.post(page)
         self.assertEqual(response.status_code, 302)
         self.assertEqual(0, PrivacyNotice.objects.count())
@@ -83,7 +73,7 @@ class PrivacyNoticeTests(LoggedInTestCase):
 
         self.login_as_super()
         self.assertEqual(self.staff_worker.privacy_notice_accepted, False)
-        page = reverse('web.views.appointments')
+        page = reverse("web.views.appointments")
         response = self.client.get(page)
         self.assertEqual(response.status_code, 200)
         messages = list(get_messages(response.wsgi_request))
@@ -104,17 +94,17 @@ class PrivacyNoticeTests(LoggedInTestCase):
 
         self.login_as_staff()
         self.assertEqual(self.staff_worker.privacy_notice_accepted, False)
-        page = reverse('web.views.appointments')
+        page = reverse("web.views.appointments")
         response = self.client.get(page)
         self.assertEqual(response.status_code, 302)
         messages = list(get_messages(response.wsgi_request))
         self.assertEqual(len(messages), 1)
         self.assertEqual(str(messages[0]), "You can't use the system until you accept the privacy notice.")
         # accept privacy notice
-        form_data = dict(privacy_notice_accepted=True)
+        form_data = {"privacy_notice_accepted": True}
         form = WorkerAcceptPrivacyNoticeForm(form_data)
         self.assertTrue(form.is_valid())
-        page = reverse('web.views.accept_privacy_notice', kwargs={'pk': pn.id})
+        page = reverse("web.views.accept_privacy_notice", kwargs={"pk": pn.id})
         response = self.client.post(page, data={**form_data})
         self.assertEqual(response.status_code, 302)
         messages = [m.message for m in get_messages(response.wsgi_request)]
@@ -122,7 +112,7 @@ class PrivacyNoticeTests(LoggedInTestCase):
         # check acceptance
         worker = Worker.objects.filter(id=self.staff_worker.id).first()
         self.assertEqual(worker.privacy_notice_accepted, True)
-        page = reverse('web.views.appointments')
+        page = reverse("web.views.appointments")
         response = self.client.get(page)
         self.assertEqual(response.status_code, 200)
         messages = list(get_messages(response.wsgi_request))
diff --git a/smash/web/views/subject.py b/smash/web/views/subject.py
index aca4e134..84106125 100644
--- a/smash/web/views/subject.py
+++ b/smash/web/views/subject.py
@@ -159,7 +159,7 @@ def subject_edit(request, subject_id):
 
             if "type" in study_subject_form.changed_data and old_type != study_subject_form.cleaned_data["type"]:
                 worker = Worker.get_by_user(request.user)
-                old_value = old_type.name
+                # old_value = old_type.name
                 new_value = None
                 if study_subject_form.cleaned_data["type"] is not None:
                     new_value = study_subject_form.cleaned_data["type"].name
diff --git a/smash/web/views/virus_mail.py b/smash/web/views/virus_mail.py
index 98064be6..a9e8e3b5 100644
--- a/smash/web/views/virus_mail.py
+++ b/smash/web/views/virus_mail.py
@@ -7,8 +7,7 @@ from django.db.models import When, Case, Min
 from django_cron import CronJobBase, Schedule
 
 from web.models import ConfigurationItem
-from web.models.constants import VIRUS_EMAIL_HOUR_CONFIGURATION_TYPE, \
-    CRON_JOB_TIMEOUT, GLOBAL_STUDY_ID
+from web.models.constants import VIRUS_EMAIL_HOUR_CONFIGURATION_TYPE, CRON_JOB_TIMEOUT, GLOBAL_STUDY_ID
 from ..models import StudySubject, Worker
 from ..models.custom_data import CustomStudySubjectField
 from ..smash_email import EmailSender
@@ -20,24 +19,44 @@ def count_subjects(date_when: datetime, status: str) -> int:
     result = 0
     str_date = date_when.strftime("%Y-%m-%d")
     for i in range(0, 10):
-        fields = CustomStudySubjectField.objects.filter(study_id=GLOBAL_STUDY_ID,
-                                                        name=f'Visit {i} RT-PCR collection date').all()
+        fields = CustomStudySubjectField.objects.filter(
+            study_id=GLOBAL_STUDY_ID, name=f"Visit {i} RT-PCR collection date"
+        ).all()
         collect_field = None
         if len(fields) > 0:
             collect_field = fields[0]
-        fields = CustomStudySubjectField.objects.filter(study_id=GLOBAL_STUDY_ID,
-                                                        name__contains=f'Virus {i} RT-PCR').all()
+        fields = CustomStudySubjectField.objects.filter(
+            study_id=GLOBAL_STUDY_ID, name__contains=f"Virus {i} RT-PCR"
+        ).all()
         status_field = None
         if len(fields) > 0:
             status_field = fields[0]
         if collect_field is not None and status_field is not None:
-            print('exist')
-            result += StudySubject.objects.annotate(
-                custom_field_update_value=Min(Case(When(customstudysubjectvalue__study_subject_field=collect_field,
-                                                        then='customstudysubjectvalue__value')))).annotate(
-                custom_field_status_value=Min(Case(When(customstudysubjectvalue__study_subject_field=status_field,
-                                                        then='customstudysubjectvalue__value')))).filter(
-                custom_field_update_value=str_date, custom_field_status_value=status).count()
+            print("exist")
+            result += (
+                StudySubject.objects.annotate(
+                    custom_field_update_value=Min(
+                        Case(
+                            When(
+                                customstudysubjectvalue__study_subject_field=collect_field,
+                                then="customstudysubjectvalue__value",
+                            )
+                        )
+                    )
+                )
+                .annotate(
+                    custom_field_status_value=Min(
+                        Case(
+                            When(
+                                customstudysubjectvalue__study_subject_field=status_field,
+                                then="customstudysubjectvalue__value",
+                            )
+                        )
+                    )
+                )
+                .filter(custom_field_update_value=str_date, custom_field_status_value=status)
+                .count()
+            )
     return result
 
 
@@ -48,9 +67,12 @@ def get_subject_statistics():
     subjects_negative_count = count_subjects(date_from, "Negative")
     subjects_inconclusive_count = count_subjects(date_from, "Inconclusive")
 
-    return {"Positive": subjects_positive_count, "Negative": subjects_negative_count,
-            "Inconclusive": subjects_inconclusive_count,
-            "total": subjects_positive_count + subjects_negative_count + subjects_inconclusive_count}
+    return {
+        "Positive": subjects_positive_count,
+        "Negative": subjects_negative_count,
+        "Inconclusive": subjects_inconclusive_count,
+        "total": subjects_positive_count + subjects_negative_count + subjects_inconclusive_count,
+    }
 
 
 def create_statistic_email_content(data, title):
@@ -70,19 +92,24 @@ def create_statistic_email_content(data, title):
 
     for status in data:
         if status != "total":
+            # pylint: disable-next=consider-using-f-string
             email_body += """
             <tr style="border: 1px solid black;">
                 <td style="border: 1px solid black;">{}</td>
                 <td style="border: 1px solid black; text-align: right;">{}</td>
             </tr>
-            """.format(status, data[status])
-
+            """.format(
+                status, data[status]
+            )
+    # pylint: disable-next=consider-using-f-string
     email_body += """
         <tr style="border: 1px solid black;">
             <td style="border: 1px solid black;">{}</td>
             <td style="border: 1px solid black; text-align: right;">{}</td>
         </tr>
-    """.format('Total', data["total"])
+    """.format(
+        "Total", data["total"]
+    )
 
     email_body += "</table>"
 
@@ -107,7 +134,7 @@ def send_mail(data):
                 if worker.email is not None and worker.email != "":
                     recipients.append(worker.email)
     cc_recipients = []
-    logger.warning('Calling to send email')
+    logger.warning("Calling to send email")
     EmailSender.send_email(title, email_body, ";".join(recipients), cc_recipients)
 
 
@@ -118,14 +145,14 @@ class KitRequestEmailSendJob(CronJobBase):
     try:
         times = ConfigurationItem.objects.get(type=VIRUS_EMAIL_HOUR_CONFIGURATION_TYPE).value.split(";")
         for entry in times:
-            if entry != '':
+            if entry != "":
                 # it's a hack assuming that we are in CEST
                 text = str((int(entry.split(":")[0]) + 22) % 24) + ":" + entry.split(":")[1]
                 RUN_AT.append(text)
     except BaseException as e:
         logger.debug("Cannot fetch data about email hour")
     schedule = Schedule(run_at_times=RUN_AT)
-    code = 'web.virus_daily_email'  # a unique code
+    code = "web.virus_daily_email"  # a unique code
 
     # pylint: disable=no-self-use
     @timeout_decorator.timeout(CRON_JOB_TIMEOUT)
-- 
GitLab