Beispiel #1
0
class PersonalFieldsMixin(CryptoMixin, models.Model):

    first_name = FirstnameField(
        null=True, blank=False)

    last_name = LastnameField(
        verbose_name="Last name",
        null=True, blank=False)

    initials = EncryptedCharField(
        validators=[RegexValidator(
            regex=r'^[A-Z]{2,3}$',
            message=('Ensure initials consist of letters '
                     'only in upper case, no spaces.'))],
        null=True, blank=False)

    dob = models.DateField(
        verbose_name="Date of birth",
        null=True,
        blank=False)

    is_dob_estimated = IsDateEstimatedField(
        verbose_name="Is date of birth estimated?",
        null=True,
        blank=False)

    gender = models.CharField(
        verbose_name="Gender",
        choices=GENDER_UNDETERMINED,
        max_length=1,
        null=True,
        blank=False)

    guardian_name = LastnameField(
        verbose_name=('Guardian\'s last and first name'),
        validators=[FullNameValidator()],
        blank=True,
        null=True,
        help_text=mark_safe(
            'Required only if participant is a minor.<BR>'
            'Format is \'LASTNAME, FIRSTNAME\'. '
            'All uppercase separated by a comma.'))

    subject_type = models.CharField(
        max_length=25)

    class Meta:
        abstract = True
Beispiel #2
0
class RegisteredSubject(BaseUuidModel):
    subject_identifier = models.CharField(max_length=25)

    first_name = FirstnameField(null=True)

    last_name = LastnameField(verbose_name="Last name")

    gender = models.CharField(max_length=1, choices=GENDER)
class ChildBirth(UniqueSubjectIdentifierFieldMixin, SiteModelMixin,
                 CryptoMixin, BaseUuidModel):
    """ A model completed by the user on the infant's birth. """

    report_datetime = models.DateTimeField(
        verbose_name="Date and Time infant enrolled",
        validators=[
            datetime_not_future,
        ])

    first_name = FirstnameField(
        max_length=25,
        verbose_name="Infant's first name",
        help_text="If infant name is unknown or not yet determined, "
        "use Baby + birth order + mother's last name, e.g. 'Baby1Malane'")

    last_name = LastnameField(
        max_length=25,
        verbose_name="Infant's last name",
        help_text="If infant name is unknown or not yet determined, "
        "use Baby + birth order + mother's last name, e.g. 'Baby1Malane'")

    initials = EncryptedCharField(validators=[
        RegexValidator(regex=r'^[A-Z]{2,3}$',
                       message=('Ensure initials consist of letters '
                                'only in upper case, no spaces.'))
    ], )

    dob = models.DateField(verbose_name='Date of Birth',
                           help_text="Must match labour and delivery report.",
                           validators=[
                               date_not_future,
                           ])

    gender = models.CharField(max_length=10, choices=GENDER_UNDETERMINED)

    def __str__(self):
        return f'{self.first_name}, {self.initials}, {self.gender}'

    @property
    def registered_subject(self):
        """Return infant registered subject.
        """
        registered_subject_cls = django_apps.get_model(
            'edc_registration.registeredsubject')
        try:
            registered_subject = registered_subject_cls.objects.get(
                subject_identifier=self.subject_identifier)
        except registered_subject_cls.DoesNotExist:
            raise ValidationError(
                f'Registered Subject is missing for {self.subject_identifier}')
        else:
            return registered_subject

    class Meta:
        app_label = 'flourish_child'
        verbose_name = "Child Birth"
Beispiel #4
0
class VulnerabilityFieldsMixin(CryptoMixin, models.Model):

    is_incarcerated = models.CharField(
        verbose_name="Is the participant under involuntary incarceration?",
        max_length=3,
        choices=YES_NO,
        validators=[eligible_if_no],
        null=True,
        help_text="( if 'Yes' STOP participant cannot be consented )",
    )

    is_literate = models.CharField(
        verbose_name="Is the participant literate?",
        max_length=3,
        choices=YES_NO,
        help_text=("If 'No' provide witness's name on this "
                   "form and signature on the paper document."),
    )

    witness_name = LastnameField(
        verbose_name="Witness's last and first name",
        validators=[FullNameValidator()],
        blank=True,
        null=True,
        help_text=mark_safe("Required only if participant is illiterate.<br>"
                            "Format is 'LASTNAME, FIRSTNAME'. "
                            "All uppercase separated by a comma."),
    )

    language = models.CharField(
        verbose_name="Language of consent",
        max_length=25,
        choices=settings.LANGUAGES,
        help_text=("The language used for the consent process will "
                   "also be used during data collection."),
    )

    class Meta:
        abstract = True
