From a755f2ffb656aadc8340c8e2d1fd5021c9d3d2a8 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Tue, 12 Dec 2017 16:17:17 +0100
Subject: [PATCH] role is study specific

---
 smash/web/api_views/daily_planning.py         | 10 +++--
 smash/web/api_views/worker.py                 |  6 ++-
 smash/web/migrations/0098_workerstudyrole.py  | 32 ++++++++++++++
 smash/web/models/__init__.py                  |  3 +-
 smash/web/models/worker.py                    | 26 ++++-------
 smash/web/models/worker_study_role.py         | 43 +++++++++++++++++++
 .../tests/api_views/test_daily_planning.py    | 21 +++------
 smash/web/tests/api_views/test_worker.py      |  2 +-
 smash/web/tests/functions.py                  |  6 ++-
 smash/web/tests/view/test_doctor.py           |  1 -
 10 files changed, 109 insertions(+), 41 deletions(-)
 create mode 100644 smash/web/migrations/0098_workerstudyrole.py
 create mode 100644 smash/web/models/worker_study_role.py

diff --git a/smash/web/api_views/daily_planning.py b/smash/web/api_views/daily_planning.py
index cca2057d..9d2dd0cf 100644
--- a/smash/web/api_views/daily_planning.py
+++ b/smash/web/api_views/daily_planning.py
@@ -4,9 +4,12 @@ import logging
 from operator import itemgetter
 
 from django.contrib.auth.decorators import login_required
+from django.db.models import Q
 from django.http import JsonResponse
 from django.shortcuts import get_object_or_404
 
+from web.models.constants import GLOBAL_STUDY_ID
+from web.models.worker_study_role import ROLE_CHOICES_DOCTOR, ROLE_CHOICES_NURSE, ROLE_CHOICES_PSYCHOLOGIST
 from web.models import Appointment, AppointmentTypeLink, Worker, Availability, Holiday
 from web.views import e500_error
 from web.views.notifications import get_filter_locations
@@ -300,9 +303,10 @@ def events(request, date):
 
 
 def get_workers_for_daily_planning(request):
-    result = Worker.objects.filter(locations__in=get_filter_locations(request.user)). \
-        filter(user__is_active=True).exclude(
-        role=Worker.ROLE_CHOICES_SECRETARY).distinct()
+    result = Worker.objects.filter(locations__in=get_filter_locations(request.user)).filter(
+        user__is_active=True).filter(
+        Q(roles__study_id=GLOBAL_STUDY_ID) & Q(
+            roles__role__in=[ROLE_CHOICES_DOCTOR, ROLE_CHOICES_NURSE, ROLE_CHOICES_PSYCHOLOGIST])).distinct()
     return result
 
 
diff --git a/smash/web/api_views/worker.py b/smash/web/api_views/worker.py
index d9edbcc1..e3ca2604 100644
--- a/smash/web/api_views/worker.py
+++ b/smash/web/api_views/worker.py
@@ -4,6 +4,7 @@ from django.contrib.auth.decorators import login_required
 from django.http import JsonResponse
 from django.utils import timezone
 
+from web.models.constants import GLOBAL_STUDY_ID
 from web.api_views.daily_planning import get_workers_for_daily_planning, get_availabilities
 from ..models import Worker
 
@@ -29,10 +30,11 @@ def workers_for_daily_planning(request):
     workers = get_workers_for_daily_planning(request)
     workers_list_for_json = []
     for worker in workers:
+        role = unicode(worker.roles.filter(study_id=GLOBAL_STUDY_ID)[0].role)
         worker_dict_for_json = {
             'id': worker.id,
-            'title': u"{} ({})".format(unicode(worker), worker.get_role_display()[:1].upper()),
-            'role': worker.get_role_display()
+            'title': u"{} ({})".format(unicode(worker), role[:1].upper()),
+            'role': role
         }
         workers_list_for_json.append(worker_dict_for_json)
     return JsonResponse(workers_list_for_json, safe=False)
diff --git a/smash/web/migrations/0098_workerstudyrole.py b/smash/web/migrations/0098_workerstudyrole.py
new file mode 100644
index 00000000..247c4ad4
--- /dev/null
+++ b/smash/web/migrations/0098_workerstudyrole.py
@@ -0,0 +1,32 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-12-12 14:15
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0097_auto_20171211_1616'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='WorkerStudyRole',
+            fields=[
+                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('role', models.CharField(choices=[(b'DOCTOR', b'Doctor'), (b'NURSE', b'Nurse'), (b'PSYCHOLOGIST', b'Psychologist'), (b'TECHNICIAN', b'Technician'), (b'SECRETARY', b'Secretary')], max_length=20, verbose_name=b'Role')),
+                ('study', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.Study')),
+                ('worker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='roles', to='web.Worker')),
+            ],
+        ),
+        migrations.RunSQL('insert into web_workerstudyrole (study_id, worker_id, role) '+
+                          'select 1, id, role from web_worker;'),
+        migrations.RemoveField(
+            model_name='worker',
+            name='role',
+        ),
+
+    ]
diff --git a/smash/web/models/__init__.py b/smash/web/models/__init__.py
index 77a30db0..9edb9cb0 100644
--- a/smash/web/models/__init__.py
+++ b/smash/web/models/__init__.py
@@ -19,6 +19,7 @@ from voucher_type_price import VoucherTypePrice
 from room import Room
 from visit import Visit
 from worker import Worker
+from worker_study_role import WorkerStudyRole
 from appointment import Appointment
 from appointment_type import AppointmentType
 from availability import Availability
@@ -39,5 +40,5 @@ from inconsistent_subject import InconsistentSubject, InconsistentField
 __all__ = [Study, FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room,
            Subject, StudySubject, StudySubjectList, SubjectColumns, StudyNotificationParameters,
            AppointmentList, AppointmentColumns, Visit, Worker, ContactAttempt, ConfigurationItem, MailTemplate,
-           AppointmentTypeLink, VoucherType, VoucherTypePrice, Voucher,
+           AppointmentTypeLink, VoucherType, VoucherTypePrice, Voucher, WorkerStudyRole,
            MissingSubject, InconsistentSubject, InconsistentField, Country, StudyColumns, VisitColumns, StudyVisitList]
diff --git a/smash/web/models/worker.py b/smash/web/models/worker.py
index 8923532e..b39603ad 100644
--- a/smash/web/models/worker.py
+++ b/smash/web/models/worker.py
@@ -5,6 +5,8 @@ import logging
 from django.contrib.auth.models import User, AnonymousUser
 from django.db import models
 
+from web.models.constants import GLOBAL_STUDY_ID
+
 logger = logging.getLogger(__name__)
 
 
@@ -40,18 +42,6 @@ class Worker(models.Model):
         verbose_name='E-mail'
     )
 
-    ROLE_CHOICES_SECRETARY = "SECRETARY"
-    ROLE_CHOICES_DOCTOR = "DOCTOR"
-    ROLE_CHOICES = (
-        (ROLE_CHOICES_DOCTOR, 'Doctor'),
-        ('NURSE', 'Nurse'),
-        ('PSYCHOLOGIST', 'Psychologist'),
-        ('TECHNICIAN', 'Technician'),
-        (ROLE_CHOICES_SECRETARY, 'Secretary')
-    )
-    role = models.CharField(max_length=20, choices=ROLE_CHOICES,
-                            verbose_name='Role'
-                            )
     specialization = models.CharField(max_length=20,
                                       verbose_name='Specialization'
                                       )
@@ -97,14 +87,16 @@ class Worker(models.Model):
 
     @staticmethod
     def get_details(the_user):
-        person = Worker.objects.filter(user=the_user)
+        persons = Worker.objects.filter(user=the_user)
 
-        if len(person) == 0:
+        if len(persons) == 0:
             return the_user.get_full_name(), '<No worker information>'
         else:
-            # For get_*_display, see:
-            # https://docs.djangoproject.com/en/1.10/topics/db/models/#field-options
-            return unicode(person[0]), person[0].get_role_display()
+            person = persons[0]
+            role = "N/A"
+            if person.roles.filter(study=GLOBAL_STUDY_ID).count() > 0:
+                role = person.roles.filter(study=GLOBAL_STUDY_ID)[0].get_role_display()
+            return unicode(person), role
 
     def __str__(self):
         return "%s %s" % (self.first_name, self.last_name)
diff --git a/smash/web/models/worker_study_role.py b/smash/web/models/worker_study_role.py
new file mode 100644
index 00000000..0615cbea
--- /dev/null
+++ b/smash/web/models/worker_study_role.py
@@ -0,0 +1,43 @@
+# coding=utf-8
+import logging
+
+from django.db import models
+
+logger = logging.getLogger(__name__)
+
+ROLE_CHOICES_SECRETARY = "SECRETARY"
+ROLE_CHOICES_DOCTOR = "DOCTOR"
+ROLE_CHOICES_NURSE = "NURSE"
+ROLE_CHOICES_PSYCHOLOGIST = "PSYCHOLOGIST"
+ROLE_CHOICES_TECHNICIAN = "TECHNICIAN"
+
+ROLE_CHOICES_HEALTH_PARTNER = "HEALTH_PARTNER"
+ROLE_CHOICES_VOUCHER_PARTNER = "VOUCHER_PARTNER"
+
+STUDY_ROLE_CHOICES = (
+    (ROLE_CHOICES_DOCTOR, 'Doctor'),
+    (ROLE_CHOICES_NURSE, 'Nurse'),
+    (ROLE_CHOICES_PSYCHOLOGIST, 'Psychologist'),
+    (ROLE_CHOICES_TECHNICIAN, 'Technician'),
+    (ROLE_CHOICES_SECRETARY, 'Secretary')
+)
+
+ROLE_CHOICES = STUDY_ROLE_CHOICES + (
+    (ROLE_CHOICES_HEALTH_PARTNER, "Health Partner"),
+    (ROLE_CHOICES_VOUCHER_PARTNER, "Voucher Partner"),
+)
+
+
+class WorkerStudyRole(models.Model):
+    class Meta:
+        app_label = 'web'
+
+    worker = models.ForeignKey("web.Worker",
+                               related_name="roles"
+                               )
+
+    study = models.ForeignKey("web.Study")
+
+    role = models.CharField(max_length=20, choices=STUDY_ROLE_CHOICES,
+                            verbose_name='Role'
+                            )
diff --git a/smash/web/tests/api_views/test_daily_planning.py b/smash/web/tests/api_views/test_daily_planning.py
index 0d48c8d1..5f2cce56 100644
--- a/smash/web/tests/api_views/test_daily_planning.py
+++ b/smash/web/tests/api_views/test_daily_planning.py
@@ -1,30 +1,23 @@
 # coding=utf-8
 import datetime
 import json
