diff --git a/smash/smash/local_settings.py.template b/smash/smash/local_settings.py.template index 652a544a7cbe0200a79bf08391d99e85743fc7fd..6a6d9320b67791836ca102e1869c0c1189b1e366 100644 --- a/smash/smash/local_settings.py.template +++ b/smash/smash/local_settings.py.template @@ -6,6 +6,8 @@ DEBUG = True WSGI_APPLICATION = 'smash.wsgi.application' +IMPORTER_USER = 'admin' #username + EMAIL_USE_TLS = False EMAIL_USE_SSL = False EMAIL_HOST = 'smtp.uni.lu' diff --git a/smash/web/importer/csv_tns_visit_import_reader.py b/smash/web/importer/csv_tns_visit_import_reader.py index ae9501c06abab72ef192b80056a2fb23e3aa1d11..4ba9eef37c2421d48809ee469bb39c379d0307f4 100644 --- a/smash/web/importer/csv_tns_visit_import_reader.py +++ b/smash/web/importer/csv_tns_visit_import_reader.py @@ -10,7 +10,7 @@ import pytz from django.conf import settings from warning_counter import MsgCounterHandler -from web.models import StudySubject, Study, Visit, Appointment, AppointmentType, Location, AppointmentTypeLink, Subject +from web.models import StudySubject, Study, Visit, Appointment, AppointmentType, Location, AppointmentTypeLink, Subject, User, Worker, Provenance from web.models.constants import GLOBAL_STUDY_ID CSV_DATE_FORMAT = "%d/%m/%Y" @@ -33,6 +33,16 @@ class TnsCsvVisitImportReader: self.processed_count = 0 self.warning_count = 0 + self.importer_user = None + + importer_user_name = getattr(settings, "IMPORTER_USER", None) + if importer_user_name is not None: + user = User.objects.filter(username=importer_user_name) + if user is None: + logger.warn("User does not exist: " + importer_user_name) + else: + self.importer_user = Worker.objects.filter(user=user) + def load_data(self, filename): warning_counter = MsgCounterHandler() logging.getLogger('').addHandler(warning_counter) @@ -80,22 +90,74 @@ class TnsCsvVisitImportReader: if len(visits) > 0: logger.debug("Visit for subject " + nd_number + " already exists. Updating") visit = visits[0] - visit.datetime_begin = date - visit.datetime_end = date + datetime.timedelta(days=14) + + changes = [('datetime_begin', date), + ('datetime_end', date + datetime.timedelta(days=14))] + + for field, new_value in changes: + old_value = getattr(visit, field) + if old_value == new_value: + continue + description = u'{} changed from "{}" to "{}"'.format(field, old_value, new_value) + p = Provenance(modified_table=Visit._meta.db_table, + modified_table_id=visit.id, + modification_author=self.importer_user, + previous_value=old_value, + new_value=new_value, + modification_description=description, + modified_field=field, + ) + setattr(visit, field, new_value) + p.save() + visit.save() else: visit = Visit.objects.create(subject=study_subject, visit_number=visit_number, datetime_begin=date, datetime_end=date + datetime.timedelta(days=14)) - visit.save() + visit.save() + #visit does not have id until .save() is done + for field in Visit._meta.get_fields(): + if field.get_internal_type() == "CharField" or field.get_internal_type() == "DateField" or field.get_internal_type() is "BooleanField": + new_value = getattr(visit, field.name) + if new_value is not None and new_value != "": + description = u'{} changed from "{}" to "{}"'.format(field, '', new_value) + p = Provenance(modified_table=Visit._meta.db_table, + modified_table_id=visit.id, + modification_author=self.importer_user, + previous_value='', + new_value=new_value, + modification_description=description, + modified_field=field, + ) + p.save() + result.append(visit) appointments = Appointment.objects.filter(visit=visit, appointment_types=self.appointment_type) if len(appointments) > 0: logger.debug("Appointment for subject " + nd_number + " already set. Updating") appointment = appointments[0] - appointment.length = 60 - appointment.datetime_when = date - appointment.location = location + + #(field, new_value) + changes = [('length', 60), + ('datetime_when', date), + ('location', location)] + + for field, new_value in changes: + old_value = getattr(appointment, field) + if old_value == new_value: + continue + description = u'{} changed from "{}" to "{}"'.format(field, old_value, new_value) + p = Provenance(modified_table=Appointment._meta.db_table, + modified_table_id=appointment.id, + modification_author=self.importer_user, + previous_value=old_value, + new_value=new_value, + modification_description=description, + modified_field=field, + ) + setattr(appointment, field, new_value) + p.save() appointment.save() else: appointment = Appointment.objects.create(visit=visit, length=60, datetime_when=date, @@ -103,6 +165,23 @@ class TnsCsvVisitImportReader: if self.appointment_type is not None: AppointmentTypeLink.objects.create(appointment_id=appointment.id, appointment_type=self.appointment_type) + + appointment.save() + #appointment does not have id until .save() is done + for field in Appointment._meta.get_fields(): + if field.get_internal_type() == "CharField" or field.get_internal_type() == "DateField" or field.get_internal_type() is "BooleanField": + new_value = getattr(appointment, field.name) + if new_value is not None and new_value != "": + description = u'{} changed from "{}" to "{}"'.format(field, '', new_value) + p = Provenance(modified_table=Appointment._meta.db_table, + modified_table_id=appointment.id, + modification_author=self.importer_user, + previous_value='', + new_value=new_value, + modification_description=description, + modified_field=field, + ) + p.save() self.processed_count += 1 except: self.problematic_count += 1 diff --git a/smash/web/redcap_connector.py b/smash/web/redcap_connector.py index a2af5169ca07e21bf5bce8098b152dbd53122891..01ada9e9c12d07b945679485dbcd6aa6dc870d7e 100644 --- a/smash/web/redcap_connector.py +++ b/smash/web/redcap_connector.py @@ -11,7 +11,7 @@ from django.conf import settings from django.forms.models import model_to_dict from django_cron import CronJobBase, Schedule -from web.models import ConfigurationItem, StudySubject, Language, AppointmentType, Appointment, Visit, Study +from web.models import ConfigurationItem, StudySubject, Language, AppointmentType, Appointment, Visit, Study, Provenance, Worker, User from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, \ REDCAP_BASE_URL_CONFIGURATION_TYPE, CRON_JOB_TIMEOUT, RED_CAP_LANGUAGE_4_FIELD_TYPE, RED_CAP_LANGUAGE_3_FIELD_TYPE, \ RED_CAP_LANGUAGE_2_FIELD_TYPE, RED_CAP_LANGUAGE_1_FIELD_TYPE, RED_CAP_MPOWER_ID_FIELD_TYPE, RED_CAP_DEAD_FIELD_TYPE, \ @@ -86,6 +86,16 @@ class RedcapConnector(object): self.study = Study.objects.get(id=GLOBAL_STUDY_ID) + self.importer_user = None + + importer_user_name = getattr(settings, "IMPORTER_USER", None) + if importer_user_name is not None: + user = User.objects.filter(username=importer_user_name) + if user is None: + logger.warn("User does not exist: " + importer_user_name) + else: + self.importer_user = Worker.objects.filter(user=user) + def find_missing(self): pid = self.get_project_id() redcap_version = self.get_redcap_version() @@ -196,43 +206,53 @@ class RedcapConnector(object): status=Appointment.APPOINTMENT_STATUS_SCHEDULED) for smasch_appointment in smasch_appointments: smasch_appointment.mark_as_finished() - smasch_appointment.visit.is_finished = True - smasch_appointment.visit.save() + if smasch_appointment.visit.is_finished != True: + description = u'{} changed from "{}" to "{}"'.format('is_finished', smasch_appointment.visit.is_finished, True) + p = Provenance(modified_table=Visit._meta.db_table, + modified_table_id=smasch_appointment.visit.id, + modification_author=self.importer_user, + previous_value=smasch_appointment.visit.is_finished, + new_value=True, + modification_description=description, + modified_field='is_finished') + smasch_appointment.visit.is_finished = True + smasch_appointment.visit.save() if visit.virus is not None or visit.virus_inconclusive: + changes = None if visit.visit_number == 1 and subject.virus_test_1 != visit.virus: - subject.virus_test_1 = visit.virus - subject.virus_test_1_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_1', visit.virus), ('virus_test_1_updated', datetime.datetime.now())] if visit.visit_number == 2 and subject.virus_test_2 != visit.virus: - subject.virus_test_2 = visit.virus - subject.virus_test_2_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_2', visit.virus), ('virus_test_2_updated', datetime.datetime.now())] if visit.visit_number == 3 and subject.virus_test_3 != visit.virus: - subject.virus_test_3 = visit.virus - subject.virus_test_3_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_3', visit.virus), ('virus_test_3_updated', datetime.datetime.now())] if visit.visit_number == 4 and subject.virus_test_4 != visit.virus: - subject.virus_test_4 = visit.virus - subject.virus_test_4_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_4', visit.virus), ('virus_test_4_updated', datetime.datetime.now())] if visit.visit_number == 5 and subject.virus_test_5 != visit.virus: - subject.virus_test_5 = visit.virus - subject.virus_test_5_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_5', 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: - subject.virus_test_1_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_1_updated', datetime.datetime.now())] if visit.visit_number == 2 and subject.virus_test_2_updated is None and visit.virus_inconclusive: - subject.virus_test_2_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_2_updated', datetime.datetime.now())] if visit.visit_number == 3 and subject.virus_test_3_updated is None and visit.virus_inconclusive: - subject.virus_test_3_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_3_updated', datetime.datetime.now())] if visit.visit_number == 4 and subject.virus_test_4_updated is None and visit.virus_inconclusive: - subject.virus_test_4_updated = datetime.datetime.now() - subject.save() + changes = [('virus_test_4_updated', datetime.datetime.now())] if visit.visit_number == 5 and subject.virus_test_5_updated is None and visit.virus_inconclusive: - subject.virus_test_5_updated = datetime.datetime.now() + changes = [('virus_test_5_updated', datetime.datetime.now())] + # + if changes is not None: + for field, new_value in changes: + old_value = getattr(subject, field) + description = u'{} changed from "{}" to "{}"'.format(field, old_value, new_value) + p = Provenance(modified_table=StudySubject._meta.db_table, + modified_table_id=subject.id, + modification_author=self.importer_user, + previous_value=old_value, + new_value=new_value, + modification_description=description, + modified_field=field) + setattr(subject, field, new_value) + p.save() subject.save() return result