Skip to content
Snippets Groups Projects
Commit 57d5b3ab authored by Piotr Gawron's avatar Piotr Gawron
Browse files

api that provides list of visits

parent 1bbfd95c
No related branches found
No related tags found
1 merge request!107Resolve "exceeded visits list & unfinished visits list"
...@@ -16,7 +16,7 @@ Including another URLconf ...@@ -16,7 +16,7 @@ Including another URLconf
from django.conf.urls import url from django.conf.urls import url
from web.api_views import worker, location, subject, appointment_type, appointment, configuration, daily_planning, \ from web.api_views import worker, location, subject, appointment_type, appointment, configuration, daily_planning, \
redcap, flying_team redcap, flying_team, visit
urlpatterns = [ urlpatterns = [
# appointments # appointments
...@@ -38,6 +38,10 @@ urlpatterns = [ ...@@ -38,6 +38,10 @@ urlpatterns = [
name='web.api.subjects.columns'), name='web.api.subjects.columns'),
url(r'^subject_types', subject.types, name='web.api.subject_types'), url(r'^subject_types', subject.types, name='web.api.subject_types'),
# visits data
url(r'^visits/(?P<visit_list_type>[A-z]+)$', visit.visits, name='web.api.visits'),
url(r'^visits:columns/(?P<visit_list_type>[A-z]+)$', visit.get_visit_columns, name='web.api.visits.columns'),
# locations # locations
url(r'^locations$', location.locations, name='web.api.locations'), url(r'^locations$', location.locations, name='web.api.locations'),
......
import logging
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from web.models import SubjectColumns
from web.models import Visit, Study, VisitColumns, StudyVisitList
from web.models.constants import GLOBAL_STUDY_ID
from web.models.study_visit_list import VISIT_LIST_GENERIC
logger = logging.getLogger(__name__)
def add_column(result, name, field_name, column_list, param, columns_used_in_study=None, visible_param=None):
add = True
if columns_used_in_study:
add = getattr(columns_used_in_study, field_name)
if add:
if visible_param is not None:
visible = visible_param
elif column_list is None:
visible = True
else:
visible = getattr(column_list, field_name)
result.append({
"type": field_name,
"name": name,
"filter": param,
"visible": visible
})
# noinspection PyUnusedLocal
@login_required
def get_visit_columns(request, visit_list_type):
study = Study.objects.filter(id=GLOBAL_STUDY_ID)[0]
study_visit_lists = StudyVisitList.objects.filter(study=study, type=visit_list_type)
if len(study_visit_lists) > 0:
visit_list = study_visit_lists[0]
visit_columns = visit_list.visible_visit_columns
visit_subject_columns = visit_list.visible_visit_columns
else:
visit_list = StudyVisitList()
visit_columns = VisitColumns()
visit_subject_columns = SubjectColumns()
result = []
add_column(result, "First name", "first_name", visit_subject_columns, "string_filter")
add_column(result, "Last name", "last_name", visit_subject_columns, "string_filter")
add_column(result, "Visit begins", "datetime_begin", visit_columns, None)
add_column(result, "Visit ends", "datetime_end", visit_columns, None)
add_column(result, "Finished", "is_finished", visit_columns, "yes_no_filter")
add_column(result, "Post mail sent", "post_mail_sent", visit_columns, "yes_no_filter")
add_column(result, "Visit number", "visit_number", visit_columns, "integer_filter")
add_column(result, "Edit", "edit", None, None)
return JsonResponse({"columns": result})
# noinspection PyUnusedLocal
@login_required
def get_visits(request, visit_type):
if visit_type == VISIT_LIST_GENERIC:
return Visit.objects.all()
else:
raise TypeError("Unknown query type: " + visit_type)
def get_visits_order(visits_to_be_ordered, order_column, order_direction):
result = visits_to_be_ordered
if order_direction == "asc":
order_direction = ""
else:
order_direction = "-"
if order_column == "first_name":
result = visits_to_be_ordered.order_by(order_direction + 'subject__subject__first_name')
elif order_column == "last_name":
result = visits_to_be_ordered.order_by(order_direction + 'subject__subject__last_name')
else:
logger.warn("Unknown sort column: " + str(order_column))
return result
def get_visits_filtered(visits_to_be_filtered, filters):
result = visits_to_be_filtered
for row in filters:
column = row[0]
value = row[1]
if column == "first_name":
result = result.filter(subject__subject__first_name__icontains=value)
elif column == "last_name":
result = result.filter(subject__subject__last_name__icontains=value)
else:
message = "UNKNOWN filter: "
if column is None:
message += "[None]"
else:
message += str(column)
logger.warn(message)
return result
@login_required
def visits(request, visit_list_type):
# id of the query from dataTable: https://datatables.net/manual/server-side
draw = int(request.GET.get("draw", "-1"))
start = int(request.GET.get("start", "0"))
length = int(request.GET.get("length", "10"))
order = int(request.GET.get("order[0][column]", "0"))
order_dir = request.GET.get("order[0][dir]", "asc")
order_column = request.GET.get("columns[" + str(order) + "][data]", "last_name")
filters = []
column_id = 0
while request.GET.get("columns[" + str(column_id) + "][search][value]", "unknown") != "unknown":
val = request.GET.get("columns[" + str(column_id) + "][search][value]", "unknown")
if val != "":
filters.append([request.GET.get("columns[" + str(column_id) + "][data]"), val])
column_id += 1
all_visits = get_visits(request, visit_list_type)
count = all_visits.count()
ordered_visits = get_visits_order(all_visits, order_column, order_dir)
filtered_visits = get_visits_filtered(ordered_visits, filters)
sliced_visits = filtered_visits[start:(start + length)]
result_visits = sliced_visits
count_filtered = filtered_visits.count()
data = []
for visit in result_visits:
data.append(serialize_visit(visit))
return JsonResponse({
"draw": draw,
"recordsTotal": count,
"recordsFiltered": count_filtered,
"data": data,
})
def serialize_visit(visit):
datetime_begin = serialize_date(visit.datetime_begin)
datetime_end = serialize_date(visit.datetime_end)
result = {
"first_name": visit.subject.subject.first_name,
"last_name": visit.subject.subject.last_name,
"datetime_begin": datetime_begin,
"datetime_end": datetime_end,
"is_finished": visit.is_finished,
"post_mail_sent": visit.post_mail_sent,
"visit_number": visit.visit_number,
"id": visit.id,
}
return result
def serialize_date(date):
if date is not None:
result = date.strftime('%Y-%m-%d')
else:
result = ""
return result
# -*- coding: utf-8 -*-
# Generated by Django 1.10.7 on 2017-12-05 12:51
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('web', '0082_studysubjectlist_visits'),
]
operations = [
migrations.CreateModel(
name='StudyVisitList',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.CharField(choices=[(b'GENERIC', b'Generic')], max_length=50, verbose_name=b'Type o list')),
('study', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.Study')),
('visible_subject_columns', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.SubjectColumns')),
],
),
migrations.CreateModel(
name='VisitColumns',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('datetime_begin', models.BooleanField(choices=[(True, b'Yes'), (False, b'No')], default=True, verbose_name=b'Visit starts date')),
('datetime_end', models.BooleanField(choices=[(True, b'Yes'), (False, b'No')], default=True, verbose_name=b'Visit ends date')),
('is_finished', models.BooleanField(choices=[(True, b'Yes'), (False, b'No')], default=True, verbose_name=b'Is finished')),
('post_mail_sent', models.BooleanField(choices=[(True, b'Yes'), (False, b'No')], default=True, verbose_name=b'Post mail sent')),
('visit_number', models.BooleanField(choices=[(True, b'Yes'), (False, b'No')], default=True, verbose_name=b'Visit number')),
],
),
migrations.AddField(
model_name='studyvisitlist',
name='visible_visit_columns',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='web.VisitColumns'),
),
]
...@@ -10,6 +10,7 @@ from appointment_type_link import AppointmentTypeLink ...@@ -10,6 +10,7 @@ from appointment_type_link import AppointmentTypeLink
from country import Country from country import Country
from subject_columns import SubjectColumns from subject_columns import SubjectColumns
from study_columns import StudyColumns from study_columns import StudyColumns
from visit_columns import VisitColumns
from notification_columns import StudyNotificationParameters from notification_columns import StudyNotificationParameters
from study import Study from study import Study
from room import Room from room import Room
...@@ -24,6 +25,7 @@ from language import Language ...@@ -24,6 +25,7 @@ from language import Language
from subject import Subject from subject import Subject
from study_subject import StudySubject from study_subject import StudySubject
from study_subject_list import StudySubjectList from study_subject_list import StudySubjectList
from study_visit_list import StudyVisitList
from contact_attempt import ContactAttempt from contact_attempt import ContactAttempt
from mail_template import MailTemplate from mail_template import MailTemplate
from missing_subject import MissingSubject from missing_subject import MissingSubject
...@@ -32,4 +34,4 @@ from inconsistent_subject import InconsistentSubject, InconsistentField ...@@ -32,4 +34,4 @@ from inconsistent_subject import InconsistentSubject, InconsistentField
__all__ = [Study, FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room, __all__ = [Study, FlyingTeam, Appointment, AppointmentType, Availability, Holiday, Item, Language, Location, Room,
Subject, StudySubject, StudySubjectList, SubjectColumns, StudyNotificationParameters, Subject, StudySubject, StudySubjectList, SubjectColumns, StudyNotificationParameters,
Visit, Worker, ContactAttempt, ConfigurationItem, MailTemplate, AppointmentTypeLink, MissingSubject, Visit, Worker, ContactAttempt, ConfigurationItem, MailTemplate, AppointmentTypeLink, MissingSubject,
InconsistentSubject, InconsistentField, Country, StudyColumns] InconsistentSubject, InconsistentField, Country, StudyColumns, VisitColumns, StudyVisitList]
# coding=utf-8
from django.db import models
from web.models import Study, SubjectColumns, VisitColumns
VISIT_LIST_GENERIC = "GENERIC"
VISIT_LIST_CHOICES = {
VISIT_LIST_GENERIC: 'Generic',
}
class StudyVisitList(models.Model):
class Meta:
app_label = 'web'
study = models.ForeignKey(
Study,
on_delete=models.CASCADE,
null=False,
)
visible_visit_columns = models.ForeignKey(
VisitColumns,
on_delete=models.CASCADE,
null=False,
)
visible_subject_columns = models.ForeignKey(
SubjectColumns,
on_delete=models.CASCADE,
null=False,
)
type = models.CharField(max_length=50,
choices=VISIT_LIST_CHOICES.items(),
verbose_name='Type o list',
)
# coding=utf-8
from django.db import models
from web.models.constants import BOOL_CHOICES
class VisitColumns(models.Model):
class Meta:
app_label = 'web'
datetime_begin = models.BooleanField(choices=BOOL_CHOICES,
verbose_name='Visit starts date',
default=True
)
datetime_end = models.BooleanField(choices=BOOL_CHOICES,
verbose_name='Visit ends date',
default=True
)
is_finished = models.BooleanField(choices=BOOL_CHOICES,
verbose_name='Is finished',
default=True
)
post_mail_sent = models.BooleanField(choices=BOOL_CHOICES,
verbose_name='Post mail sent',
default=True
)
visit_number = models.BooleanField(choices=BOOL_CHOICES,
verbose_name='Visit number',
default=True
)
# coding=utf-8
import json
import logging
from django.urls import reverse
from web.models.study_visit_list import VISIT_LIST_GENERIC
from web.tests import LoggedInWithWorkerTestCase
from web.tests.functions import create_study_subject, create_get_suffix, create_visit
logger = logging.getLogger(__name__)
class TestVisitApi(LoggedInWithWorkerTestCase):
def setUp(self):
super(TestVisitApi, self).setUp()
self.study_subject = create_study_subject()
def test_get_columns(self):
response = self.client.get(reverse('web.api.visits.columns', kwargs={'visit_list_type': VISIT_LIST_GENERIC}))
self.assertEqual(response.status_code, 200)
columns = json.loads(response.content)['columns']
self.assertTrue(len(columns) > 0)
def test_visits_general(self):
response = self.client.get(reverse('web.api.visits', kwargs={'visit_list_type': VISIT_LIST_GENERIC}))
self.assertEqual(response.status_code, 200)
def test_visits_general_search(self):
name = "Piotrek"
self.study_subject.subject.first_name = name
self.study_subject.subject.save()
create_visit(self.study_subject)
params = {
"columns[0][search][value]": "another_name",
"columns[0][data]": "first_name"
}
url = ("%s" + create_get_suffix(params)) % reverse('web.api.visits',
kwargs={'visit_list_type': VISIT_LIST_GENERIC})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertFalse(name in response.content)
params["columns[0][search][value]"] = name
url = ("%s" + create_get_suffix(params)) % reverse('web.api.visits',
kwargs={'visit_list_type': VISIT_LIST_GENERIC})
response = self.client.get(url)
self.assertEqual(response.status_code, 200)
self.assertTrue(name in response.content)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment