Beispiel #1
0
class OnSchedulePreFlourish(OnScheduleModelMixin, BaseUuidModel):

    """A model used by the system. Auto-completed by enrollment model.
    """

    subject_identifier = models.CharField(
        verbose_name="Subject Identifier",
        max_length=50)

    schedule_name = models.CharField(max_length=25, blank=True, null=True)

    on_site = CurrentSiteManager()

    objects = SubjectIdentifierManager()

    history = HistoricalRecords()

    def put_on_schedule(self):
        pass

    def save(self, *args, **kwargs):
        self.consent_version = '1'
        super().save(*args, **kwargs)

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
Beispiel #2
0
class SubjectVisit(VisitModelMixin, ReferenceModelMixin, CreatesMetadataModelMixin,
                   SiteModelMixin, RequiresConsentFieldsModelMixin, BaseUuidModel):

    """A model completed by the user that captures the covering
    information for the data collected for this timepoint/appointment,
    e.g.report_datetime.
    """
    appointment = models.OneToOneField(Appointment, on_delete=models.PROTECT)

    reason = models.CharField(
        verbose_name='What is the reason for this visit report?',
        max_length=25,
        choices=VISIT_REASON)

    reason_unscheduled = models.CharField(
        verbose_name=(
            'If \'Unscheduled\' above, provide reason for '
            'the unscheduled visit'),
        max_length=25,
        choices=VISIT_UNSCHEDULED_REASON,
        default=NOT_APPLICABLE)

    info_source = models.CharField(
        verbose_name='What is the main source of this information?',
        max_length=25,
        choices=INFO_SOURCE)

    on_site = CurrentSiteManager()

    objects = VisitModelManager()

    history = HistoricalRecords()

    class Meta(VisitModelMixin.Meta):
        pass
Beispiel #3
0
class Appointment(AppointmentModelMixin, SiteModelMixin, BaseUuidModel):

    appt_datetime = models.DateTimeField(
        verbose_name=('Appointment date and time'),
        validators=[datetime_not_before_study_start],
        db_index=True)

    site = models.ForeignKey(Site,
                             on_delete=models.PROTECT,
                             null=True,
                             editable=False,
                             related_name='appoimtment_site')

    on_site = CurrentSiteManager()

    objects = AppointmentManager()

    history = HistoricalRecords()

    def natural_key(self):
        return (self.subject_identifier, self.visit_schedule_name,
                self.schedule_name, self.visit_code, self.visit_code_sequence)

    natural_key.dependencies = ['sites.Site']

    class Meta(AppointmentModelMixin.Meta):
        pass
Beispiel #4
0
class OutgoingTransaction(TransactionModelMixin, SiteModelMixin,
                          BaseUuidModel):
    """ Transactions produced locally to be consumed/sent to a queue or
        consumer.
    """

    site = models.ForeignKey(Site,
                             on_delete=models.CASCADE,
                             null=True,
                             editable=False)

    is_consumed_middleman = models.BooleanField(default=False)

    is_consumed_server = models.BooleanField(default=False)

    using = models.CharField(max_length=25, null=True)

    on_site = CurrentSiteManager()

    objects = models.Manager()

    def save(self, *args, **kwargs):
        if not self.using:
            raise ValueError('Value for \'{}.using\' cannot be None.'.format(
                self._meta.model_name))
        if self.is_consumed_server and not self.consumed_datetime:
            self.consumed_datetime = get_utcnow()
        super().save(*args, **kwargs)

    class Meta:
        ordering = ['timestamp']
Beispiel #5
0
class InfantOffSchedule(ConsentVersionModelModelMixin, OffScheduleModelMixin,
                        BaseUuidModel):

    schedule_name = models.CharField(max_length=25, blank=True, null=True)

    on_site = CurrentSiteManager()

    objects = SubjectIdentifierManager()

    history = HistoricalRecords()

    def take_off_schedule(self):
        pass

    def get_consent_version(self):
        subject_consent_cls = django_apps.get_model(
            'td_infant.infantdummysubjectconsent')
        subject_consent_objs = subject_consent_cls.objects.filter(
            subject_identifier=self.subject_identifier).order_by(
                '-consent_datetime')
        if subject_consent_objs:
            return subject_consent_objs.first().version
        else:
            raise ValidationError(
                'Missing Infant Dummy Consent form. Cannot proceed.')

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
class CaregiverOffSchedule(OffScheduleModelMixin, BaseUuidModel):

    schedule_name = models.CharField(max_length=25, blank=True, null=True)

    objects = SubjectIdentifierManager()

    on_site = CurrentSiteManager()

    history = HistoricalRecords()

    def take_off_schedule(self):
        pass

    @property
    def latest_consent_obj_version(self):

        caregiver_consent_cls = django_apps.get_model(
            'flourish_caregiver.subjectconsent')

        subject_consents = caregiver_consent_cls.objects.filter(
            subject_identifier=self.subject_identifier, )
        if subject_consents:
            latest_consent = subject_consents.latest('consent_datetime')
            return latest_consent.version
        else:
            raise forms.ValidationError(
                'Missing Subject Consent form, cannot proceed.')

    def save(self, *args, **kwargs):
        self.consent_version = self.latest_consent_obj_version
        super().save(*args, **kwargs)

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
Beispiel #7
0
class OnSchedule(OnScheduleModelMixin, BaseUuidModel):
    """A model used by the system. Auto-completed by subject_consent.
    """
    on_site = CurrentSiteManager()

    objects = SubjectIdentifierManager()

    history = HistoricalRecords()
Beispiel #8
0
class FollowUp(ClinicalAssessmentModelMixin, CrfModelMixin):

    fluconazole_dose = models.CharField(
        verbose_name='Fluconazole dose (day prior to visit)',
        max_length=25,
        choices=FLUCONAZOLE_DOSE)

    fluconazole_dose_other = OtherCharField(
        verbose_name='If other, specify dose:', max_length=25)

    rifampicin_started = models.CharField(
        verbose_name='Rifampicin started since last visit?',
        max_length=25,
        choices=YES_NO_ALREADY_ND)

    rifampicin_start_date = models.DateField(
        verbose_name='Date Rifampicin started',
        validators=[date_not_future],
        null=True,
        blank=True,
    )

    patient_help = models.CharField(
        verbose_name=('Does the patient require help from'
                      ' anybody for everyday activities? '),
        max_length=10,
        choices=YES_NO_ND,
        help_text=('For example eating, drinking, washing,'
                   ' brushing teeth, going to the toilet'))

    patient_problems = models.CharField(
        verbose_name=
        'Has the illness left the patient with any other problems?',
        max_length=10,
        choices=YES_NO_ND)

    rankin_score = models.CharField(verbose_name='Modified Rankin score',
                                    choices=RANKIN_SCORE,
                                    max_length=10,
                                    null=True)

    other_significant_dx = models.CharField(
        verbose_name='Other significant diagnosis since last visit?',
        max_length=5,
        choices=YES_NO_NA)

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'Follow-up'
        verbose_name_plural = 'Follow-up'
