Skip to content

Commit

Permalink
Merge 542c1fa into 57c276a
Browse files Browse the repository at this point in the history
  • Loading branch information
fredkingham committed May 10, 2023
2 parents 57c276a + 542c1fa commit 45116e4
Show file tree
Hide file tree
Showing 8 changed files with 217 additions and 18 deletions.
15 changes: 15 additions & 0 deletions elcid/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,21 @@ def create(self, request):
status_code=status.HTTP_201_CREATED
)

@item_from_pk
def destroy(self, request, item):
"""
Delete a blood culture isolate.
Update the updated* and previous_mrn fields of the parent
blood culture set.
"""
blood_culture_set = item.blood_culture_set
blood_culture_set.set_updated_by_id(None, request.user)
blood_culture_set.set_updated(None, request.user)
if blood_culture_set.previous_mrn:
blood_culture_set.previous_mrn = None
blood_culture_set.save()
return super().destroy(request, item.id)


class AddToServiceViewSet(LoginRequiredViewset):
basename = 'add_to_service'
Expand Down
7 changes: 6 additions & 1 deletion elcid/assets/js/elcid/controllers/blood_culture_panel.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,15 @@ angular.module('opal.controllers').controller('BloodCulturePanelCtrl', function(
var deferred = $q.defer();
$http.get("/api/v0.1/blood_culture_set/" + bcs.id + "/").then(function(result){
var bcs_idx = _.findIndex($scope.patient.blood_culture_set, {id: bcs.id})
// when we update isolates we update the fields the previous_mrn, updated*
// fields on the set.
$scope.patient.blood_culture_set[bcs_idx].isolates = result.data.isolates;
$scope.patient.blood_culture_set[bcs_idx].previous_mrn = result.data.previous_mrn;
$scope.patient.blood_culture_set[bcs_idx].updated = result.data.updated;
$scope.patient.blood_culture_set[bcs_idx].updated_by_id = result.data.updated_by_id;
deferred.resolve();
})

return deferred.promise;
};
});
});
13 changes: 11 additions & 2 deletions elcid/assets/js/elcid/services/blood_culture_isolate.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,20 @@ angular.module('opal.services').service(
this.isolateUrl = baseUrl;
this.editing = {
consistency_token: "",
blood_culture_set_id: blood_culture_set.id
blood_culture_set_id: blood_culture_set.id,
}
this.isNew = true;
}

// we consider an isolate and a set to be one thing
// for the purposes of created*/updated*/previous_mrn
// even if when we are creating a new isolate.
this.editing.created = blood_culture_set.created;
this.editing.created_by_id = blood_culture_set.created_by_id;
this.editing.updated = blood_culture_set.updated;
this.editing.updated_by_id = blood_culture_set.updated_by_id;
this.editing.previous_mrn = blood_culture_set.previous_mrn;

var isolate = this;