class RegisteredSubject(UniqueSubjectIdentifierModelMixin, SiteModelMixin,
                        edc_models.BaseUuidModel):
    """A model mixin for the RegisteredSubject model (only)."""

    # may not be available when instance created (e.g. infants prior to birth
    # report)
    first_name = FirstnameField(null=True)

    # may not be available when instance created (e.g. infants or household
    # subject before consent)
    last_name = LastnameField(verbose_name="Last name", null=True)

    # may not be available when instance created (e.g. infants)
    initials = EncryptedCharField(
        validators=[
            RegexValidator(
                regex=r"^[A-Z]{2,3}$",
                message=("Ensure initials consist of letters "
                         "only in upper case, no spaces."),
            )
        ],
        null=True,
    )

    dob = models.DateField(
        verbose_name=_("Date of birth"),
        null=True,
        blank=False,
        help_text=_("Format is YYYY-MM-DD"),
    )

    is_dob_estimated = IsDateEstimatedField(
        verbose_name=_("Is date of birth estimated?"), null=True, blank=False)

    gender = models.CharField(verbose_name="Gender",
                              max_length=1,
                              choices=GENDER,
                              null=True,
                              blank=False)

    subject_consent_id = models.CharField(max_length=100,
                                          null=True,
                                          blank=True)

    registration_identifier = models.CharField(max_length=36,
                                               null=True,
                                               blank=True)

    sid = models.CharField(verbose_name="SID",
                           max_length=15,
                           null=True,
                           blank=True)

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

    relative_identifier = models.CharField(
        verbose_name="Identifier of immediate relation",
        max_length=36,
        null=True,
        blank=True,
        help_text=
        "For example, mother's identifier, if available / appropriate",
    )

    identity = IdentityField(null=True, blank=True)

    identity_type = IdentityTypeField(null=True, blank=True)

    screening_identifier = models.CharField(max_length=36,
                                            null=True,
                                            blank=True)

    screening_datetime = models.DateTimeField(null=True, blank=True)

    screening_age_in_years = models.IntegerField(null=True, blank=True)

    registration_datetime = models.DateTimeField(null=True, blank=True)

    # For simplicity, if going straight from screen to rando,
    # update both registration date and randomization date
    randomization_datetime = models.DateTimeField(null=True, blank=True)

    registration_status = models.CharField(verbose_name="Registration status",
                                           max_length=25,
                                           null=True,
                                           blank=True)

    consent_datetime = models.DateTimeField(null=True, blank=True)

    comment = models.TextField(verbose_name="Comment",
                               max_length=250,
                               null=True,
                               blank=True)

    additional_key = models.CharField(
        max_length=36,
        verbose_name="-",
        editable=False,
        default=None,
        null=True,
        help_text=(
            "A uuid (or some other text value) to be added to bypass the "
            "unique constraint of just firstname, initials, and dob."
            "The default constraint proves limiting since the source "
            "model usually has some other attribute in additional to "
            "first_name, initials and dob which is not captured in "
            "this model"),
    )

    dm_comment = models.CharField(
        verbose_name="Data Management comment",
        max_length=150,
        null=True,
        editable=False,
    )

    randomization_list_model = models.CharField(max_length=150, null=True)

    on_site = CurrentSiteManager()

    history = edc_models.HistoricalRecords()

    objects = RegisteredSubjectManager()

    def save(self, *args, **kwargs):
        if self.identity:
            self.additional_key = None
        self.set_uuid_as_subject_identifier_if_none()
        self.raise_on_duplicate("subject_identifier")
        self.raise_on_duplicate("identity")
        self.raise_on_changed_subject_identifier()
        super().save(*args, **kwargs)

    def natural_key(self):
        return tuple(self.subject_identifier_as_pk)

    def __str__(self):
        return self.masked_subject_identifier

    natural_key.dependencies = ["sites.Site"]

    def update_subject_identifier_on_save(self):
        """Overridden to not set the subject identifier on save."""
        if not self.subject_identifier:
            self.subject_identifier = self.subject_identifier_as_pk.hex
        elif re.match(UUID_PATTERN, self.subject_identifier):
            pass
        return self.subject_identifier

    def make_new_identifier(self):
        return self.subject_identifier_as_pk.hex

    @property
    def masked_subject_identifier(self):
        """Returns the subject identifier, if set, otherwise
        the string '<identifier not set>'.
        """
        if not self.subject_identifier_is_set:
            return "<identifier not set>"
        return self.subject_identifier

    @property
    def subject_identifier_is_set(self):
        """Returns True if subject identifier has been set to a
        subject identifier; that is, no longer the default UUID.
        """
        is_set = True
        try:
            obj = self.__class__.objects.get(pk=self.id)
        except ObjectDoesNotExist:
            is_set = False
        else:
            if re.match(UUID_PATTERN, obj.subject_identifier):
                return False
        return is_set

    def raise_on_changed_subject_identifier(self):
        """Raises an exception if there is an attempt to change
        the subject identifier for an existing instance if the subject
        identifier is already set.
        """
        if self.id and self.subject_identifier_is_set:
            with transaction.atomic():
                obj = self.__class__.objects.get(pk=self.id)
                if obj.subject_identifier != self.subject_identifier_as_pk.hex:
                    if self.subject_identifier != obj.subject_identifier:
                        raise RegisteredSubjectError(
                            "Subject identifier cannot be changed for "
                            "existing registered subject. "
                            f"Got {self.subject_identifier} <> {obj.subject_identifier}."
                        )

    def raise_on_duplicate(self, attrname):
        """Checks if the subject identifier (or other attr) is in use,
        for new and existing instances.
        """
        if getattr(self, attrname):
            with transaction.atomic():
                error_msg = (
                    f"Cannot {{action}} registered subject with a duplicate "
                    f"'{attrname}'. Got {getattr(self, attrname)}.")
                try:
                    obj = self.__class__.objects.exclude(**{
                        "pk": self.pk
                    } if self.id else {}).get(
                        **{attrname: getattr(self, attrname)})
                    if not self.id:
                        raise RegisteredSubjectError(
                            error_msg.format(action="insert"))
                    elif self.subject_identifier_is_set and obj.id != self.id:
                        raise RegisteredSubjectError(
                            error_msg.format(action="update"))
                    else:
                        raise RegisteredSubjectError(
                            error_msg.format(action="update"))
                except ObjectDoesNotExist:
                    pass

    def set_uuid_as_subject_identifier_if_none(self):
        """Inserts a random uuid as a dummy identifier for a new
        instance.

        Model uses subject_identifier_as_pk as a natural key for
        serialization/deserialization. Value must not change
        once set.
        """
        if not self.subject_identifier:
            self.subject_identifier = self.subject_identifier_as_pk.hex

    class Meta(edc_models.BaseUuidModel.Meta):
        verbose_name = "Registered Subject"
        ordering = ["subject_identifier"]
        unique_together = ("first_name", "dob", "initials", "additional_key")
        indexes = [
            models.Index(
                fields=["first_name", "dob", "initials", "additional_key"]),
            models.Index(fields=[
                "identity", "subject_identifier", "screening_identifier"
            ]),
        ]
        permissions = (
            ("display_firstname", "Can display first name"),
            ("display_lastname", "Can display last name"),
            ("display_dob", "Can display DOB"),
            ("display_identity", "Can display identity number"),
            ("display_initials", "Can display initials"),
        )
