Skip to content
Snippets Groups Projects
models.py 17.2 KiB
Newer Older
Jacek Lebioda's avatar
Jacek Lebioda committed
from __future__ import unicode_literals

from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User, AnonymousUser
from datetime import timedelta
Jacek Lebioda's avatar
Jacek Lebioda committed
def get_current_year():
    return datetime.datetime.now().year

class Location (models.Model):
    name = models.CharField(max_length=20)

    def __str__(self):
        return "%s" % (self.name)

    def __unicode__(self):
        return "%s" % (self.name)

Jacek Lebioda's avatar
Jacek Lebioda committed
    name = models.CharField(max_length=20)
Jacek Lebioda's avatar
Jacek Lebioda committed

Jacek Lebioda's avatar
Jacek Lebioda committed

Jacek Lebioda's avatar
Jacek Lebioda committed
            return u'<img class="flag-icon" src="%s" />' % (self.image.url)
Jacek Lebioda's avatar
Jacek Lebioda committed

    image_img.short_description = 'Flag icon'
class Subject(models.Model):
Jacek Lebioda's avatar
Jacek Lebioda committed
    SEX_CHOICES_MALE = 'M'
    SEX_CHOICES_FEMALE = 'F'

Jacek Lebioda's avatar
Jacek Lebioda committed
        (SEX_CHOICES_MALE,'Male'),
        (SEX_CHOICES_FEMALE,'Female'),
    SUBJECT_TYPE_CHOICES_CONTROL = 'C'
    SUBJECT_TYPE_CHOICES = (
        (SUBJECT_TYPE_CHOICES_CONTROL,'CONTROL'),
        ('P','PATIENT'),

    def finish_all_visits(self):
        visits = Visit.objects.filter(subject = self, is_finished = False)
        for visit in visits:
            visit.is_finished = True
            visit.save()

    def finish_all_appointments(self):
        appointments = Appointment.objects.filter(visit__subject = self, status = Appointment.APPOINTMENT_STATUS_SCHEDULED)
        for appointment in appointments:
            appointment.status = Appointment.APPOINTMENT_STATUS_CANCELLED
            appointment.save()

    def mark_as_dead(self):
        self.finish_all_visits()
        self.finish_all_appointments()

    def mark_as_rejected(self):
        self.finish_all_visits()
        self.finish_all_appointments()

    sex = models.CharField(max_length=1,
        choices=SEX_CHOICES,
        verbose_name='Sex'
    )
    type = models.CharField(max_length=1,
        choices=SUBJECT_TYPE_CHOICES,
        verbose_name='Type'
    )

    dead = models.BooleanField(
        verbose_name='Dead',
        default= False,
        editable=False
    )
    resigned = models.BooleanField(
        verbose_name='Resigned',
        default= False,
        editable=False
    default_location = models.ForeignKey(Location,
        verbose_name='Default appointment location',
Jacek Lebioda's avatar
Jacek Lebioda committed
    first_name = models.CharField(max_length=50,
        verbose_name='First name'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    last_name = models.CharField(max_length=50,
        verbose_name='Last name'
    )
    languages = models.ManyToManyField(Language,
        verbose_name='Known languages'
    )
    default_written_communication_language = models.ForeignKey(Language,
        null=True,
        blank=True,
        related_name="%(class)s_written_comunication",
        verbose_name='Default language for document generation'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    phone_number = models.CharField(max_length=20,
        verbose_name='Phone number'
    )
    phone_number_2 = models.CharField(max_length=20,
        null=True,
	blank=True,
        verbose_name='Phone number 2'
    )
    phone_number_3 = models.CharField(max_length=20,
        null=True,
	blank=True,
        verbose_name='Phone number 3'
    )
    email = models.EmailField(
Piotr Gawron's avatar
Piotr Gawron committed
        null=True,
Jacek Lebioda's avatar
Jacek Lebioda committed
    date_born = models.DateField(
Piotr Gawron's avatar
Piotr Gawron committed
        null=True,
Jacek Lebioda's avatar
Jacek Lebioda committed
        verbose_name='Date of birth (YYYY-MM-DD)'
    )
    address = models.CharField(max_length=255,
        verbose_name='Address'
    )
    postal_code = models.CharField(max_length=7,
        verbose_name='Postal code'
    )
    city = models.CharField(max_length=50,
        verbose_name='City'
    )
    country = models.CharField(max_length=50,
        verbose_name='Country'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    screening_number = models.CharField(max_length=50,
        verbose_name='Screening number'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    nd_number = models.CharField(max_length=6,
        verbose_name='ND number'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    mpower_id = models.CharField(max_length=20,
        verbose_name='MPower ID'
    )
    comments = models.TextField(max_length=2000,
        verbose_name='Comments'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    date_added = models.DateField(verbose_name='Added on',
        auto_now=True
    )
    referral = models.CharField(max_length=128,
        null=True,
    diagnosis = models.CharField(max_length=128,
        null=True,
        verbose_name='Diagnosis'
    )
    year_of_diagnosis = models.IntegerField(
        default=0,
        null=True,
Jacek Lebioda's avatar
Jacek Lebioda committed
        verbose_name='Year of diagnosis (YYYY)'
    def latest_visit(self):
        visits = self.visit_set.all()
        if len(visits)==0:
            return None
        result = visits[0];
        for visit in visits:
            if (visit.datetime_begin > result.datetime_begin):
                result = visit
        return result

Jacek Lebioda's avatar
Jacek Lebioda committed
        return "%s %s" % (self.first_name, self.last_name)
Jacek Lebioda's avatar
Jacek Lebioda committed
        return "%s %s" % (self.first_name, self.last_name)
class Item (models.Model):
Jacek Lebioda's avatar
Jacek Lebioda committed
    is_fixed = models.BooleanField(
        default=False,
        verbose_name='Is the item fixed?'
    )
    name = models.CharField(max_length=255,
        verbose_name='Name'
    )

    def __str__(self):
        return self.name

    def __unicode__(self):
        return self.name


class Room (models.Model):
Jacek Lebioda's avatar
Jacek Lebioda committed
    equipment = models.ManyToManyField(Item,
        verbose_name='On-site equipment',
    )
    owner = models.CharField(max_length=50,
        verbose_name='Owner'
    )
    address = models.CharField(max_length=255,
        verbose_name='Address'
    )
    city = models.CharField(max_length=50,
        verbose_name='City'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    room_number = models.IntegerField(
        verbose_name='Room number'
    )
    floor = models.IntegerField(
        verbose_name='Floor'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    is_vehicle = models.BooleanField(
        verbose_name='Is a vehicle?'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
        return "%d %s %s" % (self.room_number, self.address, self.city)

    def __unicode__(self):
        return "%d %s %s" % (self.room_number, self.address, self.city)



    DEFAULT_COLOR = '#cfc600'
    DEFAULT_FONT_COLOR = '#00000'
Jacek Lebioda's avatar
Jacek Lebioda committed
    required_equipment = models.ManyToManyField(Item,
        verbose_name='Required equipment',
        blank = True
        verbose_name='Appointment code'
    )
        verbose_name='Appointment description'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    default_duration = models.IntegerField(
        verbose_name='Default duration (in minutes)'
    calendar_color_priority = models.IntegerField(
        verbose_name='Calendar color priority',
        default=1
    )
    calendar_color = models.CharField(max_length=2000,
        verbose_name='Calendar color',
        default=DEFAULT_COLOR
    )
    calendar_font_color = models.CharField(max_length=2000,
        verbose_name='Calendar color',
        default=DEFAULT_FONT_COLOR
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    rest_time = models.IntegerField(
        verbose_name='Suggested rest time',
        default=0
    REQ_ROLE_CHOICES = (
        ('DOCTOR', 'Doctor'),
        ('NURSE', 'Nurse'),
        ('PSYCHOLOGIST', 'Psychologist'),
        ('ANY', 'Any')
    )
    required_worker = models.CharField(max_length=20, choices=REQ_ROLE_CHOICES,
        verbose_name='Type of worker required for appointment',
Jacek Lebioda's avatar
Jacek Lebioda committed
        return self.code
    def __unicode__(self):
Jacek Lebioda's avatar
Jacek Lebioda committed
        return self.code
class Worker (models.Model):
    languages = models.ManyToManyField(Language,
        verbose_name='Known languages'
    )
    locations = models.ManyToManyField(Location,
        verbose_name='Locations'
    )
    appointments = models.ManyToManyField('Appointment', blank=True,
        verbose_name='Appointments'
    )
    user = models.OneToOneField(User, blank=True, null=True,
        verbose_name='Username'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    first_name = models.CharField(max_length=50,
        verbose_name='First name'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    last_name = models.CharField(max_length=50,
        verbose_name='Last name'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    phone_number = models.CharField(max_length=20,
        verbose_name='Phone number'
    )
    unit = models.CharField(max_length=50,
        verbose_name='Unit'
    )
    email = models.EmailField(
        verbose_name='E-mail'
    )
Piotr Gawron's avatar
Piotr Gawron committed
    ROLE_CHOICES_SECRETARY = "SECRETARY"
    ROLE_CHOICES = (
        ('DOCTOR', 'Doctor'),
        ('NURSE', 'Nurse'),
        ('PSYCHOLOGIST', 'Psychologist'),
        ('TECHNICIAN', 'Technician'),
Piotr Gawron's avatar
Piotr Gawron committed
        (ROLE_CHOICES_SECRETARY, 'Secretary')
    role = models.CharField(max_length=20, choices=ROLE_CHOICES,
        verbose_name='Role'
    )
    specialization = models.CharField(max_length=20,
        verbose_name='Specialization'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed

Jacek Lebioda's avatar
Jacek Lebioda committed
    def is_on_leave(self):
        if len(self.holiday_set.filter(datetime_end__gt=datetime.datetime.now(),
                                       datetime_start__lt=datetime.datetime.now())):
    @staticmethod
    def get_details(the_user):
        if the_user.is_authenticated == False:
            return ('Guest', 'Test account')

        person = Worker.objects.filter(user=the_user)
        if len(person) == 0:
            return (the_user.get_full_name(), '<No worker information>')
        else:
            # For get_*_display, see:
            # https://docs.djangoproject.com/en/1.10/topics/db/models/#field-options
            return (str(person[0]), person[0].get_role_display())

    def __str__(self):
        return "%s %s" % (self.first_name, self.last_name)

    def __unicode__(self):
        return "%s %s" % (self.first_name, self.last_name)


class FlyingTeam(models.Model):
    # doctor = models.ForeignKey(Worker, related_name='FlyingTeamDoctor',
    #     verbose_name='Doctor'
    # )
    # nurse = models.ForeignKey(Worker, related_name='FlyingTeamNurse',
    #     verbose_name='Nurse'
    # )
    # psychologist = models.ForeignKey(Worker, related_name='FlyingTeamPsychologist',
    #     verbose_name='Psychologist'
    # )
    # datetime_called = models.DateTimeField(
    #     verbose_name='Created on'
    # )
    # datetime_until = models.DateTimeField(
    #     verbose_name='Disbanded on'
    # )
    #
    # def __str__(self):
    #     return "%s %s %s" % (self.doctor.last_name, self.nurse.last_name, self.psychologist.last_name)
    #
    # def __unicode__(self):
    #     return "%s %s %s" % (self.doctor.last_name, self.nurse.last_name, self.psychologist.last_name)


    place = models.CharField(max_length=50,
        verbose_name='Place',
        return "%s" % (self.place)
    def __unicode__(self):
        return "%s" % (self.place)
class Avaibility(models.Model):
    person = models.ForeignKey(Worker, on_delete=models.CASCADE,
        verbose_name='Worker'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    day_number = models.IntegerField(
        verbose_name='Day of the week'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    available_from = models.TimeField(
        verbose_name='Avaible since'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    available_till = models.TimeField(
        verbose_name='Avaible until'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    is_current = models.BooleanField(
Jacek Lebioda's avatar
Jacek Lebioda committed
        return "%d %s %s" % (self.day_number, self.person.last_name, self.person.first_name)

    def __unicode__(self):
        return "%d %s %s" % (self.day_number, self.person.last_name, self.person.first_name)

Jacek Lebioda's avatar
Jacek Lebioda committed

class Holiday(models.Model):
    person = models.ForeignKey(Worker, on_delete=models.CASCADE,
        verbose_name='Worker'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    datetime_start = models.DateTimeField(
        verbose_name='On leave since'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    datetime_end = models.DateTimeField(
        verbose_name='On leave until'
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
        return "%s %s" % (self.person.first_name, self.person.last_name)

    def __unicode__(self):
        return "%s %s" % (self.person.first_name, self.person.last_name)
class Visit(models.Model):
    subject = models.ForeignKey(Subject, on_delete=models.CASCADE,
        verbose_name='Subject'
    )
    datetime_begin = models.DateTimeField(
        verbose_name='Visit starts at'
    )
    datetime_end = models.DateTimeField(
        verbose_name='Visit ends at'
    ) # Deadline before which all appointments need to be scheduled

    is_finished = models.BooleanField(
        verbose_name='Has ended',
        default=False
    )

    appointment_types = models.ManyToManyField(AppointmentType,
        verbose_name='Requested appointments',
        blank=True,
    )

    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()

        if  (not self.subject.dead) and (not self.subject.resigned):
            visit_started = self.datetime_begin

            time_to_next_visit = datetime.timedelta(days=365)
            if self.subject.type== Subject.SUBJECT_TYPE_CHOICES_CONTROL:
                time_to_next_visit = datetime.timedelta(days=365*3+366)

            Visit.objects.create(
                            subject = self.subject,
                            datetime_begin = visit_started+time_to_next_visit,
                            datetime_end = visit_started+time_to_next_visit+datetime.timedelta(days=93)
                            )
Jacek Lebioda's avatar
Jacek Lebioda committed

class Appointment(models.Model):
    APPOINTMENT_STATUS_SCHEDULED = 'SCHEDULED';
    APPOINTMENT_STATUS_FINISHED = 'FINISHED';
    APPOINTMENT_STATUS_CANCELLED = 'CANCELLED';
    APPOINTMENT_STATUS_NO_SHOW = 'NO_SHOW';
    APPOINTMENT_STATUS_CHOICES = (
        (APPOINTMENT_STATUS_SCHEDULED, 'Scheduled'),
        (APPOINTMENT_STATUS_FINISHED, 'Finished'),
        (APPOINTMENT_STATUS_CANCELLED, 'Cancelled'),
        (APPOINTMENT_STATUS_NO_SHOW, 'No Show'),
Jacek Lebioda's avatar
Jacek Lebioda committed
    flying_team = models.ForeignKey(FlyingTeam,
        verbose_name='Flying team (if applicable)',
        null=True, blank=True
Jacek Lebioda's avatar
Jacek Lebioda committed
    worker_assigned = models.ForeignKey(Worker,
        verbose_name='Worker conducting the assessment (if applicable)',
        null=True, blank=True
    )
    appointment_types = models.ManyToManyField(AppointmentType,
        verbose_name='Appointment types',
    )
    room = models.ForeignKey(Room,
        verbose_name='Room ID',
        null=True,
        blank=True
    location = models.ForeignKey(Location,
        verbose_name='Location',
    )
    visit = models.ForeignKey(Visit,
        verbose_name='Visit ID'
    )
    comment = models.TextField(max_length=1024,
        verbose_name='Comment',
        null=True,
        blank=True
    )
Jacek Lebioda's avatar
Jacek Lebioda committed
    datetime_when = models.DateTimeField(
        verbose_name='Appointment on',
        null=True, blank=True
Jacek Lebioda's avatar
Jacek Lebioda committed
    length = models.IntegerField(
        verbose_name='Appointment length (in minutes)'
    )#Potentially redundant; but can be used to manually adjust appointment's length

    status = models.CharField(max_length=20, choices=APPOINTMENT_STATUS_CHOICES,
        verbose_name='Status',
        editable=False,
        default=APPOINTMENT_STATUS_SCHEDULED
    def mark_as_finished(self):
        self.status = Appointment.APPOINTMENT_STATUS_FINISHED
    def mark_as_cancelled(self):
        self.status = Appointment.APPOINTMENT_STATUS_CANCELLED
        self.save()

    def mark_as_no_show(self):
        self.status = Appointment.APPOINTMENT_STATUS_NO_SHOW
    def datetime_until(self):
        if self.datetime_when is None:
            return None
        else:
            return self.datetime_when + timedelta(minutes=max(self.length, 15))

    def color(self):
        result = AppointmentType.DEFAULT_COLOR
        priority = 1000000
        for type in self.appointment_types.all():
            if type.calendar_color_priority<priority:
                priority=type.calendar_color_priority
                result = type.calendar_color
        return result

    def font_color(self):
        result = AppointmentType.DEFAULT_FONT_COLOR
        priority = 1000000
        for type in self.appointment_types.all():
            if type.calendar_color_priority<priority:
                priority=type.calendar_color_priority
                result = type.calendar_font_color
        return result

    def title(self):
        if self.visit.subject.screening_number=="---":
            return self.comment.replace("\n", ";").replace("\r", ";")
            title = self.visit.subject.first_name + " " + self.visit.subject.last_name + " type: "
            for type in self.appointment_types.all():
                title += type.code+", "
            return title