From 025627728fa5c8d2b903b09b7e29572a6df9dc4a Mon Sep 17 00:00:00 2001 From: "Justin R. Porter" Date: Sat, 16 Jan 2021 23:10:31 -0600 Subject: [PATCH 1/4] first pass resection. --- config/settings/base.py | 6 ++ osler/core/forms.py | 69 +++++++++++-------- .../migrations/0008_patientphonenumber.py | 27 ++++++++ osler/core/models.py | 30 ++++++++ osler/core/views.py | 11 +++ .../0005_user_model_phone_phase_1.py | 39 +++++++++++ osler/users/models.py | 9 ++- requirements/base.txt | 3 +- 8 files changed, 160 insertions(+), 34 deletions(-) create mode 100644 osler/core/migrations/0008_patientphonenumber.py create mode 100644 osler/users/migrations/0005_user_model_phone_phase_1.py diff --git a/config/settings/base.py b/config/settings/base.py index 7c93f600..75e97b59 100644 --- a/config/settings/base.py +++ b/config/settings/base.py @@ -73,6 +73,7 @@ 'bootstrap3', 'simple_history', 'adminsortable', + 'phonenumber_field', ] LOCAL_APPS = [ @@ -318,6 +319,11 @@ # ----------------------------------------------------------------------------- CRISPY_TEMPLATE_PACK = 'bootstrap3' + +# django-phonenumber-field +PHONENUMBER_DB_FORMAT = 'E164' +PHONENUMBER_DEFAULT_REGION = 'US' + # osler # ----------------------------------------------------------------------------- diff --git a/osler/core/forms.py b/osler/core/forms.py index c04fe587..b7105e5a 100644 --- a/osler/core/forms.py +++ b/osler/core/forms.py @@ -1,5 +1,4 @@ '''Forms for the Oser core components.''' - from django.forms import ( Form, CharField, ModelForm, EmailField, CheckboxSelectMultiple, ModelMultipleChoiceField, CheckboxInput) @@ -10,6 +9,9 @@ from django.contrib.auth.forms import AuthenticationForm from django.contrib.auth.models import Group, Permission +from phonenumber_field.formfields import PhoneNumberField +from phonenumber_field.widgets import PhoneNumberInternationalFallbackWidget + from crispy_forms.helper import FormHelper from crispy_forms.layout import Submit, Field, Layout, Row, Column from crispy_forms.bootstrap import InlineCheckboxes @@ -21,8 +23,6 @@ class CustomCheckbox(Field): template = 'core/custom_checkbox.html' -# pylint: disable=I0011,E1305 - class DuplicatePatientForm(Form): first_name = CharField(label='First Name') @@ -35,12 +35,22 @@ def __init__(self, *args, **kwargs): self.helper.add_input(Submit('submit', 'Submit')) +class PatientPhoneNumberForm(ModelForm): + + class Meta: + model = models.PatientPhoneNumber + exclude = ['patient'] + + class PatientForm(ModelForm): class Meta(object): model = models.Patient - exclude = ['demographics'] - if not settings.OSLER_DISPLAY_CASE_MANAGERS: - exclude.append('case_managers') + exclude = ( + ['demographics', 'phone'] + + [f'alternate_phone_{i}' for i in range(1,5)] + + [f'alternate_phone_{i}_owner' for i in range(1,5)] + + ['case_managers'] if settings.OSLER_DISPLAY_CASE_MANAGERS else [] + ) if settings.OSLER_DISPLAY_CASE_MANAGERS: case_managers = ModelMultipleChoiceField( @@ -51,6 +61,16 @@ class Meta(object): .order_by("last_name") ) + phone = PhoneNumberField( + widget=PhoneNumberInternationalFallbackWidget, + required=False + ) + + description = CharField( + label='Phone Label', + required=False + ) + def __init__(self, *args, **kwargs): super(PatientForm, self).__init__(*args, **kwargs) @@ -59,34 +79,22 @@ def __init__(self, *args, **kwargs): self.helper.form_class = 'form-horizontal' self.helper.label_class = 'col-lg-2' self.helper.field_class = 'col-lg-8' - self.fields['phone'].widget.attrs['autofocus'] = True + self.fields['middle_name'].widget.attrs['autofocus'] = True self.helper['languages'].wrap(InlineCheckboxes) self.helper['ethnicities'].wrap(InlineCheckboxes) self.helper.add_input(Submit('submit', 'Submit')) self.fields['address'].widget.attrs = {'placeholder': settings.OSLER_DEFAULT_ADDRESS} + def clean(self): cleaned_data = super(ModelForm, self).clean() - N_ALTS = 5 - - alt_phones = ["alternate_phone_" + str(i) for i in range(1, N_ALTS)] - alt_owners = [phone + "_owner" for phone in alt_phones] - - for (alt_phone, alt_owner) in zip(alt_phones, alt_owners): - - if cleaned_data.get(alt_owner) and not cleaned_data.get(alt_phone): - self.add_error( - alt_phone, - "An Alternate Phone is required" + - " if a Alternate Phone Owner is specified") - - if cleaned_data.get(alt_phone) and not cleaned_data.get(alt_owner): - self.add_error( - alt_owner, - "An Alternate Phone Owner is required" + - " if a Alternate Phone is specified") + if cleaned_data.get(description) and not cleaned_data.get(phone): + self.add_error( + description, + "Phone number is required if a description is provided." + ) class AbstractActionItemForm(ModelForm): @@ -125,13 +133,14 @@ class Meta(object): model = User fields = [ 'name', - 'first_name', - 'last_name', - 'phone', - 'languages', - 'gender', + 'first_name', + 'last_name', + 'phone', + 'languages', + 'gender', 'groups' ] + widgets = {'phone': PhoneNumberInternationalFallbackWidget} def __init__(self, *args, **kwargs): super(UserInitForm, self).__init__(*args, **kwargs) diff --git a/osler/core/migrations/0008_patientphonenumber.py b/osler/core/migrations/0008_patientphonenumber.py new file mode 100644 index 00000000..8eaae595 --- /dev/null +++ b/osler/core/migrations/0008_patientphonenumber.py @@ -0,0 +1,27 @@ +# Generated by Django 3.1.2 on 2021-01-17 04:58 + +from django.db import migrations, models +import django.db.models.deletion +import phonenumber_field.modelfields + + +class Migration(migrations.Migration): + + dependencies = [ + ('core', '0007_make_encounters'), + ] + + operations = [ + migrations.CreateModel( + name='PatientPhoneNumber', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('phone_number', phonenumber_field.modelfields.PhoneNumberField(max_length=128, region=None)), + ('description', models.CharField(blank=True, max_length=256)), + ('patient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='phone_number_set', to='core.patient')), + ], + options={ + 'unique_together': {('patient', 'description'), ('patient', 'phone_number')}, + }, + ), + ] diff --git a/osler/core/models.py b/osler/core/models.py index 55e6b84c..0a9c3dd1 100644 --- a/osler/core/models.py +++ b/osler/core/models.py @@ -12,6 +12,7 @@ from simple_history.models import HistoricalRecords from adminsortable.models import SortableMixin +from phonenumber_field.modelfields import PhoneNumberField from osler.core import validators from osler.core import utils @@ -37,6 +38,35 @@ def short_name(self): return self.name[0] +class PatientPhoneNumber(models.Model): + """A phone number for a patient. + + Tracks a "description" for each phone number, which is a free text + field intended to be used for something like "cell" or "home". + """ + + class Meta: + unique_together = ( + ('patient', 'description'), + ('patient', 'phone_number'), + ) + + patient = models.ForeignKey( + 'patient', + related_name='phone_number_set', + on_delete=models.CASCADE + ) + + # phone number field from django-phonenumber-field + phone_number = PhoneNumberField() + + description = models.CharField( + max_length=256, blank=True) + + def __str__(self): + return "%s (%s)" % (self.phone_number, description) + + class ContactMethod(models.Model): '''Simple text-contiaining class for storing the method of contacting a patient for followup followed up with (i.e. phone, email, etc.)''' diff --git a/osler/core/views.py b/osler/core/views.py index fb61c9ee..57d4d55c 100644 --- a/osler/core/views.py +++ b/osler/core/views.py @@ -223,6 +223,13 @@ class PatientCreate(FormView): def form_valid(self, form): pt = form.save() pt.save() + + PatientPhoneNumber.objects.create( + patient=pt, + phone_number=form['phone'], + description=form['description'] + ) + return HttpResponseRedirect(reverse("demographics-create", args=(pt.id,))) @@ -230,6 +237,10 @@ def get_initial(self): initial = super(PatientCreate, self).get_initial() initial.update(utils.get_names_from_url_query_dict(self.request)) + # these have to be populated here rather than as defaults in the + # model or in the default parameters of the form fields because + # that code gets executed only once, which means it is not responsive + # to changes in the settings. initial['city'] = settings.OSLER_DEFAULT_CITY initial['state'] = settings.OSLER_DEFAULT_STATE initial['zip_code'] = settings.OSLER_DEFAULT_ZIP_CODE diff --git a/osler/users/migrations/0005_user_model_phone_phase_1.py b/osler/users/migrations/0005_user_model_phone_phase_1.py new file mode 100644 index 00000000..e92128e5 --- /dev/null +++ b/osler/users/migrations/0005_user_model_phone_phase_1.py @@ -0,0 +1,39 @@ +# Generated by Django 3.1.2 on 2021-01-17 05:00 + +from django.db import migrations +from phonenumber_field.modelfields import PhoneNumberField + + +class Migration(migrations.Migration): + + dependencies = [ + ('users', '0004_auto_20201114_1258'), + ] + + operations = [ + # first, rename "phone" to "phone_old". We will retain this data + # and use the shell to copy the data into the new "phone" parameter + # which will be more structured + migrations.RenameField( + model_name='historicaluser', + old_name='phone', + new_name='phone_old', + ), + migrations.RenameField( + model_name='user', + old_name='phone', + new_name='phone_old', + ), + + # now create a new PhoneNumberField named phone that's just empty. + migrations.AddField( + model_name='historicaluser', + name='phone', + field=PhoneNumberField(blank=True, max_length=128, null=True, region=None), + ), + migrations.AddField( + model_name='user', + name='phone', + field=PhoneNumberField(blank=True, max_length=128, null=True, region=None), + ), + ] diff --git a/osler/users/models.py b/osler/users/models.py index e88bb38a..0c7566b7 100644 --- a/osler/users/models.py +++ b/osler/users/models.py @@ -3,6 +3,8 @@ from django.urls import reverse from django.utils.translation import gettext_lazy as _ +from phonenumber_field.modelfields import PhoneNumberField + from simple_history.models import HistoricalRecords from osler.core import validators @@ -16,13 +18,14 @@ class Meta: # more inclusive of name patterns around the world name = models.CharField(_("Preferred name"), blank=True, max_length=255) - phone = models.CharField(max_length=40, null=True, blank=True) + phone = PhoneNumberField(null=True, blank=True) + phone_old = models.CharField(max_length=40, null=True, blank=True) languages = models.ManyToManyField( "core.Language", help_text="Specify here languages that are spoken at a " - "level sufficient to be used for medical " - "communication.") + "level sufficient to be used for medical " + "communication.") gender = models.ForeignKey("core.Gender", null=True, on_delete=models.PROTECT) history = HistoricalRecords() diff --git a/requirements/base.txt b/requirements/base.txt index 354fba96..328e70ef 100644 --- a/requirements/base.txt +++ b/requirements/base.txt @@ -16,7 +16,8 @@ django-crispy-forms==1.9.2 # https://github.com/django-crispy-forms/django-cris django-redis==4.12.1 # https://github.com/jazzband/django-redis django-bootstrap3==14.2.0 django-simple-history==2.12.0 -django-admin-sortable==2.2.3 #https://github.com/alsoicode/django-admin-sortable +django-admin-sortable==2.2.3 # https://github.com/alsoicode/django-admin-sortable +django-phonenumber-field[phonenumbers]==5.0.0 # https://github.com/stefanfoulis/django-phonenumber-field # Django REST Framework djangorestframework==3.12.1 # https://github.com/encode/django-rest-framework From 85f24150558ed7cfbf02e6202d93bf7413f82753 Mon Sep 17 00:00:00 2001 From: "Justin R. Porter" Date: Sat, 16 Jan 2021 23:46:51 -0600 Subject: [PATCH 2/4] fix all tests. --- osler/core/forms.py | 2 +- osler/core/tests/factories.py | 4 ++-- osler/core/tests/test_forms.py | 31 ++++++++----------------------- osler/core/tests/test_views.py | 6 ++++++ osler/core/views.py | 16 +++++++++++----- 5 files changed, 28 insertions(+), 31 deletions(-) diff --git a/osler/core/forms.py b/osler/core/forms.py index b7105e5a..1ba93351 100644 --- a/osler/core/forms.py +++ b/osler/core/forms.py @@ -90,7 +90,7 @@ def clean(self): cleaned_data = super(ModelForm, self).clean() - if cleaned_data.get(description) and not cleaned_data.get(phone): + if cleaned_data.get('description') and not cleaned_data.get('phone'): self.add_error( description, "Phone number is required if a description is provided." diff --git a/osler/core/tests/factories.py b/osler/core/tests/factories.py index 1df1d238..e7bcfc04 100644 --- a/osler/core/tests/factories.py +++ b/osler/core/tests/factories.py @@ -84,8 +84,8 @@ class Meta: first_name = "Juggie" last_name = "Brodeltein" middle_name = "Bayer" - phone = '+49 178 236 5288', - languages = factory.SubFactory(LanguageFactory), + phone = factory.Faker('phone_number') + languages = factory.SubFactory(LanguageFactory) gender = factory.SubFactory(GenderFactory) address = 'Schulstrasse 9' city = 'Munich' diff --git a/osler/core/tests/test_forms.py b/osler/core/tests/test_forms.py index f729cc6b..b308bb91 100644 --- a/osler/core/tests/test_forms.py +++ b/osler/core/tests/test_forms.py @@ -57,6 +57,14 @@ def setUp(self): self.valid_pt_dict = factory.build( dict, FACTORY_CLASS=factories.PatientFactory) + print(self.valid_pt_dict) + + def phone_description_only_when_phone_provided(self): + + del self.valid_pt_dict['phone'] + form = forms.PatientForm(data=self.valid_pt_dict) + assert len(form['description'].errors) > 0 + def test_form_casemanager_options(self): """PatientForm only offers valid case managers as options. @@ -105,26 +113,3 @@ def test_form_casemanager_options(self): form_data['case_managers'] = [pvds[2].pk] form = forms.PatientForm(data=form_data) assert len(form['case_managers'].errors) == 0 - - def test_missing_alt_phone(self): - '''Missing the alternative phone w/o alt phone owner should fail.''' - form_data = self.valid_pt_dict - - form_data['alternate_phone_1_owner'] = "Jamal" - # omit 'alternate_phone', should get an error - - form = forms.PatientForm(data=form_data) - - # and expect an error to be on the empty altphone field - self.assertNotEqual(len(form['alternate_phone_1'].errors), 0) - - def test_missing_alt_phone_owner(self): - '''Missing the alt phone owner w/o alt phone should fail.''' - form_data = self.valid_pt_dict - - form_data['alternate_phone_1'] = "4258612322" - # omit 'alternate_phone', should get an error - - form = forms.PatientForm(data=form_data) - # we expect errors on the empty alternate_phone_1_owner field - self.assertNotEqual(len(form['alternate_phone_1_owner'].errors), 0) diff --git a/osler/core/tests/test_views.py b/osler/core/tests/test_views.py index 76c78a6d..71b6505c 100644 --- a/osler/core/tests/test_views.py +++ b/osler/core/tests/test_views.py @@ -315,6 +315,8 @@ def test_can_intake_pt(self): new_pt = models.Patient.objects.last() for param in submitted_pt: + # these are fk relationships, shouldn't be checked this way + if param == 'phone' or param == 'description': continue try: self.assertEqual(str(submitted_pt[param]), str(getattr(new_pt, param))) @@ -323,6 +325,10 @@ def test_can_intake_pt(self): getattr(new_pt, param).all()): self.assertEqual(x, y) + assert new_pt.phone_number_set.count() == 1 + assert new_pt.phone_number_set.first().phone_number != '' + assert new_pt.phone_number_set.first().description == '' + # new patients should be marked as inactive assert not new_pt.get_status().is_active diff --git a/osler/core/views.py b/osler/core/views.py index 57d4d55c..c6c59acb 100644 --- a/osler/core/views.py +++ b/osler/core/views.py @@ -224,11 +224,17 @@ def form_valid(self, form): pt = form.save() pt.save() - PatientPhoneNumber.objects.create( - patient=pt, - phone_number=form['phone'], - description=form['description'] - ) + if form.cleaned_data['phone']: + if form.cleaned_data['description']: + kwargs = {'description': form.cleaned_data['description']} + else: + kwargs = {} + + core_models.PatientPhoneNumber.objects.create( + patient=pt, + phone_number=form.cleaned_data['phone'], + **kwargs + ) return HttpResponseRedirect(reverse("demographics-create", args=(pt.id,))) From bf063704b4810265335f7301874b84be8fb4e3f9 Mon Sep 17 00:00:00 2001 From: "Justin R. Porter" Date: Sun, 17 Jan 2021 23:06:46 -0600 Subject: [PATCH 3/4] fix views, modify tests. --- local.yml | 6 ++-- osler/core/forms.py | 15 ++++++++-- osler/core/models.py | 12 ++++---- osler/core/tests/factories.py | 16 ++++++++++- osler/core/tests/test_views.py | 26 +++++++++++++++++ osler/core/urls.py | 4 +++ osler/core/views.py | 36 ++++++++++++++++++++++-- osler/templates/core/patient_detail.html | 16 +++++++---- 8 files changed, 111 insertions(+), 20 deletions(-) diff --git a/local.yml b/local.yml index ec5f1f79..0b8ad8a6 100644 --- a/local.yml +++ b/local.yml @@ -14,7 +14,7 @@ services: depends_on: - postgres volumes: - - .:/app + - .:/app:delegated env_file: - ./.envs/.local/.django - ./.envs/.local/.postgres @@ -31,8 +31,8 @@ services: image: osler_production_postgres container_name: postgres volumes: - - local_postgres_data:/var/lib/postgresql/data - - local_postgres_data_backups:/backups + - local_postgres_data:/var/lib/postgresql/data:cached + - local_postgres_data_backups:/backups:cached env_file: - ./.envs/.local/.postgres diff --git a/osler/core/forms.py b/osler/core/forms.py index 1ba93351..9595be58 100644 --- a/osler/core/forms.py +++ b/osler/core/forms.py @@ -1,7 +1,7 @@ '''Forms for the Oser core components.''' from django.forms import ( Form, CharField, ModelForm, EmailField, CheckboxSelectMultiple, - ModelMultipleChoiceField, CheckboxInput) + ModelMultipleChoiceField, CheckboxInput, HiddenInput) from django.contrib.auth.forms import AuthenticationForm from django.conf import settings @@ -39,7 +39,18 @@ class PatientPhoneNumberForm(ModelForm): class Meta: model = models.PatientPhoneNumber - exclude = ['patient'] + fields = ['phone_number', 'description', 'patient'] + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + # self.fields['patient'].widget = HiddenInput() + + self.helper = FormHelper(self) + self.helper.form_method = 'post' + self.helper.form_class = 'form-horizontal' + self.helper.label_class = 'col-lg-2' + self.helper.field_class = 'col-lg-4' + self.helper.add_input(Submit('submit', 'Submit')) class PatientForm(ModelForm): diff --git a/osler/core/models.py b/osler/core/models.py index 0a9c3dd1..fc5fa206 100644 --- a/osler/core/models.py +++ b/osler/core/models.py @@ -64,7 +64,7 @@ class Meta: max_length=256, blank=True) def __str__(self): - return "%s (%s)" % (self.phone_number, description) + return "%s (%s)" % (self.phone_number, self.description) class ContactMethod(models.Model): @@ -373,13 +373,11 @@ def last_seen(self): return now().date() def all_phones(self): - '''Returns a list of tuples of the form (phone, owner) of all the - phones associated with this patient.''' + """Returns a list of tuples of the form (phone, owner) of all the + phones associated with this patient.""" - phones = [(self.phone, '')] - phones.extend([(getattr(self, 'alternate_phone_'+str(i)), - getattr(self, 'alternate_phone_'+str(i)+'_owner')) - for i in range(1, 5)]) + phones = [(p.phone_number, p.description) + for p in self.phone_number_set.all()] return phones diff --git a/osler/core/tests/factories.py b/osler/core/tests/factories.py index e7bcfc04..6e2befb6 100644 --- a/osler/core/tests/factories.py +++ b/osler/core/tests/factories.py @@ -42,7 +42,7 @@ class LanguageFactory(DjangoModelFactory): class Meta: model = models.Language - name = factory.Iterator(["English", "German", "Spanish", "Klingon"]) + name = factory.Faker('language_name') class ContactMethodFactory(DjangoModelFactory): @@ -132,6 +132,20 @@ def case_managers(self, create, extracted, **kwargs): self.case_managers.add(manager) +class PatientPhoneNumberFactory(DjangoModelFactory): + + class Meta: + model = models.PatientPhoneNumber + + # frustratingly, PhoneNumberField doesn't support very varied input + # formats, like those produced by faker. We should probably fix this. + # phone_number = factory.Faker('phone_number') + phone_number = '425 243 9115' + + patient = factory.SubFactory(PatientFactory) + description = factory.Faker('text', max_nb_chars=15) + + class DocumentTypeFactory(DjangoModelFactory): class Meta: diff --git a/osler/core/tests/test_views.py b/osler/core/tests/test_views.py index 71b6505c..c7fb55f5 100644 --- a/osler/core/tests/test_views.py +++ b/osler/core/tests/test_views.py @@ -1,6 +1,7 @@ import datetime import json import os +import factory from django.test import TestCase from django.urls import reverse @@ -332,6 +333,31 @@ def test_can_intake_pt(self): # new patients should be marked as inactive assert not new_pt.get_status().is_active + def test_create_phone(self): + + from phonenumber_field.modelfields import PhoneNumber + + pt = factories.PatientFactory() + pt.save() + + pn_data = factory.build( + dict, FACTORY_CLASS=factories.PatientPhoneNumberFactory) + pn_data['patient'] = pt.pk + + url = reverse('core:patient-add-phone', + kwargs={'pk': pt.pk}) + response = self.client.post(url, pn_data) + + assert response.status_code == 302 + assert reverse('core:patient-detail', args=(pt.id,)) in response.url + assert models.PatientPhoneNumber.objects.count() == 1 + + new_pn = models.PatientPhoneNumber.objects.first() + + assert new_pn.patient == pt + assert new_pn.description == pn_data['description'] + assert new_pn.phone_number == pn_data['phone_number'] + class ActionItemTest(TestCase): diff --git a/osler/core/urls.py b/osler/core/urls.py index 57ba5ac1..94b5a6f0 100644 --- a/osler/core/urls.py +++ b/osler/core/urls.py @@ -42,6 +42,10 @@ r'^patient/activate_home/(?P[0-9]+)$', views.patient_activate_home, name='patient-activate-home'), + re_path( + r'^patient/(?P[0-9]+)/add-phone$', + views.PhoneNumberCreate.as_view(), + name='patient-add-phone'), # USER MANAGEMENT re_path( diff --git a/osler/core/views.py b/osler/core/views.py index c6c59acb..7b7e9c0a 100644 --- a/osler/core/views.py +++ b/osler/core/views.py @@ -2,15 +2,16 @@ import collections import datetime -from django.conf import settings from django.apps import apps +from django.conf import settings +from django.db.models import Prefetch +from django.forms import modelformset_factory from django.shortcuts import get_object_or_404, render from django.http import HttpResponseRedirect, HttpResponseServerError from django.views.generic.edit import FormView, UpdateView from django.views.generic.list import ListView from django.urls import reverse from django.core.exceptions import ImproperlyConfigured -from django.db.models import Prefetch from django.utils.http import url_has_allowed_host_and_scheme from django.utils.timezone import now @@ -286,6 +287,37 @@ def form_valid(self, form): args=(pt.id,))) +class PhoneNumberCreate(FormView): + """Create a new phone number for a patient""" + template_name = 'core/form_submission.html' + form_class = forms.PatientPhoneNumberForm + + def get_initial(self): + initial = super().get_initial() + initial['patient'] = self.kwargs['pk'] + return initial + + def get_context_data(self, *args, **kwargs): + + context = super().get_context_data(*args, **kwargs) + context['note_type'] = 'Phone Number' + + if 'pk' in self.kwargs: + context['patient'] = core_models.Patient.objects. \ + get(pk=self.kwargs['pk']) + + return context + + def form_valid(self, form): + form.save() + return super().form_valid(form) + + def get_success_url(self): + pt = get_object_or_404(core_models.Patient, pk=self.kwargs['pk']) + + return reverse("core:patient-detail", args=(pt.id, )) + + def choose_role(request): RADIO_CHOICE_KEY = 'radio-roles' diff --git a/osler/templates/core/patient_detail.html b/osler/templates/core/patient_detail.html index 697f55da..cebce750 100644 --- a/osler/templates/core/patient_detail.html +++ b/osler/templates/core/patient_detail.html @@ -119,13 +119,19 @@

  Demographic Information

Phone Number {% for phone, owner in patient.all_phones %} - {% if phone or owner %} + {% if phone or owner %} + + {{ owner | default:"Primary" }} + {{ phone }} + + {% endif %} + {% endfor %} - {{ owner | default:"Primary" }} - {{ phone }} + + + + - {% endif %} - {% endfor %} From 153c3d3a12e29afd62dcd5cd9a8485e94c5d518a Mon Sep 17 00:00:00 2001 From: "Justin R. Porter" Date: Thu, 11 Mar 2021 09:21:36 -0600 Subject: [PATCH 4/4] fix migrations for patient phone number excision --- .../{0008_patientphonenumber.py => 0009_patientphonenumber.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename osler/core/migrations/{0008_patientphonenumber.py => 0009_patientphonenumber.py} (94%) diff --git a/osler/core/migrations/0008_patientphonenumber.py b/osler/core/migrations/0009_patientphonenumber.py similarity index 94% rename from osler/core/migrations/0008_patientphonenumber.py rename to osler/core/migrations/0009_patientphonenumber.py index 8eaae595..7c1d1fa0 100644 --- a/osler/core/migrations/0008_patientphonenumber.py +++ b/osler/core/migrations/0009_patientphonenumber.py @@ -8,7 +8,7 @@ class Migration(migrations.Migration): dependencies = [ - ('core', '0007_make_encounters'), + ('core', '0008_verbose_name_20210118_1256'), ] operations = [