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

export_subjects permission implemented

parent 916865ab
No related branches found
No related tags found
1 merge request!228Resolve "some permissions should be added"
# -*- coding: utf-8 -*-
# Generated by Django 1.11.5 on 2020-03-19 15:18
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('web', '0143_auto_20200319_1446'),
]
operations = [
migrations.AlterModelOptions(
name='subject',
options={'permissions': [('send_sample_mail_for_appointments', 'Can send sample collection list'), ('export_subjects', 'Can export subject data to excel/csv')]},
),
]
# coding=utf-8 # coding=utf-8
import logging import logging
from django.db import models from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from constants import SEX_CHOICES, COUNTRY_OTHER_ID from constants import SEX_CHOICES, COUNTRY_OTHER_ID
from web.models import Country, Visit, Appointment from web.models import Country, Visit, Appointment
from . import Language from . import Language
from django.db.models.signals import post_save
from django.dispatch import receiver
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class Subject(models.Model):
class Subject(models.Model):
class Meta: class Meta:
app_label = 'web' app_label = 'web'
permissions = [
("send_sample_mail_for_appointments", "Can send sample collection list"),
("export_subjects", "Can export subject data to excel/csv"),
]
sex = models.CharField(max_length=1, sex = models.CharField(max_length=1,
choices=SEX_CHOICES, choices=SEX_CHOICES,
...@@ -103,7 +108,7 @@ class Subject(models.Model): ...@@ -103,7 +108,7 @@ class Subject(models.Model):
) )
def pretty_address(self): def pretty_address(self):
return u'{} ({}), {}. {}'.format(self.address, self.postal_code, self.city, self.country) return u'{} ({}), {}. {}'.format(self.address, self.postal_code, self.city, self.country)
def mark_as_dead(self): def mark_as_dead(self):
self.dead = True self.dead = True
...@@ -130,8 +135,8 @@ class Subject(models.Model): ...@@ -130,8 +135,8 @@ class Subject(models.Model):
return "%s %s" % (self.first_name, self.last_name) return "%s %s" % (self.first_name, self.last_name)
#SIGNALS # SIGNALS
@receiver(post_save, sender=Subject) @receiver(post_save, sender=Subject)
def set_as_deceased(sender, instance, **kwargs): def set_as_deceased(sender, instance, **kwargs):
if instance.dead: if instance.dead:
instance.mark_as_dead() instance.mark_as_dead()
\ No newline at end of file
...@@ -83,12 +83,14 @@ ...@@ -83,12 +83,14 @@
</li> </li>
{% endif %} {% endif %}
<li data-desc="export"> {% if "export_subjects" in permissions %}
<a href="{% url 'web.views.export' %}"> <li data-desc="export">
<i class="fa fa-file-excel-o"></i> <a href="{% url 'web.views.export' %}">
<span>Export</span> <i class="fa fa-file-excel-o"></i>
</a> <span>Export</span>
</li> </a>
</li>
{% endif %}
{% if study.has_vouchers and "change_voucher" in permissions%} {% if study.has_vouchers and "change_voucher" in permissions%}
<li data-desc="vouchers"> <li data-desc="vouchers">
......
...@@ -9,26 +9,47 @@ from web.views.export import subject_to_row_for_fields, DROP_OUT_FIELD ...@@ -9,26 +9,47 @@ from web.views.export import subject_to_row_for_fields, DROP_OUT_FIELD
class TestExportView(LoggedInTestCase): class TestExportView(LoggedInTestCase):
def test_export_subjects_to_csv(self): def test_export_subjects_to_csv(self):
self.login_as_admin()
create_study_subject() create_study_subject()
response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "subjects"})) response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "subjects"}))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_export_subjects_to_csv_without_permission(self):
response = self.client.get(reverse("web.views.mail_templates"))
create_study_subject()
response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "subjects"}))
self.assertEqual(response.status_code, 302)
def test_render_export(self): def test_render_export(self):
self.login_as_admin()
create_study_subject() create_study_subject()
response = self.client.get(reverse('web.views.export')) response = self.client.get(reverse('web.views.export'))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_render_export_without_permission(self):
create_study_subject()
response = self.client.get(reverse('web.views.export'))
self.assertEqual(response.status_code, 302)
def test_export_appointments_to_csv(self): def test_export_appointments_to_csv(self):
self.login_as_admin()
create_appointment() create_appointment()
response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "appointments"})) response = self.client.get(reverse('web.views.export_to_csv', kwargs={'data_type': "appointments"}))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_export_subjects_to_excel(self): def test_export_subjects_to_excel(self):
self.login_as_admin()
create_study_subject() create_study_subject()
response = self.client.get(reverse('web.views.export_to_excel', kwargs={'data_type': "subjects"})) response = self.client.get(reverse('web.views.export_to_excel', kwargs={'data_type': "subjects"}))
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_export_subjects_to_excel_without_permission(self):
create_study_subject()
response = self.client.get(reverse('web.views.export_to_excel', kwargs={'data_type': "subjects"}))
self.assertEqual(response.status_code, 302)
def test_export_appointments_to_excel(self): def test_export_appointments_to_excel(self):
self.login_as_admin()
appointment = create_appointment() appointment = create_appointment()
appointment.visit = None appointment.visit = None
appointment.save() appointment.save()
......
...@@ -5,10 +5,12 @@ import django_excel as excel ...@@ -5,10 +5,12 @@ import django_excel as excel
from django.http import HttpResponse from django.http import HttpResponse
from notifications import get_today_midnight_date from notifications import get_today_midnight_date
from web.decorators import PermissionDecorator
from . import e500_error, wrap_response from . import e500_error, wrap_response
from ..models import Subject, StudySubject, Appointment from ..models import Subject, StudySubject, Appointment
@PermissionDecorator('export_subjects', 'subject')
def export_to_csv(request, data_type="subjects"): def export_to_csv(request, data_type="subjects"):
# Create the HttpResponse object with the appropriate CSV header. # Create the HttpResponse object with the appropriate CSV header.
selected_fields = request.GET.get('fields', None) selected_fields = request.GET.get('fields', None)
...@@ -29,6 +31,7 @@ def export_to_csv(request, data_type="subjects"): ...@@ -29,6 +31,7 @@ def export_to_csv(request, data_type="subjects"):
return response return response
@PermissionDecorator('export_subjects', 'subject')
def export_to_excel(request, data_type="subjects"): def export_to_excel(request, data_type="subjects"):
selected_fields = request.GET.get('fields', None) selected_fields = request.GET.get('fields', None)
filename = data_type + '-' + get_today_midnight_date().strftime("%Y-%m-%d") + ".xls" filename = data_type + '-' + get_today_midnight_date().strftime("%Y-%m-%d") + ".xls"
...@@ -53,26 +56,27 @@ class CustomField: ...@@ -53,26 +56,27 @@ class CustomField:
DROP_OUT_FIELD = CustomField({'verbose_name': "DROP OUT", 'name': "custom-drop-out"}) DROP_OUT_FIELD = CustomField({'verbose_name': "DROP OUT", 'name': "custom-drop-out"})
APPOINTMENT_TYPE_FIELD = CustomField({ APPOINTMENT_TYPE_FIELD = CustomField({
'name': 'appointment_types', 'name': 'appointment_types',
'verbose_name': 'Appointment Types' 'verbose_name': 'Appointment Types'
}) })
STUDY_SUBJECT_FIELDS = [CustomField({ STUDY_SUBJECT_FIELDS = [CustomField({
'name': 'nd_number', 'name': 'nd_number',
'verbose_name' : 'ND number' 'verbose_name': 'ND number'
})] })]
SUBJECT_FIELDS = [CustomField({ SUBJECT_FIELDS = [CustomField({
'name': 'last_name', 'name': 'last_name',
'verbose_name': 'Family name' 'verbose_name': 'Family name'
}), }),
CustomField({ CustomField({
'name': 'first_name', 'name': 'first_name',
'verbose_name': 'Name' 'verbose_name': 'Name'
})] })]
VISIT_FIELDS = [CustomField({ VISIT_FIELDS = [CustomField({
'name': 'visit_number', 'name': 'visit_number',
'verbose_name': 'Visit' 'verbose_name': 'Visit'
})] })]
def filter_fields_from_selected_fields(fields, selected_fields): def filter_fields_from_selected_fields(fields, selected_fields):
if selected_fields is None: if selected_fields is None:
...@@ -80,6 +84,7 @@ def filter_fields_from_selected_fields(fields, selected_fields): ...@@ -80,6 +84,7 @@ def filter_fields_from_selected_fields(fields, selected_fields):
selected_fields = set(selected_fields.split(',')) selected_fields = set(selected_fields.split(','))
return [field for field in fields if field.name in selected_fields] return [field for field in fields if field.name in selected_fields]
def get_default_subject_fields(): def get_default_subject_fields():
subject_fields = [] subject_fields = []
for field in Subject._meta.fields: for field in Subject._meta.fields:
...@@ -91,12 +96,13 @@ def get_default_subject_fields(): ...@@ -91,12 +96,13 @@ def get_default_subject_fields():
subject_fields.append(DROP_OUT_FIELD) subject_fields.append(DROP_OUT_FIELD)
return subject_fields return subject_fields
def get_subjects_as_array(selected_fields=None): def get_subjects_as_array(selected_fields=None):
result = [] result = []
subject_fields = get_default_subject_fields() subject_fields = get_default_subject_fields()
subject_fields = filter_fields_from_selected_fields(subject_fields, selected_fields) subject_fields = filter_fields_from_selected_fields(subject_fields, selected_fields)
field_names = [field.verbose_name for field in subject_fields] #faster than loop field_names = [field.verbose_name for field in subject_fields] # faster than loop
result.append(field_names) result.append(field_names)
subjects = StudySubject.objects.order_by('-subject__last_name') subjects = StudySubject.objects.order_by('-subject__last_name')
...@@ -105,6 +111,7 @@ def get_subjects_as_array(selected_fields=None): ...@@ -105,6 +111,7 @@ def get_subjects_as_array(selected_fields=None):
result.append([unicode(s).replace("\n", ";").replace("\r", ";") for s in row]) result.append([unicode(s).replace("\n", ";").replace("\r", ";") for s in row])
return result return result
def subject_to_row_for_fields(study_subject, subject_fields): def subject_to_row_for_fields(study_subject, subject_fields):
row = [] row = []
for field in subject_fields: for field in subject_fields:
...@@ -128,31 +135,33 @@ def subject_to_row_for_fields(study_subject, subject_fields): ...@@ -128,31 +135,33 @@ def subject_to_row_for_fields(study_subject, subject_fields):
row.append(cell) row.append(cell)
return row return row
def get_appointment_fields(): def get_appointment_fields():
appointments_fields = [] appointments_fields = []
for field in Appointment._meta.fields: for field in Appointment._meta.fields:
if field.name.upper() != "VISIT" and field.name.upper() != "ID" and \ if field.name.upper() != "VISIT" and field.name.upper() != "ID" and \
field.name.upper() != "WORKER_ASSIGNED" and field.name.upper() != "APPOINTMENT_TYPES" and \ field.name.upper() != "WORKER_ASSIGNED" and field.name.upper() != "APPOINTMENT_TYPES" and \
field.name.upper() != "ROOM" and field.name.upper() != "FLYING_TEAM": field.name.upper() != "ROOM" and field.name.upper() != "FLYING_TEAM":
appointments_fields.append(field) appointments_fields.append(field)
all_fields = STUDY_SUBJECT_FIELDS + SUBJECT_FIELDS + VISIT_FIELDS + appointments_fields + [APPOINTMENT_TYPE_FIELD] all_fields = STUDY_SUBJECT_FIELDS + SUBJECT_FIELDS + VISIT_FIELDS + appointments_fields + [APPOINTMENT_TYPE_FIELD]
return all_fields, appointments_fields return all_fields, appointments_fields
def get_appointments_as_array(selected_fields=None): def get_appointments_as_array(selected_fields=None):
result = [] result = []
all_fields, appointments_fields = get_appointment_fields() all_fields, appointments_fields = get_appointment_fields()
all_fields = filter_fields_from_selected_fields(all_fields, selected_fields) all_fields = filter_fields_from_selected_fields(all_fields, selected_fields)
appointments_fields = filter_fields_from_selected_fields(appointments_fields, selected_fields) appointments_fields = filter_fields_from_selected_fields(appointments_fields, selected_fields)
field_names = [field.verbose_name for field in all_fields] #faster than loop field_names = [field.verbose_name for field in all_fields] # faster than loop
result.append(field_names) result.append(field_names)
appointments = Appointment.objects.order_by('-datetime_when') appointments = Appointment.objects.order_by('-datetime_when')
for appointment in appointments: for appointment in appointments:
#add field_names ['ND number', 'Family name', 'Name', 'Visit'] first # add field_names ['ND number', 'Family name', 'Name', 'Visit'] first
row = [] row = []
for field in STUDY_SUBJECT_FIELDS: for field in STUDY_SUBJECT_FIELDS:
if field.verbose_name in field_names: if field.verbose_name in field_names:
...@@ -175,15 +184,16 @@ def get_appointments_as_array(selected_fields=None): ...@@ -175,15 +184,16 @@ def get_appointments_as_array(selected_fields=None):
for field in appointments_fields: for field in appointments_fields:
row.append(getattr(appointment, field.name)) row.append(getattr(appointment, field.name))
if APPOINTMENT_TYPE_FIELD.verbose_name in field_names: if APPOINTMENT_TYPE_FIELD.verbose_name in field_names:
#avoid last comma in the list of appointment types # avoid last comma in the list of appointment types
type_string = ','.join([appointment_type.code for appointment_type in appointment.appointment_types.all()]) type_string = ','.join([appointment_type.code for appointment_type in appointment.appointment_types.all()])
row.append(type_string) row.append(type_string)
result.append([unicode(s).replace("\n", ";").replace("\r", ";") for s in row]) result.append([unicode(s).replace("\n", ";").replace("\r", ";") for s in row])
return result return result
@PermissionDecorator('export_subjects', 'subject')
def export(request): def export(request):
return wrap_response(request, 'export/index.html', { return wrap_response(request, 'export/index.html', {
'subject_fields': get_default_subject_fields(), 'subject_fields': get_default_subject_fields(),
'appointment_fields': get_appointment_fields()[0] 'appointment_fields': get_appointment_fields()[0]
}) })
\ No newline at end of file
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