diff --git a/castellum_core/castellum_core/recruitment/admin.py b/castellum_core/castellum_core/recruitment/admin.py
index 87e5ca31072c83e0c4a5d149f9fe9829b8a0a417..627d221ae3d5734b03602f4b3aa35a5ecee780da 100644
--- a/castellum_core/castellum_core/recruitment/admin.py
+++ b/castellum_core/castellum_core/recruitment/admin.py
@@ -22,5 +22,7 @@
from django.contrib import admin
from .models import AttributeSet
+from .models import Participation
admin.site.register(AttributeSet)
+admin.site.register(Participation)
diff --git a/castellum_core/castellum_core/recruitment/migrations/0002_participation.py b/castellum_core/castellum_core/recruitment/migrations/0002_participation.py
new file mode 100644
index 0000000000000000000000000000000000000000..61c6dc3379d83b81cd605c4a88c335997bfc1857
--- /dev/null
+++ b/castellum_core/castellum_core/recruitment/migrations/0002_participation.py
@@ -0,0 +1,25 @@
+# Generated by Django 2.0.4 on 2018-06-25 14:13
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('studies', '0001_initial'),
+ ('recruitment', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Participation',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('subject_pk', models.CharField(max_length=128)),
+ ('status', models.IntegerField(choices=[(0, 'missed call'), (1, 'unsuitable'), (2, 'invited')], default=1, verbose_name='status of participation')),
+ ('updated_at', models.DateTimeField(blank=True, null=True, verbose_name='last updated at')),
+ ('study', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='studies.Study', verbose_name='study')),
+ ],
+ ),
+ ]
diff --git a/castellum_core/castellum_core/recruitment/models.py b/castellum_core/castellum_core/recruitment/models.py
index f0f96706912d9f14e519785231526807f405ca06..bc6e3fc87ee0ebfb96cf157202fe6fd287b12456 100644
--- a/castellum_core/castellum_core/recruitment/models.py
+++ b/castellum_core/castellum_core/recruitment/models.py
@@ -22,6 +22,8 @@
from django.db import models
from django.utils.translation import ugettext_lazy as _
+from studies.models import Study
+
class AttributeSet(models.Model):
handedness = models.CharField(_('Handedness'), blank=True, max_length=10, choices=(
@@ -30,3 +32,23 @@ class AttributeSet(models.Model):
))
first_language = models.CharField(_('First Language'), blank=True, max_length=5)
date_of_birth = models.DateField(_('Date of birth'), null=True, blank=True)
+
+
+class Participation(models.Model):
+ MISSED_CALL = 0
+ UNSUITABLE = 1
+ INVITED = 2
+ STATUS_OPTIONS = (
+ (MISSED_CALL, _('missed call')),
+ (UNSUITABLE, _('unsuitable')),
+ (INVITED, _('invited')),
+ )
+
+ study = models.ForeignKey(Study, verbose_name=_('study'), on_delete=models.CASCADE)
+
+ # just a placeholder until proper pseudonyms are available
+ subject_pk = models.CharField(max_length=128)
+
+ status = models.IntegerField(
+ _('status of participation'), choices=STATUS_OPTIONS, default=UNSUITABLE)
+ updated_at = models.DateTimeField(_('last updated at'), blank=True, null=True)
diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html b/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html
new file mode 100644
index 0000000000000000000000000000000000000000..21e2f5042bf46714414fe4cbc3cbf3abba673bed
--- /dev/null
+++ b/castellum_core/castellum_core/recruitment/templates/recruitment/contact.html
@@ -0,0 +1,51 @@
+{% extends "base.html" %}
+{% load i18n bootstrap4 %}
+
+{% block content %}
+
+
+
+ {{ subject.first_name|default:_('not provided') }} {{ subject.last_name|default:_('not provided') }}
+
+
+
+
+ {% trans 'Gender:' %} |
+ {{ subject.gender|default:_('not provided') }} |
+
+
+ {% trans 'Birthday:' %} |
+ {{ subject.birthday|default:_('not provided') }} |
+
+
+ {% trans 'Address:' %} |
+ {{ subject.address|default:_('not provided') }} |
+
+
+ {% trans 'Email:' %} |
+ {{ subject.email|default:_('not provided') }} |
+
+
+ {% trans 'Phone number:' %} |
+ {{ subject.phone_number|default:_('not provided') }} |
+
+
+ {% trans 'Second phone number:' %} |
+ {{ subject.phone_number_alternative|default:_('not provided') }} |
+
+
+
+
+
+
+{% endblock %}
diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html b/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html
deleted file mode 100644
index 687f0481225c5fad5cc3741356ade5639f6cacfe..0000000000000000000000000000000000000000
--- a/castellum_core/castellum_core/recruitment/templates/recruitment/subject_detail_view.html
+++ /dev/null
@@ -1,39 +0,0 @@
-{% extends "base.html" %}
-{% load i18n %}
-
-{% block content %}
-
-
-
- {{ object.first_name|default:_('not provided') }} {{ object.last_name|default:_('not provided') }}
-
-
-
-
- {% trans 'Gender:' %} |
- {{ object.gender|default:_('not provided') }} |
-
-
- {% trans 'Birthday:' %} |
- {{ object.birthday|default:_('not provided') }} |
-
-
- {% trans 'Address:' %} |
- {{ object.address|default:_('not provided') }} |
-
-
- {% trans 'Email:' %} |
- {{ object.email|default:_('not provided') }} |
-
-
- {% trans 'Phone number:' %} |
- {{ object.phone_number|default:_('not provided') }} |
-
-
- {% trans 'Second phone number:' %} |
- {{ object.phone_number_alternative|default:_('not provided') }} |
-
-
-
- {% trans "Back" %}
-{% endblock %}
\ No newline at end of file
diff --git a/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html b/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html
index b5e3c631670c8e0f8b97c15319b18d97e215bdcd..29e8cabb100d786c6740a5f9b6c9aa580de5dee0 100644
--- a/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html
+++ b/castellum_core/castellum_core/recruitment/templates/recruitment/subjects_list.html
@@ -34,7 +34,7 @@
{{ subject.first_name|default:_('not provided') }} |
{{ subject.last_name|default:_('not provided') }} |
- {% trans 'Call' %} |
+ {% trans 'Call' %} |
{% endfor %}
diff --git a/castellum_core/castellum_core/recruitment/urls.py b/castellum_core/castellum_core/recruitment/urls.py
index 293678129207d45bd6dfdf7a3ba947098162efc8..a310cd47bf48c92a466d5f449fc484e8f801ec4c 100644
--- a/castellum_core/castellum_core/recruitment/urls.py
+++ b/castellum_core/castellum_core/recruitment/urls.py
@@ -27,5 +27,5 @@ app_name = 'recruitment'
urlpatterns = [
path('', views.StudyChoiceView.as_view(), name='select_study'),
path('/', views.SubjectChoiceView.as_view(), name='select_subject'),
- path('//', views.SubjectDetailsView.as_view(), name='detail_subject'),
+ path('//', views.ContactView.as_view(), name='contact'),
]
diff --git a/castellum_core/castellum_core/recruitment/views.py b/castellum_core/castellum_core/recruitment/views.py
index a8bb69621d99cf06ba60b6236b3226b3daaf1025..a54e7fd6e3818b2cb80957da378c1f3e45238a65 100644
--- a/castellum_core/castellum_core/recruitment/views.py
+++ b/castellum_core/castellum_core/recruitment/views.py
@@ -21,12 +21,16 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import get_object_or_404
-from django.views.generic import DetailView
+from django.urls import reverse
+from django.utils import timezone
from django.views.generic import ListView
+from django.views.generic import UpdateView
from studies.models import Study
from subject_management.models import Subject
+from .models import Participation
+
class StudyChoiceView(LoginRequiredMixin, ListView):
model = Study
@@ -51,14 +55,31 @@ class SubjectChoiceView(LoginRequiredMixin, ListView):
return context
-class SubjectDetailsView(LoginRequiredMixin, DetailView):
- model = Subject
- slug_field = 'id'
- slug_url_kwarg = 'subject_pk'
- template_name = 'recruitment/subject_detail_view.html'
+class ContactView(LoginRequiredMixin, UpdateView):
+ model = Participation
+ fields = ['status']
+ template_name = 'recruitment/contact.html'
+
+ def get_object(self, queryset=None):
+ if queryset is None:
+ queryset = self.get_queryset()
- def get_context_data(self, **kwargs):
- context = super(DetailView, self).get_context_data(**kwargs)
study = get_object_or_404(Study, pk=self.kwargs['study_pk'])
- context['study'] = study
+ subject_pk = self.kwargs['subject_pk']
+
+ participation, __ = queryset.get_or_create(study=study, subject_pk=subject_pk)
+ return participation
+
+ def get_success_url(self):
+ return reverse('recruitment:select_subject', args=[self.object.study.pk])
+
+ def get_context_data(self, **kwargs):
+ context = super().get_context_data(**kwargs)
+ context['study'] = self.object.study
+ context['subject'] = get_object_or_404(Subject, pk=self.object.subject_pk)
return context
+
+ def form_valid(self, form):
+ instance = form.save(commit=False)
+ instance.updated_at = timezone.now()
+ return super(ContactView, self).form_valid(form)
diff --git a/castellum_core/tests/recruitment/views/test_contact_view.py b/castellum_core/tests/recruitment/views/test_contact_view.py
new file mode 100644
index 0000000000000000000000000000000000000000..c55cb214e7d058a7af1cdd7545c1bb988edf97aa
--- /dev/null
+++ b/castellum_core/tests/recruitment/views/test_contact_view.py
@@ -0,0 +1,34 @@
+from freezegun import freeze_time
+
+from recruitment.models import Participation
+
+
+def test_404_page_returned_if_study_is_not_provided(client, user, subject):
+ client.force_login(user)
+ url = '/recruitment/3/{}/'.format(subject.pk)
+ response = client.get(url)
+ assert response.status_code == 404
+
+
+def test_200_page_returned_if_study_is_provided(client, user, study, subject):
+ client.force_login(user)
+ url = '/recruitment/{}/{}/'.format(study.pk, subject.pk)
+ response = client.get(url)
+ assert response.status_code == 200
+
+
+def test_post_redirect(client, user, study, subject):
+ client.force_login(user)
+ url = '/recruitment/{}/{}/'.format(study.pk, subject.pk)
+ response = client.post(url, {'status': 2})
+ assert response.status_code == 302
+ assert response.url == '/recruitment/{}/'.format(study.pk)
+
+
+@freeze_time('2018-01-01')
+def test_post_updated_at(client, user, study, subject):
+ client.force_login(user)
+ url = '/recruitment/{}/{}/'.format(study.pk, subject.pk)
+ client.post(url, {'status': 2})
+ participation = Participation.objects.get()
+ assert participation.updated_at.strftime('%Y-%m-%d') == '2018-01-01'
diff --git a/castellum_core/tests/recruitment/views/test_subject_details_view.py b/castellum_core/tests/recruitment/views/test_subject_details_view.py
deleted file mode 100644
index 519456bc06d705cdc21e26b46635c3e283c0e4e4..0000000000000000000000000000000000000000
--- a/castellum_core/tests/recruitment/views/test_subject_details_view.py
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-def test_404_page_returned_if_study_is_not_provided(client, user, subject):
- client.force_login(user)
- url = '/recruitment/3/{}/'.format(subject.pk)
- response = client.get(url)
- assert response.status_code == 404
-
-
-def test_200_page_returned_if_study_is_provided(client, user, study, subject):
- client.force_login(user)
- url = '/recruitment/{}/{}/'.format(study.pk, subject.pk)
- response = client.get(url)
- assert response.status_code == 200