class MaternalDataset(NonUniqueSubjectIdentifierFieldMixin, SiteModelMixin,
                      SearchSlugModelMixin, BaseUuidModel):

    identifier_cls = ScreeningIdentifier

    screening_identifier = models.CharField(
        verbose_name="Eligibility Identifier",
        max_length=36,
        blank=True,
        null=True,
        unique=True)

    study_maternal_identifier = models.CharField(
        verbose_name="Study maternal Subject Identifier",
        max_length=50,
        unique=True)

    first_name = FirstnameField(verbose_name='Firstname',
                                null=True,
                                blank=False)

    last_name = LastnameField(verbose_name='Lastname', null=True, blank=False)

    protocol = models.CharField(max_length=150)

    delivdt = models.DateField(verbose_name='Delivery date',
                               blank=True,
                               null=True)

    site_name = models.CharField(max_length=150)

    mom_enrolldate = models.DateField(verbose_name='Maternal enrollment date',
                                      blank=True,
                                      null=True)

    delivmeth = models.CharField(verbose_name='Method of delivery',
                                 max_length=150,
                                 blank=True,
                                 null=True)

    delivery_location = models.CharField(verbose_name='Delivery location',
                                         max_length=150,
                                         blank=True,
                                         null=True)

    ega_delivery = models.IntegerField(verbose_name='EGA at delivery',
                                       blank=True,
                                       null=True)

    mom_age_enrollment = models.CharField(
        verbose_name='Mother\'s age at enrollment',
        max_length=150,
        blank=True,
        null=True)

    mom_hivstatus = models.CharField(
        verbose_name='Maternal HIV infection status', max_length=150)

    parity = models.IntegerField(blank=True, null=True)

    gravida = models.IntegerField(blank=True, null=True)

    mom_education = models.CharField(verbose_name='Maternal education level',
                                     max_length=150,
                                     blank=True,
                                     null=True)

    mom_maritalstatus = models.CharField(
        verbose_name='Maternal marital status',
        max_length=150,
        blank=True,
        null=True)

    mom_personal_earnings = models.CharField(
        verbose_name='Mother\'s personal earnings',
        max_length=150,
        blank=True,
        null=True)

    mom_moneysource = models.CharField(
        verbose_name='Maternal source of income',
        max_length=150,
        blank=True,
        null=True)

    mom_occupation = models.CharField(verbose_name='Mother\'s occupation',
                                      max_length=150,
                                      blank=True,
                                      null=True)

    mom_pregarv_strat = models.CharField(
        verbose_name='Maternal ARVs during pregnancy',
        max_length=150,
        blank=True,
        null=True)

    mom_arvstart_date = models.DateField(
        verbose_name='Date mother started HAART', blank=True, null=True)

    mom_baseline_cd4 = models.IntegerField(
        verbose_name='Maternal baseline CD4 count', blank=True, null=True)

    mom_baseline_cd4date = models.DateField(
        verbose_name='Draw data of mother\'s baseline CD4',
        blank=True,
        null=True)

    mom_baseline_vl = models.IntegerField(
        verbose_name='Maternal baseline viral load', blank=True, null=True)

    mom_baseline_vldate = models.DateField(
        verbose_name='Draw date of mother\'s baseline VL',
        blank=True,
        null=True)

    mom_baseline_hgb = models.DecimalField(
        verbose_name='Maternal baseline HGB',
        decimal_places=1,
        max_digits=10,
        blank=True,
        null=True)

    mom_baseline_hgbdt = models.DateField(
        verbose_name='Date of maternal baseline HGB', blank=True, null=True)

    mom_deathdate = models.DateField(verbose_name='Date mother died',
                                     blank=True,
                                     null=True)

    cooking_method = models.CharField(verbose_name='Primary cooking method',
                                      max_length=200,
                                      blank=True,
                                      null=True)

    home_eletrified = models.CharField(verbose_name='Electricity in home',
                                       max_length=150,
                                       blank=True,
                                       null=True)

    house_type = models.CharField(verbose_name='Type of dwelling',
                                  max_length=150,
                                  blank=True,
                                  null=True)

    toilet = models.CharField(verbose_name='Toilet facilities',
                              max_length=150,
                              blank=True,
                              null=True)

    toilet_indoors = models.CharField(verbose_name='House has indoor toilet',
                                      max_length=150,
                                      blank=True,
                                      null=True)

    toilet_private = models.CharField(
        verbose_name='Private toilet for compound',
        max_length=150,
        blank=True,
        null=True)

    piped_water = models.CharField(verbose_name='Water piped into home',
                                   max_length=150,
                                   blank=True,
                                   null=True)

    home_refridgeration = models.CharField(
        verbose_name='Refrigeration in home',
        max_length=150,
        blank=True,
        null=True)

    drinking_water = models.CharField(verbose_name='Source of drinking water',
                                      max_length=150,
                                      blank=True,
                                      null=True)

    live_inhouse_number = models.IntegerField(
        verbose_name='Number of people living in household',
        blank=True,
        null=True)

    twin_triplet = models.IntegerField(verbose_name='Twins or thiplets',
                                       blank=True,
                                       null=True)

    preg_dtg = models.IntegerField(verbose_name='Preg DTG',
                                   blank=True,
                                   null=True)

    preg_pi = models.IntegerField(verbose_name='Preg PI',
                                  blank=True,
                                  null=True)

    preg_efv = models.IntegerField(verbose_name='Preg EFV',
                                   blank=True,
                                   null=True)

    on_worklist = models.BooleanField(default=False, blank=True, null=True)

    objects = MaternalDatasetManager()

    def __str__(self):
        return self.study_maternal_identifier

    def save(self, *args, **kwargs):
        if not self.screening_identifier:
            self.screening_identifier = self.identifier_cls().identifier
        super().save(*args, **kwargs)

    def get_search_slug_fields(self):
        fields = super().get_search_slug_fields()
        fields.append('screening_identifier')
        fields.append('study_maternal_identifier')
        fields.append('first_name')
        return fields

    class Meta:
        app_label = 'flourish_caregiver'
        verbose_name = 'Maternal Dataset'
Beispiel #7
0
class InformedConsent(SiteModelMixin, BaseUuidModel):
    consent_datetime = models.DateTimeField(
        verbose_name='Consent datetime',
        default=get_utcnow,
        help_text='Date and time of consent.')

    first_name = FirstnameField(blank=False)

    last_name = LastnameField(blank=False)

    language = models.CharField(
        verbose_name='Language of consent',
        max_length=50,
        choices=settings.LANGUAGES,
        null=True,
        blank=True,
        help_text=('The language used for the consent process will '
                   'also be used during data collection.'))

    is_literate = models.CharField(
        verbose_name='Is the participant literate?',
        max_length=5,
        choices=YES_NO,
        help_text='If No provide witness name on this form and signature'
        'on the paper document')

    witness_fname = FirstnameField(
        verbose_name='Witness first name',
        max_length=5,
    )

    witness_lname = LastnameField(
        verbose_name='Witness last name',
        max_length=5,
    )

    gender = models.CharField(verbose_name="Gender",
                              choices=GENDER,
                              max_length=1)

    date_of_birth = models.DateField(verbose_name="Date of birth",
                                     validators=[
                                         date_not_future,
                                     ])

    is_estimated = IsDateEstimatedField(
        verbose_name="Is date of birth estimated?", null=True, blank=False)
    national_identity = IdentityField(
        verbose_name='Patient ID number (Omang)',
        # validators=[identity_check, ],
        unique=True)

    identity_type = models.CharField(
        verbose_name='What type of identity number is this?',
        max_length=25,
        choices=IDENTITY_TYPE)
    """"Review Questions"""

    reviewed_consent = models.CharField(
        verbose_name='I have reviewed the consent with the participant',
        max_length=3,
        choices=YES_NO,
        help_text='If no, participant is not eligible.')

    answered_all_questions = models.CharField(
        verbose_name='I have answered all questions the participant'
        ' had about the study',
        max_length=3,
        choices=YES_NO,
        help_text='If no, participant is not eligible.')

    asked_questions = models.CharField(
        verbose_name='I have asked the participant questions about'
        ' this study and the participant has demonstrated '
        'understanding',
        max_length=3,
        choices=YES_NO,
        help_text='If no, participant is not eligible.')

    have_verified = models.CharField(
        verbose_name='I have verified that the participant has'
        'signed the consent form',
        max_length=3,
        choices=YES_NO,
        help_text='If no, participant is not eligible.')

    copy_of_consent = models.CharField(
        verbose_name='I have provided the participant with a copy'
        ' of their signed informed consent',
        max_length=3,
        choices=YES_NO,
        help_text='if declined, return copy with the consent')

    class Meta:
        verbose_name = "Informed Consent"
        verbose_name_plural = "Informed Consent"
Beispiel #8
0
class PersonalFieldsMixin(CryptoMixin, models.Model):

    first_name = FirstnameField(
        null=True,
        blank=False,
        validators=[
            RegexValidator(
                regex=r"^([A-Z]+$|[A-Z]+\ [A-Z]+)$",
                message="Ensure name consist of letters only in upper case",
            )
        ],
        help_text="Use UPPERCASE letters only.",
    )

    last_name = LastnameField(
        verbose_name="Surname",
        null=True,
        blank=False,
        validators=[
            RegexValidator(
                regex=r"^([A-Z]+$|[A-Z]+\ [A-Z]+)$",
                message="Ensure name consist of letters only in upper case",
            )
        ],
        help_text="Use UPPERCASE letters only.",
    )

    initials = EncryptedCharField(
        validators=[
            RegexValidator(
                regex=r"^[A-Z]{2,3}$",
                message=
                "Ensure initials consist of letters only in upper case, no spaces.",
            )
        ],
        null=True,
        blank=False,
    )

    dob = models.DateField(verbose_name="Date of birth",
                           null=True,
                           blank=False)

    is_dob_estimated = IsDateEstimatedField(
        verbose_name="Is date of birth estimated?", null=True, blank=False)

    gender = models.CharField(
        verbose_name="Gender",
        choices=GENDER_UNDETERMINED,
        max_length=1,
        null=True,
        blank=False,
    )

    guardian_name = LastnameField(
        verbose_name="Guardian's last and first name",
        validators=[FullNameValidator()],
        blank=True,
        null=True,
        help_text=mark_safe("Required only if participant is a minor.<BR>"
                            "Format is 'LASTNAME, FIRSTNAME'. "
                            "All uppercase separated by a comma."),
    )

    subject_type = models.CharField(max_length=25)

    class Meta:
        abstract = True
