151 lines
4.9 KiB
Python
151 lines
4.9 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 simplejson as json
|
|
|
|
from datetime import datetime
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from django.db import models
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.utils.translation import ungettext
|
|
from django.core.urlresolvers import reverse
|
|
|
|
|
|
class TimestampedAbstractModel(models.Model):
|
|
"""
|
|
Abstract class used to ensure the creation date setting on recording
|
|
models.
|
|
"""
|
|
creation = models.DateTimeField(_(u'Creation date'), auto_now_add=True)
|
|
|
|
def __unicode__(self):
|
|
return '%s %d %s' % (self.__class__.__name__, self.id, self.creation)
|
|
|
|
def __repr__(self):
|
|
return '<%r>' % unicode(self)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
ordering = ['creation']
|
|
|
|
|
|
class Person(TimestampedAbstractModel):
|
|
SEX = (
|
|
(1, 'Male'),
|
|
(2, 'Female'),
|
|
)
|
|
firstname = models.CharField(_(u'First name'), max_length=512)
|
|
lastname = models.CharField(_(u'Last name'),
|
|
max_length=512, db_index=True)
|
|
display_name = models.CharField(max_length=1025,
|
|
editable=False, db_index=True)
|
|
sex = models.IntegerField(_(u'Sex'), choices=SEX,
|
|
blank=True, null=True)
|
|
birthdate = models.DateField(_(u'Date of birth'),
|
|
null=True, blank=True)
|
|
|
|
class Meta:
|
|
verbose_name = _('Patient')
|
|
verbose_name_plural = _('Patients')
|
|
|
|
@property
|
|
def first_letter(self):
|
|
return self.lastname and self.lastname[0].upper() or ''
|
|
|
|
@property
|
|
def age(self, age_format=None):
|
|
'''
|
|
age < 3 months display months and days
|
|
age < 2 years display months
|
|
age < 6 years display years and months
|
|
else display years.
|
|
'''
|
|
if not self.birthdate:
|
|
return None
|
|
now = datetime.today().date()
|
|
age = relativedelta(now, self.birthdate)
|
|
months = age.years * 12 + age.months
|
|
if months == 0:
|
|
components = []
|
|
elif age.years < 2:
|
|
components = [ungettext(u'%(month)d month', u'%(month)d months',
|
|
months) % {'month': months}]
|
|
else:
|
|
components = [ungettext(u'%(year)d year', u'%(year)d years',
|
|
age.years) % {'year': age.years}]
|
|
if age.months and age.years < 3:
|
|
components.append(ungettext(u'%(month)d month', u'%(month)d months',
|
|
months) % {'month': months})
|
|
# under three months, we display the number of days
|
|
if months < 3 and age.days:
|
|
components.append(ungettext(u'%(day)d day', u'%(day)d days',
|
|
age.days) % {'day': age.days})
|
|
return ' '.join(components)
|
|
|
|
def get_absolute_url(self):
|
|
return reverse('patient_detail', kwargs={'pk': self.pk})
|
|
|
|
def save(self, **kwargs):
|
|
self.display_name = u"{0} {1}".format(self.lastname.title(),
|
|
self.firstname.title())
|
|
super(Person, self).save(**kwargs)
|
|
|
|
def __unicode__(self):
|
|
return self.display_name
|
|
|
|
|
|
class Patient(Person):
|
|
monitoring_place = models.TextField(_(u'Monitoring place'),
|
|
blank=True, null=True)
|
|
simple_alert_profile = models.TextField(_(u'Simple monitoring profile'),
|
|
blank=True, null=True)
|
|
alert_profile = models.TextField(_(u'Monitoring profile'),
|
|
blank=True, null=True)
|
|
medical_comment = models.TextField(_(u'Medical comment'),
|
|
null=True, blank=True)
|
|
enabled = models.BooleanField(_(u'Enabled'), default=True)
|
|
|
|
# XXX: Check well formed alert profile at saving.
|
|
|
|
def get_simple_alert_profile(self):
|
|
if not self.simple_alert_profile:
|
|
return None
|
|
try:
|
|
return json.loads(self.simple_alert_profile)
|
|
except ValueError:
|
|
"Sanitize"
|
|
self.simple_alert_profile = None
|
|
self.save()
|
|
return None
|
|
|
|
def get_alert_profile(self):
|
|
if not self.alert_profile:
|
|
return None
|
|
try:
|
|
return json.loads(self.alert_profile)
|
|
except ValueError:
|
|
"Sanitize"
|
|
self.alert_profile = None
|
|
self.save()
|
|
return None
|