diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py
index 808cf020e38baab072d52113df9c2f29c2eb635f..2ee56a843200565748644a27b4c298291cf526df 100644
--- a/smash/web/api_views/subject.py
+++ b/smash/web/api_views/subject.py
@@ -1,7 +1,6 @@
 from django.db.models import F
 import logging
 import re
-from distutils.util import strtobool
 
 from django.core.handlers.wsgi import WSGIRequest
 from django.db.models import Count, Case, When, Min, Max, QuerySet
@@ -9,6 +8,7 @@ from django.db.models import Q
 from django.http import JsonResponse, HttpRequest, HttpResponseNotAllowed, HttpResponse
 from django.urls import reverse
 
+from web.utils import strtobool
 from web.api_views.serialization_utils import (
     str_to_yes_no_null,
     bool_to_yes_no,
@@ -42,7 +42,10 @@ from web.models.constants import (
     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.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,
@@ -63,20 +66,28 @@ logger = logging.getLogger(__name__)
 
 # noinspection PyUnusedLocal
 def cities(request):
-    result_subjects = Subject.objects.filter(city__isnull=False).values_list("city").distinct()
+    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()
+    result_subjects = (
+        StudySubject.objects.filter(referral__isnull=False)
+        .values_list("referral")
+        .distinct()
+    )
     return JsonResponse({"referrals": [x[0] for x in result_subjects]})
 
 
 # noinspection PyUnusedLocal
 def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonResponse:
     study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0]
-    study_subject_lists = StudySubjectList.objects.filter(study=study, type=subject_list_type)
+    study_subject_lists = StudySubjectList.objects.filter(
+        study=study, type=subject_list_type
+    )
     if len(study_subject_lists) > 0:
         study_subject_list = study_subject_lists[0]
         subject_columns = study_subject_list.visible_subject_columns
@@ -87,19 +98,59 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
         study_subject_columns = StudyColumns()
 
     result = []
-    add_column(result, "Subject number", "nd_number", study_subject_columns, "string_filter", study.columns)
-    add_column(result, "Screening", "screening_number", study_subject_columns, "string_filter", study.columns)
+    add_column(
+        result,
+        "Subject number",
+        "nd_number",
+        study_subject_columns,
+        "string_filter",
+        study.columns,
+    )
+    add_column(
+        result,
+        "Screening",
+        "screening_number",
+        study_subject_columns,
+        "string_filter",
+        study.columns,
+    )
     add_column(result, "First name", "first_name", subject_columns, "string_filter")
     add_column(result, "Last name", "last_name", subject_columns, "string_filter")
     add_column(result, "Address", "address", subject_columns, "string_filter")
-    add_column(result, "Social Security Number", "social_security_number", subject_columns, "string_filter")
+    add_column(
+        result,
+        "Social Security Number",
+        "social_security_number",
+        subject_columns,
+        "string_filter",
+    )
     add_column(result, "Phone number", "phone_number", subject_columns, "string_filter")
-    add_column(result, "Phone number 2", "phone_number_2", subject_columns, "string_filter")
-    add_column(result, "Phone number 3", "phone_number_3", subject_columns, "string_filter")
+    add_column(
+        result, "Phone number 2", "phone_number_2", subject_columns, "string_filter"
+    )
+    add_column(
+        result, "Phone number 3", "phone_number_3", subject_columns, "string_filter"
+    )
     add_column(result, "Date of birth", "date_born", subject_columns, None)
-    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,
+        "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",
@@ -118,19 +169,80 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
         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
+        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, "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)
-    add_column(result, "Postponed", "postponed", study_subject_columns, "yes_no_filter", study.columns)
-    add_column(result, "Next of kin", "next_of_kin_name", subject_columns, "string_filter")
-    add_column(result, "Next of kin phone", "next_of_kin_phone", subject_columns, "string_filter")
-    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,
+        "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,
+    )
+    add_column(
+        result,
+        "Postponed",
+        "postponed",
+        study_subject_columns,
+        "yes_no_filter",
+        study.columns,
+    )
+    add_column(
+        result, "Next of kin", "next_of_kin_name", subject_columns, "string_filter"
+    )
+    add_column(
+        result,
+        "Next of kin phone",
+        "next_of_kin_phone",
+        subject_columns,
+        "string_filter",
+    )
+    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",
@@ -139,16 +251,22 @@ def get_subject_columns(request: HttpRequest, subject_list_type: str) -> JsonRes
         "language_filter",
     )
 
-    visit_from_zero = ConfigurationItem.objects.get(type=VISIT_SHOW_VISIT_NUMBER_FROM_ZERO).value
+    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):
         visit_numbers = list(range(0, study.visits_to_show_in_subject_list + 0))
     else:
         visit_numbers = list(range(1, study.visits_to_show_in_subject_list + 1))
 