Beispiel #9
0
class SubjectLocator(UniqueSubjectIdentifierFieldMixin, SiteModelMixin,
                     SubjectContactFieldsMixin, SearchSlugModelMixin,
                     BaseUuidModel):
    """A model completed by the user to that captures participant
    locator information and permission to contact.
    """

    loc_admin = models.CharField(verbose_name='Administered by', max_length=50)

    first_name = FirstnameField(verbose_name='First Names', max_length=50)

    last_name = LastnameField(verbose_name='Surname', max_length=50)

    initials = EncryptedCharField(validators=[
        RegexValidator(regex=r'^[A-Z]{2,3}$',
                       message=('Ensure initials consist of letters '
                                'only in upper case, no spaces.'))
    ],
                                  null=True,
                                  blank=False)

    loc_date = models.DateField(
        verbose_name='Date Completed',
        default=get_utcnow,
        validators=[date_not_before_study_start, date_not_future])

    may_call = models.CharField(
        max_length=3,
        choices=YES_NO,
        verbose_name=mark_safe(
            'Has the participant given permission <b>to be contacted on this '
            'cell number</b>?'),
        blank=True,
        null=True)

    may_call_alt = models.CharField(
        max_length=3,
        choices=YES_NO,
        verbose_name=mark_safe(
            'Has the participant given permission <b>to be contacted on this '
            'cell number</b>?'),
        blank=True,
        null=True)

    subject_cell_alt_3 = EncryptedCharField(
        verbose_name='Cell number (second alternate)', blank=True, null=True)

    may_call_tel = models.CharField(
        max_length=3,
        choices=YES_NO,
        verbose_name=mark_safe(
            'Has the participant given permission <b>to be contacted on this '
            'telephone number</b>?'),
        blank=True,
        null=True)

    loc_email = models.EmailField(blank=True,
                                  null=True,
                                  help_text='If no email, write None')

    may_contact_email = models.CharField(
        max_length=3,
        choices=YES_NO_NA,
        verbose_name=mark_safe(
            'Has the participant given permission <b>to be contacted by '
            'email</b>?'),
        blank=True,
        null=True)

    loc_village = EncryptedTextField(verbose_name='Home Village',
                                     max_length=500,
                                     help_text='')

    loc_address = EncryptedTextField(
        verbose_name='Physical address with detailed description',
        max_length=500,
        blank=True,
        null=True,
        help_text='')

    may_visit_home = models.CharField(
        max_length=25,
        choices=YES_NO,
        blank=True,
        null=True,
        verbose_name=mark_safe(
            'Has the participant given permission for study '
            'staff <b>to make home visits</b> for follow-up purposes?'))

    idcc_clinic = models.CharField(verbose_name='Name of IDCC Clinic',
                                   max_length=25,
                                   blank=True,
                                   null=True)

    may_contact_idcc = models.CharField(verbose_name=(
        'Has the participant given permission to be contacted, '
        'through their IDCC clinic?, if unable to contact phone numbers'),
                                        max_length=3,
                                        choices=YES_NO_NA,
                                        blank=True,
                                        null=True)

    loc_workplace = models.CharField(verbose_name='Name of workplace',
                                     max_length=25,
                                     blank=True,
                                     null=True,
                                     help_text='(for those who are working)')

    loc_workphone = EncryptedCharField(verbose_name='Work Telephone',
                                       blank=True,
                                       null=True)

    may_contact_work = models.CharField(verbose_name=(
        'Has participant given permission to be contacted at their '
        'workplace?, if unable to contact phone numbers'),
                                        max_length=3,
                                        choices=YES_NO_NA,
                                        blank=True,
                                        null=True)

    loc_kincontact = EncryptedTextField(verbose_name=(
        'Name and contact details of next of kin or any individuals '
        'participant allows us to contact if they can\'t be reached.'
        '(can list multiple people)'),
                                        max_length=500,
                                        blank=True,
                                        null=True)

    may_contact_kin = models.CharField(verbose_name=(
        'Has participant given permission to contact anyone else?'
        ' , if unable to contact phone numbers'),
                                       max_length=3,
                                       choices=YES_NO_NA,
                                       blank=True,
                                       null=True)

    date_followup = models.DateField(verbose_name='Date of follow-up visit')

    initial_call_date = models.DateField(verbose_name='Initial call date',
                                         default=get_utcnow)

    review_locator = models.CharField(
        verbose_name=('Did you review this form with the participant to '
                      'find out if there are any updates?'),
        max_length=3,
        choices=YES_NO)

    history = HistoricalRecords()

    objects = LocatorManager()

    def __str__(self):
        return '{}'.format(self.subject_identifier)

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

    natural_key.dependencies = ['sites.Site']

    def save(self, *args, **kwargs):
        if not self.initials:
            self.initials = f'{self.first_name[:1]}{self.last_name[:1]}'
        super().save(*args, **kwargs)

    class Meta:
        app_label = 'motheo_call_manager'
        verbose_name = 'Subject Locator'