Beispiel #9
0
class EducationHoh(EducationModelMixin, CrfModelMixin):

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'Health Economics: Education (Person who earns the highest income)'
        verbose_name_plural = 'Health Economics: Education (Person who earns the highest income)'
Beispiel #10
0
class MedicalExpensesTwo(CrfModelMixin):

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'Health Economics: Medical Expenses Part 2'
        verbose_name_plural = 'Health Economics: Medical Expenses Part 2'
class ChildOffSchedule(OffScheduleModelMixin, BaseUuidModel):

    schedule_name = models.CharField(max_length=25, blank=True, null=True)

    objects = SubjectIdentifierManager()

    on_site = CurrentSiteManager()

    history = HistoricalRecords()

    def take_off_schedule(self):
        pass

    def get_consent_version(self):
        preg_subject_screening_cls = django_apps.get_model(
            'flourish_caregiver.screeningpregwomen')
        prior_subject_screening_cls = django_apps.get_model(
            'flourish_caregiver.screeningpriorbhpparticipants')

        consent_version_cls = django_apps.get_model(
            'flourish_caregiver.flourishconsentversion')

        subject_screening_obj = None

        try:
            subject_screening_obj = preg_subject_screening_cls.objects.get(
                subject_identifier=self.subject_identifier[:-3])
        except preg_subject_screening_cls.DoesNotExist:

            try:
                subject_screening_obj = prior_subject_screening_cls.objects.get(
                    subject_identifier=self.subject_identifier[:-3])
            except prior_subject_screening_cls.DoesNotExist:
                raise ValidationError(
                    'Missing Subject Screening form. Please complete '
                    'it before proceeding.')

        if subject_screening_obj:
            try:
                consent_version_obj = consent_version_cls.objects.get(
                    screening_identifier=subject_screening_obj.
                    screening_identifier)
            except consent_version_cls.DoesNotExist:
                raise ValidationError(
                    'Missing Consent Version form. Please complete '
                    'it before proceeding.')
            return consent_version_obj.version

    def save(self, *args, **kwargs):
        self.consent_version = self.get_consent_version()
        super().save(*args, **kwargs)

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
Beispiel #12
0
class OnScheduleModelMixin(BaseOnScheduleModelMixin, BaseUuidModel):
    """A model used by the system. Auto-completed by enrollment model.
    """

    subject_identifier = models.CharField(
        verbose_name="Subject Identifier",
        max_length=50)

    schedule_name = models.CharField(max_length=25,
                                     blank=True,
                                     null=True)

    on_site = CurrentSiteManager()

    objects = SubjectIdentifierManager()

    history = HistoricalRecords()

    def put_on_schedule(self):
        pass

    def save(self, *args, **kwargs):
        self.consent_version = self.latest_consent_obj_version
        super().save(*args, **kwargs)

    @property
    def consent_version_cls(self):
        return django_apps.get_model('flourish_caregiver.flourishconsentversion')

    @property
    def subject_consent_cls(self):
        return django_apps.get_model('flourish_caregiver.subjectconsent')

    @property
    def latest_consent_obj_version(self):

        child_consent_cls = django_apps.get_model(
            'flourish_child.childdummysubjectconsent')

        subject_consents = child_consent_cls.objects.filter(
             subject_identifier=self.subject_identifier,)
        if subject_consents:
            latest_consent = subject_consents.latest('consent_datetime')
            return latest_consent.version
        else:
            raise forms.ValidationError('Missing dummy consent obj, cannot proceed.')

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
        abstract = True
Beispiel #13
0
class CaregiverOffSchedule(OffScheduleModelMixin, BaseUuidModel):

    schedule_name = models.CharField(max_length=25, blank=True, null=True)

    objects = SubjectIdentifierManager()

    on_site = CurrentSiteManager()

    history = HistoricalRecords()

    def take_off_schedule(self):
        pass

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
Beispiel #14
0
class SubjectRequisition(
        NonUniqueSubjectIdentifierFieldMixin, RequisitionModelMixin,
        RequisitionStatusMixin, RequisitionIdentifierMixin,
        VisitTrackingCrfModelMixin, SubjectScheduleCrfModelMixin,
        RequiresConsentFieldsModelMixin, PreviousVisitModelMixin,
        RequisitionReferenceModelMixin, UpdatesRequisitionMetadataModelMixin,
        SearchSlugModelMixin, BaseUuidModel):

    lab_profile_name = 'ambition_subject'

    subject_visit = models.ForeignKey(SubjectVisit, on_delete=PROTECT)

    reason_not_drawn = models.CharField(
        verbose_name='If not drawn, please explain',
        max_length=25,
        default=NOT_APPLICABLE,
        choices=REASON_NOT_DRAWN)

    on_site = CurrentSiteManager()

    objects = Manager()

    history = HistoricalRecords()

    def __str__(self):
        return (f'{self.requisition_identifier} '
                f'{self.panel_object.verbose_name}')

    def save(self, *args, **kwargs):
        if not self.id:
            edc_protocol_app_config = django_apps.get_app_config(
                'edc_protocol')
            self.protocol_number = edc_protocol_app_config.protocol_number
        self.subject_identifier = self.subject_visit.subject_identifier
        super().save(*args, **kwargs)

    def get_search_slug_fields(self):
        fields = super().get_search_slug_fields()
        fields.extend([
            'requisition_identifier', 'human_readable_identifier',
            'identifier_prefix'
        ])
        return fields

    class Meta:
        unique_together = ('panel', 'subject_visit')
