From 7555a4919dbf2024f4fc3e24ae8659c4ee1e8450 Mon Sep 17 00:00:00 2001
From: Piotr Gawron <piotr.gawron@uni.lu>
Date: Fri, 27 Oct 2017 12:59:58 +0200
Subject: [PATCH] field for storing visit number added

---
 smash/web/api_views/appointment.py            |  2 +-
 smash/web/forms.py                            |  4 +--
 .../web/migrations/0056_visit_visit_number.py | 20 +++++++++++++++
 smash/web/models/visit.py                     | 25 ++++++++++++++++---
 smash/web/templates/visits/details.html       |  4 +--
 .../test_visit.py}                            |  3 +--
 smash/web/tests/test_VisitAddForm.py          |  2 +-
 .../test_subjects.py}                         |  4 +--
 smash/web/views/export.py                     |  2 +-
 smash/web/views/subject.py                    |  2 +-
 10 files changed, 52 insertions(+), 16 deletions(-)
 create mode 100644 smash/web/migrations/0056_visit_visit_number.py
 rename smash/web/tests/{test_model_visit.py => models/test_visit.py} (93%)
 rename smash/web/tests/{test_view_subjects.py => view/test_subjects.py} (97%)

diff --git a/smash/web/api_views/appointment.py b/smash/web/api_views/appointment.py
index b8a7ce93..a51ddfc0 100644
--- a/smash/web/api_views/appointment.py
+++ b/smash/web/api_views/appointment.py
@@ -86,7 +86,7 @@ def serialize_appointment(appointment):
     subject_string = ""
     nd_number = screening_number = phone_numbers = appointment_types = None
     if appointment.visit is not None:
-        title = appointment.visit.follow_up_title()
+        title = "Visit " + str(appointment.visit.visit_number)
         subject = appointment.visit.subject
         subject_string = subject.last_name + " " + subject.first_name
         nd_number = subject.nd_number
diff --git a/smash/web/forms.py b/smash/web/forms.py
index 10b925e9..e4e4c2bb 100644
--- a/smash/web/forms.py
+++ b/smash/web/forms.py
@@ -320,7 +320,7 @@ class VisitDetailForm(ModelForm):
 
     class Meta:
         model = Visit
-        exclude = ['is_finished']
+        exclude = ['is_finished', 'visit_number']
 
 
 class VisitAddForm(ModelForm):
@@ -336,7 +336,7 @@ class VisitAddForm(ModelForm):
 
     class Meta:
         model = Visit
-        exclude = ['is_finished']
+        exclude = ['is_finished', 'visit_number']
 
     def clean(self):
         super(VisitAddForm, self).clean()
diff --git a/smash/web/migrations/0056_visit_visit_number.py b/smash/web/migrations/0056_visit_visit_number.py
new file mode 100644
index 00000000..3be1cb19
--- /dev/null
+++ b/smash/web/migrations/0056_visit_visit_number.py
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2017-10-27 10:22
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('web', '0055_auto_20170925_0905'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='visit',
+            name='visit_number',
+            field=models.IntegerField(default=1, verbose_name=b'Visit number'),
+        ),
+    ]
diff --git a/smash/web/models/visit.py b/smash/web/models/visit.py
index 7554e398..e11b52d7 100644
--- a/smash/web/models/visit.py
+++ b/smash/web/models/visit.py
@@ -2,6 +2,8 @@
 import datetime
 
 from django.db import models
+from django.db.models.signals import post_save
+from django.dispatch import receiver
 
 from constants import BOOL_CHOICES, SUBJECT_TYPE_CHOICES_CONTROL
 
@@ -33,16 +35,18 @@ class Visit(models.Model):
                                                blank=True,
                                                )
 
+    # this value is automatically computed by signal handled by update_visit_number method
+    visit_number = models.IntegerField(
+        verbose_name='Visit number',
+        default=1
+    )
+
     def __unicode__(self):
         return "%s %s" % (self.subject.first_name, self.subject.last_name)
 
     def __str__(self):
         return "%s %s" % (self.subject.first_name, self.subject.last_name)
 
-    def follow_up_title(self):
-        count = Visit.objects.filter(subject=self.subject, datetime_begin__lt=self.datetime_begin).count()
-        return "Visit " + str(count + 1)
-
     def mark_as_finished(self):
         self.is_finished = True
         self.save()
@@ -59,3 +63,16 @@ class Visit(models.Model):
                 datetime_begin=visit_started + time_to_next_visit,
                 datetime_end=visit_started + time_to_next_visit + datetime.timedelta(days=93)
             )
