Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
create_dummy_data.py 31.26 KiB
# coding=utf-8
import os, sys
sys.path.append(sys.path.append(os.path.join(os.path.dirname(__file__), '..'))) #run script as it was on parent folder
from django.conf import settings
from django.core.files import File  # you need this somewhere
import urllib.request, urllib.parse, urllib.error
from django.core.files.uploadedfile import SimpleUploadedFile
import django
import datetime
from django.utils import timezone
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "smash.settings")
django.setup()
from django.contrib.auth.models import User
# 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, ROLE_CHOICES_TECHNICIAN, ROLE_CHOICES_PSYCHOLOGIST, ROLE_CHOICES_NURSE

from collections import defaultdict
import logging
logger = logging.getLogger(__name__)

from web.utils import get_today_midnight_date
from faker.providers import BaseProvider, color
from numpy.random import choice
from faker import Faker
import platform
import tempfile
from shutil import copyfile


class smashProvider(BaseProvider):

    __provider__ = 'smash'
    __lang__ = 'fr_FR'
    fake = Faker()
    Faker.seed(4321)

    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_TECHNICIAN, ROLE_CHOICES_PSYCHOLOGIST, ROLE_CHOICES_NURSE]

    #towns and cities
    near_fr_towns = ['Metz', 'Audun-le-Tiche', 'Thionville']
    near_de_towns = ['Trier']
    near_be_towns = ['Aubange', 'Arlon']
    luxtowns = ['Luxembourg City', 'Esch-sur-Alzette', 'Differdange', 'Dudelange', 'Ettelbruck',
                'Diekirch', 'Wiltz', 'Rumelange', 'Echternach', 'Grevenmacher', 'Remich', 'Vianden']

    # if you add or remove cities, be careful and change the probabilities as well
    # here the probs ensure the luxembourgish towns have 0.8 prob, and so on...
    cities = luxtowns + near_fr_towns + near_de_towns + near_be_towns
    city_prob = [0.8 / len(luxtowns)]      * len(luxtowns) + \
        [0.1 / len(near_fr_towns)] * len(near_fr_towns) + \
        [0.05 / len(near_de_towns)] * len(near_de_towns) + \
        [0.05 / len(near_be_towns)] * len(near_be_towns)

    alreadyCreatedLocations = {}
    # languages
    language_base_dir = 'web/static/flags/'
    language_flags = {
        'French': 'FR.png',
        'English': 'GB.png',
        'Spanish': 'ES.png',
        'Portuguese': 'PT.png',
        'Luxembourgish': 'LU.png',
        '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 = ['Saliva', 'Blood', 'Liquid Biopsy',
             'X-Ray Examination', 'Urine', 'Tissue Biopsy', 'Skin sample']
    alreadyCreatedItems = {}
    # flying teams
    places = ['Belval', 'Belvaux', 'Arlon', 'Metz']
    alreadyCreatedFlyingTeams = {}
    # countries
    countries = ['France', 'Luxembourg', 'Germamny', 'Belgium']
    alreadyCreatedCountries = {}
    # screening number
    screening_number_ctrs = defaultdict(int)
    # template file
    template_file = os.path.join(os.path.dirname(__file__), '../web/tests/data', 'upcoming_appointment_FR.docx')
    template_context = [MAIL_TEMPLATE_CONTEXT_APPOINTMENT, MAIL_TEMPLATE_CONTEXT_VOUCHER,
                        MAIL_TEMPLATE_CONTEXT_VISIT, MAIL_TEMPLATE_CONTEXT_SUBJECT]
    # subjects
    alreadyCreatedSubjects = []
    alreadyCreatedStudySubjects = []
    # appointment type
    alreadyCreatedAppointmentTypes = []
    # workers
    alreadyCreatedWorkers = []
    # rooms
    alreadyCreatedRooms = []
    # nd_number_ctr
    nd_number_ctr = 0

    def getLuxembourgTown(self):
        return self.fake.word(ext_word_list=self.luxtowns)

    def getFrenchTown(self):
        return self.fake.word(ext_word_list=self.near_fr_towns)

    def getBelgiumTown(self):
        return self.fake.word(ext_word_list=self.near_be_towns)

    def getDeutschTown(self):
        return self.fake.word(ext_word_list=self.near_de_towns)

    def getWorkerRole(self):
        return self.fake.word(ext_word_list=self.workerRoles)

    # availability
    def createSmashAvailabilities(self):
        for worker in self.alreadyCreatedWorkers:
            for weekday in set(choice(list(range(1, 6)), 4)):
                availability = self.createSmashAvailability(
                    worker=worker, day_number=weekday)

    def createSmashAvailability(self, worker=None, day_number=None, available_from=None, available_till=None):
        if worker is None:
            worker = choice(self.alreadyCreatedWorkers)
        if day_number is None:
            day_number = choice(list(range(1, 6)))
        if available_from is None:
            available_from = '{}:00'.format(choice(list(range(8, 10))))
        if available_till is None:
            available_till = '{}:00'.format(choice(list(range(13, 18))))

        availability, _ = Availability.objects.update_or_create(person=worker,
                                                                day_number=day_number,
                                                                available_from=available_from,
                                                                available_till=available_till)
        return availability

    # appointments
    def createSmashAppointments(self):
        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(list(range(9, 18)))
            minute = choice(list(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, worker_assigned=worker_assigned,
            status=status, datetime_when=datetime_when, room=room)

        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, 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 studySubject is None:
            studySubject = choice(self.alreadyCreatedStudySubjects)

        visit, _ = Visit.objects.update_or_create(datetime_begin=datetime_begin, datetime_end=datetime_end,
                                                  subject=studySubject, is_finished=is_finished, visit_number=visit_number)
        return visit

    # AppointmentTypes
    def getAlreadyCreatedAppointmentTypes(self, n=3):
        return set(choice(self.alreadyCreatedAppointmentTypes, n))

    def createSmashAppointmentTypes(self, n_max=5):
        return [self.createSmashAppointmentType() for _ in range(n_max)]

    def createSmashAppointmentType(self, code=None, default_duration=10, rest_time=5, description=None):
        if code is None:
            code = self.fake.word(ext_word_list=['C', 'A', 'N', 'P'])
        if description is None:
            description = self.fake.word(
                ext_word_list=['Examination', 'Analysis', 'Questions', 'Test'])
        equipment = self.getSmashAlreadyCreatedItems()
        appointmentType, _ = AppointmentType.objects.update_or_create(code=code, rest_time=rest_time,
                                                                      default_duration=default_duration, description=description)

        appointmentType.required_equipment.set(equipment)
        appointmentType.required_worker = choice(
            ['DOCTOR', 'NURSE', 'PSYCHOLOGIST', 'ANY'])
        appointmentType.save()

        self.alreadyCreatedAppointmentTypes.append(appointmentType)

        return appointmentType

    # mail template
    def createSmashMailTemplates(self):
        '''
        Returns a list of template objects
        '''
        languages = self.getAlreadyCreatedSmashLanguages()
        templates = []
        for context in self.template_context:
            for language in languages:
                template = self.createSmashMailTemplate(
                    language=language, context=context)
                templates.append(template)
        return templates

    def createSmashMailTemplate(self, name=None, language=None, context=MAIL_TEMPLATE_CONTEXT_APPOINTMENT, template_file=None):
        if language is None:
            language = self.getAlreadyCreatedSmashLanguages()[0]
        if name is None:
            name = '{} Template'.format(language.name)
        if template_file is None:
            template_file = self.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
    def createSmashFlyingTeams(self):
        return [self.createSmashFlyingTeam(place=place) for place in self.places]

    def createSmashFlyingTeam(self, place=None):
        if place is None:
            place = self.fake.word(ext_word_list=self.places)
        flying_team, _ = FlyingTeam.objects.update_or_create(place=place)

        self.alreadyCreatedFlyingTeams[place] = flying_team

        return flying_team

    # item
    def createSmashItems(self):
        '''
        Returns a list of Item objects
        '''
        return [self.createSmashItem(name=item) for item in self.items]

    def createSmashItem(self, name=None, is_fixed=None, disposable=None):
        '''
        Returns an Item object
        '''
        if name is None:
            name = self.fake.word(ext_word_list=self.items)

        if is_fixed is None:
            is_fixed = self.fake.boolean(chance_of_getting_true=75)

        if disposable is None:
            disposable = self.fake.boolean(chance_of_getting_true=75)

        item, _ = Item.objects.update_or_create(
            name=name, is_fixed=is_fixed, disposable=disposable)

        self.alreadyCreatedItems[name] = item

        return item

    def getSmashAlreadyCreatedItems(self, max_n=3):
        if len(list(self.alreadyCreatedItems.keys())) == 0:
            self.createSmashItems()

        keys = set(choice(list(self.alreadyCreatedItems.keys()), max_n))
        return [self.alreadyCreatedItems[key] for key in keys]

    # room
    def createSmashRooms(self, n=4):
        return [self.createSmashRoom() for _ in range(n)]

    def createSmashRoom(self, equipment=None, owner=None, address=None, city=None, room_number=None, floor=None, is_vehicle=None):
        '''
        equipment: List of Item objects: 
        owner: string: 
        address: string: 
        city: string: 
        room_number: int: 
        floor: int: 
        is_vehicle: boolean: 
        '''
        if equipment is None:
            item = self.fake.word(
                ext_word_list=list(self.alreadyCreatedItems.keys()))
            equipment = self.getSmashAlreadyCreatedItems()

        if owner is None:
            owner = self.fake.first_name()

        if address is None:
            address = '{}, {} {}'.format(self.fake.word(
                ext_word_list=self.cities), self.fake.random_digit_not_null_or_empty(), self.fake.street_name())
            address = address.replace('\n', ' ')

        if city is None:
            city = self.fake.word(ext_word_list=self.cities)

        if room_number is None:
            room_number = choice(list(range(10)), 1)[0]  # choice returns a list

        if floor is None:
            floor = choice(list(range(10)), 1)[0]

        if is_vehicle is None:
            is_vehicle = self.fake.boolean(chance_of_getting_true=25)

        dicc = {'owner': owner, 'city': city, 'address': address,
                'floor': floor, 'room_number': room_number, 'is_vehicle': is_vehicle}
        room, _ = Room.objects.update_or_create(**dicc)
        room.equipment.set(equipment)
        room.save()

        self.alreadyCreatedRooms.append(room)

        return room

    # country
    def getAlreadyCreatedSmashCountry(self):
        if len(self.alreadyCreatedCountries) == 0:
            self.createSmashCountries()

        name = self.fake.word(ext_word_list=self.countries)
        return self.alreadyCreatedCountries[name]

    def createSmashCountries(self):
        return [self.createSmashCountry(name=country) for country in self.countries]

    def createSmashCountry(self, name=None, order=0):
        if name is None:
            name = self.fake.word(ext_word_list=self.countries)
        country, _ = Country.objects.update_or_create(name=name, order=order)
        self.alreadyCreatedCountries[name] = country
        return country

    def createSmashScreeningNumber(self, prefix):
        self.screening_number_ctrs[prefix] += 1
        return '{}-{:03}'.format(prefix, self.screening_number_ctrs[prefix])

    # subject
    def createSmashStudySubjects(self, n=30):
        '''
        Returns a list of tuples (subject, study_subject)
        '''
        study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0]
        return [self.createSmashStudySubject(study=study) for _ in range(n)]

    def createSmashStudySubject(self, nd_number=None, subject=None, study=None, postponed=None,
                                datetime_contact_reminder=None, type=None, default_location=None, flying_team=None,
                                screening_number=None):  # complete code and args...

        if nd_number is None:
            nd_number = 'ND{:04}'.format(self.nd_number_ctr)
            self.nd_number_ctr += 1

        if subject is None:
            subject = self.createSmashSubject()

        if study is None:
            study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0]

        if type is None:
            type = choice([SUBJECT_TYPE_CHOICES_CONTROL,
                           SUBJECT_TYPE_CHOICES_PATIENT], 1, p=[0.2, 0.8])
            type = type[0]

        if default_location is None:
            default_location = self.getAlreadyCreatedSmashLocation()

        if screening_number is None:
            screening_number = self.createSmashScreeningNumber(
                default_location.prefix)

        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_result is None:
            virus_test_1_collection_date = ''
            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')
            virus_test_1_collection_date = choice([None, virus_test_1_updated], 1, p=[0.7, 0.3])[0]
        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:
            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')

        study_subject, _ = StudySubject.objects.update_or_create(nd_number=nd_number, subject=subject,
                                                                 defaults={'default_location': default_location, 'type': type,
                                                                           'screening_number': screening_number, 'study': study})
        study_subject.set_custom_field_value('Visit 0 RT-PCR update date', virus_test_1_updated)
        study_subject.set_custom_field_value('Virus 0 RT-PCR', virus_test_1_result)
        study_subject.set_custom_field_value('Visit 0 RT-PCR collection date', virus_test_1_collection_date)
        study_subject.set_custom_field_value('Visit 0 IgA Status', virus_iga_1)
        study_subject.set_custom_field_value('Visit 0 IgG Status', virus_igg_1)
        self.alreadyCreatedStudySubjects.append(study_subject)

        return study_subject

    def createSmashSubject(self, first_name=None, last_name=None, languages=None,
                           default_written_communication_language=None, phone_number=None, social_security_number=None,
                           sex=None, country_id=None, date_born=None, address=None,
                           postal_code=None, city=None, country=None, dead=None):

        if first_name is None:
            first_name = self.fake.first_name()

        if last_name is None:
            last_name = self.fake.last_name()

        if languages is None:
            languages = self.getAlreadyCreatedSmashLanguages()

        if default_written_communication_language is None:
            getAlreadyCreatedSmashLanguages = languages[0]

        if phone_number is None:
            phone_number = self.fake.phone_number()[:20]

        if social_security_number is None:
            social_security_number = ''

        if sex is None:
            sex = self.fake.word(
                ext_word_list=[SEX_CHOICES_MALE, SEX_CHOICES_FEMALE])

        if country_id is None:
            country_id = COUNTRY_AFGHANISTAN_ID

        if date_born is None:
            date_born = self.fake.date_of_birth(
                minimum_age=50, maximum_age=105).strftime('%Y-%m-%d')
        if address is None:
            address = self.fake.address()
        if postal_code is None:
            postal_code = self.fake.postcode()
        if city is None:
            city = self.fake.word(ext_word_list=self.cities)
        if country is None:
            country = self.getAlreadyCreatedSmashCountry()
        if dead is None:
            dead = self.fake.boolean(chance_of_getting_true=1)

        dicc = {'first_name': first_name, 'last_name': last_name,
                'default_written_communication_language': default_written_communication_language,
                'phone_number': phone_number, 'social_security_number': social_security_number,
                'sex': sex, 'country_id': country_id, 'date_born': date_born, 'address': address,
                'postal_code': postal_code, 'city': city, 'country': country, 'dead': dead}

        subject, _ = Subject.objects.update_or_create(**dicc)
        subject.languages.set(languages)
        subject.save()

        self.alreadyCreatedSubjects.append(subject)

        return subject

    # user
    def createSmashUser(self, username=None, email=None, password='smashtest007'):
        '''
        username: string: Sets the username. By default None. Random values are generated unless other value is provided.
        email: string: Sets the email. By default None. Random values are generated unless other value is provided.
        password: string: Sets the password. By default password1234 unless other value is provided.
        Returns a user
        '''
        first_name = self.fake.first_name().lower()
        last_name = self.fake.last_name().lower()
        if username is None:
            username = '{}_{}'.format(first_name, last_name)
        username = username.lower().replace(' ', '_')

        if email is None:
            email = '{}.{}@smash.lu'.format(first_name, last_name)
        email = email
        # create user
        defaults = {'email': email, 'password': password}
        user, _ = User.objects.update_or_create(
            username=username, defaults=defaults)
        user.set_password(password)
        user.save()
        return user

    # worker
    def createSmashWorkers(self, n=10):
        '''
        :n int: number of workers to create

        Returns a list of tuples (user, worker, workerStuyRole)
        '''
        logger.info('creating Smash Worker...')
        return [self.createSmashWorker() for _ in range(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,
                          locations=None, languages=None, is_super=False):
        '''
        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
        username: string: Sets the username. By default None. Random values are generated. Provide a value to overwrite random generation
        email: string: Sets the email. By default None. Random values are generated. Provide a value to overwrite random generation
        specialization: string: Sets the specialization. By default None. Random values are generated. Provide a value to overwrite random generation
        unit: string: Sets the unit. By default None. Random values are generated. Provide a value to overwrite random generation
        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:
            first_name = self.fake.first_name()

        if last_name is None:
            last_name = self.fake.last_name()

        if username is None:
            username = '{}_{}'.format(
                first_name, last_name).lower().replace(' ', '_')

        if email is None:
            email = '{}.{}@smash.lu'.format(first_name, last_name)

        if specialization is None:
            specialization = self.getSmashSpecialization()

        if unit is None:
            unit = self.getSmashUnit()

        if phone_number is None:
            phone_number = self.fake.phone_number()[:20]

        if role is None:
            role = self.getWorkerRole()

        # create user
        user = self.createSmashUser(
            username=username, email=email, password=password)

        if is_super:
            user.is_superuser = True
            user.is_staff = True
            user.is_admin = True
            user.save()

        # create worker
        defaults = {'first_name': first_name, 'last_name': last_name,
                    'email': email, 'unit': unit, 'specialization': specialization,
                    'phone_number': phone_number, 'user': user}

        worker, _ = Worker.objects.update_or_create(first_name=first_name,
                                                    last_name=last_name, defaults=defaults)

        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)

        # create workerStudyRole
        workerStudyRole, _ = WorkerStudyRole.objects.update_or_create(worker=worker,
                                                                      study_id=GLOBAL_STUDY_ID, name=role)

    # unit
    def getSmashUnit(self):
        return self.fake.word(ext_word_list=self.units)

    # specialization
    def getSmashSpecialization(self):
        return self.fake.word(ext_word_list=self.specialists)

    # languages
    def createSmashLanguages(self):
        '''
        Returns a list of Language objects
        '''
        logger.info('creating Smash Languages...')
        return [self.createSmashLanguage(name=name) for name in self.languages]

    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)
            # .save(basename, File(open(dst, 'rb'))) #SimpleUploadedFile(name=path, content=open(path, 'rb').read(), content_type='image/png')
            language.image = basename
            language.save()

        return language

    def getAlreadyCreatedSmashLanguages(self, max_n=3):
        '''
        Returns a list of Languages from the already created languages, 
        if no languages are created, then the list is generated.

        max_n: int: maximum number of languages to return

        Returns a list of Language objects.
        '''
        if len(list(self.alreadyCreatedLanguages.keys())) == 0:
            self.createSmashLanguages()

        languages = choice(self.languages, max_n, p=self.languages_prob)
        keys = set(languages)  # unique
        return [self.alreadyCreatedLanguages[key] for key in keys]

    # locations
    def getAlreadyCreatedSmashLocation(self):
        return self.random_element(list(self.alreadyCreatedLocations.values()))

    def createSmashLocations(self, n=5):
        logger.info('creating Smash Locations...')
        return [self.createSmashLocation() for _ in range(n)]

    def createSmashLocation(self, city=None, color=None, prefix=None):
        if city is None:
            city = choice(self.cities, 1, p=self.city_prob)[0]

        if color is None:
            color = self.fake.hex_color()

        if prefix is None:
            prefix = city[:1]

        location, _ = Location.objects.update_or_create(
            name=city, color=color, prefix=prefix)

        self.alreadyCreatedLocations[city] = location

        return location

    def getAllCreatedLocations(self):
        return list(self.alreadyCreatedLocations.values())

    def getAllCreatedLanguages(self):
        return list(self.alreadyCreatedLanguages.values())

if __name__ == "__main__":
    if not os.path.exists(MEDIA_ROOT):
        os.makedirs(MEDIA_ROOT)
    fake = Faker()
    Faker.seed(4321)
    fake.add_provider(smashProvider)
    fake.createSmashFlyingTeams()
    fake.createSmashItems()
    fake.createSmashAppointmentTypes()
    fake.createSmashRooms()
    fake.createSmashLocations()
    fake.createSmashLanguages()
    fake.createSmashMailTemplates()
    fake.createSmashCountries()

    fake.createSmashWorkers()
    fake.createSmashAvailabilities()
    fake.createSmashStudySubjects()
    fake.createSmashAppointments()
    fake.createSmashWorker(first_name='System', last_name='Admin',
                           email='carlos.vega@uni.lu', role=ROLE_CHOICES_TECHNICIAN, password='smashtest007',
                           locations=fake.getAllCreatedLocations(), languages=fake.getAllCreatedLanguages(), is_super=True)