class ChildDataset(NonUniqueSubjectIdentifierFieldMixin, SiteModelMixin,
                   BaseUuidModel):

    study_child_identifier = models.CharField(
        max_length=150,
        unique=True,
        verbose_name='Study Child Subject Identifier')

    study_maternal_identifier = models.CharField(
        verbose_name="Study maternal Subject Identifier", max_length=50)

    first_name = FirstnameField(verbose_name='Firstname',
                                null=True,
                                blank=False)

    last_name = LastnameField(null=True, blank=False)

    dob = models.DateField(null=True, blank=True)

    age_today = models.DecimalField(verbose_name='Age today',
                                    decimal_places=2,
                                    max_digits=10,
                                    blank=True,
                                    null=True)

    age_calculation_date = models.DateField(
        verbose_name='Age calculation date', blank=True, null=True)

    infant_enrolldate = models.DateField(verbose_name='Infant enrollment date')

    infant_randdt = models.DateField(
        verbose_name='Date of infant randomization', blank=True, null=True)

    infant_sex = models.CharField(verbose_name='Infant gender', max_length=7)

    infant_azt_birth = models.CharField(verbose_name='Infant started AZT',
                                        max_length=15,
                                        blank=True,
                                        null=True)

    infant_azt_days = models.IntegerField(
        verbose_name='Duration of infant AZT (days)', blank=True, null=True)

    infant_azt_startdate = models.DateField(verbose_name='AZT start date',
                                            blank=True,
                                            null=True)

    infant_azt_stopdate = models.DateField(verbose_name='AZT stop date',
                                           blank=True,
                                           null=True)

    infant_sdnvp_birth = models.CharField(verbose_name='Infant received sdNVP',
                                          max_length=15,
                                          null=True)

    infant_hiv_exposed = models.CharField(
        verbose_name='Infant HIV exposure status', max_length=150)

    infant_hiv_status = models.CharField(
        verbose_name='Infant HIV infection status', max_length=150)

    infant_breastfed = models.CharField(verbose_name='Infant breastfed',
                                        max_length=150,
                                        blank=True,
                                        null=True)

    infant_breastfed_days = models.IntegerField(
        verbose_name='Breastfeeding duration (days)', blank=True, null=True)

    weaned = models.CharField(verbose_name='Weaning indicator',
                              max_length=150,
                              blank=True,
                              null=True)

    weandt = models.DateField(verbose_name='Weaning date',
                              blank=True,
                              null=True)

    weancat = models.CharField(verbose_name='Weaning by category',
                               max_length=150,
                               blank=True,
                               null=True)

    birthweight = models.DecimalField(verbose_name='Birth weight (kg)',
                                      decimal_places=2,
                                      max_digits=10,
                                      blank=True,
                                      null=True)

    birthwtcat = models.CharField(verbose_name='Birth weight (kg) by category',
                                  max_length=150,
                                  blank=True,
                                  null=True)

    height_0 = models.DecimalField(verbose_name='Height (cm) at delivery',
                                   decimal_places=2,
                                   max_digits=10,
                                   blank=True,
                                   null=True)

    headcirc_0 = models.DecimalField(
        verbose_name='Head circumference (cm) at delivery',
        decimal_places=2,
        max_digits=10,
        blank=True,
        null=True)

    apgarscore_1min = models.IntegerField(verbose_name='APGAR score at 1min',
                                          blank=True,
                                          null=True)

    apgarscore_5min = models.IntegerField(verbose_name='APGAR score at 5min',
                                          blank=True,
                                          null=True)

    apgarscore_10min = models.IntegerField(verbose_name='APGAR score at 10min',
                                           blank=True,
                                           null=True)

    low_birthweight = models.CharField(
        verbose_name='Infant born low birth weight',
        max_length=150,
        blank=True,
        null=True)

    infant_premature = models.CharField(
        verbose_name='Infant born premature (<37 weeks)',
        max_length=150,
        blank=True,
        null=True)

    height_6mo = models.DecimalField(verbose_name='Height (cm) at 6 months',
                                     decimal_places=2,
                                     max_digits=10,
                                     blank=True,
                                     null=True)

    height_18mo = models.DecimalField(verbose_name='Height (cm) at 18 months',
                                      decimal_places=2,
                                      max_digits=10,
                                      blank=True,
                                      null=True)

    height_24mo = models.DecimalField(verbose_name='Height (cm) at 24 months',
                                      decimal_places=2,
                                      max_digits=10,
                                      blank=True,
                                      null=True)

    headcirc_18mo = models.DecimalField(
        verbose_name='Head circumference (cm) at 18 months',
        decimal_places=2,
        max_digits=10,
        blank=True,
        null=True)

    headcirc_24mo = models.DecimalField(
        verbose_name='Head circumference (cm) at 24 months',
        decimal_places=2,
        max_digits=10,
        blank=True,
        null=True)

    weight_18mo = models.DecimalField(verbose_name='Weight (kg) at 18 months',
                                      decimal_places=2,
                                      max_digits=10,
                                      blank=True,
                                      null=True)

    weight_24mo = models.DecimalField(verbose_name='Weight (kg) at 18 months',
                                      decimal_places=2,
                                      max_digits=10,
                                      blank=True,
                                      null=True)

    infant_vitalstatus_final = models.CharField(
        verbose_name='Final infant vital status', max_length=150)

    deathdt = models.DateField(verbose_name='Death date',
                               blank=True,
                               null=True)

    deathcause = models.CharField(verbose_name='Cause of death',
                                  max_length=150,
                                  blank=True,
                                  null=True)

    firsthospdt = models.DateField(
        verbose_name='Date of first hospitalization', blank=True, null=True)

    hospnum = models.IntegerField(verbose_name='Number of times hospitalized',
                                  blank=True,
                                  null=True)

    idth = models.IntegerField(
        verbose_name='Infant death indicator (0= censored)',
        blank=True,
        null=True)

    idth_days = models.IntegerField(
        verbose_name='Days from infant birth to death (censored)',
        blank=True,
        null=True)

    ihiv = models.IntegerField(
        verbose_name='Indicator of HIV endpoint (0=censored)',
        blank=True,
        null=True)

    ihiv_days = models.IntegerField(
        verbose_name='Time to HIV endpoint (days from birth)',
        blank=True,
        null=True)

    ihosp = models.IntegerField(
        verbose_name='Infant hospitalization indicator (0= censored)',
        blank=True,
        null=True)

    ihosp_days = models.IntegerField(
        verbose_name=
        'Days from infant birth to first hospitalization (censored)',
        blank=True,
        null=True)

    infantvacc_bcg = models.CharField(verbose_name='BCG vaccine received?',
                                      max_length=150,
                                      blank=True,
                                      null=True)

    infantvacc_dtap = models.CharField(verbose_name='DTAP vaccine received?',
                                       max_length=150,
                                       blank=True,
                                       null=True)

    infantvacc_hbv = models.CharField(verbose_name='HBV vaccine received?',
                                      max_length=150,
                                      blank=True,
                                      null=True)

    infantvacc_hiv = models.CharField(verbose_name='HIV vaccine received?',
                                      max_length=150,
                                      blank=True,
                                      null=True)

    infantvacc_measles = models.CharField(
        verbose_name='Measles vaccine received?',
        max_length=150,
        blank=True,
        null=True)

    infantvacc_mmr = models.CharField(verbose_name='MMR vaccine received?',
                                      max_length=150,
                                      blank=True,
                                      null=True)

    infantvacc_pneum = models.CharField(
        verbose_name='Pneumoccal vaccine received?',
        max_length=150,
        blank=True,
        null=True)

    infantvacc_polio = models.CharField(verbose_name='Polio vaccine received?',
                                        max_length=150,
                                        blank=True,
                                        null=True)

    infantvacc_rota = models.CharField(
        verbose_name='Rotavirus vaccine received?',
        max_length=150,
        blank=True,
        null=True)

    infant_offstudydate = models.DateField(blank=True, null=True)

    infant_lastcontactdt = models.DateField(blank=True, null=True)

    infant_onstudy_days = models.IntegerField(blank=True, null=True)

    infant_offstudy_reason = models.CharField(
        verbose_name='Days infant on-study', max_length=200)

    curr_age = models.DecimalField(verbose_name='Current Age',
                                   decimal_places=2,
                                   max_digits=10,
                                   blank=True,
                                   null=True)

    age_gt17_5 = models.IntegerField(verbose_name='Age greater than 17.5')

    infant_offstudy_complete = models.IntegerField(
        verbose_name='Infant Offstudy Complete')

    # today = models.DateField(
    #     blank=True, null=True)

    offstrs = models.CharField(verbose_name='Offstrs',
                               max_length=150,
                               blank=True,
                               null=True)

    offstcd = models.CharField(verbose_name='Offstcd',
                               max_length=50,
                               blank=True,
                               null=True)

    twin_triplet = models.BooleanField(default=False, editable=False)

    class Meta:
        app_label = 'flourish_child'
        verbose_name = 'Infant Dataset'
