from __future__ import unicode_literals from django.db import models from django.utils import timezone from django.contrib.auth.models import User, AnonymousUser import datetime from datetime import timedelta 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) class Language (models.Model): name = models.CharField(max_length=20) image = models.ImageField() def __str__(self): return self.name def image_img(self): if self.image: return u'<img class="flag-icon" src="%s" />' % (self.image.url) else: return 'No image' image_img.short_description = 'Flag icon' image_img.allow_tags = True class Subject(models.Model): SEX_CHOICES_MALE = 'M' SEX_CHOICES_FEMALE = 'F' SEX_CHOICES = ( (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.dead = True self.save() self.finish_all_visits() self.finish_all_appointments() def mark_as_rejected(self): self.resigned = True self.save() 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', ) first_name = models.CharField(max_length=50, verbose_name='First name' ) last_name = models.CharField(max_length=50, verbose_name='Last name' ) languages = models.ManyToManyField(Language, blank=True, 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' ) phone_number = models.CharField(max_length=20, null=True, blank=True, 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( null=True, blank=True, verbose_name='E-mail' ) date_born = models.DateField( null=True, blank=True, verbose_name='Date of birth (YYYY-MM-DD)' ) address = models.CharField(max_length=255, blank=True, verbose_name='Address' ) postal_code = models.CharField(max_length=7, blank=True, verbose_name='Postal code' ) city = models.CharField(max_length=50, blank=True, verbose_name='City' ) country = models.CharField(max_length=50, verbose_name='Country' ) screening_number = models.CharField(max_length=50, unique=True, verbose_name='Screening number' ) nd_number = models.CharField(max_length=6, blank=True, verbose_name='ND number' ) mpower_id = models.CharField(max_length=20, blank=True, verbose_name='MPower ID' ) comments = models.TextField(max_length=2000, blank=True, verbose_name='Comments' ) date_added = models.DateField(verbose_name='Added on', auto_now=True ) referral = models.CharField(max_length=128, null=True, blank=True, verbose_name='Referred by' ) diagnosis = models.CharField(max_length=128, null=True, blank=True, verbose_name='Diagnosis' ) year_of_diagnosis = models.IntegerField( default=0, null=True, blank=True, 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 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 Item (models.Model): 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): equipment = models.ManyToManyField(Item, verbose_name='On-site equipment', blank=True ) 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' ) room_number = models.IntegerField( verbose_name='Room number' ) floor = models.IntegerField( verbose_name='Floor' ) is_vehicle = models.BooleanField( verbose_name='Is a vehicle?' ) def __str__(self): 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) class AppointmentType (models.Model): DEFAULT_COLOR = '#cfc600' DEFAULT_FONT_COLOR = '#00000' required_equipment = models.ManyToManyField(Item, verbose_name='Required equipment', blank = True ) code = models.CharField(max_length=20, verbose_name='Appointment code' ) description = models.CharField(max_length=2000, verbose_name='Appointment description' ) 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 ) 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', default='ANY' ) def __str__(self): return self.code def __unicode__(self): 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' ) first_name = models.CharField(max_length=50, verbose_name='First name' ) last_name = models.CharField(max_length=50, verbose_name='Last name' ) 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' ) ROLE_CHOICES_SECRETARY = "SECRETARY" ROLE_CHOICES = ( ('DOCTOR', 'Doctor'), ('NURSE', 'Nurse'), ('PSYCHOLOGIST', 'Psychologist'), ('TECHNICIAN', 'Technician'), (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' ) def is_on_leave(self): if len(self.holiday_set.filter(datetime_end__gt=datetime.datetime.now(), datetime_start__lt=datetime.datetime.now())): return True return False @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=255, verbose_name='Place', ) def __str__(self): 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' ) day_number = models.IntegerField( verbose_name='Day of the week' ) available_from = models.TimeField( verbose_name='Avaible since' ) available_till = models.TimeField( verbose_name='Avaible until' ) is_current = models.BooleanField( verbose_name='Is current?', default=True ) def __str__(self): 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) class Holiday(models.Model): person = models.ForeignKey(Worker, on_delete=models.CASCADE, verbose_name='Worker' ) datetime_start = models.DateTimeField( verbose_name='On leave since' ) datetime_end = models.DateTimeField( verbose_name='On leave until' ) def __str__(self): 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) ) 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'), ) flying_team = models.ForeignKey(FlyingTeam, verbose_name='Flying team (if applicable)', null=True, blank=True ) 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', blank=True ) 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 ) datetime_when = models.DateTimeField( verbose_name='Appointment on', null=True, blank=True ) 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 self.save() 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 self.save() 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", ";") else: title = self.visit.subject.first_name + " " + self.visit.subject.last_name + " type: " for type in self.appointment_types.all(): title += type.code+", " return title