Newer
Older
Piotr Gawron
committed
import logging
import re
from collections import OrderedDict
Piotr Gawron
committed
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
Piotr Gawron
committed
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
Piotr Gawron
committed
logger = logging.getLogger(__name__)
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)
Piotr Gawron
committed
initial_permissions = None
Piotr Gawron
committed
if instance is not None and instance.pk:
Piotr Gawron
committed
worker_type = worker_type_by_worker(instance)
roles = WorkerStudyRole.objects.filter(worker=instance, study_id=GLOBAL_STUDY_ID)
Piotr Gawron
committed
Piotr Gawron
committed
initial_role = roles[0].role
initial_permissions = roles[0].permissions.all()
Piotr Gawron
committed
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)
Piotr Gawron
committed
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]
Piotr Gawron
committed
del self.fields['user']
Piotr Gawron
committed
if worker_type == WORKER_STAFF:
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
Piotr Gawron
committed
del self.fields['voucher_types']
del self.fields['name']
Piotr Gawron
committed
else:
del self.fields['locations']
del self.fields['first_name']
del self.fields['last_name']
Piotr Gawron
committed
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
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