Referencedata.load().then(function(referenceData){
Expand Down Expand Up @@ -101,4 +110,4 @@ recently changed it - refresh the page and try again');
}

return BloodCultureIsolate;
});
});
56 changes: 56 additions & 0 deletions elcid/migrations/0069_blood_culture_updated_created.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
BloodCultureIsolate will no longer have created*/updated* attributes
and instead we will use the BloodCultureSet created*/updated*
If the isolate has been updated more recently than the set, make
sure the set has the most recent data.
"""
# Generated by Django 2.2.16 on 2023-05-10 07:39

from django.db import migrations

def forwards(apps, schema_editor):
"""
If the isolate has been updated more recently than the blood culture set
copy the isolates updated/updated_by onto the set.
"""
BloodCultureIsolate = apps.get_model('elcid', 'BloodCultureIsolate')
isolates = BloodCultureIsolate.objects.exclude(updated=None).select_related('blood_culture_set')
for isolate in isolates:
if isolate.blood_culture_set.updated is None:
bcs = isolate.blood_culture_set
bcs.updated = isolate.updated
bcs.updated_by = isolate.updated_by
bcs.save()
elif isolate.updated > isolate.blood_culture_set.updated:
bcs = isolate.blood_culture_set
bcs.updated = isolate.updated
bcs.updated_by = isolate.updated_by
bcs.save()

def backwards(apps, schema_editor):
"""
As defaults copy the created*/updated* fields back onto the blood culture
set.
"""
BloodCultureSet = apps.get_model('elcid', 'BloodCultureSet')
for bcs in BloodCultureSet.objects.all():
bcs.isolates.update(
created=bcs.created,
created_by=bcs.created_by,
updated=bcs.updated,
updated_by=bcs.updated_by,
)


class Migration(migrations.Migration):

dependencies = [
('elcid', '0068_remove_mergedmrn_upstream_merge_datetime'),
]

operations = [
migrations.RunPython(
forwards, backwards
)
]
29 changes: 29 additions & 0 deletions elcid/migrations/0070_auto_20230510_0750.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 2.2.16 on 2023-05-10 07:50

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('elcid', '0069_blood_culture_updated_created'),
]

operations = [
migrations.RemoveField(
model_name='bloodcultureisolate',
name='created',
),
migrations.RemoveField(
model_name='bloodcultureisolate',
name='created_by',
),
migrations.RemoveField(
model_name='bloodcultureisolate',
name='updated',
),
migrations.RemoveField(
model_name='bloodcultureisolate',
name='updated_by',
),
]
31 changes: 30 additions & 1 deletion elcid/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,6 @@ class Meta:
class BloodCultureIsolate(
omodels.UpdatesFromDictMixin,
omodels.ToDictMixin,
omodels.TrackedModel,
models.Model
):
AEROBIC = "Aerobic"
Expand Down Expand Up @@ -663,6 +662,36 @@ class BloodCultureIsolate(
)
notes = models.TextField(blank=True)

def update_from_dict(self, data, user, *args, **kwargs):
"""
Changes updated*/previousMRN on the related
BloodCultureSet when the isolate is updated.
"""
# created*/updated*/previous_mrn are hoisted onto
# the blood culture isolate from the blood culture set
# by the blood_culture_isolate.js, they are not fields
# on the isolate so need to be removed.
blood_culture_set_fields = [
"previous_mrn", "created", "created_by_id", "updated", "updated_by_id"
]
for field in blood_culture_set_fields:
if field in data:
data.pop(field)

blood_culture_set_id = data.get('blood_culture_set_id')
blood_culture_set = BloodCultureSet.objects.get(
id=blood_culture_set_id
)
# data is ignored by the below for functions
blood_culture_set.set_updated_by_id(data, user)
blood_culture_set.set_updated(data, user)
blood_culture_set.save()

if blood_culture_set.previous_mrn:
blood_culture_set.previous_mrn = None
blood_culture_set.save()
return super().update_from_dict(data, user, *args, **kwargs)

@classmethod
def get_api_name(cls):
return camelcase_to_underscore(cls._meta.object_name)
Expand Down
38 changes: 24 additions & 14 deletions elcid/test/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
from django.utils import timezone
from django.test import override_settings
from rest_framework.reverse import reverse
from django.contrib.auth.models import User
from django.conf import settings

from elcid import models as emodels
from elcid import patient_lists
Expand Down Expand Up @@ -600,8 +602,6 @@ def test_retrieve_with_isolates(self):
'date_positive': datetime.date(2019, 5, 9),
'blood_culture_set_id': 1,
'consistency_token': '111',
'created': None,
'created_by_id': None,
'gpc_staph': '',
'gpc_strep': '',
'gram_stain': 'Gram -ve Rods',
Expand All @@ -612,8 +612,6 @@ def test_retrieve_with_isolates(self):
'sepsityper_organism': '',
'resistance': [],
'sensitivities': [],
'updated': None,
'updated_by_id': None
}],
'lab_number': '111',
'patient_id': 1,
Expand Down Expand Up @@ -746,10 +744,10 @@ def test_update_with_empty_isolates(self):
class BloodCultureIsolateTestCase(OpalTestCase):
def setUp(self):
positive = datetime.date(2019, 5, 8)
yesterday = positive - datetime.timedelta(1)
self.yesterday = positive - datetime.timedelta(1)
patient, _ = self.new_patient_and_episode_please()
self.bcs = emodels.BloodCultureSet.objects.create(
date_ordered=yesterday,
date_ordered=self.yesterday,
source="Hickman",
lab_number="111",
patient=patient
Expand Down Expand Up @@ -790,17 +788,13 @@ def test_retrieve(self):
'resistance': [],
'sepsityper_organism': '',
'gpc_strep': '',
'created_by_id': None,
'updated': None,
'id': self.isolate.id,
'gram_stain': 'Gram -ve Rods',
'date_positive': datetime.date(2019, 5, 8),
'sensitivities': [],
'updated_by_id': None,
'quick_fish': 'Negative',
'blood_culture_set_id': 1,
'gpc_staph': '',
'created': None,
'organism': '',
'consistency_token': '111',
'aerobic_or_anaerobic': 'Aerobic'
Expand All @@ -819,17 +813,13 @@ def test_list(self):
'resistance': [],
'date_positive': datetime.date(2019, 5, 8),
'gpc_strep': '',
'created_by_id': None,
'updated': None,
'id': self.isolate.id,
'gram_stain': 'Gram -ve Rods',
'sensitivities': [],
'sepsityper_organism': '',
'updated_by_id': None,
'quick_fish': 'Negative',
'blood_culture_set_id': 1,
'gpc_staph': '',
'created': None,
'organism': '',
'consistency_token': '111',
'aerobic_or_anaerobic': 'Aerobic'
Expand Down Expand Up @@ -874,6 +864,9 @@ def test_create(self):
)

def test_update(self):
# created should be updated on the blood culture set
# make sure we start with None
self.assertIsNone(self.bcs.created)
data = {
'id': self.isolate.id,
'notes': '',
Expand Down Expand Up @@ -905,6 +898,23 @@ def test_update(self):
self.assertEqual(
reloaded_isolate.aerobic_or_anaerobic, 'Anerobic'
)
# created should be updated on the blood culture set
self.bcs.created = self.user

def test_delete(self):
self.bcs.updated = self.yesterday
other_user = User.objects.create(username="other user")
self.bcs.updated_by = other_user
self.bcs.save()
self.client.delete(self.detail_url)
self.bcs.refresh_from_db()
# it should be approximately now
self.assertTrue(
self.bcs.updated > timezone.now() - datetime.timedelta(minutes=1)
)
self.assertEqual(self.bcs.updated_by, self.user)



@override_settings(NEW_LAB_TEST_SUMMARY_DISPLAY=True)
class LabTestSummaryTestCase(OpalTestCase):
Expand Down
46 changes: 46 additions & 0 deletions elcid/test/test_models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import datetime
from unittest import mock
from django.urls import reverse
from django.test import TestCase
from django.utils import timezone
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User
from django.conf import settings
from elcid import episode_categories

from opal.core import exceptions
Expand Down Expand Up @@ -766,3 +769,46 @@ def test_only_one_instance_created(self):
self.episode.set_tag_names(["bacteraemia"], self.user)
self.episode.set_tag_names(["bacteraemia"], self.user)
self.assertEqual(self.patient.positivebloodculturehistory_set.count(), 1)


class BloodCultureIsolateTestCase(OpalTestCase):
def setUp(self):
self.patient, _ = self.new_patient_and_episode_please()
self.now = timezone.now()
self.yesterday = self.now - datetime.timedelta(1)
self.bcs = self.patient.bloodcultureset_set.create(
date_ordered=self.yesterday,
source="Hickman",
lab_number="111",
patient=self.patient,
created=self.yesterday,
created_by=self.user,
previous_mrn="123"
)
self.other_user = User.objects.create(
username="other_user"
)

def test_update_from_dict(self):
update_dict = {
"organism": "Aspergillus",
"blood_culture_set_id": self.bcs.id,
"created": self.yesterday,
"created_by_id": self.user.id,
"updated": self.now,
"updated_by_id": self.other_user.id
}
isolate = emodels.BloodCultureIsolate()
isolate.update_from_dict(update_dict, self.other_user)
self.bcs.refresh_from_db()
self.assertEqual(
self.bcs.created.strftime(settings.DATETIME_INPUT_FORMATS[0]),
self.yesterday.strftime(settings.DATETIME_INPUT_FORMATS[0])
)
self.assertEqual(self.bcs.created_by, self.user)
self.assertEqual(
self.bcs.updated.strftime(settings.DATETIME_INPUT_FORMATS[0]),
self.now.strftime(settings.DATETIME_INPUT_FORMATS[0])
)
self.assertEqual(self.bcs.updated_by, self.other_user)
self.assertIsNone(self.bcs.previous_mrn)

0 comments on commit 45116e4

Please sign in to comment.