Skip to content
Snippets Groups Projects
study_subject.py 7.85 KiB
Newer Older
# coding=utf-8
from django.db import models

Piotr Gawron's avatar
Piotr Gawron committed
from web.models import VoucherType, Appointment, Location, Visit
from web.models.constants import BOOL_CHOICES, SUBJECT_TYPE_CHOICES, FILE_STORAGE
from django.db.models.signals import post_save
from django.dispatch import receiver
class StudySubject(models.Model):
    class Meta:
        app_label = 'web'

    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_resigned(self):
        self.resigned = True
        self.finish_all_visits()
        self.finish_all_appointments()

    def mark_as_excluded(self):
        self.excluded = True
        self.finish_all_visits()
        self.finish_all_appointments()

    subject = models.ForeignKey("web.Subject",
                                verbose_name='Subject',
    study = models.ForeignKey("web.Study",
                              verbose_name='Study',
                              editable=False,
                              null=False,
                              )

    postponed = models.BooleanField(choices=BOOL_CHOICES,
                                    verbose_name='Postponed',
                                    default=False
                                    )
    datetime_contact_reminder = models.DateTimeField(
        null=True,
        blank=True,
Piotr Gawron's avatar
Piotr Gawron committed
        verbose_name='Please make a contact on',
    )
    type = models.CharField(max_length=1,
                            choices=SUBJECT_TYPE_CHOICES.items(),
                            )

    default_location = models.ForeignKey(Location,
                                         verbose_name='Default appointment location',

    flying_team = models.ForeignKey("web.FlyingTeam",
                                    verbose_name='Default flying team location (if applicable)',
    screening_number = models.CharField(max_length=50,
                                        verbose_name='Screening number',
                                        blank=True,
                                        null=True
    nd_number = models.CharField(max_length=25,
                                 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_add=True
                                  )
    referral = models.CharField(max_length=128,
                                null=True,
                                blank=True,
                                verbose_name='Referred by'
                                )
Piotr Gawron's avatar
Piotr Gawron committed
    referral_letter = models.FileField(
        storage=FILE_STORAGE,
        upload_to='referral_letters',
        verbose_name='Referral letter',
        blank=True,
        null=True,
    )

    health_partner = models.ForeignKey("web.Worker",
                                       verbose_name='Health partner',
                                       null=True,
                                       blank=True
                                       )

    health_partner_feedback_agreement = models.BooleanField(
        verbose_name='Agrees to give information to referral',
        default=False,
    )

    screening = models.CharField(max_length=1024,
                                 null=True,
                                 blank=True,
                                 verbose_name='Screening'
                                 )

    diagnosis = models.CharField(max_length=1024,
                                 null=True,
                                 blank=True,
                                 verbose_name='Diagnosis'
                                 )
Piotr Gawron's avatar
Piotr Gawron committed

    previously_in_study = models.BooleanField(
        verbose_name='Previously in PDP study',
        default=False,
    )

    voucher_types = models.ManyToManyField(VoucherType,
                                           blank=True,
                                           verbose_name='Voucher types'
                                           )

    year_of_diagnosis = models.IntegerField(
        null=True,
        blank=True,
        verbose_name='Year of diagnosis (YYYY)'
    )

    information_sent = models.BooleanField(
        verbose_name='Information sent',
        default=False
    )
    pd_in_family = models.NullBooleanField(
        verbose_name='PD in family',
    resigned = models.BooleanField(
        verbose_name='Resigned',
        default=False,
        editable=True
    )
    resign_reason = models.TextField(max_length=2000,
                                     blank=True,
                                     verbose_name='Resign reason'
                                     )
    excluded = models.BooleanField(
        verbose_name='Excluded',
        default=False,
        editable=True
    )
    exclude_reason = models.TextField(max_length=2000,
                                      blank=True,
                                      verbose_name='Exclude reason'
                                      )
    def sort_matched_screening_first(self, pattern, reverse=False):
      if self.screening_number is None:
        return None

      parts = self.screening_number.split(';')
      matches, reminder = [], []
      for part in parts:
          chunks = part.strip().split('-')
          if len(chunks) == 2:
              letter, number = chunks
              tupl = (letter, int(number))
          else:
              logger.warn('There are {} chunks in some parts of this screening_number: |{}|.'.format(
                  len(chunks), self.screening_number))
              tupl = (part.strip(), None)
          if pattern is not None and pattern in part:
              matches.append(tupl)
          else:
              reminder.append(tupl)

      return matches + sorted(reminder, reverse=reverse)

    @staticmethod
    def check_nd_number_regex(regex_str):
        nd_numbers = StudySubject.objects.all().values_list('nd_number', flat=True)
        regex = re.compile(regex_str)
        for nd_number in nd_numbers:
            if regex.match(nd_number) is None:
                return False
        return True

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

    def __unicode__(self):
        return "%s %s" % (self.subject.first_name, self.subject.last_name)
@receiver(post_save, sender=StudySubject)
def set_as_resigned_or_excluded(sender, instance, **kwargs):
  if instance.excluded:
    instance.mark_as_excluded()
  if instance.resigned: