diff --git a/smash/db_scripts/create_dummy_data.py b/smash/db_scripts/create_dummy_data.py index aef885576c0f122d9f64dab0fa4408b6c2b705ed..dfcb4ffff8a5da756d07e56e1e0eb635afb5b28d 100644 --- a/smash/db_scripts/create_dummy_data.py +++ b/smash/db_scripts/create_dummy_data.py @@ -431,15 +431,15 @@ class smashProvider(BaseProvider): screening_number = self.createSmashScreeningNumber( default_location.prefix) - virus_test_1 = choice([None, True, False], 1, p=[0.2, 0.3, 0.5])[0] + virus_test_1_result = choice([None, "Positive", "Negative", "Inconclusive"], 1, p=[0.2, 0.2, 0.3, 0.3])[0] virus_iga_1 = choice(["Borderline", "Positive", "Negative"], 1, p=[0.02, 0.03, 0.95])[0] virus_igg_1 = choice(["Borderline", "Positive", "Negative"], 1, p=[0.02, 0.03, 0.95])[0] - if virus_test_1 is None: + if virus_test_1_result is None: + virus_test_1_updated = fake.date_between(start_date='-30d', end_date='-4d') + elif virus_test_1_result == "Inconclusive": virus_test_1_updated = fake.date_between(start_date='-30d', end_date='-4d') - #inconclusive results have a date - virus_test_1_updated = choice([None, virus_test_1_updated], 1, p=[0.7, 0.3])[0] virus_test_1_collection_date = choice([None, virus_test_1_updated], 1, p=[0.7, 0.3])[0] - elif virus_test_1 == True: + elif virus_test_1_result == "Positive": virus_test_1_updated = fake.date_between(start_date='-30d', end_date='-4d') virus_test_1_collection_date = fake.date_between(start_date='-30d', end_date='-4d') else: @@ -447,7 +447,8 @@ class smashProvider(BaseProvider): virus_test_1_collection_date = fake.date_between(start_date='-30d', end_date='-4d') study_subject, _ = StudySubject.objects.update_or_create(nd_number=nd_number, subject=subject, - virus_test_1=virus_test_1, virus_test_1_updated=virus_test_1_updated, + virus_test_1_result=virus_test_1_result, + virus_test_1_updated=virus_test_1_updated, virus_test_1_collection_date=virus_test_1_collection_date, virus_test_1_iga_status=virus_iga_1, virus_test_1_igg_status=virus_igg_1, diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py index ca4f2ba097caae012c6ac47e0ad44cdeb71b63be..6796e46610f95e52857643fed375724fe3553097 100644 --- a/smash/web/api_views/subject.py +++ b/smash/web/api_views/subject.py @@ -8,7 +8,7 @@ from django.http import JsonResponse 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, virus_test_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 from web.models.constants import SUBJECT_TYPE_CHOICES, GLOBAL_STUDY_ID, VISIT_SHOW_VISIT_NUMBER_FROM_ZERO, \ @@ -97,7 +97,7 @@ def get_subject_columns(request, subject_list_type): for one_based_idx, virus_visit_number in enumerate(virus_visit_numbers, 1): add_column(result, 'Virus {} RT-PCR'.format(virus_visit_number), - 'virus_test_{}'.format(one_based_idx), # always starts in 1 + 'virus_test_{}_result'.format(one_based_idx), # always starts in 1 study_subject_columns, 'yes_no_null_inconclusive_filter', study.columns) add_column(result, @@ -280,7 +280,7 @@ def get_subjects_order(subjects_to_be_ordered: QuerySet, order_column, order_dir 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_direction, visit_number) - elif re.search(r'^virus_test_[1-5]$', order_column): + elif re.search(r'^virus_test_[1-5]_result$', order_column): result = subjects_to_be_ordered.order_by(order_direction + order_column) elif re.search(r'^virus_test_[1-5]_updated$', order_column): result = subjects_to_be_ordered.order_by(order_direction + order_column) @@ -397,17 +397,14 @@ def get_subjects_filtered(subjects_to_be_filtered: QuerySet, filters) -> QuerySe result = result.filter(resigned=(value == "true")) elif column == "endpoint_reached": result = result.filter(endpoint_reached=(value == "true")) - elif re.search(r'^virus_test_[1-5]$', column): - visit_number = column.replace("virus_test_", "") - virus_test__isnull_param = "virus_test_{}__isnull".format(visit_number) - virus_test__updated__isnull_param = "virus_test_{}_updated__isnull".format(visit_number) - visit_test_param = "virus_test_{}".format(visit_number) + elif re.search(r'^virus_test_[1-5]_result$', column): + visit_number = column.replace("virus_test_", "").replace("_result","") + virus_test__isnull_param = "virus_test_{}_result__isnull".format(visit_number) + visit_test_param = "virus_test_{}_result".format(visit_number) if value == "null": - result = result.filter(**{virus_test__isnull_param: True, virus_test__updated__isnull_param: True}) - elif value == "inconclusive": - result = result.filter(**{virus_test__isnull_param: True, virus_test__updated__isnull_param: False}) + result = result.filter(**{virus_test__isnull_param: True}) else: - result = result.filter(**{visit_test_param: (value == "true")}) + result = result.filter(**{visit_test_param: value}) elif re.search(r'^virus_test_[1-5]_iga_status$', column): visit_number = column.replace("virus_test_", "").replace("_iga_status", "") virus_test_iga_status_param = "virus_test_{}_iga_status".format(visit_number) @@ -530,7 +527,7 @@ def types(request): }) -def serialize_subject(study_subject): +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') @@ -620,8 +617,7 @@ def serialize_subject(study_subject): "visits": serialized_visits, } for i in range(1, 6): - result['virus_test_{}'.format(i)] = virus_test_to_str(getattr(study_subject, "virus_test_{}".format(i)), - getattr(study_subject, "virus_test_{}_updated".format(i))) + result['virus_test_{}_result'.format(i)] = getattr(study_subject, "virus_test_{}_result".format(i)) result["virus_test_{}_updated".format(i)] = getattr(study_subject, "virus_test_{}_updated".format(i)) result["virus_test_{}_collection_date".format(i)] = getattr(study_subject, "virus_test_{}_collection_date".format(i)) diff --git a/smash/web/forms/study_subject_forms.py b/smash/web/forms/study_subject_forms.py index 6211544bd6817c549a35561bb9ce1e60786a3b86..8b6d57082adc773c9af460cf7a1470bc6486f35b 100644 --- a/smash/web/forms/study_subject_forms.py +++ b/smash/web/forms/study_subject_forms.py @@ -124,7 +124,7 @@ class StudySubjectForm(ModelForm): if strtobool(visit_from_zero): virus_visit_numbers = list(range(0, 5)) for one_based_idx, virus_visit_number in enumerate(virus_visit_numbers, 1): - field = 'virus_test_{}'.format(one_based_idx) + field = 'virus_test_{}_result'.format(one_based_idx) self.fields[field].label = 'Visit {} RT-PCR'.format(virus_visit_number) date_field = 'virus_test_{}_updated'.format(one_based_idx) @@ -140,19 +140,6 @@ class StudySubjectForm(ModelForm): for visit_number in range(1, 6): disable_virus_test_field(self, visit_number) - self.update_virus_inconclusive_data(visit_number) - - def update_virus_inconclusive_data(self, visit_number): - test_result_column_name = 'virus_test_{}'.format(visit_number) - test_date_column_name = 'virus_test_{}_updated'.format(visit_number) - - self.fields[test_result_column_name].widget.choices.append(("Inc", 'Inconclusive')) - instance = getattr(self, 'instance', None) - if instance and instance.id: - test_result = getattr(instance, test_result_column_name) - test_date = getattr(instance, test_date_column_name) - if test_result is None and test_date is not None: - self.initial[test_result_column_name] = "Inc" def clean(self): cleaned_data = super(StudySubjectForm, self).clean() @@ -338,7 +325,7 @@ class StudySubjectEditForm(StudySubjectForm): def disable_virus_test_field(self, visit_number): - test_result_column_name = 'virus_test_{}'.format(visit_number) + test_result_column_name = 'virus_test_{}_result'.format(visit_number) test_result_date_column_name = 'virus_test_{}_updated'.format(visit_number) test_collection_date_column_name = 'virus_test_{}_collection_date'.format(visit_number) test_iga_status_column_name = 'virus_test_{}_iga_status'.format(visit_number) @@ -392,11 +379,11 @@ def prepare_study_subject_fields(fields, study): prepare_field(fields, study.columns, 'previously_in_study') prepare_field(fields, study.columns, 'voucher_types') - prepare_field(fields, study.columns, 'virus_test_1') - prepare_field(fields, study.columns, 'virus_test_2') - prepare_field(fields, study.columns, 'virus_test_3') - prepare_field(fields, study.columns, 'virus_test_4') - prepare_field(fields, study.columns, 'virus_test_5') + prepare_field(fields, study.columns, 'virus_test_1_result') + prepare_field(fields, study.columns, 'virus_test_2_result') + prepare_field(fields, study.columns, 'virus_test_3_result') + prepare_field(fields, study.columns, 'virus_test_4_result') + prepare_field(fields, study.columns, 'virus_test_5_result') prepare_field(fields, study.columns, 'virus_test_1_updated') prepare_field(fields, study.columns, 'virus_test_2_updated') prepare_field(fields, study.columns, 'virus_test_3_updated') diff --git a/smash/web/migrations/0188_studysubject_virus_test_1_result.py b/smash/web/migrations/0188_studysubject_virus_test_1_result.py new file mode 100644 index 0000000000000000000000000000000000000000..5a7403bbaf2b91320cedfc11cf87dd4d662007db --- /dev/null +++ b/smash/web/migrations/0188_studysubject_virus_test_1_result.py @@ -0,0 +1,98 @@ +# Generated by Django 3.1.3 on 2020-12-01 07:55 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('web', '0187_auto_20201130_1224'), + ] + + operations = [ + migrations.AddField( + model_name='studysubject', + name='virus_test_1_result', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='studysubject', + name='virus_test_2_result', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='studysubject', + name='virus_test_3_result', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='studysubject', + name='virus_test_4_result', + field=models.CharField(max_length=20, null=True), + ), + migrations.AddField( + model_name='studysubject', + name='virus_test_5_result', + field=models.CharField(max_length=20, null=True), + ), + migrations.RunSQL("update web_studysubject set virus_test_1_result='Positive' " + "where virus_test_1 is not null and virus_test_1"), + migrations.RunSQL("update web_studysubject set virus_test_1_result='Negative' " + "where virus_test_1 is not null and not virus_test_1"), + migrations.RunSQL("update web_studysubject set virus_test_1_result='Inconclusive' " + "where virus_test_1 is null and virus_test_1_updated is not null"), + + migrations.RunSQL("update web_studysubject set virus_test_2_result='Positive' " + "where virus_test_2 is not null and virus_test_2"), + migrations.RunSQL("update web_studysubject set virus_test_2_result='Negative' " + "where virus_test_2 is not null and not virus_test_2"), + migrations.RunSQL("update web_studysubject set virus_test_2_result='Inconclusive' " + "where virus_test_2 is null and virus_test_2_updated is not null"), + + migrations.RunSQL("update web_studysubject set virus_test_3_result='Positive' " + "where virus_test_3 is not null and virus_test_3"), + migrations.RunSQL("update web_studysubject set virus_test_3_result='Negative' " + "where virus_test_3 is not null and not virus_test_3"), + migrations.RunSQL("update web_studysubject set virus_test_3_result='Inconclusive' " + "where virus_test_3 is null and virus_test_3_updated is not null"), + + migrations.RunSQL("update web_studysubject set virus_test_4_result='Positive' " + "where virus_test_4 is not null and virus_test_4"), + migrations.RunSQL("update web_studysubject set virus_test_4_result='Negative' " + "where virus_test_4 is not null and not virus_test_4"), + migrations.RunSQL("update web_studysubject set virus_test_4_result='Inconclusive' " + "where virus_test_4 is null and virus_test_4_updated is not null"), + + migrations.RunSQL("update web_studysubject set virus_test_5_result='Positive' " + "where virus_test_5 is not null and virus_test_5"), + migrations.RunSQL("update web_studysubject set virus_test_5_result='Negative' " + "where virus_test_5 is not null and not virus_test_5"), + migrations.RunSQL("update web_studysubject set virus_test_5_result='Inconclusive' " + "where virus_test_5 is null and virus_test_5_updated is not null"), + migrations.RenameField( + model_name='studycolumns', + old_name='virus_test_1', + new_name='virus_test_1_result', + ), + migrations.RenameField( + model_name='studycolumns', + old_name='virus_test_2', + new_name='virus_test_2_result', + ), + migrations.RenameField( + model_name='studycolumns', + old_name='virus_test_3', + new_name='virus_test_3_result', + ), + migrations.RenameField( + model_name='studycolumns', + old_name='virus_test_4', + new_name='virus_test_4_result', + ), + migrations.RenameField( + model_name='studycolumns', + old_name='virus_test_5', + new_name='virus_test_5_result', + ), + + ] diff --git a/smash/web/migrations/0189_remove_studysubject_virus_test_1.py b/smash/web/migrations/0189_remove_studysubject_virus_test_1.py new file mode 100644 index 0000000000000000000000000000000000000000..e18f54cb8db7ba0a3d6dd133526dfac6e058e906 --- /dev/null +++ b/smash/web/migrations/0189_remove_studysubject_virus_test_1.py @@ -0,0 +1,33 @@ +# Generated by Django 3.1.3 on 2020-12-01 08:03 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('web', '0188_studysubject_virus_test_1_result'), + ] + + operations = [ + migrations.RemoveField( + model_name='studysubject', + name='virus_test_1', + ), + migrations.RemoveField( + model_name='studysubject', + name='virus_test_2', + ), + migrations.RemoveField( + model_name='studysubject', + name='virus_test_3', + ), + migrations.RemoveField( + model_name='studysubject', + name='virus_test_4', + ), + migrations.RemoveField( + model_name='studysubject', + name='virus_test_5', + ), + ] diff --git a/smash/web/models/mail_template.py b/smash/web/models/mail_template.py index bf101409a62f905e7c1c9f658bc262460517e4a9..4879740c5566148c0573732fa27d53a42d6aaa7b 100644 --- a/smash/web/models/mail_template.py +++ b/smash/web/models/mail_template.py @@ -277,11 +277,11 @@ class MailTemplate(models.Model): if appointment.datetime_when is not None: # TODO: 2to3 # Was: - #appointment_date_full = appointment.datetime_when.strftime(DATETIME_FORMAT).decode( + # appointment_date_full = appointment.datetime_when.strftime(DATETIME_FORMAT).decode( # date_format_encoding()) - #appointment_date_short = appointment.datetime_when.strftime(DATE_FORMAT_SHORT).decode( + # appointment_date_short = appointment.datetime_when.strftime(DATE_FORMAT_SHORT).decode( # date_format_encoding()) - #appointment_date_time = appointment.datetime_when.strftime(DATE_FORMAT_TIME).decode( + # appointment_date_time = appointment.datetime_when.strftime(DATE_FORMAT_TIME).decode( # date_format_encoding()) # Is: appointment_date_full = appointment.datetime_when.strftime(DATETIME_FORMAT) @@ -315,8 +315,8 @@ class MailTemplate(models.Model): # "##V_DATE_START_FULL##": visit.datetime_begin.strftime(DATETIME_FORMAT).decode(date_format_encoding()), # "##V_DATE_START_SHORT##": visit.datetime_begin.strftime(DATE_FORMAT_SHORT).decode( # date_format_encoding()), - #"##V_DATE_ENDS_FULL##": visit.datetime_end.strftime(DATETIME_FORMAT).decode(date_format_encoding()), - #"##V_DATE_ENDS_SHORT##": visit.datetime_end.strftime(DATE_FORMAT_SHORT).decode(date_format_encoding()), + # "##V_DATE_ENDS_FULL##": visit.datetime_end.strftime(DATETIME_FORMAT).decode(date_format_encoding()), + # "##V_DATE_ENDS_SHORT##": visit.datetime_end.strftime(DATE_FORMAT_SHORT).decode(date_format_encoding()), # Is: "##V_DATE_START_FULL##": visit.datetime_begin.strftime(DATETIME_FORMAT), "##V_DATE_START_SHORT##": visit.datetime_begin.strftime(DATE_FORMAT_SHORT), @@ -368,8 +368,9 @@ class MailTemplate(models.Model): for i in range(1, 6): virus_test_field = "##S_VIRUS_{}_RESULT##".format(i) - virus_test_value = virus_test_to_str(getattr(study_subject, "virus_test_{}".format(i)), - getattr(study_subject, "virus_test_{}_updated".format(i))) + virus_test_value = getattr(study_subject, "virus_test_{}_result".format(i)) + if virus_test_value == "" or virus_test_value is None: + virus_test_value = "N/A" virus_test_date_field = "##S_VIRUS_{}_SAMPLE_COLLECTION_DATE##".format(i) virus_test_date_value = date_to_str(getattr(study_subject, "virus_test_{}_collection_date".format(i)), @@ -386,8 +387,6 @@ class MailTemplate(models.Model): virus_igg_status_value = "" if virus_test_date_value != "": - if virus_test_value == "": - virus_test_value = "N/A" if virus_iga_status_value == "": virus_iga_status_value = "N/A" if virus_igg_status_value == "": @@ -428,14 +427,3 @@ class MailTemplate(models.Model): "##C_HOURS##": str(voucher.hours), } return {} - - -def virus_test_to_str(test, date): - if test is None and date is not None: - return "Inconclusive" - if test is None: - return "" - if test: - return "Positive" - else: - return "Negative" diff --git a/smash/web/models/study_columns.py b/smash/web/models/study_columns.py index 03f8d30a1b0ea34662af991c58b27359a5c47fdd..1f89f2bd2452848125b68fc087b09b4a418bfde2 100644 --- a/smash/web/models/study_columns.py +++ b/smash/web/models/study_columns.py @@ -124,23 +124,23 @@ class StudyColumns(models.Model): verbose_name='Brain donation agreement', ) - virus_test_1 = models.BooleanField( + virus_test_1_result = models.BooleanField( default=False, verbose_name='Visit 1 virus results', ) - virus_test_2 = models.BooleanField( + virus_test_2_result = models.BooleanField( default=False, verbose_name='Visit 2 virus results', ) - virus_test_3 = models.BooleanField( + virus_test_3_result = models.BooleanField( default=False, verbose_name='Visit 3 virus results', ) - virus_test_4 = models.BooleanField( + virus_test_4_result = models.BooleanField( default=False, verbose_name='Visit 4 virus results', ) - virus_test_5 = models.BooleanField( + virus_test_5_result = models.BooleanField( default=False, verbose_name='Visit 5 virus results', ) diff --git a/smash/web/models/study_subject.py b/smash/web/models/study_subject.py index 39c77a02dac4b98add0562649b69cb6f6f44c07e..57b25a0f86e4758e3cff929b5e460c3e5b25b4fa 100644 --- a/smash/web/models/study_subject.py +++ b/smash/web/models/study_subject.py @@ -8,9 +8,11 @@ from django.db.models.signals import post_save from django.dispatch import receiver from web.models import VoucherType, Appointment, Location, Visit, Provenance -from web.models.constants import BOOL_CHOICES, SUBJECT_TYPE_CHOICES, FILE_STORAGE, BOOL_CHOICES_WITH_NONE +from web.models.constants import BOOL_CHOICES, SUBJECT_TYPE_CHOICES, FILE_STORAGE from web.models.custom_data import CustomStudySubjectValue, CustomStudySubjectField +VIRUS_CHOICES = ((None, 'N/A'), ('Inconclusive', 'Inconclusive'), ('Positive', 'Positive'), ('Negative', 'Negative')) + logger = logging.getLogger(__name__) @@ -205,31 +207,12 @@ class StudySubject(models.Model): verbose_name='Endpoint reached comments' ) - virus_test_1 = models.BooleanField(choices=BOOL_CHOICES_WITH_NONE, - verbose_name='Visit 1 virus result', - default=None, - null=True - ) - virus_test_2 = models.BooleanField(choices=BOOL_CHOICES_WITH_NONE, - verbose_name='Visit 2 virus result', - default=None, - null=True - ) - virus_test_3 = models.BooleanField(choices=BOOL_CHOICES_WITH_NONE, - verbose_name='Visit 3 virus result', - default=None, - null=True - ) - virus_test_4 = models.BooleanField(choices=BOOL_CHOICES_WITH_NONE, - verbose_name='Visit 4 virus result', - default=None, - null=True - ) - virus_test_5 = models.BooleanField(choices=BOOL_CHOICES_WITH_NONE, - verbose_name='Visit 5 virus result', - default=None, - null=True - ) + virus_test_1_result = models.CharField(max_length=20, null=True, choices=VIRUS_CHOICES) + virus_test_2_result = models.CharField(max_length=20, null=True, choices=VIRUS_CHOICES) + virus_test_3_result = models.CharField(max_length=20, null=True, choices=VIRUS_CHOICES) + virus_test_4_result = models.CharField(max_length=20, null=True, choices=VIRUS_CHOICES) + virus_test_5_result = models.CharField(max_length=20, null=True, choices=VIRUS_CHOICES) + virus_test_1_updated = models.DateField(verbose_name='Visit 1 virus result date', blank=True, null=True, diff --git a/smash/web/redcap_connector.py b/smash/web/redcap_connector.py index 70ae1d34e475aca3d2ab02faa0a0383fa9c5e8b3..57c63767745448f654fb525bce5829967ca54c4e 100644 --- a/smash/web/redcap_connector.py +++ b/smash/web/redcap_connector.py @@ -245,20 +245,20 @@ class RedcapConnector(object): smasch_appointment.visit.save() if visit.virus is not None or visit.virus_inconclusive: changes = [] - if visit.visit_number == 1 and subject.virus_test_1 != visit.virus: - changes.extend([('virus_test_1', visit.virus), + if visit.visit_number == 1 and subject.virus_test_1_result != visit.virus: + changes.extend([('virus_test_1_result', visit.virus), ('virus_test_1_updated', datetime.datetime.now())]) - if visit.visit_number == 2 and subject.virus_test_2 != visit.virus: - changes.extend([('virus_test_2', visit.virus), + if visit.visit_number == 2 and subject.virus_test_2_result != visit.virus: + changes.extend([('virus_test_2_result', visit.virus), ('virus_test_2_updated', datetime.datetime.now())]) - if visit.visit_number == 3 and subject.virus_test_3 != visit.virus: - changes.extend([('virus_test_3', visit.virus), + if visit.visit_number == 3 and subject.virus_test_3_result != visit.virus: + changes.extend([('virus_test_3_result', visit.virus), ('virus_test_3_updated', datetime.datetime.now())]) - if visit.visit_number == 4 and subject.virus_test_4 != visit.virus: - changes.extend([('virus_test_4', visit.virus), + if visit.visit_number == 4 and subject.virus_test_4_result != visit.virus: + changes.extend([('virus_test_4_result', visit.virus), ('virus_test_4_updated', datetime.datetime.now())]) - if visit.visit_number == 5 and subject.virus_test_5 != visit.virus: - changes.extend([('virus_test_5', visit.virus), + if visit.visit_number == 5 and subject.virus_test_5_result != visit.virus: + changes.extend([('virus_test_5_result', visit.virus), ('virus_test_5_updated', datetime.datetime.now())]) if visit.visit_number == 1 and subject.virus_test_1_updated is None and visit.virus_inconclusive: changes.extend([('virus_test_1_updated', datetime.datetime.now())]) @@ -435,11 +435,11 @@ class RedcapConnector(object): visit.visit_number = 1 if self.virus_field != "": if row.get(self.virus_field) == "Negative": - visit.virus = False + visit.virus = "Negative" elif row.get(self.virus_field) == "Positive": - visit.virus = True + visit.virus = "Positive" elif row.get(self.virus_field) == "Inconclusive": - visit.virus_inconclusive = True + visit.virus_inconclusive = "Inconclusive" if self.sample_date_field != "": date_str = row.get(self.sample_date_field) if date_str is not None and date_str != "" and date_str != "Not done" and date_str != "Not known": @@ -474,11 +474,11 @@ class RedcapConnector(object): visit.visit_number = i + self.study.redcap_first_visit_number + 1 if self.virus_field != "": if row.get(self.virus_field) == "Negative": - visit.virus = False + visit.virus = "Negative" elif row.get(self.virus_field) == "Positive": - visit.virus = True + visit.virus = "Positive" elif row.get(self.virus_field) == "Inconclusive": - visit.virus_inconclusive = True + visit.virus_inconclusive = "Inconclusive" if self.sample_date_field != "": date_str = row.get(self.sample_date_field) if date_str is not None and date_str != "" and date_str != "Not done" and date_str != "Not known": diff --git a/smash/web/static/js/smash.js b/smash/web/static/js/smash.js index a7a3dcba9c3c820b7337fd3d5ec3451fdf77d8a7..408d2335df9751b63a12085aedc5e8e70d810ad4 100644 --- a/smash/web/static/js/smash.js +++ b/smash/web/static/js/smash.js @@ -314,7 +314,7 @@ function createTable(params) { $(this).html('<select style="width:60px" ><option value selected="selected">---</option><option value="true">YES</option><option value="false">NO</option><option value="null">N/A</option></select>'); }); $(tableElement).find('tfoot div[name="yes_no_null_inconclusive_filter"]').each(function () { - $(this).html('<select style="width:100px" ><option value selected="selected">---</option><option value="true">Positive</option><option value="false">Negative</option><option value="null">N/A</option><option value="inconclusive">Inconclusive</option></select>'); + $(this).html('<select style="width:100px" ><option value selected="selected">---</option><option value="Positive">Positive</option><option value="Negative">Negative</option><option value="null">N/A</option><option value="Inconclusive">Inconclusive</option></select>'); }); $(tableElement).find('tfoot div[name="serology_filter"]').each(function () { $(this).html('<select style="width:100px" ><option value selected="selected">---</option><option value="Positive">Positive</option><option value="Negative">Negative</option><option value="Borderline">Borderline</option></select>'); diff --git a/smash/web/tests/api_views/test_subject.py b/smash/web/tests/api_views/test_subject.py index 9ecdc98169c49f37ccd62eb893bdd55c3bc1a57c..47caeef1f6356594efa88948aee41a3d11ae24f4 100644 --- a/smash/web/tests/api_views/test_subject.py +++ b/smash/web/tests/api_views/test_subject.py @@ -29,7 +29,7 @@ logger = logging.getLogger(__name__) class TestSubjectApi(LoggedInWithWorkerTestCase): def setUp(self): - super(TestSubjectApi, self).setUp() + super().setUp() self.study_subject = create_study_subject() self.warning_counter = MsgCounterHandler() logging.getLogger('').addHandler(self.warning_counter) @@ -701,22 +701,22 @@ class TestSubjectApi(LoggedInWithWorkerTestCase): self.assertEqual(self.get_warning_count(), 0, msg="Sorting by \"" + order + "\" does not work") def test_subjects_filter_virus_test(self): - study_subject_positive = create_study_subject(2) - study_subject_positive.virus_test_1 = True + study_subject_positive = create_study_subject() + study_subject_positive.virus_test_1_result = "Positive" study_subject_positive.save() - study_subject_negative = create_study_subject(2) - study_subject_negative.virus_test_1 = False + study_subject_negative = create_study_subject() + study_subject_negative.virus_test_1_result = "Negative" study_subject_negative.save() - study_subject_inconclusive = create_study_subject(2) - study_subject_inconclusive.virus_test_1 = None + study_subject_inconclusive = create_study_subject() + study_subject_inconclusive.virus_test_1_result = "Inconclusive" study_subject_inconclusive.virus_test_1_updated = timezone.now() study_subject_inconclusive.save() - self.check_subject_filtered([["virus_test_1", "true"]], [study_subject_positive]) - self.check_subject_filtered([["virus_test_1", "false"]], [study_subject_negative]) - self.check_subject_filtered([["virus_test_1", "inconclusive"]], [study_subject_inconclusive]) + self.check_subject_filtered([["virus_test_1_result", "Positive"]], [study_subject_positive]) + self.check_subject_filtered([["virus_test_1_result", "Negative"]], [study_subject_negative]) + self.check_subject_filtered([["virus_test_1_result", "Inconclusive"]], [study_subject_inconclusive]) @parameterized.expand([ ('text', CUSTOM_FIELD_TYPE_TEXT, 'bla'), diff --git a/smash/web/tests/view/test_mail.py b/smash/web/tests/view/test_mail.py index 1f11340a796aedc4e9c0eebf7662ddd50d3cce33..36fbf90a0d6fca6ca9b0d5d03da612f167d645e2 100644 --- a/smash/web/tests/view/test_mail.py +++ b/smash/web/tests/view/test_mail.py @@ -1,31 +1,13 @@ import logging -from django.urls import reverse - -from web.models import MailTemplate -from web.models.constants import MAIL_TEMPLATE_CONTEXT_VOUCHER from web.tests import LoggedInTestCase -from web.tests.functions import create_voucher, get_resource_path +from web.views.virus_mail import KitRequestEmailSendJob logger = logging.getLogger(__name__) -class MailTests(LoggedInTestCase): - def test_generate_vouchers(self): - voucher = create_voucher() - MailTemplate(name="name", language=None, - context=MAIL_TEMPLATE_CONTEXT_VOUCHER, - template_file=get_resource_path('upcoming_appointment_FR.docx')).save() - - page = reverse('web.views.mail_template_generate_for_vouchers') + "?voucher_id=" + str(voucher.id) - response = self.client.get(page) - self.assertEqual(response.status_code, 200) - - def test_list_mail_templates(self): - self.login_as_admin() - response = self.client.get(reverse("web.views.mail_templates")) - self.assertEqual(response.status_code, 200) - - def test_list_mail_templates_without_permission(self): - response = self.client.get(reverse("web.views.mail_templates")) - self.assertEqual(response.status_code, 302) +class VirusMailTests(LoggedInTestCase): + def test_send_email(self): + job = KitRequestEmailSendJob() + result = job.do() + self.assertEqual("mail sent", result) diff --git a/smash/web/tests/view/test_subjects.py b/smash/web/tests/view/test_subjects.py index 9551f3e7ed64921324fd712cca08a5634e9b06b1..c7cf50653eb0743465fdb64b200cb2737594a94f 100644 --- a/smash/web/tests/view/test_subjects.py +++ b/smash/web/tests/view/test_subjects.py @@ -21,7 +21,7 @@ logger = logging.getLogger(__name__) class SubjectsViewTests(LoggedInWithWorkerTestCase): def setUp(self): - super(SubjectsViewTests, self).setUp() + super().setUp() self.study_subject = create_study_subject() self.study = get_test_study() diff --git a/smash/web/tests/view/test_virus_mail.py b/smash/web/tests/view/test_virus_mail.py new file mode 100644 index 0000000000000000000000000000000000000000..1f11340a796aedc4e9c0eebf7662ddd50d3cce33 --- /dev/null +++ b/smash/web/tests/view/test_virus_mail.py @@ -0,0 +1,31 @@ +import logging + +from django.urls import reverse + +from web.models import MailTemplate +from web.models.constants import MAIL_TEMPLATE_CONTEXT_VOUCHER +from web.tests import LoggedInTestCase +from web.tests.functions import create_voucher, get_resource_path + +logger = logging.getLogger(__name__) + + +class MailTests(LoggedInTestCase): + def test_generate_vouchers(self): + voucher = create_voucher() + MailTemplate(name="name", language=None, + context=MAIL_TEMPLATE_CONTEXT_VOUCHER, + template_file=get_resource_path('upcoming_appointment_FR.docx')).save() + + page = reverse('web.views.mail_template_generate_for_vouchers') + "?voucher_id=" + str(voucher.id) + response = self.client.get(page) + self.assertEqual(response.status_code, 200) + + def test_list_mail_templates(self): + self.login_as_admin() + response = self.client.get(reverse("web.views.mail_templates")) + self.assertEqual(response.status_code, 200) + + def test_list_mail_templates_without_permission(self): + response = self.client.get(reverse("web.views.mail_templates")) + self.assertEqual(response.status_code, 302) diff --git a/smash/web/views/virus_mail.py b/smash/web/views/virus_mail.py index 9b6099cc04263b73261772d4e28f37317ad8f232..cd03ad1dde02831db43340784c1c556154ac8cee 100644 --- a/smash/web/views/virus_mail.py +++ b/smash/web/views/virus_mail.py @@ -14,40 +14,20 @@ from ..smash_email import EmailSender logger = logging.getLogger(__name__) +def count_subjects(date_from: datetime, status: str) -> int: + return StudySubject.objects.filter(virus_test_1_updated__gt=date_from, virus_test_1_result=str).count() + \ + StudySubject.objects.filter(virus_test_2_updated__gt=date_from, virus_test_2_result=str).count() + \ + StudySubject.objects.filter(virus_test_3_updated__gt=date_from, virus_test_3_result=str).count() + \ + StudySubject.objects.filter(virus_test_4_updated__gt=date_from, virus_test_4_result=str).count() + \ + StudySubject.objects.filter(virus_test_5_updated__gt=date_from, virus_test_5_result=str).count() + + def get_subject_statistics(): date_from = datetime.datetime.now() - datetime.timedelta(days=1) - subjects_positive_count = StudySubject.objects.filter(virus_test_1_updated__gt=date_from, virus_test_1=True).count() - subjects_positive_count += StudySubject.objects.filter(virus_test_2_updated__gt=date_from, - virus_test_2=True).count() - subjects_positive_count += StudySubject.objects.filter(virus_test_3_updated__gt=date_from, - virus_test_3=True).count() - subjects_positive_count += StudySubject.objects.filter(virus_test_4_updated__gt=date_from, - virus_test_4=True).count() - subjects_positive_count += StudySubject.objects.filter(virus_test_5_updated__gt=date_from, - virus_test_5=True).count() - - subjects_negative_count = StudySubject.objects.filter(virus_test_1_updated__gt=date_from, - virus_test_1=False).count() - subjects_negative_count += StudySubject.objects.filter(virus_test_2_updated__gt=date_from, - virus_test_2=False).count() - subjects_negative_count += StudySubject.objects.filter(virus_test_3_updated__gt=date_from, - virus_test_3=False).count() - subjects_negative_count += StudySubject.objects.filter(virus_test_4_updated__gt=date_from, - virus_test_4=False).count() - subjects_negative_count += StudySubject.objects.filter(virus_test_5_updated__gt=date_from, - virus_test_5=False).count() - - subjects_inconclusive_count = StudySubject.objects.filter(virus_test_1_updated__gt=date_from, - virus_test_1__isnull=True).count() - subjects_inconclusive_count += StudySubject.objects.filter(virus_test_2_updated__gt=date_from, - virus_test_2__isnull=True).count() - subjects_inconclusive_count += StudySubject.objects.filter(virus_test_3_updated__gt=date_from, - virus_test_3__isnull=True).count() - subjects_inconclusive_count += StudySubject.objects.filter(virus_test_4_updated__gt=date_from, - virus_test_4__isnull=True).count() - subjects_inconclusive_count += StudySubject.objects.filter(virus_test_5_updated__gt=date_from, - virus_test_5__isnull=True).count() + subjects_positive_count = count_subjects(date_from, "Positive") + 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, @@ -87,11 +67,11 @@ def create_statistic_email_content(data, title): email_body += "</table>" - #SARS-COV2 Virus  | Number of Donors - #Inconclusive  | 5 - #Positive  | 15 - #Negative  | 45 - #Total  | 65 + # SARS-COV2 Virus  | Number of Donors + # Inconclusive  | 5 + # Positive  | 15 + # Negative  | 45 + # Total  | 65 return email_body