class CaregiverChildConsent(SiteModelMixin, NonUniqueSubjectIdentifierFieldMixin,
                            IdentityFieldsMixin, ReviewFieldsMixin,
                            PersonalFieldsMixin, VerificationFieldsMixin, BaseUuidModel):

    """Inline table for caregiver's children"""

    subject_consent = models.ForeignKey(
        SubjectConsent,
        on_delete=models.PROTECT)

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

    first_name = FirstnameField(
        null=True, blank=True)

    last_name = LastnameField(
        verbose_name="Last name",
        null=True, blank=True)

    study_child_identifier = models.CharField(
        verbose_name='Previous study identifier',
        max_length=50,
        null=True,
        blank=True)

    gender = models.CharField(
        verbose_name="Gender",
        choices=GENDER,
        max_length=1,
        null=True,
        blank=True)

    identity = IdentityField(
        verbose_name='Identity number',
        null=True,
        blank=True)

    identity_type = models.CharField(
        verbose_name='What type of identity number is this?',
        max_length=25,
        choices=CHILD_IDENTITY_TYPE,
        null=True,
        blank=True)

    confirm_identity = IdentityField(
        help_text='Retype the identity number',
        null=True,
        blank=True)

    child_dob = models.DateField(
        verbose_name="Date of birth",
        validators=[date_not_future, ],
        null=True,
        blank=True)

    child_test = models.CharField(
        verbose_name='Will you allow for HIV testing and counselling of '
                     'your Child',
        max_length=5,
        choices=YES_NO,
        help_text='If no, participant is not eligible.')

    child_remain_in_study = models.CharField(
        verbose_name='Is your child willing to remain in the study area until '
                     '2025?',
        max_length=5,
        choices=YES_NO,
        help_text='If no, participant is not eligible.')

    child_preg_test = models.CharField(
        verbose_name='If your child is female and will be 12 years or older '
                     'prior to 30-Jun-2025, will you allow the female child '
                     'to undergo pregnancy testing?',
        max_length=5,
        choices=YES_NO_NA,
        help_text='If no, participant is not eligible.')

    child_knows_status = models.CharField(
        verbose_name='If your child is ≥ 16 years, have they been told about '
                     'your HIV?',
        max_length=5,
        choices=YES_NO_NA,
        help_text='If no, participant is not eligible.')

    future_studies_contact = models.CharField(
        verbose_name=('Do you give us permission for us to contact you or your child'
                      ' for future studies?'),
        max_length=3,
        choices=YES_NO,)

    specimen_consent = models.CharField(
        verbose_name=('Do you give us permission for us to use your child\'s blood '
                      'samples for future studies?'),
        max_length=3,
        choices=YES_NO,)

    child_age_at_enrollment = models.DecimalField(
        decimal_places=2,
        max_digits=4)

    consent_datetime = models.DateTimeField(
        verbose_name='Consent date and time',
        validators=[
            datetime_not_before_study_start,
            datetime_not_future])

    version = models.CharField(
        verbose_name='Consent version',
        max_length=4,
        choices=CHILD_CONSENT_VERSION,
        blank=True)

    cohort = models.CharField(
        max_length=12,
        choices=COHORTS,
        blank=True,
        null=True)

    caregiver_visit_count = models.IntegerField(
        validators=[MinValueValidator(1), MaxValueValidator(3)],
        blank=True,
        null=True)

    is_eligible = models.BooleanField(
        default=False,
        editable=False)

    preg_enroll = models.BooleanField(
        default=False,
        editable=False)

    ineligibility = models.TextField(
        verbose_name="Reason not eligible",
        max_length=150,
        null=True,
        editable=False)

    def save(self, *args, **kwargs):

        self.preg_enroll = self.is_preg

        eligibility_criteria = CaregiverChildConsentEligibility(
            self.child_test, self.child_remain_in_study, self.child_preg_test,
            self.child_knows_status)

        self.is_eligible = eligibility_criteria.is_eligible
        self.ineligibility = eligibility_criteria.error_message

        self.child_age_at_enrollment = (
            self.get_child_age_at_enrollment() if self.child_dob else 0)

        self.set_defaults()

        if self.is_eligible and (not self.subject_identifier or not self.version):

            # if self.consent_datetime >=
            self.version = '2.1'

            if self.preg_enroll:
                self.duplicate_subject_identifier_preg()

            if not self.subject_identifier:
                self.subject_identifier = InfantIdentifier(
                    maternal_identifier=self.subject_consent.subject_identifier,
                    birth_order=self.birth_order,
                    live_infants=self.live_infants,
                    registration_status=self.registration_status,
                    registration_datetime=self.consent_datetime,
                    subject_type=INFANT,
                    supplied_infant_suffix=self.subject_identifier_sufix).identifier

        super().save(*args, **kwargs)

    def set_defaults(self):

        if (not self.preg_enroll and self.study_child_identifier):

            child_dataset = self.get_child_dataset(self.study_child_identifier)

            if child_dataset:
                self.child_dob = child_dataset.dob
                self.gender = child_dataset.infant_sex.upper()[0]

    def get_child_dataset(self, study_child_identifier):
        child_dataset_cls = django_apps.get_model(
            'flourish_child.childdataset')

        try:
            child_dataset_obj = child_dataset_cls.objects.get(
                study_child_identifier=study_child_identifier)
        except child_dataset_cls.DoesNotExist:
            pass
        else:
            return child_dataset_obj

    def duplicate_subject_identifier_preg(self):
        try:
            child_consent = self._meta.model.objects.get(
                preg_enroll=True,
                subject_identifier__startswith=self.subject_consent.subject_identifier)
        except self._meta.model.DoesNotExist:
            pass
        else:
            self.subject_identifier = child_consent.subject_identifier

    @property
    def child_consent_version(self):

        consent_version_cls = django_apps.get_model(
            'flourish_caregiver.flourishconsentversion')
        try:
            consent_version_obj = consent_version_cls.objects.get(
                screening_identifier=self.subject_consent.screening_identifier)
        except consent_version_cls.DoesNotExist:
            pass
        else:
            return consent_version_obj.child_version

    @property
    def is_preg(self):

        if not self.study_child_identifier:
            return (self.child_dob and self.child_dob > self.consent_datetime.date()
                    or self.child_dob is None)
        return False

    @property
    def live_infants(self):
        child_dummy_consent_cls = django_apps.get_model(
            'flourish_child.childdummysubjectconsent')
        return child_dummy_consent_cls.objects.filter(
            subject_identifier__icontains=self.subject_consent.subject_identifier).exclude(
                identity=self.identity).count() + 1

    @property
    def subject_identifier_sufix(self):

        caregiver_child_consent_cls = django_apps.get_model(self._meta.label_lower)
        child_identifier_postfix = ''
        if self.child_dataset:
            if self.subject_consent.multiple_birth:
                if (self.subject_consent.multiple_births == 'twins'
                        and self.child_dataset.twin_triplet):
                    twin_id = self.subject_consent.subject_identifier + '-' + '25'
                    try:
                        caregiver_child_consent_cls.objects.get(
                            subject_identifier=twin_id)
                    except caregiver_child_consent_cls.DoesNotExist:
                        child_identifier_postfix = '25'
                    else:
                        child_identifier_postfix = '35'
                elif (self.subject_consent.multiple_births == 'triplets'
                        and self.child_dataset.twin_triplet):
                    twin_id = self.subject_consent.subject_identifier + '-' + '36'
                    try:
                        caregiver_child_consent_cls.objects.get(
                            subject_identifier=twin_id)
                    except caregiver_child_consent_cls.DoesNotExist:
                        child_identifier_postfix = '36'
                    else:
                        twin_id = self.subject_consent.subject_identifier + '-' + '46'
                        try:
                            caregiver_child_consent_cls.objects.get(
                                subject_identifier=twin_id)
                        except caregiver_child_consent_cls.DoesNotExist:
                            child_identifier_postfix = '46'
                        else:
                            child_identifier_postfix = '56'
            else:
                children_count = caregiver_child_consent_cls.objects.filter(
                    subject_identifier__startswith=self.subject_consent.subject_identifier).exclude(
                        child_dob=self.child_dob,
                        first_name=self.first_name).count()
                if children_count:
                    child_identifier_postfix = str((children_count + 5) * 10)
                else:
                    child_identifier_postfix = 10
        else:
            children_count = caregiver_child_consent_cls.objects.filter(
                    subject_identifier__startswith=self.subject_consent.subject_identifier).exclude(
                        child_dob=self.child_dob,
                        first_name=self.first_name).count()
            if children_count:
                child_identifier_postfix = str((children_count + 5) * 10)
            else:
                child_identifier_postfix = 10
        return child_identifier_postfix

    @property
    def child_dataset(self):
        child_dataset_cls = django_apps.get_model('flourish_child.childdataset')
        try:
            child_dataset = child_dataset_cls.objects.get(
                study_child_identifier=self.study_child_identifier)
        except child_dataset_cls.DoesNotExist:
            pass
        else:
            return child_dataset
        return None

    @property
    def registration_status(self):
        return 'REGISTERED'

    @property
    def birth_order(self):
        caregiver_child_consent_cls = django_apps.get_model(self._meta.label_lower)
        return caregiver_child_consent_cls.objects.filter(
            subject_identifier__icontains=self.subject_consent.subject_identifier).exclude(
                identity=self.identity).count() + 1

    def get_child_age_at_enrollment(self):
        return Cohort().age_at_enrollment(
            child_dob=self.child_dob,
            check_date=self.created.date())

    class Meta:
        app_label = 'flourish_caregiver'
        verbose_name = 'Caregiver Consent On Behalf Of Child'
        verbose_name_plural = 'Caregiver Consent On Behalf Of Child'
