diff --git a/smash/create_dummy_data.py b/smash/create_dummy_data.py index 00123ca144d7c33a55e85aa07888b3c8d8fce745..8adbda03fd8d14c3b12fe9f3a665e336dabc4462 100644 --- a/smash/create_dummy_data.py +++ b/smash/create_dummy_data.py @@ -1,16 +1,23 @@ from django.conf import settings +from django.core.files import File # you need this somewhere +import urllib +from django.core.files.uploadedfile import SimpleUploadedFile import django +import datetime +from django.utils import timezone import os os.environ.setdefault("DJANGO_SETTINGS_MODULE", "smash.settings") django.setup() from django.contrib.auth.models import User -from web.models import StudySubject, Availability, Appointment, AppointmentType, Study, Subject, Worker, Location, Language, Country, WorkerStudyRole, Item, FlyingTeam, Room, MailTemplate +#models (please add in both lines) +from web.models import StudySubject, Availability, Visit, Appointment, AppointmentType, AppointmentTypeLink, Study, Subject, Worker, Location, Language, Country, WorkerStudyRole, Item, FlyingTeam, Room, MailTemplate +from smash.local_settings import MEDIA_ROOT from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, REDCAP_BASE_URL_CONFIGURATION_TYPE, \ SEX_CHOICES_MALE, SEX_CHOICES_FEMALE, SUBJECT_TYPE_CHOICES_CONTROL, SUBJECT_TYPE_CHOICES_PATIENT, CONTACT_TYPES_PHONE, \ MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID, VOUCHER_STATUS_NEW, GLOBAL_STUDY_ID, DEFAULT_LOCALE_NAME from web.models.constants import MAIL_TEMPLATE_CONTEXT_APPOINTMENT, MAIL_TEMPLATE_CONTEXT_VISIT, \ MAIL_TEMPLATE_CONTEXT_SUBJECT, MAIL_TEMPLATE_CONTEXT_VOUCHER -from web.models.worker_study_role import ROLE_CHOICES_PROJECT_MANAGER, ROLE_CHOICES_SECRETARY, ROLE_CHOICES_DOCTOR, WORKER_VOUCHER_PARTNER +from web.models.worker_study_role import ROLE_CHOICES_PROJECT_MANAGER, ROLE_CHOICES_SECRETARY, ROLE_CHOICES_DOCTOR, WORKER_VOUCHER_PARTNER, ROLE_CHOICES_TECHNICIAN, ROLE_CHOICES_PSYCHOLOGIST, ROLE_CHOICES_NURSE from web.tests.functions import get_resource_path from collections import defaultdict @@ -21,7 +28,8 @@ from web.views.notifications import get_today_midnight_date from faker.providers import BaseProvider, color from numpy.random import choice from faker import Faker -import unidecode +import platform, tempfile, unidecode +from shutil import copyfile class smashProvider(BaseProvider): @@ -32,7 +40,7 @@ class smashProvider(BaseProvider): specialists = ['Psychiatrist', 'Radiologist', 'Immunologist', 'Anesthesiologist', 'Surgeon', 'Pediatrician', 'Neurologist', 'Medical examiner'] units = ['LHI', 'PCR', 'LCSB', 'ACO', 'PLI', 'LRSU'] - workerRoles = [ROLE_CHOICES_PROJECT_MANAGER, ROLE_CHOICES_SECRETARY, ROLE_CHOICES_DOCTOR, ROLE_CHOICES_DOCTOR] + workerRoles = [ROLE_CHOICES_PROJECT_MANAGER, ROLE_CHOICES_SECRETARY, ROLE_CHOICES_DOCTOR, ROLE_CHOICES_TECHNICIAN, ROLE_CHOICES_PSYCHOLOGIST, ROLE_CHOICES_NURSE] #towns and cities near_fr_towns = ['Metz', 'Audun-le-Tiche', 'Thionville'] @@ -50,7 +58,7 @@ class smashProvider(BaseProvider): alreadyCreatedLocations = {} #languages - language_base_dir = './smash/web/static/flags/' + language_base_dir = 'web/static/flags/' language_flags = { 'French' : 'FR.png', 'English': 'GB.png', @@ -60,11 +68,20 @@ class smashProvider(BaseProvider): 'German': 'DE.png', 'Dutch' : 'NL.png' } + language_locale = { + 'French' : 'fr_FR', + 'Luxembourgish' : 'lb_LU', + 'Spanish' : 'es_ES', + 'English' : 'en_GB', + 'Portuguese': 'pt_PT', + 'German' : 'de_DE', + 'Dutch' : 'nl_NL' + } languages = ['English', 'Luxembourgish', 'French', 'German', 'Portuguese', 'Spanish', 'Dutch'] languages_prob = [0.25, 0.2, 0.16, 0.16, 0.13, 0.05, 0.05] alreadyCreatedLanguages = {} #items - items = ['Ambulance', 'Bandages', 'Examination Table', 'X-Ray Machine', 'Lab Coat', 'Needle', 'Stretcher', 'Vial', 'Wheelchair'] + items = ['Saliva', 'Blood', 'Liquid Biopsy', 'X-Ray Examination', 'Urine', 'Tissue Biopsy', 'Skin sample'] alreadyCreatedItems = {} #flying teams places = ['Belval', 'Belvaux', 'Arlon', 'Metz'] @@ -84,6 +101,8 @@ class smashProvider(BaseProvider): alreadyCreatedAppointmentTypes = [] #workers alreadyCreatedWorkers = [] + #rooms + alreadyCreatedRooms = [] def getLuxembourgTown(self): return self.fake.word(ext_word_list=self.luxtowns) @@ -112,9 +131,9 @@ class smashProvider(BaseProvider): if day_number is None: day_number = choice(range(1,6)) if available_from is None: - available_from = '8:00' + available_from = '{}:00'.format(choice(range(8,10))) if available_till is None: - available_till = '18:00' + available_till = '{}:00'.format(choice(range(13,18))) availability, _ = Availability.objects.update_or_create(person=worker, day_number=day_number, @@ -124,44 +143,76 @@ class smashProvider(BaseProvider): #appointments def createSmashAppointments(self): - for subject in self.alreadyCreatedSubjects: - visit = self.createSmashVisit(subject=subject) - appointment = self.createSmashAppointment(visit=visit) - - def createSmashAppointment(self, visit=None, datetime_when=None, location=None, length=30, status=Appointment.APPOINTMENT_STATUS_SCHEDULED): + today = timezone.now() + #create first visit, in between -2y and -1y from now and first appointment + for studySubject in self.alreadyCreatedStudySubjects: + #date_between does not support months so we use days + visit_start_date = fake.date_between(start_date='-1y', end_date='-334d') - datetime.timedelta(days=-31) + visit_end_date = visit_start_date + datetime.timedelta(days=31) + visit = self.createSmashVisit(studySubject=studySubject, datetime_begin=visit_start_date, + datetime_end=visit_end_date, is_finished=True) + appointment_types = self.getAlreadyCreatedAppointmentTypes() + visit.appointment_types.set(appointment_types) + #appointment + duration = sum([app.default_duration for app in appointment_types]) + appointment_start_date = fake.date_time_between(start_date=visit_start_date, end_date=visit_end_date, + tzinfo=today.tzinfo) + hour = choice(range(9, 18)) + minute = choice(range(0, 30, 5)) + #ensure the time is between office hours + appointment_start_date = appointment_start_date.replace(hour=hour, minute=minute, tzinfo=today.tzinfo) + + room = choice(self.alreadyCreatedRooms) + appointment = self.createSmashAppointment(visit=visit, datetime_when=appointment_start_date, + length=duration, appointment_types=appointment_types, room=room, status=Appointment.APPOINTMENT_STATUS_FINISHED) + + def createSmashAppointment(self, visit=None, datetime_when=None, location=None, length=30, + status=Appointment.APPOINTMENT_STATUS_SCHEDULED, appointment_types=None, room=None, worker_assigned=None): if visit is None: visit = self.createSmashVisit() if datetime_when is None: datetime_when = get_today_midnight_date() if location is None: location = self.getAlreadyCreatedSmashLocation() + if room is None: + room = choice(self.alreadyCreatedRooms) + if worker_assigned is None: + worker_assigned = choice(self.alreadyCreatedWorkers) appointment, _ = Appointment.objects.update_or_create( - visit=visit, length=length, location=location, - status=status, datetime_when=datetime_when) + visit=visit, length=length, location=location, worker_assigned=worker_assigned, + status=status, datetime_when=datetime_when, room=room) - appointment.types.set(self.getAlreadyCreatedAppointmentTypes()) - appointment.save() + if appointment_types is None: + appointment_types = self.getAlreadyCreatedAppointmentTypes() + + #create connection for each appointment type + when = datetime_when + for appointment_type in appointment_types: + worker=choice(self.alreadyCreatedWorkers) + when = when + datetime.timedelta(minutes=appointment_type.default_duration) + app_type_link = AppointmentTypeLink(appointment=appointment, date_when=when, + appointment_type=appointment_type, worker=worker) return appointment #visit - def createSmashVisit(self, datetime_begin=None, datetime_end=None, subject=None, is_finished=False): + def createSmashVisit(self, datetime_begin=None, datetime_end=None, studySubject=None, is_finished=False, visit_number=1): if datetime_begin is None: datetime_begin = get_today_midnight_date() + datetime.timedelta(days=-31) if datetime_end is None: datetime_end = get_today_midnight_date() + datetime.timedelta(days=31) - if subject is None: - subject = choice(self.alreadyCreatedSubjects, 1)[0] + if studySubject is None: + studySubject = choice(self.alreadyCreatedStudySubjects) visit, _ = Visit.objects.update_or_create(datetime_begin=datetime_begin, datetime_end=datetime_end, - subject=subject, is_finished=is_finished) + subject=studySubject, is_finished=is_finished, visit_number=visit_number) return visit #AppointmentTypes def getAlreadyCreatedAppointmentTypes(self, n=3): - return choice(self.alreadyCreatedAppointmentTypes, n) + return set(choice(self.alreadyCreatedAppointmentTypes, n)) def createSmashAppointmentTypes(self, n_max=5): return [self.createSmashAppointmentType() for _ in xrange(n_max)] @@ -203,7 +254,10 @@ class smashProvider(BaseProvider): name = '{} Template'.format(language.name) if template_file is None: template_file = self.template_file - template, _ = MailTemplate.objects.update_or_create(name=name, language=language, context=context, template_file = template_file) + basename = os.path.basename(template_file) + dst = os.path.join(MEDIA_ROOT, basename) + copyfile(template_file, dst) + template, _ = MailTemplate.objects.update_or_create(name=name, language=language, context=context, template_file = dst) return template #flying teams @@ -295,6 +349,8 @@ class smashProvider(BaseProvider): room.equipment.set(equipment) room.save() + self.alreadyCreatedRooms.append(room) + return room #country @@ -419,11 +475,11 @@ class smashProvider(BaseProvider): password: string: Sets the password. By default password1234 unless other value is provided. Returns a user ''' - first_name = self.fake.first_name().lower().replace('_', '') - last_name = self.fake.last_name().lower().replace('_', '') + first_name = self.fake.first_name().lower() + last_name = self.fake.last_name().lower() if username is None: username = u'{}_{}'.format(first_name, last_name) - username = unidecode.unidecode(username) + username = unidecode.unidecode(username).lower().replace(' ', '_') if email is None: email = u'{}.{}@smash.lu'.format(first_name, last_name) @@ -445,7 +501,9 @@ class smashProvider(BaseProvider): logger.info('creating Smash Worker...') return [self.createSmashWorker() for _ in xrange(n)] - def createSmashWorker(self, first_name=None, last_name=None, username=None, email=None, specialization=None, unit=None, phone_number=None, password='password1234', role=None): + def createSmashWorker(self, first_name=None, last_name=None, username=None, email=None, + specialization=None, unit=None, phone_number=None, password='password1234', role=None, + locations=None, languages=None): ''' first_name: string: Sets the first_name. By default None. Random values are generated. Provide a value to overwrite random generation last_name: string: Sets the last_name. By default None. Random values are generated. Provide a value to overwrite random generation @@ -456,6 +514,8 @@ class smashProvider(BaseProvider): phone_number: string: Sets the phone_number. By default None. Random values are generated. Provide a value to overwrite random generation password: string: Sets the password. By default None. Random values are generated. Provide a value to overwrite random generation role: string: Sets the role. By default None. Random values are generated. Provide a value to overwrite random generation + locations: list: Sets the worker locations. By default None. Random values are generated. Provide a value to overwrite random generation + languages: list: Sets the worker languages. By default None. Random values are generated. Provide a value to overwrite random generation Returns a tuple with (user, worker, workerStuyRole) ''' if first_name is None: @@ -465,7 +525,7 @@ class smashProvider(BaseProvider): last_name = self.fake.last_name() if username is None: - username = u'{}_{}'.format(first_name, last_name) + username = u'{}_{}'.format(first_name, last_name).lower().replace(' ', '_') if email is None: email = u'{}.{}@smash.lu'.format(first_name, last_name) @@ -492,8 +552,12 @@ class smashProvider(BaseProvider): worker, _ = Worker.objects.update_or_create(first_name=first_name, last_name=last_name, defaults=defaults) - worker.locations.set([self.getAlreadyCreatedSmashLocation()]) - worker.languages.set(self.getAlreadyCreatedSmashLanguages()) + if locations is None: + locations = [self.getAlreadyCreatedSmashLocation()] + worker.locations.set(locations) + if languages is None: + languages = self.getAlreadyCreatedSmashLanguages() + worker.languages.set(languages) worker.save() self.alreadyCreatedWorkers.append(worker) @@ -518,15 +582,30 @@ class smashProvider(BaseProvider): logger.info('creating Smash Languages...') return [self.createSmashLanguage(name=name) for name in self.languages] - def createSmashLanguage(self, name=None, locale=DEFAULT_LOCALE_NAME): + def createSmashLanguage(self, name=None, locale=None): ''' Returns a Language object ''' if name is None: name = self.fake.word(ext_word_list=self.languages) + if locale is None: + if name in self.language_locale: + locale = self.language_locale[name] + else: + locale = DEFAULT_LOCALE_NAME + language, _ = Language.objects.update_or_create(name=name, locale=locale) self.alreadyCreatedLanguages[name] = language + + if name in self.language_flags: + src = os.path.join(self.language_base_dir, self.language_flags[name]) + basename = os.path.basename(src) + dst = os.path.join(MEDIA_ROOT, basename) + copyfile(src, dst) + language.image = basename #.save(basename, File(open(dst, 'rb'))) #SimpleUploadedFile(name=path, content=open(path, 'rb').read(), content_type='image/png') + language.save() + return language def getAlreadyCreatedSmashLanguages(self, max_n=3): @@ -569,11 +648,16 @@ class smashProvider(BaseProvider): return location + def getAllCreatedLocations(self): + return self.alreadyCreatedLocations.values() + + def getAllCreatedLanguages(self): + return self.alreadyCreatedLanguages.values() + if __name__ == "__main__": fake = Faker() fake.seed(4321) fake.add_provider(smashProvider) - fake.createSmashFlyingTeams() fake.createSmashItems() fake.createSmashAppointmentTypes() @@ -586,7 +670,10 @@ if __name__ == "__main__": fake.createSmashWorkers() fake.createSmashAvailabilities() fake.createSmashStudySubjects() - + fake.createSmashAppointments() + fake.createSmashWorker(first_name=u'System', last_name=u'Admin', + email=u'carlos.vega@uni.lu', role=ROLE_CHOICES_TECHNICIAN, + locations=fake.getAllCreatedLocations(), languages=fake.getAllCreatedLanguages()) # flying_teams = add_flying_teams() # items = add_items() # add_rooms(items)