Skip to content
Snippets Groups Projects
worker_form.py 5.85 KiB
Newer Older
import re
from collections import OrderedDict
from django import forms
from django.forms import ModelForm
from django_common.auth_backends import User

from web.models import Worker, WorkerStudyRole
from web.models.constants import GLOBAL_STUDY_ID
from web.models.worker import role_choices_by_worker_type, worker_type_by_worker
from web.models.worker_study_role import WORKER_STAFF, WORKER_VOUCHER_PARTNER, WORKER_HEALTH_PARTNER
from web.decorators import PermissionDecorator

class WorkerForm(ModelForm):
    class Meta:
        model = Worker
        exclude = ['appointments']

    def __init__(self, *args, **kwargs):
        worker_type = kwargs.pop('worker_type', WORKER_STAFF)
        super(WorkerForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
Piotr Gawron's avatar
Piotr Gawron committed
        initial_role = None
        initial_permissions = None
        if instance is not None and instance.pk:
            worker_type = worker_type_by_worker(instance)
            roles = WorkerStudyRole.objects.filter(worker=instance, study_id=GLOBAL_STUDY_ID)
            if roles.count() > 0:
                initial_permissions  = roles[0].permissions.all()

        choices = role_choices_by_worker_type(worker_type)
        if worker_type in [WORKER_VOUCHER_PARTNER, WORKER_HEALTH_PARTNER]:
            '''
            Since ChoiceField expects tuples (id, label), for a *custom* HiddenInput field we need to create a charfield with TextInput widget
            providing the value of the *id*. hidden_form_field CSS class is defined in templates/doctors/add.html and has display:none property.
            '''
            if initial_role is None:
                initial_role = choices[0][0] # get 1st element of 1st tuple (('VOUCHER_PARTNER', 'Voucher Partner'),)
            self.fields['role'] = forms.CharField(label='Role', widget=forms.TextInput(attrs={'class': 'hidden_form_field'}), disabled=True)
        else:
            self.fields['role'] = forms.ChoiceField(label='Role', choices=choices)
        
        self.fields['role'].initial = initial_role
        #use only the codename used in the code decorators 
        self.fields['permissions'] = forms.ModelMultipleChoiceField(required=False, queryset=PermissionDecorator.get_permissions()) 
        if initial_permissions is not None:
            self.fields['permissions'].initial = [c.pk for c in initial_permissions]
            if instance.user is not None:
                self.fields['Superuser'] = forms.BooleanField(label='Is Superuser?', disabled=True, required=False,
            help_text='Super users have all permissions. This is a read only field.')
                self.fields['Superuser'].initial = instance.user.is_superuser
            del self.fields['first_name']
            del self.fields['last_name']
        if worker_type != WORKER_VOUCHER_PARTNER:
            del self.fields['voucher_partner_code']

        fields = OrderedDict()

        if worker_type == WORKER_STAFF:
            if instance is None or instance.pk is None:
                fields['login'] = forms.CharField(label='Login')
                fields['password'] = forms.CharField(label='Password', widget=forms.PasswordInput)
                fields['password2'] = forms.CharField(label='Repeat password', widget=forms.PasswordInput)

        for key, value in self.fields.items():
            fields[key] = value

        self.fields = fields

    def save(self, commit=True):
        create_user = self.cleaned_data.get("login", None) is not None
        user = None
        if create_user:
            user = User.objects.create_user(username=self.cleaned_data['login'],
                                            email=self.cleaned_data['email'],
                                            password=self.cleaned_data['password'])
        instance = super(WorkerForm, self).save(commit)
        if create_user:
            instance.user = user
            instance.save()
        roles = WorkerStudyRole.objects.filter(worker=instance, study_id=GLOBAL_STUDY_ID)
        if roles.count() > 0:
            for role in roles: #should be only one
                role.role=self.cleaned_data['role']
                role.permissions.set(self.cleaned_data['permissions'])
                role.save()
            role = WorkerStudyRole.objects.create(worker=instance, study_id=GLOBAL_STUDY_ID, role=self.cleaned_data['role'])
            role.permissions.set(self.cleaned_data['permissions'])
            role.save()

    def clean(self):
        cleaned_data = super(WorkerForm, self).clean()
        if cleaned_data.get('password', None) is not None:
            password = cleaned_data['password']
            if cleaned_data['password'] != cleaned_data['password2']:
                self.add_error('password', "Password don't match")
                self.add_error('password2', "Password don't match")
            min_length = 10
            if len(password) < min_length:
                self.add_error('password', 'Password must be at least ' + str(min_length) + ' characters long.')

            # check for digit
            if not any(char.isdigit() for char in password):
                self.add_error('password', 'Password must contain at least 1 digit.')

            # check for letter
            if not any(char.isalpha() for char in password):
                self.add_error('password', 'Password must contain at least 1 letter.')

        if cleaned_data.get('login', None) is not None:
            if not re.match('^[.a-zA-Z0-9]+$', cleaned_data['login']):
                self.add_error('login', 'Login can contain only alphanumeric characters or dot.')

        return cleaned_data