Beispiel #15
0
class Week16(CrfModelMixin):

    patient_alive = models.CharField(verbose_name='Is the patient alive?',
                                     max_length=5,
                                     choices=YES_NO)

    death_datetime = models.DateTimeField(
        verbose_name='If dead, date and time of death',
        validators=[date_not_future],
        null=True,
        blank=True)

    activities_help = models.CharField(
        verbose_name=
        ('Does the patient require help from anybody for everyday activities?'
         ),
        max_length=5,
        choices=YES_NO_NA,
        help_text=('For example eating, drinking, washing, brushing teeth, '
                   'going to the toilet.'))

    illness_problems = models.CharField(
        verbose_name=
        'Has the illness left the patient with any other problems?',
        max_length=5,
        choices=YES_NO_NA)

    rankin_score = models.CharField(verbose_name='Modified Rankin score',
                                    max_length=10,
                                    choices=RANKIN_SCORE)

    week16_narrative = models.TextField(verbose_name='Narrative',
                                        max_length=1000,
                                        null=True,
                                        blank=True)

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name_plural = 'Week16'
Beispiel #16
0
class Education(EducationModelMixin, CrfModelMixin):

    household_head = models.CharField(
        verbose_name='Are you the person who earns the highest income?',
        max_length=5,
        choices=YES_NO,
        help_text=('If NO, please complete the form "Health Economics: '
                   'Education (Person who earns the highest income)" on behalf of the '
                   'Person who earns the highest income.'))

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'Health Economics: Education'
        verbose_name_plural = 'Health Economics: Education'
class StudyTerminationConclusionW10(OffScheduleModelMixin,
                                    ActionItemModelMixin,
                                    TrackingIdentifierModelMixin,
                                    BaseUuidModel):

    action_cls = StudyTerminationConclusionW10Action
    tracking_identifier_prefix = 'ST'

    last_study_fu_date = models.DateField(
        verbose_name='Date of last research follow up (if different):',
        validators=[date_not_future],
        blank=True,
        null=True)

    termination_reason = models.CharField(
        verbose_name='Reason for study termination',
        max_length=75,
        choices=REASON_STUDY_TERMINATED_W10,
        help_text=(
            'If included in error, be sure to fill in protocol deviation form.'
        ))

    death_date = models.DateField(verbose_name='Date of Death',
                                  validators=[date_not_future],
                                  blank=True,
                                  null=True)

    consent_withdrawal_reason = models.CharField(
        verbose_name='Reason for withdrawing consent',
        max_length=75,
        blank=True,
        null=True)

    on_site = CurrentSiteManager()

    objects = SubjectIdentifierManager()

    history = HistoricalRecords()

    class Meta:
        verbose_name = 'W10 Study Termination/Conclusion'
        verbose_name_plural = 'W10 Study Terminations/Conclusions'
Beispiel #18
0
class IncomingTransaction(TransactionModelMixin, SiteModelMixin,
                          BaseUuidModel):
    """ Transactions received from a remote host.
    """

    site = models.ForeignKey(Site,
                             on_delete=models.CASCADE,
                             null=True,
                             editable=False)

    is_consumed = models.BooleanField(default=False)

    is_self = models.BooleanField(default=False)

    on_site = CurrentSiteManager()

    objects = models.Manager()

    class Meta:
        ordering = ['timestamp']
Beispiel #19
0
class OnScheduleMaternalLabourDel(ConsentVersionModelModelMixin,
                                  OnScheduleModelMixin, BaseUuidModel):
    """A model used by the system. Auto-completed by subject_consent.
    """
    subject_identifier = models.CharField(verbose_name="Subject Identifier",
                                          max_length=50)

    schedule_name = models.CharField(max_length=25, blank=True, null=True)

    on_site = CurrentSiteManager()

    objects = SubjectIdentifierManager()

    history = HistoricalRecords()

    def put_on_schedule(self):
        pass

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
Beispiel #20
0
class Week4(ClinicalAssessmentModelMixin, CrfModelMixin):

    fluconazole_dose = models.CharField(
        verbose_name='Fluconazole dose (day prior to visit)',
        max_length=25,
        choices=FLUCONAZOLE_DOSE)

    fluconazole_dose_other = OtherCharField(max_length=25)

    rifampicin_started = models.CharField(
        verbose_name='Rifampicin started since last visit?',
        max_length=25,
        choices=YES_NO_ALREADY_ND)

    rifampicin_start_date = models.DateField(
        verbose_name='Date Rifampicin started',
        validators=[date_not_future],
        null=True,
        blank=True)

    lp_done = models.CharField(verbose_name='LP done?',
                               max_length=5,
                               choices=YES_NO,
                               help_text='If yes, ensure LP CRF completed.')

    other_significant_dx = models.CharField(
        verbose_name='Other significant diagnosis since last visit?',
        max_length=5,
        choices=YES_NO_NA)

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'Week 4'
        verbose_name_plural = 'Week 4'
class Appointment(AppointmentModelMixin, SiteModelMixin, BaseUuidModel):

    site = models.ForeignKey(Site,
                             on_delete=models.PROTECT,
                             null=True,
                             editable=False,
                             related_name='appoimtment_site')

    on_site = CurrentSiteManager()

    objects = AppointmentManager()

    history = HistoricalRecords()

    def natural_key(self):
        return (self.subject_identifier, self.visit_schedule_name,
                self.schedule_name, self.visit_code, self.visit_code_sequence)

    natural_key.dependencies = ['sites.Site']

    class Meta(AppointmentModelMixin.Meta):
        pass
Beispiel #22
0
class SubjectLocator(LocatorModelMixin, RequiresConsentFieldsModelMixin,
                     ActionItemModelMixin, SiteModelMixin,
                     TrackingIdentifierModelMixin, BaseUuidModel):
    """A model completed by the user to that captures participant
    locator information and permission to contact.
    """
    action_cls = SubjectLocatorAction

    tracking_identifier_prefix = 'SL'

    on_site = CurrentSiteManager()

    objects = LocatorManager()

    history = HistoricalRecords()

    def natural_key(self):
        return (self.subject_identifier, )

    natural_key.dependencies = ['sites.Site']

    class Meta:
        verbose_name = 'Subject Locator'
Beispiel #23
0
class OnScheduleInfantBirth(OnScheduleModelMixin, BaseUuidModel):
    """A model used by the system. Auto-completed by infant birth.
    """

    subject_identifier = models.CharField(verbose_name="Subject Identifier",
                                          max_length=50)

    schedule_name = models.CharField(max_length=25, blank=True, null=True)

    on_site = CurrentSiteManager()

    objects = SubjectIdentifierManager()

    history = HistoricalRecords()

    def put_on_schedule(self):
        pass

    def save(self, *args, **kwargs):
        self.consent_version = self.get_consent_version()
        super(OnScheduleInfantBirth, self).save(*args, **kwargs)

    def get_consent_version(self):
        subject_consent_cls = django_apps.get_model(
            'td_infant.infantdummysubjectconsent')
        subject_consent_objs = subject_consent_cls.objects.filter(
            subject_identifier=self.subject_identifier).order_by(
                '-consent_datetime')
        if subject_consent_objs:
            return subject_consent_objs.first().version
        else:
            raise ValidationError(
                'Missing Infant Dummy Consent form. Cannot proceed.')

    class Meta:
        unique_together = ('subject_identifier', 'schedule_name')
Beispiel #24
0
class RandomizationList(BaseUuidModel):

    subject_identifier = models.CharField(
        verbose_name="Subject Identifier",
        max_length=50,
        null=True,
        unique=True)

    sid = models.IntegerField(unique=True)

    drug_assignment = EncryptedTextField(
        choices=(
            (SINGLE_DOSE, SINGLE_DOSE_NAME),
            (CONTROL, CONTROL_NAME)))

    site_name = models.CharField(max_length=100)

    allocation = EncryptedTextField(
        verbose_name='Original integer allocation',
        null=True)

    allocated = models.BooleanField(default=False)

    allocated_datetime = models.DateTimeField(null=True)

    allocated_user = models.CharField(max_length=50, null=True)

    allocated_site = models.ForeignKey(
        Site, null=True, on_delete=models.CASCADE)

    verified = models.BooleanField(default=False)

    verified_datetime = models.DateTimeField(null=True)

    verified_user = models.CharField(max_length=50, null=True)

    objects = RandomizationListManager()

    history = HistoricalRecords()

    on_site = CurrentSiteManager('allocated_site')

    def __str__(self):
        return f'{self.site_name}.{self.sid} subject={self.subject_identifier}'

    def save(self, *args, **kwargs):
        try:
            self.treatment_description
        except RandomizationError as e:
            raise RandomizationListModelError(e)
        try:
            Site.objects.get(name=self.site_name)
        except ObjectDoesNotExist:
            site_names = [obj.name for obj in Site.objects.all()]
            raise RandomizationListModelError(
                f'Invalid site name. Got {self.site_name}. '
                f'Expected one of {site_names}.')
        super().save(*args, **kwargs)

    @property
    def short_label(self):
        return (f'{self.drug_assignment} SID:{self.site_name}.{self.sid}')

    @property
    def treatment_description(self):
        if self.drug_assignment == CONTROL:
            return CONTROL_NAME
        elif self.drug_assignment == SINGLE_DOSE:
            return SINGLE_DOSE_NAME
        raise RandomizationError(
            f'Invalid drug assignment. Got {self.drug_assignment}')

    def natural_key(self):
        return (self.sid, )

    class Meta:
        ordering = ('site_name', 'sid', )
        unique_together = ('site_name', 'sid')
Beispiel #25
0
class RecurrenceSymptom(NonUniqueSubjectIdentifierFieldMixin,
                        ActionItemModelMixin, TrackingIdentifierModelMixin,
                        SiteModelMixin, BaseUuidModel):

    tracking_identifier_prefix = 'RS'

    action_cls = RecurrenceOfSymptomsAction

    report_datetime = models.DateTimeField(
        verbose_name="Report Date and Time",
        default=get_utcnow)

    meningitis_symptom = models.ManyToManyField(
        MeningitisSymptom,
        verbose_name='What are your current symptoms?')

    meningitis_symptom_other = models.CharField(
        verbose_name='If other symptom, please specify',
        max_length=50,
        null=True,
        blank=True)

    patient_readmitted = models.CharField(
        verbose_name=(
            'Has the patient been re-admitted due to these recurrent symptoms?'),
        max_length=5,
        choices=YES_NO)

    glasgow_coma_score = models.IntegerField(
        verbose_name='Score:',
        validators=[MinValueValidator(3), MaxValueValidator(15)],
        help_text='/15')

    recent_seizure = models.CharField(
        verbose_name=(
            'Recent seizure (<72 hrs):'),
        max_length=5,
        choices=YES_NO)

    behaviour_change = models.CharField(
        max_length=5,
        choices=YES_NO)

    confusion = models.CharField(
        max_length=5,
        choices=YES_NO)

    neurological = models.ManyToManyField(
        Neurological,
        verbose_name='neurologic:')

    focal_neurologic_deficit = models.CharField(
        verbose_name='If "Focal neurologic deficit" chosen, please specify',
        max_length=15,
        null=True,
        blank=True)

    cn_palsy_chosen_other = models.CharField(
        verbose_name='If other CN Palsy',
        max_length=15,
        null=True,
        blank=True)

    lp_completed = models.CharField(
        verbose_name='LP completed',
        max_length=5,
        choices=YES_NO,
        help_text='If YES, complete LP form')

    amb_administered = models.CharField(
        max_length=5,
        choices=YES_NO)

    amb_duration = models.IntegerField(
        verbose_name='If YES, specify length of course',
        validators=[MinValueValidator(1)],
        null=True,
        blank=True)

    tb_treatment = models.CharField(
        verbose_name='TB treatment:',
        max_length=5,
        choices=YES_NO)

    steroids_administered = models.CharField(
        max_length=5,
        choices=YES_NO)

    steroids_duration = models.IntegerField(
        verbose_name='If YES, specify the length of course in days:',
        validators=[MinValueValidator(1)],
        null=True,
        blank=True)

    steroids_choices = models.CharField(
        verbose_name='If YES',
        max_length=25,
        default=NOT_APPLICABLE,
        choices=STEROIDS_CHOICES)

    steroids_choices_other = models.CharField(
        blank=True,
        max_length=50,
        verbose_name='If other steroids, please specify')

    CD4_count = models.IntegerField(
        verbose_name='CD4 count (if available)',
        validators=[MinValueValidator(1)],
        null=True,
        blank=True)

    antibiotic_treatment = models.ManyToManyField(
        AntibioticTreatment,
        verbose_name='Antibiotics treatment')

    antibiotic_treatment_other = models.CharField(
        verbose_name='If other antibiotic treatment, please specify',
        max_length=50,
        blank=True,
        null=True)

    on_arvs = models.CharField(
        verbose_name='On ARVs:',
        max_length=26,
        choices=YES_NO_ALREADY_ARV)

    arv_date = models.DateField(
        verbose_name='Study date ARVs started.',
        validators=[date_not_future],
        null=True,
        blank=True)

    arvs_stopped = models.CharField(
        verbose_name='ARVs stopped this clinical episode?',
        max_length=5,
        choices=YES_NO_NA)

    narrative_summary = models.TextField(
        verbose_name='Narrative summary of recurrence of symptoms:',
        help_text=(
            'Please ensure the following forms have been completed: '
            'LP, Bloods, Microbiology, Radiology'))

    dr_opinion = models.CharField(
        verbose_name='Study doctor\'s opinion:',
        max_length=10,
        choices=DR_OPINION)

    dr_opinion_other = models.CharField(
        verbose_name='If other doctor\'s opinion, please specify',
        blank=True,
        max_length=50,
        null=True)

    on_site = CurrentSiteManager()

    objects = TrackingIdentifierManager()

    history = HistoricalRecords()

    def natural_key(self):
        return (self.tracking_identifier, )

    class Meta:
        verbose_name = 'Recurrence of Symptoms'
        verbose_name_plural = 'Recurrence of Symptoms'