+import logging
 
 from django.contrib.auth.models import User
-from django.test import Client, RequestFactory
-from django.test import TestCase
+from django.test import RequestFactory
 from django.urls import reverse
 
+from web.tests import LoggedInWithWorkerTestCase
 from web.api_views.daily_planning import get_workers_for_daily_planning, get_generic_appointment_events
-from web.models import Worker, Availability, Holiday, AppointmentTypeLink
+from web.models import Availability, Holiday, AppointmentTypeLink
 from web.models.constants import TUESDAY_AS_DAY_OF_WEEK
 from web.tests.functions import create_worker, create_study_subject, create_appointment, create_flying_team, \
     create_visit, create_appointment_type, get_test_location
 
+logger = logging.getLogger(__name__)
 
-class TestApi(TestCase):
-    def setUp(self):
-        self.client = Client()
-        username = 'piotr'
-        password = 'top_secret'
-        self.user = User.objects.create_user(
-            username=username, email='jacob@bla', password=password)
-        self.worker = create_worker(self.user, True)
-        self.worker.role = Worker.ROLE_CHOICES_DOCTOR
-        self.worker.save()
-        self.client.login(username=username, password=password)
+
+class TestDailyPlanningApi(LoggedInWithWorkerTestCase):
 
     def test_empty_availabilities(self):
         response = self.client.get(reverse('web.api.events', kwargs={'date': "2017-09-05"}))
diff --git a/smash/web/tests/api_views/test_worker.py b/smash/web/tests/api_views/test_worker.py
index 0b32a0b3..22b8e76e 100644
--- a/smash/web/tests/api_views/test_worker.py
+++ b/smash/web/tests/api_views/test_worker.py
@@ -10,7 +10,7 @@ from web.api_views.worker import availabilities
 from web.tests import LoggedInWithWorkerTestCase
 
 
-class TestApi(LoggedInWithWorkerTestCase):
+class TestWorkerApi(LoggedInWithWorkerTestCase):
     def test_specializations(self):
         specialization_name = "some spec"
 
diff --git a/smash/web/tests/functions.py b/smash/web/tests/functions.py
index 8261bd63..dab991b8 100644
--- a/smash/web/tests/functions.py
+++ b/smash/web/tests/functions.py
@@ -4,12 +4,13 @@ import os
 
 from django.contrib.auth.models import User
 
+from web.models.worker_study_role import ROLE_CHOICES_DOCTOR
 from web.models import Location, AppointmentType, StudySubject, Worker, Visit, Appointment, ConfigurationItem, \
     Language, ContactAttempt, FlyingTeam, Availability, Subject, Study, StudyColumns, StudyNotificationParameters, \
-    VoucherType, VoucherTypePrice, Voucher
+    VoucherType, VoucherTypePrice, Voucher, WorkerStudyRole
 from web.models.constants import REDCAP_TOKEN_CONFIGURATION_TYPE, REDCAP_BASE_URL_CONFIGURATION_TYPE, \
     SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, CONTACT_TYPES_PHONE, \
-    MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID, VOUCHER_STATUS_NEW
+    MONDAY_AS_DAY_OF_WEEK, COUNTRY_AFGHANISTAN_ID, VOUCHER_STATUS_NEW, GLOBAL_STUDY_ID
 from web.redcap_connector import RedcapSubject
 from web.views.notifications import get_today_midnight_date
 
@@ -193,6 +194,7 @@ def create_worker(user=None, with_test_location=False):
     if with_test_location:
         worker.locations = [get_test_location()]
         worker.save()
+    WorkerStudyRole.objects.create(worker=worker, study_id=GLOBAL_STUDY_ID, role=ROLE_CHOICES_DOCTOR)
     return worker
 
 
diff --git a/smash/web/tests/view/test_doctor.py b/smash/web/tests/view/test_doctor.py
index 5689a186..16da568b 100644
--- a/smash/web/tests/view/test_doctor.py
+++ b/smash/web/tests/view/test_doctor.py
@@ -40,7 +40,6 @@ class DoctorViewTests(LoggedInTestCase):
         form_data["phone_number"] = "0123456789"
         form_data["unit"] = "TEST DEPARTMENT"
         form_data["email"] = "john.doe@unknown.domain.com"
-        form_data["role"] = Worker.ROLE_CHOICES_DOCTOR
         form_data["specialization"] = "tester"
         form_data["languages"] = [language.id]
         form_data["locations"] = [location.id]
-- 
GitLab