-    add_column(result, "Type", "type", study_subject_columns, "type_filter", study.columns)
+    add_column(
+        result, "Type", "type", study_subject_columns, "type_filter", study.columns
+    )
     for custom_study_subject_field in study.customstudysubjectfield_set.all():
-        visible = study_subject_columns.is_custom_field_visible(custom_study_subject_field)
+        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,
@@ -222,7 +340,12 @@ 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
+            result,
+            f"Visit {visit_number}",
+            visit_key,
+            None,
+            "visit_filter",
+            visible_param=study_subject_list.visits,
         )
 
     return JsonResponse({"columns": result})
@@ -243,11 +366,15 @@ 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")))
+        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):
+def get_subjects_order(
+    subjects_to_be_ordered: QuerySet, order_column, order_direction, column_filters=None
+):
     if column_filters is None:
         column_filters = {}
     result = subjects_to_be_ordered
@@ -274,13 +401,17 @@ def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_dir
     elif order_column == "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"))
     elif order_column == "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"))
     elif order_column == "phone_number_2":
@@ -295,7 +426,9 @@ def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_dir
         result = subjects_to_be_ordered.all()
         result = sorted(
             result,
-            key=lambda t: t.sort_matched_screening_first(pattern, reverse=order_direction != "asc"),
+            key=lambda t: t.sort_matched_screening_first(
+                pattern, reverse=order_direction != "asc"
+            ),
             reverse=order_direction != "asc",
         )
     elif order_column == "default_location":
@@ -315,7 +448,9 @@ def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_dir
     elif order_column == "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"))
     elif order_column == "excluded":
@@ -330,9 +465,9 @@ def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_dir
         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)
@@ -342,7 +477,8 @@ def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_dir
             custom_field_value=Min(
                 Case(
                     When(
-                        customstudysubjectvalue__study_subject_field__id=field_id, then="customstudysubjectvalue__value"
+                        customstudysubjectvalue__study_subject_field__id=field_id,
+                        then="customstudysubjectvalue__value",
                     )
                 )
             )
@@ -362,8 +498,12 @@ def filter_by_visit(result, visit_number, visit_type):
     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"
+    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
@@ -372,7 +512,13 @@ def filter_by_visit(result, visit_number, visit_type):
     result = result.annotate(
         **{
             is_finished_filter: Count(
-                Case(When(Q(visit__is_finished=True) & Q(visit__visit_number=visit_number), then=1))
+                Case(
+                    When(
+                        Q(visit__is_finished=True)
+                        & Q(visit__visit_number=visit_number),
+                        then=1,
+                    )
+                )
             )
         }
     )