class ProtocolDeviationViolation(NonUniqueSubjectIdentifierFieldMixin,
                                 SiteModelMixin, ActionItemModelMixin,
                                 TrackingIdentifierModelMixin, BaseUuidModel):

    tracking_identifier_prefix = 'PD'

    action_cls = ProtocolDeviationViolationAction

    report_datetime = models.DateTimeField(verbose_name="Report Date and Time",
                                           default=get_utcnow)

    short_description = models.CharField(
        verbose_name='Provide a short description of this occurrence',
        max_length=35,
        null=True,
        blank=False,
        help_text=(
            'Max 35 characters. Note: If this occurrence is a "violation" '
            'there is additional space below for a more detailed '
            'description'))

    report_type = models.CharField(verbose_name='Type of occurrence',
                                   max_length=25,
                                   choices=DEVIATION_VIOLATION)

    safety_impact = models.CharField(
        verbose_name='Could this occurrence have an impact on safety of the '
        'participant?',
        max_length=25,
        choices=YES_NO)

    safety_impact_details = models.TextField(
        verbose_name='If "Yes", provide details', null=True, blank=True)

    study_outcomes_impact = models.CharField(
        verbose_name='Could this occurrence have an impact on study outcomes?',
        max_length=25,
        choices=YES_NO)

    study_outcomes_impact_details = models.TextField(
        verbose_name='If "Yes", provide details', null=True, blank=True)

    violation_datetime = models.DateTimeField(
        verbose_name='Date violation occurred',
        validators=[datetime_not_future],
        null=True,
        blank=True)

    violation_type = models.CharField(verbose_name='Type of violation',
                                      max_length=75,
                                      choices=PROTOCOL_VIOLATION,
                                      default=NOT_APPLICABLE)

    violation_type_other = models.CharField(
        null=True,
        blank=True,
        verbose_name='If other, please specify',
        max_length=75)

    violation_description = models.TextField(
        verbose_name='Describe the violation',
        null=True,
        blank=True,
        help_text=('Describe in full. Explain how the violation '
                   'happened, what occurred, etc.'))

    violation_reason = models.TextField(
        verbose_name='Explain the reason why the violation occurred',
        null=True,
        blank=True)

    corrective_action_datetime = models.DateTimeField(
        verbose_name='Corrective action date and time',
        validators=[datetime_not_future],
        null=True,
        blank=True)

    corrective_action = models.TextField(
        verbose_name='Corrective action taken', null=True, blank=True)

    preventative_action_datetime = models.DateTimeField(
        verbose_name='Preventative action date and time',
        validators=[datetime_not_future],
        null=True,
        blank=True)

    preventative_action = models.TextField(
        verbose_name='Preventative action taken', null=True, blank=True)

    action_required = models.CharField(max_length=45, choices=ACTION_REQUIRED)

    report_status = models.CharField(
        verbose_name='What is the status of this report?',
        max_length=25,
        choices=REPORT_STATUS)

    report_closed_datetime = models.DateTimeField(
        blank=True,
        null=True,
        validators=[datetime_not_future],
        verbose_name=('Date and time report closed.'))

    on_site = CurrentSiteManager()

    objects = TrackingIdentifierManager()

    history = HistoricalRecords()

    def natural_key(self):
        return (self.tracking_identifier, )

    natural_key.dependencies = ['sites.Site']

    class Meta:
        verbose_name = 'Protocol Deviation/Violation'
        verbose_name_plural = 'Protocol Deviations/Violations'
