diff --git a/smash/import_file.py b/smash/import_file.py index 6eff049dc433c8aa9c7e53ffa7934e4acb7061e1..c46e183646632e7a15627ae327a33f0b0ea63239 100644 --- a/smash/import_file.py +++ b/smash/import_file.py @@ -25,7 +25,7 @@ from web.utils import is_valid_social_security_number from web.models import VoucherType, Voucher, Country, AppointmentTypeLink, AppointmentType, Study, Worker, Language, Subject, WorkerStudyRole, StudySubject, Location, FlyingTeam, Visit, Appointment, AppointmentType from web.models.worker_study_role import ROLE_CHOICES_TECHNICIAN, WORKER_STAFF, ROLE_CHOICES_SECRETARY, ROLE_CHOICES_HEALTH_PARTNER, \ - WORKER_HEALTH_PARTNER, ROLE_CHOICES_VOUCHER_PARTNER, WORKER_VOUCHER_PARTNER + WORKER_HEALTH_PARTNER, ROLE_CHOICES_DOCTOR, ROLE_CHOICES_VOUCHER_PARTNER, ROLE_CHOICES, ROLE_CHOICES_NURSE, ROLE_CHOICES_PSYCHOLOGIST, ROLE_CHOICES_PROJECT_MANAGER DEFAULT_LOCATION = 'CHL' DEFAULT_LOCATION_PREFIX = 'P' @@ -149,7 +149,13 @@ def parse_boolean(boolean_Y_N): def parse_column_date_of_birth(date): - return datetime.datetime.strptime(date, '%d.%m.%Y').strftime('%Y-%m-%d') + try: + return datetime.datetime.strptime(date, '%d.%m.%Y %H:%M').strftime('%Y-%m-%d') + except ValueError: + try: + return datetime.datetime.strptime(date, '%d.%m.%Y').strftime('%Y-%m-%d') + except: + return None # gender gender_table = {'m': SEX_CHOICES_MALE, 'f': SEX_CHOICES_FEMALE} @@ -179,6 +185,18 @@ def parse_column_ss_number(ss): logging.debug('Invalid SS number: (Length not valid) |{}|'.format(ss)) return ss +def parse_role(role_name): + d = { + 'NURSE': ROLE_CHOICES_NURSE, + 'PSYCHOLOGIST': ROLE_CHOICES_PSYCHOLOGIST, + 'SECRETARY': ROLE_CHOICES_SECRETARY, + 'PROJECT MANAGER': ROLE_CHOICES_PROJECT_MANAGER, + 'DOCTOR': ROLE_CHOICES_DOCTOR, + 'HEALTH_PARTNER': ROLE_CHOICES_HEALTH_PARTNER, + 'VOUCHER_PARTNER': ROLE_CHOICES_VOUCHER_PARTNER + } + return d[role_name] #crash if no valid role_name is given + # Language @@ -188,6 +206,7 @@ language_table = { 'IT': 'Italian', 'F': 'French', 'D': 'German', + 'G': 'German', 'E': 'English', 'P': 'Portuguese', 'A': 'Arabic', @@ -278,7 +297,7 @@ converters = { # add voucher for subject voucher_partners = {} voucher_partners['ZIT'] = 'Zitha' -def add_subject_vouchers(voucher_reference, referral, voucher_types): +def add_subject_vouchers(voucher_reference, referral, voucher_types, subject_nd_number): nd_number, date, voucher_partner, voucher_type, num = voucher_reference.split('-') nd_number = nd_number.upper().replace('ND', 'PDP') issue_date = datetime.datetime.strptime(date, '%Y%m%d') @@ -297,7 +316,9 @@ def add_subject_vouchers(voucher_reference, referral, voucher_types): vt = VoucherType.objects.get(code=voucher_type) - study_subject = StudySubject.objects.get(nd_number=nd_number) + if nd_number != subject_nd_number: + logging.warn('voucher reference nd_number is not the same! {} != {}'.format(nd_number, subject_nd_number)) + study_subject = StudySubject.objects.get(nd_number=subject_nd_number) voucher, created = Voucher.objects.update_or_create(number=voucher_reference, issue_date=issue_date, expiry_date=expiry_date, voucher_type=vt, study_subject=study_subject, @@ -305,8 +326,21 @@ def add_subject_vouchers(voucher_reference, referral, voucher_types): logging.warn('New Voucher added: {}'.format(voucher_reference)) return voucher - # create voucher types +voucher_type_codes = set() +def create_voucher_code(description): + code = re.sub(r'\([^)]*\)', '', description.strip()) + code = re.sub(r'[aeiou]+', '', code.lower()).strip() + code = ''.join([e.capitalize() for e in code.split(' ')[:2]]) + while code in voucher_type_codes: + if re.match(r'.*_\d+$', code) is None: + code = code + '_2' + else: + spt = code.split('_') + num = int(spt[-1])+1 + code = ''.join(spt[:len(spt)]) + str(num) + return code + def create_voucher_types(voucher_types_dict, study): voucher_types = {} for name, code in voucher_types_dict.items(): @@ -325,21 +359,11 @@ def create_appointment_types(assessments): appointmentTypes.append(appointmentType) return appointmentTypes - -def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_worker): - # Languages - if len(row['LANGUAGES']) == 0 and len(row['PREFERED WRITEN LANGUAGE']) == 0: - logging.warn('No Languages available') - elif len(row['LANGUAGES']) == 0 and len(row['PREFERED WRITEN LANGUAGE']) > 0: - row['LANGUAGES'] = row['PREFERED WRITEN LANGUAGE'] - elif len(row['LANGUAGES']) > 0 and len(row['PREFERED WRITEN LANGUAGE']) == 0: - row['PREFERED WRITEN LANGUAGE'] = row['LANGUAGES'] - +def create_languages(languages_cell): languages = [] - for language in row['LANGUAGES']: + for language in languages_cell: lang, created = Language.objects.get_or_create( name=language, locale=locale_table.get(language,(None, None))[0]) - languages.append(lang) if created: logging.warn('New Language added: {}'.format(language)) @@ -355,13 +379,25 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_w lang.image = basename lang.save() - for language in row['PREFERED WRITEN LANGUAGE'][:1]: - pref_lang, created = Language.objects.get_or_create(name=language - ,locale=locale_table.get(language,(None, None))[0]) - if created: - logging.warn( - 'New Language (from Prefered) added: {}'.format(language)) - pref_lang.save() + languages.append(lang) + + return languages + +def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_worker): + # Languages + if len(row['LANGUAGES']) == 0 and len(row['PREFERED WRITEN LANGUAGE']) == 0: + logging.warn('No Languages available') + elif len(row['LANGUAGES']) == 0 and len(row['PREFERED WRITEN LANGUAGE']) > 0: + row['LANGUAGES'] = row['PREFERED WRITEN LANGUAGE'] + elif len(row['LANGUAGES']) > 0 and len(row['PREFERED WRITEN LANGUAGE']) == 0: + row['PREFERED WRITEN LANGUAGE'] = row['LANGUAGES'] + + languages = create_languages(row['LANGUAGES']) + pref_lang = create_languages(row['PREFERED WRITEN LANGUAGE'][:1]) + if len(pref_lang) > 0: + pref_lang = pref_lang[0] + elif len(languages) > 0: + pref_lang = languages[0] # Country country = row['COUNTRY'] @@ -399,15 +435,20 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_w # Health Partner # create health partner (Referral) - health_partner, created = Worker.objects.get_or_create(name=row['REFERRAL']) - health_partner.roles.update(role=ROLE_CHOICES_HEALTH_PARTNER) - # create workerStudyRole - workerStudyRole, _ = WorkerStudyRole.objects.update_or_create( - worker=health_partner, study_id=GLOBAL_STUDY_ID, role=ROLE_CHOICES_HEALTH_PARTNER) - health_partner.save() - if created: - logging.warn('New Health Partner added: {}'.format(row['REFERRAL'])) + health_partner = None + if row['REFERRAL'].strip() != '': + logging.warn('Trying to get or create Worker: {}'.format(row['REFERRAL'])) + health_partner, created = Worker.objects.get_or_create(name=row['REFERRAL']) + health_partner.roles.update(role=ROLE_CHOICES_HEALTH_PARTNER) + # create workerStudyRole + workerStudyRole, _ = WorkerStudyRole.objects.update_or_create( + worker=health_partner, study_id=GLOBAL_STUDY_ID, role=ROLE_CHOICES_HEALTH_PARTNER) + health_partner.save() + if created: + logging.warn('New Health Partner added: {}'.format(row['REFERRAL'])) + if row['SS NUMBER'] is None: + row['SS NUMBER'] = '' subject, created = Subject.objects.get_or_create(social_security_number=row['SS NUMBER'], first_name=row['FIRST NAME'], last_name=row['LAST NAME'], @@ -466,7 +507,7 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_w #VOUCHERS voucher_references = row['VOUCHER REFERENCE'] for voucher_reference in voucher_references: - voucher = add_subject_vouchers(voucher_reference, health_partner, voucher_types) + voucher = add_subject_vouchers(voucher_reference, health_partner, voucher_types, nd_number) # Visits # Consider all visits as part of the same visit with multiple appointments @@ -478,8 +519,14 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_w sum(Ans, []) flattens the resulting list from the map since each findall returns a list map to convert string to datetime ''' - visit_dates = map(lambda x: datetime.datetime.strptime( - x, '%d.%m.%Y'), sum(map(date_regex.findall, row[visit_columns].values), [])) + def parse_visit_date(date_string): + try: + dtime = datetime.datetime.strptime(date_string, '%d.%m.%Y %H:%M') + except ValueError: + dtime = datetime.datetime.strptime(date_string, '%d.%m.%Y') + return dtime + + visit_dates = map(lambda x: parse_visit_date(x), sum(map(date_regex.findall, row[visit_columns].values), [])) # get first and last elements of the sorted element datetime_begin, datetime_end = itemgetter(*[0, -1])(sorted(visit_dates)) @@ -502,8 +549,9 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_w ''' starting_hour = 9 for visit_date in set(visit_dates): - datetime_when = visit_date.replace(hour=starting_hour, minute=0, second=0, microsecond=0) - starting_hour+=1 + if visit_date.hour == 0: + datetime_when = visit_date.replace(hour=starting_hour, minute=0, second=0, microsecond=0) + starting_hour+=1 # get the indices of each occurrence of the date and use them to get # the appointment types @@ -528,34 +576,37 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types, lcsb_w app_type_link.save() def createWorker(password, email='', username='admin', first_name='LCSB', last_name='Admin', - specialization='Technician', unit='LCSB'): - - # create user - defaults = {'email': email, 'password': password} - user, _ = User.objects.update_or_create(username=username, defaults=defaults) - user.set_password(password) - user.is_superuser = True - user.is_staff = True - user.is_admin = True - user.save() + specialization='Technician', unit='LCSB', languages=[], role=ROLE_CHOICES_TECHNICIAN, + name='', comment=None): + user = None + if username is not None: + # create user + defaults = {'email': email, 'password': password} + user, _ = User.objects.update_or_create(username=username, defaults=defaults) + user.set_password(password) + 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 - , 'user': user} + , 'user': user, 'name': name, 'comment': comment} + worker, _ = Worker.objects.update_or_create(first_name=first_name, last_name=last_name, defaults=defaults) - locations = Location.objects.all() worker.locations.set(locations) - languages = Language.objects.all() + if len(languages) == 0: + languages = Language.objects.all() worker.languages.set(languages) worker.save() # create workerStudyRole workerStudyRole, _ = WorkerStudyRole.objects.update_or_create(worker=worker, - study_id=GLOBAL_STUDY_ID, role=ROLE_CHOICES_TECHNICIAN) + study_id=GLOBAL_STUDY_ID, role=role) workerStudyRole.save() logging.info('SuperUser and Worker {} created'.format(username)) return worker @@ -570,16 +621,66 @@ if __name__ == '__main__': logging.warn('Please, execute the program with a valid file path.') sys.exit(1) + admin_password = None + if len(sys.argv) >= 3: + admin_password = sys.argv[2] + #create worker and super user - pass1 = '' - pass2 = None - while pass1 != pass2: - pass1 = getpass.getpass('Please type a password for the Admin user: ') - pass2 = getpass.getpass('Please type your password again: ') - if pass1 != pass2: - print 'Password mismatch, please try again' + if admin_password is None: + pass1 = '' + pass2 = None + while pass1 != pass2: + pass1 = getpass.getpass('Please type a password for the Admin user: ') + pass2 = getpass.getpass('Please type your password again: ') + if pass1 != pass2: + print 'Password mismatch, please try again' + else: + pass1 = admin_password lcsb_worker = createWorker(pass1) + #STUDY + study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0] + #enable vouchers + study.columns.voucher_types = True + study.columns.vouchers = True + study.nd_number_study_subject_regex = r'^PDP\d{4}$' + study.columns.save() + study.save() + + #READ WORKERS SHEET + df = pd.read_excel(file, dtype=object, sheet_name='Workers') + #convert column name to upper case + df.columns = [c.upper() for c in df.columns] + #convert languages + df['LANGUAGES'] = df['LANGUAGES'].apply(apply_column_languages) + df['ROLE'] = df['ROLE'].apply(parse_role) + for index, row in df.iterrows(): + languages = create_languages(row['LANGUAGES']) + createWorker(row['PASSWORD'], email=row['MAIL'], username=row['USERNAME'], first_name=row['FIRST NAME'], last_name=row['LAST NAME'], + specialization=row['ROLE'], role=row['ROLE'], unit='CHL', languages=languages) + + #READ VOUCHER PARTNER SHEET + df = pd.read_excel(file, dtype=object, sheet_name='Voucher Partners') + #convert column name to upper case + df.columns = [c.upper() for c in df.columns] + df['ROLE'] = df['ROLE'].apply(parse_role) + for index, row in df.iterrows(): + worker = createWorker(None, email='', username=None, first_name='', last_name='', specialization=row['ROLE'], + role=row['ROLE'], unit='CHL', languages=[], name=row['NAME'], comment=row.get('COMMENT', '')) + if type(row['OFFER']) != float: + offers = row['OFFER'].split(';') + voucher_types = [] + for offer in offers: + code = create_voucher_code(offer) + voucher_type_codes.add(code) + voucher_type, created = VoucherType.objects.update_or_create(description=offer.title(), study=study, code=code) + if created: + logging.warn(u'Voucher type created: {} ({})'.format(offer, code)) + voucher_types.append(voucher_type) + worker.voucher_types.set(voucher_types) + worker.save() + + #READ FIRST SHEET df = pd.read_excel(file, dtype=object) df = df.fillna('').astype(unicode) df.columns = [c.upper() for c in df.columns] @@ -590,14 +691,6 @@ if __name__ == '__main__': # get visits columns regex = re.compile(r'\(V\d\)') # - study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0] - #enable vouchers - study.columns.voucher_types = True - study.columns.vouchers = True - study.nd_number_study_subject_regex = r'^PDP\d{4}$' - study.columns.save() - study.save() - # visit_columns = filter(regex.search, df.columns) assessments = OrderedDict([('Cognitive Test', 180), ('Risk Factor', 120),