Beispiel #12
0
class CorrectConsent(CorrectConsentMixin, BaseUuidModel):

    """A model linked to the subject consent to record corrections."""

    subject_consent = models.OneToOneField(
        SubjectConsent, on_delete=PROTECT)

    report_datetime = models.DateTimeField(
        verbose_name="Correction report date ad time",
        null=True,
        validators=[
            datetime_not_future],
    )

    old_first_name = FirstnameField(
        null=True,
        blank=True,
    )

    new_first_name = FirstnameField(
        null=True,
        blank=True,
    )

    old_last_name = LastnameField(
        null=True,
        blank=True,
    )
    new_last_name = LastnameField(
        null=True,
        blank=True,
    )

    old_initials = EncryptedCharField(
        blank=True,
        null=True,
        validators=[RegexValidator(
            regex=r'^[A-Z]{2,3}$',
            message='Ensure initials consist of letters only in upper case, no spaces.'), ],
    )

    new_initials = EncryptedCharField(
        validators=[RegexValidator(
            regex=r'^[A-Z]{2,3}$',
            message='Ensure initials consist of letters only in upper case, no spaces.'), ],
        null=True,
        blank=True,
    )

    old_dob = models.DateField(
        verbose_name="Old Date of birth",
        null=True,
        blank=True,
        help_text="Format is YYYY-MM-DD",
    )

    new_dob = models.DateField(
        verbose_name="New Date of birth",
        null=True,
        blank=True,
        help_text="Format is YYYY-MM-DD",
    )

    old_gender = models.CharField(
        choices=GENDER_UNDETERMINED,
        blank=True,
        null=True,
        max_length=1)

    new_gender = models.CharField(
        choices=GENDER_UNDETERMINED,
        max_length=1,
        null=True,
        blank=True,
    )

    old_guardian_name = LastnameField(
        validators=[
            RegexValidator('^[A-Z]{1,50}\, [A-Z]{1,50}$',
                           'Invalid format. Format is '
                           '\'LASTNAME, FIRSTNAME\'. All uppercase separated by a comma')],
        blank=True,
        null=True,
    )

    new_guardian_name = LastnameField(
        validators=[
            RegexValidator('^[A-Z]{1,50}\, [A-Z]{1,50}$',
                           'Invalid format. Format is \'LASTNAME, FIRSTNAME\'. '
                           'All uppercase separated by a comma')],
        blank=True,
        null=True,
    )

    old_may_store_samples = models.CharField(
        verbose_name="Old Sample storage",
        max_length=3,
        blank=True,
        null=True,
        choices=YES_NO,
    )

    new_may_store_samples = models.CharField(
        verbose_name="New Sample storage",
        max_length=3,
        blank=True,
        null=True,
        choices=YES_NO,
    )

    old_is_literate = models.CharField(
        verbose_name="(Old) Is the participant LITERATE?",
        max_length=3,
        blank=True,
        null=True,
        choices=YES_NO,
    )

    new_is_literate = models.CharField(
        verbose_name="(New) Is the participant LITERATE?",
        max_length=3,
        blank=True,
        null=True,
        choices=YES_NO,
    )

    old_witness_name = LastnameField(
        verbose_name="Witness\'s Last and first name (illiterates only)",
        validators=[
            RegexValidator(
                '^[A-Z]{1,50}\, [A-Z]{1,50}$',
                'Invalid format. Format '
                'is \'LASTNAME, FIRSTNAME\'. All uppercase separated by a comma')],
        blank=True,
        null=True,
        help_text=('Required only if subject is illiterate. '
                   'Format is \'LASTNAME, FIRSTNAME\'. '
                   'All uppercase separated by a comma'),
    )

    new_witness_name = LastnameField(
        verbose_name="Witness\'s Last and first name (illiterates only)",
        validators=[
            RegexValidator(
                '^[A-Z]{1,50}\, [A-Z]{1,50}$',
                'Invalid format. Format is \'LASTNAME, FIRSTNAME\'. '
                'All uppercase separated by a comma')],
        blank=True,
        null=True,
        help_text=('Required only if subject is illiterate. '
                   'Format is \'LASTNAME, FIRSTNAME\'. '
                   'All uppercase separated by a comma'),
    )

    objects = CorrectConsentManager()

    history = HistoricalRecords()

    def __str__(self):
        return str(self.subject_consent,)

    def natural_key(self):
        return self.subject_consent.natural_key()
    natural_key.dependencies = ['bcpp_subject.subject_consent']

    def dashboard(self):
        ret = None
        dashboard_type = self.subject_consent.registered_subject.subject_type.lower()
        if self.appointment:
            url = reverse('bcpp_subject_dashboard:dashboard_url',
                          kwargs={'dashboard_type': dashboard_type,
                                  'dashboard_model': 'appointment',
                                  'dashboard_id': self.appointment.pk,
                                  'show': 'appointments'})
            ret = """<a href="{url}" />dashboard</a>""".format(url=url)
        return ret
    dashboard.allow_tags = True

    class Meta:
        app_label = 'bcpp_subject'