@@ -383,7 +529,9 @@ def filter_by_visit(result, visit_number, visit_type):
             finished_appointments_filter: Count(
                 Case(
                     When(
-                        Q(visit__appointment__status=Appointment.APPOINTMENT_STATUS_FINISHED)
+                        Q(
+                            visit__appointment__status=Appointment.APPOINTMENT_STATUS_FINISHED
+                        )
                         & Q(visit__visit_number=visit_number),
                         then=1,
                     )
@@ -397,7 +545,9 @@ def filter_by_visit(result, visit_number, visit_type):
             scheduled_appointments_filter: Count(
                 Case(
                     When(
-                        Q(visit__appointment__status=Appointment.APPOINTMENT_STATUS_SCHEDULED)
+                        Q(
+                            visit__appointment__status=Appointment.APPOINTMENT_STATUS_SCHEDULED
+                        )
                         & Q(visit__visit_number=visit_number),
                         then=1,
                     )
@@ -408,11 +558,21 @@ def filter_by_visit(result, visit_number, visit_type):
 
     # 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":
@@ -448,7 +608,9 @@ def filter_by_visit(result, visit_number, visit_type):
             .filter(**{scheduled_appointments_filter: 0})
         )
     elif visit_type == "UPCOMING":
-        result = result.filter(**{datetime_begin_filter + "__gt": get_today_midnight_date()})
+        result = result.filter(
+            **{datetime_begin_filter + "__gt": get_today_midnight_date()}
+        )
 
     return result
 
@@ -482,7 +644,9 @@ def get_subjects_filtered(subjects_to_be_filtered: QuerySet, filters) -> QuerySe
         elif column == "referral":
             result = result.filter(referral__icontains=value)
         elif column == "default_written_communication_language":
-            result = result.filter(subject__default_written_communication_language__id=value)
+            result = result.filter(
+                subject__default_written_communication_language__id=value
+            )
         elif column == "phone_number":
             result = result.filter(subject__phone_number__icontains=value)
         elif column == "phone_number_2":
@@ -534,19 +698,26 @@ def get_subjects_filtered(subjects_to_be_filtered: QuerySet, filters) -> QuerySe
                     )
                 else:
                     result = result.filter(
-                        customstudysubjectvalue__study_subject_field__id=field_id, customstudysubjectvalue__value=""
+                        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
+                    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
+                    customstudysubjectvalue__study_subject_field__id=field_id,
+                    customstudysubjectvalue__value=value,
                 )
-            elif field.type in (CUSTOM_FIELD_TYPE_INTEGER, CUSTOM_FIELD_TYPE_SELECT_LIST):
+            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
+                    customstudysubjectvalue__study_subject_field__id=field_id,
+                    customstudysubjectvalue__value=value,
                 )
             elif field.type == CUSTOM_FIELD_TYPE_FILE:
                 result = result.filter(
@@ -583,7 +754,9 @@ def subjects(request: WSGIRequest, subject_list_type: str) -> HttpResponse:
         length = int(request_data.get("length", "10"))
         order = int(request_data.get("order[0][column]", "0"))
         order_dir = request_data.get("order[0][dir]", "asc")
-        order_column = request_data.get("columns[" + str(order) + "][data]", "last_name")
+        order_column = request_data.get(
+            "columns[" + str(order) + "][data]", "last_name"
+        )
 
         filters = get_filters_for_data_table_request(request_data)
 
@@ -592,11 +765,13 @@ def subjects(request: WSGIRequest, subject_list_type: str) -> HttpResponse:
         count = all_subjects.count()
 
         filtered_subjects = get_subjects_filtered(all_subjects, filters)
-        ordered_subjects = get_subjects_order(filtered_subjects, order_column, order_dir, column_filters=dict(filters))
+        ordered_subjects = get_subjects_order(
+            filtered_subjects, order_column, order_dir, column_filters=dict(filters)
+        )
         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
 
@@ -661,7 +836,9 @@ 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."]
 
@@ -670,14 +847,18 @@ def serialize_subject(study_subject: StudySubject):
                 "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,)),
+                "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")
+    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 = (
@@ -700,7 +881,9 @@ def serialize_subject(study_subject: StudySubject):
         health_partner_last_name = study_subject.health_partner.last_name
     default_written_communication_language = ""
     if study_subject.subject.default_written_communication_language:
-        default_written_communication_language = study_subject.subject.default_written_communication_language.name
+        default_written_communication_language = (
+            study_subject.subject.default_written_communication_language.name
+        )
 
     result = {
         "first_name": study_subject.subject.first_name,
@@ -746,17 +929,25 @@ def serialize_subject(study_subject: StudySubject):
                 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)
+            result[get_study_subject_field_id(field_value.study_subject_field)] = (
+                str_to_yes_no_null(field_value.value)
+            )
         elif field_value.study_subject_field.type == CUSTOM_FIELD_TYPE_DATE:
-            result[get_study_subject_field_id(field_value.study_subject_field)] = field_value.value
+            result[get_study_subject_field_id(field_value.study_subject_field)] = (
+                field_value.value
+            )
         elif field_value.study_subject_field.type == CUSTOM_FIELD_TYPE_SELECT_LIST:
-            result[get_study_subject_field_id(field_value.study_subject_field)] = field_value.value
+            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)] = ""
             else:
                 result[get_study_subject_field_id(field_value.study_subject_field)] = (
-                    reverse("web.views.uploaded_files") + "?file=" + str(field_value.value)
+                    reverse("web.views.uploaded_files")
+                    + "?file="
+                    + str(field_value.value)
                 )
         else:
             raise NotImplementedError
diff --git a/smash/web/api_views/visit.py b/smash/web/api_views/visit.py
index 37fb202edd14632da34c24ca17f04bc4cfdf4faf..880906734e36792a960a63f8ea9afd0b8a75a243 100644
--- a/smash/web/api_views/visit.py
+++ b/smash/web/api_views/visit.py
@@ -1,10 +1,10 @@
 import logging
-from distutils.util import strtobool
 
 from django.core.handlers.wsgi import WSGIRequest
 from django.db.models import Q
 from django.http import JsonResponse, HttpResponseNotAllowed
 
+from web.utils import strtobool
 from web.api_views.serialization_utils import bool_to_yes_no, flying_team_to_str, location_to_str, add_column, \
     serialize_date, get_filters_for_data_table_request
 from web.models import AppointmentType, Appointment
diff --git a/smash/web/forms/forms.py b/smash/web/forms/forms.py
index 6d6f40a39d77d5bde4a35dc2dd2ec6c4aad4784d..ab2469d2df76277ec4de740e0d5559cc8ba56118 100644
--- a/smash/web/forms/forms.py
+++ b/smash/web/forms/forms.py
@@ -1,11 +1,11 @@
 import datetime
 import logging
-from distutils.util import strtobool
 
 from django import forms
 from django.forms import ModelForm, Form
 from django.utils.dates import MONTHS
 
