diff --git a/smash/import_file.py b/smash/import_file.py index d3a2e78cadb86978fc3b2c7d1dd4aa66d59160be..00de3e19e853cff7b88c624f4e4518074651ac24 100644 --- a/smash/import_file.py +++ b/smash/import_file.py @@ -1,5 +1,6 @@ # coding=utf-8 import os +import getpass import django from django.conf import settings os.environ.setdefault("DJANGO_SETTINGS_MODULE", "smash.settings") @@ -13,18 +14,35 @@ from operator import itemgetter from collections import OrderedDict, defaultdict import sys import string +from django.contrib.auth.models import User from web.models.constants import VOUCHER_STATUS_IN_USE, SUBJECT_TYPE_CHOICES_PATIENT, GLOBAL_STUDY_ID, SEX_CHOICES, SEX_CHOICES_MALE, SEX_CHOICES_FEMALE from web.algorithm import VerhoeffAlgorithm, LuhnAlgorithm 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 WORKER_STAFF, ROLE_CHOICES_SECRETARY, ROLE_CHOICES_HEALTH_PARTNER, \ +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 DEFAULT_LOCATION = 'CHL' +DEFAULT_LOCATION_PREFIX = 'P' date_regex = re.compile(r'\d{1,2}\.\d{1,2}\.\d{4}') +def get_new_screening_number(screening_number_prefix): + result_number = 0 + subjects = StudySubject.objects.filter(screening_number__contains=screening_number_prefix) + for subject in subjects: + screening_numbers = subject.screening_number.split(";") + for screening_number in screening_numbers: + screening_number = screening_number.strip() + if screening_number.startswith(screening_number_prefix): + number = screening_number[len(screening_number_prefix)+1:] + try: + result_number = max(result_number, int(number)) + except ValueError: + pass + + return screening_number_prefix + '-' + str(result_number + 1).zfill(3) def itembetter(items, lst): if len(items) == 1: @@ -161,6 +179,19 @@ language_table = { 'FIN': 'Finnish' } +locale_table = { + 'Luxembourgish': ('lb_LU', 'LU'), + 'Lithuanian': ('lt_LT', 'LT'), + 'Italian': ('it_IT', 'IT'), + 'French': ('fr_FR', 'FR'), + 'German': ('de_DE', 'DE'), + 'English': ('en_GB', 'GB'), + 'Portuguese': ('pt_PT', 'PT'), + 'Arabic': ('ar_sa', None), + 'Spanish': ('es_ES', 'ES') , + 'Finnish': ('fi_FI', 'FI') +} + language_translation_table = { # deletions ord(u')'): None, @@ -233,6 +264,7 @@ voucher_partners = {} voucher_partners['ZIT'] = 'Zitha' def add_subject_vouchers(voucher_reference, referral, voucher_types): 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') expiry_date = issue_date + datetime.timedelta(days=365) usage_partner, created = Worker.objects.update_or_create( @@ -290,14 +322,15 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types): languages = [] for language in row['LANGUAGES']: lang, created = Language.objects.get_or_create( - name=language) + name=language, locale=locale_table.get(language,(None, None))[0]) languages.append(lang) if created: logging.warn('New Language added: {}'.format(language)) lang.save() for language in row['PREFERED WRITEN LANGUAGE'][:1]: - pref_lang, created = Language.objects.get_or_create(name=language) + 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)) @@ -314,15 +347,18 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types): # If no FT, then default location is CHL ft = None location = None + prefix = None if not row['FLYING TEAM (FT)']: + prefix = DEFAULT_LOCATION_PREFIX location, created = Location.objects.get_or_create( - name=DEFAULT_LOCATION) + name=DEFAULT_LOCATION, prefix=prefix) if created: logging.warn('New location added: {}'.format(DEFAULT_LOCATION)) location.save() else: + prefix = 'F' location, created = Location.objects.get_or_create( - name='Flying Team') + name='Flying Team', prefix=prefix) if created: logging.warn('New location added: Flying Team') location.save() @@ -373,13 +409,13 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types): # StudySubject study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0] - - studySubject, created = StudySubject.objects.get_or_create(subject=subject, nd_number=row['ND NUMBER'], + nd_number = row['ND NUMBER'].upper().replace('ND', 'PDP') + studySubject, created = StudySubject.objects.get_or_create(subject=subject, nd_number=nd_number, defaults={ 'subject': subject, 'study': study, 'postponed': row['POSTPONED'], - 'nd_number': row['ND NUMBER'], + 'nd_number': nd_number, 'resigned': row['RESIGNED'], 'resign_reason': row['REASON'], 'type': SUBJECT_TYPE_CHOICES_PATIENT, @@ -389,6 +425,7 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types): 'comments': row['COMMENT'], 'default_location': location, 'flying_team': ft, + 'screening_number': get_new_screening_number(prefix), 'date_added': parse_column_date_of_birth(row['DATE ADDED (V1)']) }) @@ -397,7 +434,7 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types): studySubject.save() if created: - logging.warn('New StudySubject added with ND number: {}'.format(row['ND NUMBER'])) + logging.warn('New StudySubject added with ND number: {}'.format(nd_number)) #VOUCHERS voucher_references = row['VOUCHER REFERENCE'] @@ -427,7 +464,7 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types): 'is_finished': True}) if created: logging.warn('New Visit added for ND number {} starting on {}'.format( - row['ND NUMBER'], datetime_begin)) + nd_number, datetime_begin)) appointment_types = appointmentTypes[:len(set(visit_dates))] #in this case appointment types are incremental visit.appointment_types.set(appointment_types) @@ -459,6 +496,38 @@ def parse_row(index, row, visit_columns, appointmentTypes, voucher_types): appointment_type=appointment_type) date_when += datetime.timedelta( minutes=appointment_type.default_duration) + 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() + + # create worker + defaults = {'first_name': first_name, 'last_name': last_name, + 'email': email, 'unit': unit, 'specialization': specialization + , 'user': user} + 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() + 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) + logging.info('SuperUser and Worker {} created'.format(username)) if __name__ == '__main__': logging.basicConfig(level=logging.DEBUG) @@ -483,6 +552,7 @@ if __name__ == '__main__': #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() # @@ -500,3 +570,12 @@ if __name__ == '__main__': # process each row for index, row in df.iterrows(): parse_row(index, row, visit_columns, appointmentTypes, voucher_types) + #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' + createWorker(pass1) \ No newline at end of file diff --git a/smash/web/api_views/subject.py b/smash/web/api_views/subject.py index ab07fde9176079240b8225a31d40a0b652fd6fa7..6bf6bc78d0c6b507e82f70551a361d427186a848 100644 --- a/smash/web/api_views/subject.py +++ b/smash/web/api_views/subject.py @@ -71,7 +71,7 @@ def get_subject_columns(request, subject_list_type): add_column(result, "Info sent", "information_sent", study_subject_columns, "yes_no_filter", study.columns) add_column(result, "Type", "type", study_subject_columns, "type_filter", study.columns) add_column(result, "Edit", "edit", None, None, sortable=False) - for visit_number in range(1, 9): + for visit_number in range(1, study.visits_to_show_in_subject_list+1): visit_key = "visit_" + str(visit_number) add_column(result, "Visit " + str(visit_number), visit_key, None, "visit_filter", visible_param=study_subject_list.visits) diff --git a/smash/web/migrations/0130_study_visits_to_show_in_subject_list.py b/smash/web/migrations/0130_study_visits_to_show_in_subject_list.py new file mode 100644 index 0000000000000000000000000000000000000000..071741cd8f575ff3254356110b915a4775bb8dff --- /dev/null +++ b/smash/web/migrations/0130_study_visits_to_show_in_subject_list.py @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.5 on 2018-11-06 15:37 +from __future__ import unicode_literals + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('web', '0129_auto_20181031_1348'), + ] + + operations = [ + migrations.AddField( + model_name='study', + name='visits_to_show_in_subject_list', + field=models.IntegerField(default=5, validators=[django.core.validators.MaxValueValidator(100), django.core.validators.MinValueValidator(1)], verbose_name=b'Number of visits to show in the subject list'), + ), + ] diff --git a/smash/web/models/study.py b/smash/web/models/study.py index c7b90db332762b349b86edca75fe179f6cc620e7..c8b2461e1c986deb2b04c80cc3c024f25cb94753 100644 --- a/smash/web/models/study.py +++ b/smash/web/models/study.py @@ -2,6 +2,7 @@ from django.db import models from web.models import StudyColumns, StudyNotificationParameters +from django.core.validators import MaxValueValidator, MinValueValidator import re @@ -31,6 +32,12 @@ class Study(models.Model): verbose_name="Auto create follow up visit" ) + visits_to_show_in_subject_list = models.IntegerField( + verbose_name='Number of visits to show in the subject list', + default=5, + validators=[MaxValueValidator(100), MinValueValidator(1)] + ) + def check_nd_number(self, nd_number): regex = re.compile(self.nd_number_study_subject_regex) return regex.match(nd_number) is not None diff --git a/smash/web/models/study_subject.py b/smash/web/models/study_subject.py index 97c8e6708453242663fcd2016f3e44d32c789af6..d1807814503eac61e967646ce8381e375bbd70ca 100644 --- a/smash/web/models/study_subject.py +++ b/smash/web/models/study_subject.py @@ -179,23 +179,26 @@ class StudySubject(models.Model): ) def sort_matched_screening_first(self, pattern, reverse=False): - parts = self.screening_number.split(';') - matches, reminder = [], [] - for part in parts: - chunks = part.strip().split('-') - if len(chunks) == 2: - letter, number = chunks - tupl = (letter, int(number)) - else: - logger.warn('There are {} chunks in some parts of this screening_number: |{}|.'.format( - len(chunks), self.screening_number)) - tupl = (part.strip(), None) - if pattern is not None and pattern in part: - matches.append(tupl) - else: - reminder.append(tupl) - - return matches + sorted(reminder, reverse=reverse) + if self.screening_number is None: + return None + + parts = self.screening_number.split(';') + matches, reminder = [], [] + for part in parts: + chunks = part.strip().split('-') + if len(chunks) == 2: + letter, number = chunks + tupl = (letter, int(number)) + else: + logger.warn('There are {} chunks in some parts of this screening_number: |{}|.'.format( + len(chunks), self.screening_number)) + tupl = (part.strip(), None) + if pattern is not None and pattern in part: + matches.append(tupl) + else: + reminder.append(tupl) + + return matches + sorted(reminder, reverse=reverse) @staticmethod def check_nd_number_regex(regex_str): diff --git a/smash/web/tests/test_office_availability.py b/smash/web/tests/test_office_availability.py index 80939ae9ecaeb5b0246f9b50272188d8eb22fba5..58652fbc2abf3b6fa34d5d15dbed90162b32cc08 100644 --- a/smash/web/tests/test_office_availability.py +++ b/smash/web/tests/test_office_availability.py @@ -25,7 +25,9 @@ class OfficeAvailabilityTest(TestCase): start_date = datetime.datetime(today.year, today.month, today.day, tzinfo=today.tzinfo) #today midnight end_date = start_date + datetime.timedelta(days=1) - office_availability = OfficeAvailability('FirstName LastName', + first_name = u'âêîôûŵŷäëïöüẅÿà ' + last_name = u'èìòùáºá»³Ã¡Ã©Ãóúẃýćńóśźżąę' + office_availability = OfficeAvailability(u'{} {}'.format(first_name, last_name), start=start_date, end=end_date, office_start='8:00', office_end='18:00') #no availabilties added yet