+
+
+@receiver(post_save, sender=Visit)
+def update_visit_number(sender, instance, **kwargs):
+    visit = instance
+    if visit.subject is not None:
+        count = Visit.objects.filter(subject=visit.subject).filter(datetime_begin__lte=visit.datetime_begin).count()
+        if count != visit.visit_number:
+            visit.visit_number = count
+            visit.save()
+            subject_visits = Visit.objects.filter(subject=visit.subject).all()
+            for subject_visit in subject_visits:
+                update_visit_number(sender, subject_visit)
diff --git a/smash/web/templates/visits/details.html b/smash/web/templates/visits/details.html
index 6953e3a9..f6c632b9 100644
--- a/smash/web/templates/visits/details.html
+++ b/smash/web/templates/visits/details.html
@@ -11,10 +11,10 @@
 {% endblock styles %}
 
 {% block ui_active_tab %}'visits'{% endblock ui_active_tab %}
-{% block page_header %}Details of the visit ({{ visit.follow_up_title }}) {% endblock page_header %}
+{% block page_header %}Details of the visit ({{ visit.visit_number }}) {% endblock page_header %}
 {% block page_description %}{% endblock page_description %}
 
-{% block title %}{{ block.super }} - Details of visit ({{ visit.follow_up_title }}) {% endblock %}
+{% block title %}{{ block.super }} - Details of visit ({{ visit.visit_number }}) {% endblock %}
 
 {% block breadcrumb %}
     {% include "subjects/breadcrumb.html" %}
diff --git a/smash/web/tests/test_model_visit.py b/smash/web/tests/models/test_visit.py
similarity index 93%
rename from smash/web/tests/test_model_visit.py
rename to smash/web/tests/models/test_visit.py
index 2a54bcb9..3b302837 100644
--- a/smash/web/tests/test_model_visit.py
+++ b/smash/web/tests/models/test_visit.py
@@ -1,7 +1,6 @@
 from django.test import TestCase
 
-from functions import create_subject
-from functions import create_visit
+from web.tests.functions import create_subject, create_visit
 from web.models import Visit
 
 
diff --git a/smash/web/tests/test_VisitAddForm.py b/smash/web/tests/test_VisitAddForm.py
index 2a2dfe0c..2efa428b 100644
--- a/smash/web/tests/test_VisitAddForm.py
+++ b/smash/web/tests/test_VisitAddForm.py
@@ -7,7 +7,7 @@ from functions import get_test_location
 from web.forms import VisitAddForm
 
 
-class SubjectAddFormTests(TestCase):
+class VisitAddFormTests(TestCase):
     def setUp(self):
         get_test_location()
         self.subject = create_subject()
diff --git a/smash/web/tests/test_view_subjects.py b/smash/web/tests/view/test_subjects.py
similarity index 97%
rename from smash/web/tests/test_view_subjects.py
rename to smash/web/tests/view/test_subjects.py
index ef13ec1f..8c721780 100644
--- a/smash/web/tests/test_view_subjects.py
+++ b/smash/web/tests/view/test_subjects.py
@@ -5,7 +5,7 @@ from django.test import Client
 from django.test import TestCase
 from django.urls import reverse
 
-from functions import create_subject, create_visit, create_appointment, create_worker, get_test_location
+from web.tests.functions import create_subject, create_visit, create_appointment, create_worker, get_test_location
 from web.forms import SubjectAddForm, SubjectEditForm
 from web.models import Subject
 from web.models.constants import SEX_CHOICES_MALE, SUBJECT_TYPE_CHOICES_CONTROL, SUBJECT_TYPE_CHOICES_PATIENT
@@ -44,7 +44,7 @@ class SubjectsViewTests(TestCase):
         self.assertEqual(response.status_code, 200)
         self.assertFalse("Add visit" in response.content)
 
-    def test_render_subject_visit_details(self):
+    def test_render_subject_visit_details_without_visit(self):
         subject = create_subject()
 
         response = self.client.get(reverse('web.views.subject_visit_details', kwargs={'id': subject.id}))
diff --git a/smash/web/views/export.py b/smash/web/views/export.py
index 359386c2..b1962c7e 100644
--- a/smash/web/views/export.py
+++ b/smash/web/views/export.py
@@ -91,7 +91,7 @@ def get_appointments_as_array():
     for appointment in appointments:
         if appointment.visit is not None:
             row = [appointment.visit.subject.nd_number, appointment.visit.subject.last_name,
-                   appointment.visit.subject.first_name, appointment.visit.follow_up_title()]
+                   appointment.visit.subject.first_name, appointment.visit.visit_number]
         else:
             row = ["---", "---", "---", "---"]
         for field in appointments_fields:
diff --git a/smash/web/views/subject.py b/smash/web/views/subject.py
index da6675ea..1bb75f3f 100644
--- a/smash/web/views/subject.py
+++ b/smash/web/views/subject.py
@@ -90,7 +90,7 @@ def subject_visit_details(request, id):
         appointments = visit.appointment_set.all()
         finished = visit.is_finished
         visit_id = visit.id
-        visit_title = visit.follow_up_title()
+        visit_title = "Visit " + str(visit.visit_number)
         visit_form = VisitDetailForm(instance=visit)
         visits_data.append((visit_form, appointments, finished, visit_id, visit_title))
         if not visit.is_finished:
-- 
GitLab