Beispiel #27
0
class ActionItem(NonUniqueSubjectIdentifierFieldMixin, SiteModelMixin,
                 BaseUuidModel):

    subject_identifier_model = 'edc_registration.registeredsubject'

    action_identifier = models.CharField(max_length=25, unique=True)

    report_datetime = models.DateTimeField(default=get_utcnow)

    action_type = models.ForeignKey(ActionType,
                                    on_delete=PROTECT,
                                    related_name='action_type',
                                    verbose_name='Action')

    reference_model = models.CharField(max_length=50, null=True)

    reference_identifier = models.CharField(
        max_length=50,
        null=True,
        help_text='e.g. tracking identifier updated from the reference model')

    related_reference_model = models.CharField(max_length=100,
                                               null=True,
                                               editable=False)

    related_reference_identifier = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        help_text=('May be left blank. e.g. tracking identifier from '
                   'source model that opened the item.'))

    parent_reference_model = models.CharField(max_length=100,
                                              null=True,
                                              editable=False)

    parent_reference_identifier = models.CharField(
        max_length=50,
        null=True,
        blank=True,
        help_text=('May be left blank. e.g. tracking identifier from '
                   'source model that opened the item.'))

    priority = models.CharField(
        max_length=25,
        choices=PRIORITY,
        null=True,
        blank=True,
        help_text='Leave blank to use default for this action type.')

    parent_action_item = models.ForeignKey('self',
                                           on_delete=PROTECT,
                                           null=True,
                                           blank=True)

    status = models.CharField(max_length=25,
                              default=NEW,
                              choices=ACTION_STATUS)

    instructions = models.TextField(null=True,
                                    blank=True,
                                    help_text='populated by action class')

    auto_created = models.BooleanField(default=False)

    auto_created_comment = models.CharField(max_length=25,
                                            null=True,
                                            blank=True)

    on_site = CurrentSiteManager()

    objects = ActionItemManager()

    history = HistoricalRecords()

    def __str__(self):
        return (f'{self.action_identifier[-9:]} {self.action_type.name} '
                f'({self.get_status_display()})')

    def save(self, *args, **kwargs):
        """See also signals."""
        if not self.id:
            # a new action item always has a unique action identifier
            self.action_identifier = ActionIdentifier().identifier
            self.check_registered_subject()
            self.priority = self.priority or self.action_type.priority
            self.reference_model = self.action_type.reference_model
            self.related_reference_model = self.action_type.related_reference_model
            self.instructions = self.action_type.instructions
        super().save(*args, **kwargs)

    def check_registered_subject(self):
        # subject_identifier
        if self.subject_identifier:
            subject_identifier_model_cls = django_apps.get_model(
                self.subject_identifier_model)
            try:
                subject_identifier_model_cls.objects.get(
                    subject_identifier=self.subject_identifier)
            except ObjectDoesNotExist:
                raise SubjectDoesNotExist(
                    f'Invalid subject identifier. Subject does not exist '
                    f'in \'{self.subject_identifier_model}\'. '
                    f'Got \'{self.subject_identifier}\'.')

    def natural_key(self):
        return (self.action_identifier, )

    natural_key.dependencies = ['sites.Site']

    @property
    def last_updated(self):
        return None if self.status == NEW else self.modified

    @property
    def user_last_updated(self):
        return None if self.status == NEW else self.user_modified or self.user_created

    @property
    def action_cls(self):
        """Returns the action_cls.
        """
        return site_action_items.get(self.action_type.name)

    @property
    def parent_reference_model_obj(self):
        """Returns the parent reference model instance or None.
        """
        try:
            reference_model = self.parent_action_item.reference_model
        except AttributeError:
            pass
        else:
            return django_apps.get_model(reference_model).objects.get(
                tracking_identifier=self.parent_action_item.
                reference_identifier)
        return None

    @property
    def related_reference_model_obj(self):
        """Returns the related reference model instance or None.
        """
        try:
            reference_model = self.related_reference_model
        except AttributeError:
            pass
        else:
            return django_apps.get_model(reference_model).objects.get(
                tracking_identifier=self.related_reference_identifier)
        return None

    @property
    def identifier(self):
        """Returns a shortened action identifier.
        """
        return self.action_identifier[-9:]

    @property
    def parent(self):
        """Returns a url to the parent action item
        for display in admin.
        """
        if self.parent_action_item:
            url_name = '_'.join(self._meta.label_lower.split('.'))
            namespace = edc_action_item_admin.name
            url = reverse(f'{namespace}:{url_name}_changelist')
            return mark_safe(
                f'<a data-toggle="tooltip" title="go to parent action item" '
                f'href="{url}?q={self.parent_action_item.action_identifier}">'
                f'{self.parent_action_item.identifier}</a>')
        return None

    @property
    def reference(self):
        """Returns a shortened reference_identifier which in
        most cases is the reference model's tracking identifier.
        """
        if self.reference_identifier:
            return self.reference_identifier[-9:]
        return None

    @property
    def parent_reference(self):
        """Returns a shortened reference_identifier of the
        parent model reference which in most cases is the
        parent reference model's tracking identifier.
        """
        try:
            reference_identifier = self.parent_action_item.reference_identifier
        except AttributeError:
            reference_identifier = None
        if reference_identifier:
            return reference_identifier[-9:]
        return None

    @property
    def related_reference(self):
        """Returns a shortened reference_identifier of the
        parent model reference which in most cases is the
        parent reference model's tracking identifier.
        """
        try:
            reference_identifier = self._related_reference_identifier
        except AttributeError:
            reference_identifier = None
        if reference_identifier:
            return reference_identifier[-9:]
        return None

    class Meta:
        verbose_name = 'Action Item'
        verbose_name_plural = 'Action Items'
        unique_together = ('subject_identifier', 'action_type',
                           'reference_identifier')
Beispiel #28
0
class Microbiology(CrfModelMixin):

    urine_culture_performed = models.CharField(
        max_length=5,
        choices=YES_NO,
        help_text='only for patients with >50 white cells in urine')

    urine_taken_date = models.DateField(
        validators=[date_not_before_study_start, date_not_future],
        null=True,
        blank=True)

    urine_culture_results = models.CharField(
        verbose_name='Urine culture results, if completed',
        max_length=10,
        choices=CULTURE_RESULTS,
        default=NOT_APPLICABLE)

    urine_culture_organism = models.CharField(
        verbose_name='If positive, organism',
        max_length=25,
        choices=URINE_CULTURE_RESULTS_ORGANISM,
        default=NOT_APPLICABLE)

    urine_culture_organism_other = OtherCharField(
        max_length=50,
        null=True,
        blank=True)

    blood_culture_performed = models.CharField(
        max_length=5,
        choices=YES_NO)

    blood_culture_results = models.CharField(
        verbose_name='Blood culture results, if completed',
        max_length=10,
        choices=CULTURE_RESULTS,
        default=NOT_APPLICABLE)

    blood_taken_date = models.DateField(
        validators=[date_not_before_study_start, date_not_future],
        null=True,
        blank=True)

    day_blood_taken = models.IntegerField(
        verbose_name='If positive, study day positive culture sample taken',
        validators=[MinValueValidator(1)],
        null=True,
        blank=True)

    blood_culture_organism = models.CharField(
        verbose_name='If growth positive, organism',
        max_length=50,
        choices=BLOOD_CULTURE_RESULTS_ORGANISM,
        default=NOT_APPLICABLE)

    blood_culture_organism_other = OtherCharField(
        max_length=50,
        null=True,
        blank=True)

    bacteria_identified = models.CharField(
        verbose_name='If bacteria, type',
        max_length=50,
        choices=BACTERIA_TYPE,
        default=NOT_APPLICABLE)

    bacteria_identified_other = OtherCharField(
        max_length=100,
        null=True,
        blank=True)

    sputum_afb_performed = models.CharField(
        verbose_name='AFB microscopy performed?',
        max_length=5,
        choices=YES_NO,
        help_text='Was sputum AFB done?')

    sputum_afb_date = models.DateField(
        validators=[date_not_before_study_start, date_not_future],
        null=True,
        blank=True)

    sputum_results_afb = models.CharField(
        verbose_name='AFB results',
        max_length=10,
        choices=POS_NEG_NA,
        default=NOT_APPLICABLE)

    sputum_performed = models.CharField(
        verbose_name='Culture performed?',
        max_length=15,
        choices=YES_NO_NA,
        default=NOT_APPLICABLE)

    sputum_taken_date = models.DateField(
        validators=[date_not_before_study_start, date_not_future],
        null=True,
        blank=True)

    sputum_results_culture = models.CharField(
        verbose_name='Culture results',
        max_length=10,
        choices=POS_NEG_NA,
        default=NOT_APPLICABLE)

    sputum_results_positive = models.CharField(
        verbose_name='If culture is positive, please specify:',
        max_length=50,
        null=True,
        blank=True)

    sputum_genexpert_performed = models.CharField(
        verbose_name='Sputum Gene-Xpert performed?',
        max_length=15,
        choices=YES_NO_NA,
        default=NOT_APPLICABLE)

    sputum_genexpert_date = models.DateField(
        verbose_name='Date sputum Gene-Xpert taken',
        validators=[date_not_before_study_start, date_not_future],
        null=True,
        blank=True)

    sputum_result_genexpert = models.CharField(
        verbose_name='Gene-Xpert results',
        max_length=45,
        choices=SPUTUM_GENEXPERT,
        default=NOT_APPLICABLE)

    tissue_biopsy_taken = models.CharField(
        max_length=5,
        choices=YES_NO)

    tissue_biopsy_results = models.CharField(
        verbose_name='If YES, results',
        max_length=10,
        choices=CULTURE_RESULTS,
        default=NOT_APPLICABLE)

    biopsy_date = models.DateField(
        validators=[date_not_before_study_start, date_not_future],
        null=True,
        blank=True)

    day_biopsy_taken = models.IntegerField(
        verbose_name='If positive, Study day positive culture sample taken',
        validators=[MinValueValidator(1)],
        null=True,
        blank=True)

    tissue_biopsy_organism = models.CharField(
        verbose_name='If growth positive, organism',
        max_length=50,
        choices=BIOPSY_RESULTS_ORGANISM,
        default=NOT_APPLICABLE)

    tissue_biopsy_organism_other = OtherCharField(
        max_length=50,
        null=True,
        blank=True)

    histopathology_report = models.TextField(
        null=True,
        blank=True)

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'Microbiology'
        verbose_name_plural = 'Microbiology'