Beispiel #13
0
class KaraboSubjectConsent(CryptoMixin, VerificationFieldsMixin,
                           SiteModelMixin, BaseUuidModel):

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

    screening_identifier = models.CharField(
        verbose_name="Screening Identifier", max_length=36, unique=True)

    report_datetime = models.DateTimeField(
        verbose_name="Report Date",
        validators=[datetime_not_before_study_start, datetime_not_future],
        default=get_utcnow,
        help_text=('If reporting today, use today\'s date/time, otherwise use '
                   'the date/time this information was reported.'))

    first_name = FirstnameField(verbose_name='First Name',
                                help_text=('(Must match name on file'
                                           ' with Tshilo Dikotla Study)'))

    last_name = LastnameField(verbose_name='Surname',
                              help_text=('(Must match name on file '
                                         'with Tshilo Dikotla Study)'))

    initials = EncryptedCharField(verbose_name='Initials ',
                                  help_text=('(Must match initials on file '
                                             'with Tshilo Dikotla Study)'))

    dob = models.DateField(verbose_name="Date of birth",
                           null=True,
                           blank=False)

    is_dob_estimated = IsDateEstimatedField(
        verbose_name="Is date of birth estimated?", null=True, blank=False)

    language = models.CharField(verbose_name='Language of consent:',
                                max_length=25,
                                choices=settings.LANGUAGES)

    is_literate = models.CharField(verbose_name='Is the participant literate?',
                                   max_length=25,
                                   choices=YES_NO)

    guardian_name = LastnameField(
        verbose_name='Witness\'s last and first name',
        validators=[FullNameValidator()],
        blank=True,
        null=True,
        help_text=mark_safe('Required only if participant is illiterate.<br>'
                            'Format is \'LASTNAME, FIRSTNAME\'. '
                            'All uppercase separated by a comma.'))

    consent_datetime = models.DateTimeField(
        verbose_name='Consent date and time',
        validators=[datetime_not_before_study_start, datetime_not_future])

    identity = IdentityField(verbose_name='Omang of consenting woman',
                             help_text=mark_safe(
                                 '(must match Omang on file '
                                 'with Tshilo Dikotla Study)'
                                 ' (Confirm that all Tshilo Dikotla '
                                 'women have enrolled with an Omang, '
                                 'otherwise will need additional ID '
                                 'questions.)'))

    consent_reviewed = models.CharField(
        verbose_name='I have reviewed the Karabo study '
        'consent with the client.',
        max_length=3,
        choices=YES_NO)

    study_questions = models.CharField(
        verbose_name='I have answered all questions the client'
        ' had about the Karabo study consent.',
        max_length=3,
        choices=YES_NO)

    assessment_score = models.CharField(
        verbose_name='I have asked the client questions'
        ' about the Karabo study and they have demonstrated an'
        ' understanding of the study by their answers.',
        max_length=3,
        choices=YES_NO)

    consent_signature = models.CharField(
        verbose_name='The client has signed the consent form.',
        max_length=3,
        choices=YES_NO)

    consent_copy = models.CharField(
        verbose_name='I have offered the client a signed copy'
        ' of the consent form.',
        max_length=25,
        choices=ANSWERS)

    def __str__(self):
        return f'{self.subject_identifier} {self.screening_identifier}'

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

    objects = KaraboSubjectConsentManager()

    history = HistoricalRecords()

    on_site = CurrentSiteManager()

    class Meta:
        app_label = 'td_maternal'
        verbose_name = "Karabo Subject Consent"
        verbose_name_plural = "Karabo Subject Consents"
Beispiel #14
0
class MoccaRegister(SiteModelMixin, BaseUuidModel):

    report_datetime = models.DateTimeField(default=get_utcnow)

    screening_identifier = models.CharField(
        verbose_name="MOCCA (ext) screening identifier",
        max_length=15,
        null=True,
    )

    mocca_screening_identifier = models.CharField(
        verbose_name="MOCCA (original) screening identifier",
        max_length=15,
        null=True,
        blank=True,
        help_text="If known",
    )

    mocca_study_identifier = models.CharField(
        verbose_name="MOCCA (original) study identifier",
        max_length=25,
        validators=[
            RegexValidator(
                r"0[0-9]{1}\-0[0-9]{3}|[0-9]{6}",
                "Invalid format. Expected 12-3456 for UG, 123456 for TZ",
            )
        ],
        help_text="Format must match original identifier. e.g. 12-3456 for UG, 123456 for TZ",
    )

    mocca_country = models.CharField(
        max_length=25, choices=(("uganda", "Uganda"), ("tanzania", "Tanzania"))
    )

    mocca_site = models.ForeignKey(
        MoccaOriginalSites,
        on_delete=models.PROTECT,
        limit_choices_to=get_mocca_site_limited_to,
    )

    first_name = FirstnameField(null=True)

    last_name = LastnameField(null=True)

    initials = EncryptedCharField(
        validators=[
            RegexValidator("[A-Z]{1,3}", "Invalid format"),
            MinLengthValidator(2),
            MaxLengthValidator(3),
        ],
        help_text="Use UPPERCASE letters only. May be 2 or 3 letters.",
        null=True,
        blank=False,
    )
    gender = models.CharField(max_length=10, choices=GENDER, null=True, blank=False)

    age_in_years = models.IntegerField(
        validators=[MinValueValidator(18), MaxValueValidator(110)],
        null=True,
        blank=False,
    )

    birth_year = models.IntegerField(
        validators=[MinValueValidator(1900), MaxValueValidator(2002)],
        null=True,
        blank=False,
    )
    dob = models.DateField(null=True, blank=True)

    survival_status = models.CharField(
        max_length=25, choices=ALIVE_DEAD_UNKNOWN, default=UNKNOWN
    )

    contact_attempts = models.IntegerField(default=0, help_text="auto-updated")

    call = models.CharField(verbose_name="Call?", max_length=15, choices=YES_NO, default=YES)

    subject_present = models.CharField(
        verbose_name="Patient is present. Screen now instead of calling?",
        max_length=15,
        choices=YES_NO,
        default=NO,
        help_text="Only select 'yes' if the patient is present in the clinic now.",
    )

    date_last_called = models.DateField(null=True, help_text="auto-updated")

    next_appt_date = models.DateField(
        verbose_name="Appt", null=True, blank=True, help_text="auto-updated"
    )

    notes = EncryptedTextField(verbose_name="General notes", null=True, blank=True)

    tel_one = EncryptedCharField("Tel/Mobile(1)", max_length=15, null=True)
    tel_two = EncryptedCharField("Tel/Mobile(2)", max_length=15, null=True)
    tel_three = EncryptedCharField("Tel/Mobile(3)", max_length=15, null=True)
    best_tel = models.CharField(
        verbose_name="Prefered Telephone / Mobile",
        max_length=15,
        choices=TEL_CHOICES,
        null=True,
        blank=True,
        help_text="If any, select the best telephone/mobile from above",
    )

    on_site = CurrentSiteManager()
    objects = Manager()
    history = HistoricalRecords()

    def __str__(self):
        return (
            f"{self.mocca_study_identifier} {self.initials} {self.age_in_years} {self.gender}"
        )

    def save(self, *args, **kwargs):
        if self.screening_identifier:
            self.call = NO
        super().save(*args, **kwargs)

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

    natural_key.dependencies = [
        "sites.Site",
        "mocca_lists.MoccaOriginalSites",
    ]

    class Meta(BaseUuidModel.Meta):
        verbose_name = "MOCCA Patient Register"
        verbose_name_plural = "MOCCA Patient Register"
        ordering = ["mocca_country", "mocca_site"]
        indexes = [
            Index(fields=["mocca_country", "mocca_site"]),
            Index(fields=["mocca_study_identifier", "initials", "gender"]),
        ]
        constraints = [
            UniqueConstraint(
                fields=["mocca_screening_identifier"],
                name="unique_mocca_screening_identifier",
            ),
            UniqueConstraint(
                fields=["mocca_study_identifier"], name="unique_mocca_study_identifier"
            ),
        ]