+from web.utils import strtobool
 from web.models import AppointmentType, Availability, FlyingTeam, Holiday, Item, \
     StudySubject, Room, Worker, Visit, ConfigurationItem, SubjectType
 from web.models.constants import VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
diff --git a/smash/web/models/configuration_item.py b/smash/web/models/configuration_item.py
index 23a15f40a0db5c224757d4988d2f7c34c04409f6..a38cba7ce76980de662e831c9f0e54a522c95a41 100644
--- a/smash/web/models/configuration_item.py
+++ b/smash/web/models/configuration_item.py
@@ -1,11 +1,11 @@
 # coding=utf-8
 import re
-from distutils.util import strtobool
 
 from django.core.exceptions import ValidationError
 from django.core.validators import validate_email
 from django.db import models
 
+from web.utils import strtobool
 from web.models.constants import CANCELLED_APPOINTMENT_COLOR_CONFIGURATION_TYPE, \
     NO_SHOW_APPOINTMENT_COLOR_CONFIGURATION_TYPE, KIT_EMAIL_HOUR_CONFIGURATION_TYPE, \
     KIT_EMAIL_DAY_OF_WEEK_CONFIGURATION_TYPE, KIT_DAILY_EMAIL_TIME_FORMAT_TYPE, KIT_DAILY_EMAIL_DAYS_PERIOD_TYPE, \
diff --git a/smash/web/templatetags/filters.py b/smash/web/templatetags/filters.py
index 339bd0e3753f14d34b3f39a0f73702e1ac043b96..795cde21fda8f8478a2838957dedf35a65b9cada 100644
--- a/smash/web/templatetags/filters.py
+++ b/smash/web/templatetags/filters.py
@@ -1,13 +1,13 @@
 # See: http://stackoverflow.com/a/18962481
 import datetime
 import os
-from distutils.util import strtobool
 from functools import reduce
 
 from django import template
 from django.forms import CheckboxSelectMultiple, CheckboxInput
 from django.utils.safestring import mark_safe
 
+from web.utils import strtobool
 from web.models import ConfigurationItem
 from web.models.constants import VISIT_SHOW_VISIT_NUMBER_FROM_ZERO
 
diff --git a/smash/web/utils.py b/smash/web/utils.py
index 544aa884517ada9a712b312b098563ac60a1aefc..f1a3715e43bb1dcfdb61beb9a04fcf6d787263f8 100644
--- a/smash/web/utils.py
+++ b/smash/web/utils.py
@@ -11,6 +11,22 @@ from django.utils.text import capfirst
 
 from web.algorithm import VerhoeffAlgorithm, LuhnAlgorithm
 
+def strtobool (val):
+    """Convert a string representation of truth to true (1) or false (0).
+
+    True values are 'y', 'yes', 't', 'true', 'on', and '1'; false values
+    are 'n', 'no', 'f', 'false', 'off', and '0'.  Raises ValueError if
+    'val' is anything else.
+
+    From distutils lib
+    """
+    val = val.lower()
+    if val in ('y', 'yes', 't', 'true', 'on', '1'):
+        return 1
+    elif val in ('n', 'no', 'f', 'false', 'off', '0'):
+        return 0
+    else:
+        raise ValueError(f"invalid truth value {val}")
 
 def get_deleted_objects(objs: List[models.Model]):
     collector = NestedObjects(using='default')
diff --git a/smash/web/views/subject.py b/smash/web/views/subject.py
index f181b08d3e40c1376a29f5436a0af2b92e56c4bc..091090c21ddaccdf978520b1ec463ff3aaaf1f7c 100644
--- a/smash/web/views/subject.py
+++ b/smash/web/views/subject.py
@@ -218,15 +218,17 @@ def subject_edit(request, subject_id):
                     curr_value = study_subject_form.cleaned_data[field_id]
                     if prev_value != curr_value:
                         worker = Worker.get_by_user(request.user)
+                        mod_desc = (f'Worker "{worker}" changed study subject '
+                                    f'"{study_subject.nd_number}" field '
+                                    f'"{field.study_subject_field.name}"'
+                                    f' value from study '
+                                    f'"{study_subject.study}"')
                         p = Provenance(modified_table=StudySubject._meta.db_table,
                                        modified_table_id=study_subject.id,
                                        modification_author=worker,
                                        previous_value=prev_value,
                                        new_value=curr_value,
-                                       modification_description='Worker "{}" changed study subject "{}" field "{}" '
-                                                                'value from study "{}"'
-                                       .format(worker, study_subject.nd_number, field.study_subject_field.name,
-                                               study_subject.study),
+                                       modification_description=mod_desc,
                                        modified_field=field.study_subject_field.name,
                                        request_path=request.path,
                                        request_ip_addr=ip