Beispiel #29
0
class PkPdCrf(CrfModelMixin):

    albumin = models.IntegerField(verbose_name='Albumin',
                                  null=True,
                                  blank=True,
                                  help_text='Units in g/L')

    ambisome_dose = models.IntegerField(verbose_name='Ambisome dose given',
                                        null=True,
                                        blank=True,
                                        help_text='Units in mg')

    ambisome_started_datetime = models.DateTimeField(
        verbose_name='Date and time Ambisome infusion started?',
        null=True,
        blank=True)

    ambisome_ended_datetime = models.DateTimeField(
        verbose_name='Date and time Ambisome infusion stopped',
        null=True,
        blank=True)

    full_ambisome_dose_given = models.CharField(
        verbose_name='Was the entire Ambisome dose given?',
        choices=YES_NO,
        max_length=5,
        null=True,
        blank=True)

    flucytosine_dose = models.IntegerField(verbose_name='Flucytosine dose?',
                                           null=True,
                                           blank=True,
                                           help_text='Units in mg')

    flucytosine_dose_one_given = models.CharField(
        verbose_name='Flucytosine <u>DOSE&nbsp;1</u> given? ',
        choices=YES_NO,
        max_length=5,
        null=True,
        blank=True)

    flucytosine_dose_one_datetime = models.DateTimeField(
        verbose_name=mark_safe(
            'Date and time Flucytosine <u>DOSE&nbsp;1</u> was swallowed?'),
        null=True,
        blank=True)

    flucytosine_dose_two_given = models.CharField(
        verbose_name='Flucytosine <u>DOSE&nbsp;2</u> given? ',
        choices=YES_NO,
        max_length=5,
        null=True,
        blank=True)

    flucytosine_dose_two_datetime = models.DateTimeField(
        verbose_name=mark_safe(
            'Date and time Flucytosine <u>DOSE&nbsp;2</u> was swallowed?'),
        null=True,
        blank=True)

    flucytosine_dose_three_given = models.CharField(
        verbose_name='Flucytosine <u>DOSE&nbsp;3</u> given? ',
        choices=YES_NO,
        max_length=5,
        null=True,
        blank=True)

    flucytosine_dose_three_datetime = models.DateTimeField(
        verbose_name=mark_safe(
            'Date and time Flucytosine <u>DOSE&nbsp;3</u> was swallowed?'),
        null=True,
        blank=True)

    flucytosine_dose_four_given = models.CharField(
        verbose_name='Flucytosine <u>DOSE&nbsp;4</u> given? ',
        choices=YES_NO,
        max_length=5,
        null=True,
        blank=True)

    flucytosine_dose_four_datetime = models.DateTimeField(
        verbose_name=mark_safe(
            'Date and time Flucytosine <u>DOSE&nbsp;4</u> was swallowed?'),
        null=True,
        blank=True)

    flucytosine_dose_reason_missed = models.TextField(
        verbose_name='If any Flucytosine doses not given, provide reason',
        max_length=75,
        null=True,
        blank=True)

    fluconazole_dose = models.IntegerField(verbose_name='Fluconazole dose?',
                                           null=True,
                                           blank=True,
                                           help_text='Units in mg')

    fluconazole_dose_given = models.CharField(
        verbose_name='Was the Fluconazole dose given?',
        choices=YES_NO,
        max_length=5,
        null=True,
        blank=True)

    fluconazole_dose_datetime = models.DateTimeField(
        verbose_name='Date and time Fluconazole was swallowed?',
        null=True,
        blank=True)

    fluconazole_dose_reason_missed = models.TextField(
        verbose_name='If Fluconazole dose not given, provide reason',
        max_length=75,
        null=True,
        blank=True)

    blood_sample_one_datetime = models.DateTimeField(verbose_name=mark_safe(
        'Date and time blood <u>SAMPLE&nbsp;1</u> taken?'),
                                                     null=True,
                                                     blank=True)

    blood_sample_two_datetime = models.DateTimeField(verbose_name=mark_safe(
        'Date and time blood <u>SAMPLE&nbsp;2</u> taken?'),
                                                     null=True,
                                                     blank=True)

    blood_sample_three_datetime = models.DateTimeField(verbose_name=mark_safe(
        'Date and time blood <u>SAMPLE&nbsp;3</u> taken?'),
                                                       null=True,
                                                       blank=True)

    blood_sample_four_datetime = models.DateTimeField(verbose_name=mark_safe(
        'Date and time blood <u>SAMPLE&nbsp;4</u> taken?'),
                                                      null=True,
                                                      blank=True)

    blood_sample_five_datetime = models.DateTimeField(verbose_name=mark_safe(
        'Date and time blood <u>SAMPLE&nbsp;5</u> taken?'),
                                                      null=True,
                                                      blank=True)

    blood_sample_six_datetime = models.DateTimeField(verbose_name=mark_safe(
        'Date and time blood <u>SAMPLE&nbsp;6</u> taken?'),
                                                     null=True,
                                                     blank=True)

    blood_sample_missed = models.CharField(
        verbose_name='Were any blood samples missed?',
        choices=YES_NO,
        max_length=5,
        null=True,
        blank=True)

    blood_sample_reason_missed = models.TextField(
        verbose_name='If any blood samples missed, provide reason',
        max_length=75,
        null=True,
        blank=True)

    pre_dose_lp = models.CharField(verbose_name='Is this a pre-dose LP?',
                                   choices=YES_NO,
                                   max_length=5,
                                   null=True,
                                   blank=True)

    post_dose_lp = models.CharField(verbose_name='Is this a post-dose LP?',
                                    choices=YES_NO,
                                    max_length=5,
                                    null=True,
                                    blank=True)

    time_csf_sample_taken = models.DateTimeField(
        verbose_name='What date and time was the CSF sample taken?',
        null=True,
        blank=True)

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'PK/PD'
        verbose_name_plural = 'PK/PD'
