371 lines
12 KiB
Python
371 lines
12 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
'''
|
|
biomon - Signs monitoring and patient management application
|
|
|
|
Copyright (C) 2015 Entr'ouvert
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
'''
|
|
|
|
|
|
import requests
|
|
|
|
from datetime import datetime
|
|
|
|
from django.views.generic import (TemplateView, FormView, View, ListView,
|
|
CreateView, UpdateView, DeleteView)
|
|
from django.contrib.auth import authenticate, login, logout
|
|
from django.contrib.auth import forms as auth_forms
|
|
from django.http import HttpResponseRedirect
|
|
from django.core.urlresolvers import reverse_lazy
|
|
from django.contrib import messages
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.conf import settings
|
|
from django.http import JsonResponse
|
|
from django.shortcuts import get_object_or_404
|
|
|
|
from . import cbv
|
|
from . import models
|
|
from . import forms
|
|
from . import whisper_backend
|
|
from . import time_utils
|
|
from medibot import models as medibot_models
|
|
|
|
LAST_PATIENT_COOKIE = 'last-patient'
|
|
|
|
|
|
class HomepageView(TemplateView):
|
|
template_name="biomon/homepage.html"
|
|
|
|
|
|
class LoginView(FormView):
|
|
form_class = auth_forms.AuthenticationForm
|
|
template_name = 'biomon/login.html'
|
|
|
|
def form_valid(self, form):
|
|
username = self.request.POST.get('username')
|
|
password = self.request.POST.get('password')
|
|
user = authenticate(username=username, password=password)
|
|
if user is not None:
|
|
if user.is_active:
|
|
login(self.request, user)
|
|
return super(LoginView, self).form_valid(form)
|
|
|
|
def get_success_url(self):
|
|
next_url = self.request.POST.get('next', None)
|
|
if next_url:
|
|
return "%s" % (next_url)
|
|
return reverse_lazy('patient_list')
|
|
|
|
|
|
class LogoutView(View):
|
|
|
|
def get(self, request, *args, **kwargs):
|
|
logout(request)
|
|
return HttpResponseRedirect(reverse_lazy('login'))
|
|
|
|
|
|
class PatientList(ListView):
|
|
model = models.Patient
|
|
|
|
def get_queryset(self):
|
|
return models.Patient.objects.order_by('display_name')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(PatientList, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class PatientCreate(CreateView):
|
|
model = models.Patient
|
|
fields = ['firstname', 'lastname', 'sex', 'birthdate', 'monitoring_place',
|
|
'room', 'emergency_contact', 'regular_doctor', 'medical_comment',
|
|
'enabled']
|
|
|
|
def form_valid(self, form):
|
|
messages.add_message(self.request, messages.INFO, u'Patient créé.')
|
|
return super(PatientCreate, self).form_valid(form)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(PatientCreate, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
class PatientUpdate(UpdateView):
|
|
model = models.Patient
|
|
fields = ['firstname', 'lastname', 'sex', 'birthdate', 'monitoring_place',
|
|
'room', 'emergency_contact', 'regular_doctor', 'medical_comment']
|
|
|
|
|
|
class PatientDetail(cbv.MultiUpdateView):
|
|
model = models.Patient
|
|
forms_classes = {
|
|
'main': forms.MainForm,
|
|
'simple_alert_profile' : forms.SimpleAlertProfileForm,
|
|
't_check' : forms.TemperatureCheckForm,
|
|
'hr_check' : forms.HeartrateCheckForm,
|
|
}
|
|
template_name = "biomon/patient_detail.html"
|
|
success_url = '.'
|
|
|
|
def dispatch(self, *args, **kwargs):
|
|
result = super(PatientDetail, self).dispatch(*args, **kwargs)
|
|
result.set_cookie(LAST_PATIENT_COOKIE, str(self.object.pk),
|
|
max_age=3600*24*365, httponly=True)
|
|
return result
|
|
|
|
def form_valid(self, form):
|
|
if 't_check' in form and form.get('t_check').is_valid():
|
|
form.get('t_check').cleaned_data['patient'] = self.get_object()
|
|
tc = models.TemperatureCheck(**form.get('t_check').cleaned_data)
|
|
tc.save()
|
|
if 'hr_check' in form and form.get('hr_check').is_valid():
|
|
form.get('hr_check').cleaned_data['patient'] = self.get_object()
|
|
hrc = models.HeartrateCheck(**form.get('hr_check').cleaned_data)
|
|
hrc.save()
|
|
messages.add_message(self.request, messages.INFO,
|
|
_(u'Patient record updated.'))
|
|
return super(PatientDetail, self).form_valid(form)
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(PatientDetail, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
def process(subject, metric, values, lookup_range=600):
|
|
backend = whisper_backend.WhisperBackend(subject, metric)
|
|
l = []
|
|
for value in values:
|
|
timestamp = time_utils.unix_time(datetime.combine(value.date, value.time))
|
|
l.append((value, backend.get_closest(timestamp=timestamp, lookup_range=lookup_range)))
|
|
return l
|
|
subject = str(self.get_object().id)
|
|
metric = settings.WHISPER_HEARTRATE_METRIC
|
|
values = models.HeartrateCheck.objects.filter(patient=self.get_object()).order_by('-date').order_by('-time')
|
|
context['hr_checks'] = process(subject, metric, values)
|
|
metric = settings.WHISPER_TEMPERATURE_METRIC
|
|
values = models.TemperatureCheck.objects.filter(patient=self.get_object()).order_by('-date').order_by('-time')
|
|
context['t_checks'] = process(subject, metric, values)
|
|
context['display_alert_profile'] = settings.DISPLAY_ALERT_PROFILE
|
|
context['default_episode_duration'] = settings.DEFAULT_EPISODE_DURATION
|
|
return context
|
|
|
|
|
|
class PatientDelete(DeleteView):
|
|
model = models.Patient
|
|
success_url = reverse_lazy('patient_list')
|
|
|
|
|
|
class PatientUpdateEnabledField(cbv.AjaxableResponseMixin, UpdateView):
|
|
model = models.Patient
|
|
fields = ['enabled']
|
|
|
|
|
|
class AlertCheckView(cbv.AjaxableResponseMixin, UpdateView):
|
|
model = medibot_models.Episode
|
|
fields = ['checked']
|
|
success_url = '.'
|
|
|
|
def form_valid(self, form):
|
|
form.instance.checker = self.request.user
|
|
return super(AlertCheckView, self).form_valid(form)
|
|
|
|
|
|
class AllAlertCheckPatientView(View):
|
|
def post(self, request, *args, **kwargs):
|
|
patient = None
|
|
#XXX list exceptions or don't catch, it is better to crash
|
|
try:
|
|
patient = models.Patient.objects.get(id=self.kwargs.get('pk', None))
|
|
except:
|
|
return JsonResponse({'message': 'patient not found',})
|
|
medibot_models.Episode.objects.filter(patient=patient).update(checked=True, checker=request.user)
|
|
return JsonResponse({'message': 'ok',})
|
|
|
|
|
|
class AllAlertsView(TemplateView):
|
|
template_name="biomon/alerts.html"
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(AllAlertsView, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class AllAlertsCheckView(View):
|
|
def post(self, request, *args, **kwargs):
|
|
medibot_models.Episode.objects.all().update(checked=True, checker=request.user)
|
|
return JsonResponse({'message': 'ok',})
|
|
|
|
|
|
class RoomList(ListView):
|
|
model = models.Room
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(RoomList, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class RoomCreate(CreateView):
|
|
model = models.Room
|
|
success_url = reverse_lazy('room_list')
|
|
fields = ['number']
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(RoomCreate, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class RoomUpdate(UpdateView):
|
|
model = models.Room
|
|
success_url = reverse_lazy('room_list')
|
|
fields = ['number']
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(RoomUpdate, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class RoomDelete(DeleteView):
|
|
model = models.Room
|
|
success_url = reverse_lazy('room_list')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(RoomDelete, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class RoomNumberToPid(View):
|
|
def get(self, request, *args, **kwargs):
|
|
room = get_object_or_404(models.Room,
|
|
number=kwargs.get('number', None))
|
|
infos = {'pid' : ''}
|
|
try:
|
|
infos = {'pid' : room.patient.id}
|
|
except models.Patient.DoesNotExist:
|
|
pass
|
|
return JsonResponse(infos)
|
|
|
|
|
|
class ReaderList(ListView):
|
|
model = models.Reader
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(ReaderList, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class ReaderCreate(CreateView):
|
|
model = models.Reader
|
|
success_url = reverse_lazy('reader_list')
|
|
fields = ['ip_address', 'management_port', 'room']
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(ReaderCreate, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class ReaderUpdate(UpdateView):
|
|
model = models.Reader
|
|
success_url = reverse_lazy('reader_list')
|
|
fields = ['ip_address', 'management_port', 'room']
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(ReaderUpdate, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class ReaderDelete(DeleteView):
|
|
model = models.Reader
|
|
success_url = reverse_lazy('reader_list')
|
|
|
|
def get_context_data(self, **kwargs):
|
|
context = super(ReaderDelete, self).get_context_data(**kwargs)
|
|
try:
|
|
context['lastpatient'] = models.Patient.objects.get(
|
|
pk=int(self.request.COOKIES.get(LAST_PATIENT_COOKIE)))
|
|
except:
|
|
pass
|
|
return context
|
|
|
|
|
|
class ReaderConfig(View):
|
|
def get(self, request, *args, **kwargs):
|
|
reader = get_object_or_404(models.Reader,
|
|
id=kwargs.get('pk', None))
|
|
infos = {'status' : 'unknown'}
|
|
target = "http://{}:{}/config".format(reader.ip_address,
|
|
reader.management_port)
|
|
response = None
|
|
try:
|
|
response = requests.get(target)
|
|
except requests.ConnectionError:
|
|
infos['status'] = 'disconnected'
|
|
else:
|
|
infos['status'] = 'connected'
|
|
if response.status_code != 404:
|
|
infos['config'] = response.json()
|
|
return JsonResponse(infos)
|