Beispiel #30
0
class Week2(ClinicalAssessmentModelMixin, CrfModelMixin):

    discharged = models.CharField(verbose_name='Discharged?',
                                  max_length=25,
                                  choices=YES_NO)

    discharge_date = models.DateField(validators=[date_not_future],
                                      null=True,
                                      blank=True)

    died = models.CharField(verbose_name='Died?',
                            max_length=25,
                            choices=YES_NO)

    death_date_time = models.DateTimeField(validators=[datetime_not_future],
                                           null=True,
                                           blank=True)

    ampho_start_date = models.DateField(
        verbose_name='Amphotericin B start date: ',
        validators=[date_not_future],
        null=True,
        blank=True)

    ampho_end_date = models.DateField(verbose_name='Amphotericin B end date: ',
                                      validators=[date_not_future],
                                      null=True,
                                      blank=True)

    ampho_duration = models.IntegerField(
        verbose_name='Amphotericin B treatment duration',
        null=True,
        blank=True)

    flucon_start_date = models.DateField(
        verbose_name='Fluconazole start date:',
        validators=[date_not_future],
        null=True,
        blank=True)

    flucon_stop_date = models.DateField(verbose_name='Fluconazole end date:',
                                        validators=[date_not_future],
                                        null=True,
                                        blank=True)

    flucon_duration = models.IntegerField(
        verbose_name='Fluconazole treatment duration:', null=True, blank=True)

    flucy_start_date = models.DateField(verbose_name='Flucytosine start date:',
                                        validators=[date_not_future],
                                        null=True,
                                        blank=True)

    flucy_stop_date = models.DateField(verbose_name='Flucytosine end date:',
                                       validators=[date_not_future],
                                       null=True,
                                       blank=True)

    flucy_duration = models.IntegerField(
        verbose_name='Flucytosine treatment duration:', null=True, blank=True)

    ambi_start_date = models.DateField(verbose_name='Ambisome start date:',
                                       validators=[date_not_future],
                                       null=True,
                                       blank=True)

    ambi_stop_date = models.DateField(verbose_name='Ambisome end date:',
                                      validators=[date_not_future],
                                      null=True,
                                      blank=True)

    ambi_duration = models.IntegerField(
        verbose_name='Ambisome treatment duration:', null=True, blank=True)

    drug_intervention = models.ManyToManyField(
        OtherDrug,
        verbose_name="Other drugs/interventions given during first 14 days",
    )

    drug_intervention_other = models.CharField(
        verbose_name='If other, please specify:',
        blank=True,
        max_length=50,
        null=True)

    antibiotic = models.ManyToManyField(
        Antibiotic,
        blank=True,
        verbose_name="Were any of the following antibiotics given?",
    )

    antibiotic_other = models.CharField(
        verbose_name='If other antibiotics, please specify:',
        max_length=50,
        null=True,
        blank=True)

    blood_received = models.CharField(
        verbose_name='Blood transfusion received?',
        max_length=25,
        choices=YES_NO)

    units = models.IntegerField(verbose_name='If YES, no. of units',
                                validators=[MinValueValidator(1)],
                                null=True,
                                blank=True)

    temperature = models.FloatField(verbose_name='Temperature',
                                    null=True,
                                    blank=True,
                                    default=None)

    weight = models.DecimalField(
        verbose_name='Weight:',
        validators=[MinValueValidator(20),
                    MaxValueValidator(150)],
        decimal_places=1,
        max_digits=4,
        help_text='kg')

    medicines = models.ManyToManyField(Day14Medication,
                                       verbose_name='Medicine day 14:')

    medicine_other = models.CharField(verbose_name='If other, please specify:',
                                      max_length=50,
                                      null=True,
                                      blank=True)

    significant_dx = models.CharField(
        verbose_name='Other significant diagnoses since enrolment?',
        max_length=25,
        choices=YES_NO)

    significant_dx_datetime = models.DateTimeField(
        validators=[date_not_future], null=True, blank=True)

    flucon_missed_doses = models.CharField(
        verbose_name='Were any Fluconazole drug doses missed?',
        max_length=25,
        choices=YES_NO)

    amphotericin_missed_doses = models.CharField(
        verbose_name='Were any Amphotericin B drug doses missed?',
        max_length=25,
        choices=YES_NO)

    other_significant_dx = models.CharField(
        verbose_name='Other significant diagnosis since enrollment?',
        max_length=5,
        choices=YES_NO)

    on_site = CurrentSiteManager()

    objects = CrfModelManager()

    history = HistoricalRecords()

    class Meta(CrfModelMixin.Meta):
        verbose_name = 'Week 2'
        verbose_name_plural = 'Week 2'