Ejemplo n.º 1
0
class CaregiverChildScreeningConsent(
        ConsentModelMixin, SiteModelMixin,
        UpdatesOrCreatesRegistrationModelMixin,
        NonUniqueSubjectIdentifierModelMixin, IdentityFieldsMixin,
        ReviewFieldsMixin, PersonalFieldsMixin, VulnerabilityFieldsMixin,
        CitizenFieldsMixin, SearchSlugModelMixin, BaseUuidModel):

    screening_identifier = models.CharField(
        verbose_name='Screening identifier', max_length=50)

    consent = ConsentManager()

    history = HistoricalRecords()

    objects = CaregiverChildScreeningConsentManager()

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

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

    def get_search_slug_fields(self):
        fields = super().get_search_slug_fields()
        fields.extend(
            ['identity', 'screening_identifier', 'first_name', 'last_name'])
        return fields

    class Meta(ConsentModelMixin.Meta):
        app_label = 'pre_flourish'
        verbose_name = ' Consent of Caregiver for Child/Adolescent Screening Participation'
        verbose_name_plural = ' Consent of Caregiver for Child/Adolescent Screening Participation'
        unique_together = (('subject_identifier', 'version'),
                           ('subject_identifier', 'screening_identifier',
                            'version'), ('first_name', 'dob', 'initials',
                                         'version'))
Ejemplo n.º 2
0
class SubjectConsent(
        ConsentModelMixin,
        SiteModelMixin,
        UpdatesOrCreatesRegistrationModelMixin,
        NonUniqueSubjectIdentifierModelMixin,
        IdentityFieldsMixin,
        ReviewFieldsMixin,
        PersonalFieldsMixin,
        SampleCollectionFieldsMixin,
        CitizenFieldsMixin,
        VulnerabilityFieldsMixin,
        SearchSlugModelMixin,
        BaseUuidModel,
):
    """ A model completed by the user that captures the ICF.
    """

    subject_identifier_cls = SubjectIdentifier

    subject_screening_model = "inte_screening.subjectscreening"

    screening_identifier = models.CharField(
        verbose_name="Screening identifier",
        max_length=50,
        unique=True,
        help_text="(readonly)",
    )

    screening_datetime = models.DateTimeField(
        verbose_name="Screening datetime", null=True, editable=False)

    clinic_type = models.CharField(
        verbose_name="In which type of clinic was the patient screened",
        max_length=25,
        choices=CLINIC_CHOICES,
        help_text="Should match that reported on the Screening form.",
    )

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

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

    on_site = CurrentSiteManager()

    objects = SubjectConsentManager()

    consent = ConsentManager()

    history = HistoricalRecords()

    def __str__(self):
        return f"{self.subject_identifier} V{self.version}"

    def save(self, *args, **kwargs):
        subject_screening = self.get_subject_screening()
        self.screening_datetime = subject_screening.report_datetime
        self.subject_type = "subject"
        self.citizen = NOT_APPLICABLE
        super().save(*args, **kwargs)

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

    def get_subject_screening(self):
        """Returns the subject screening model instance.

        Instance must exist since SubjectScreening is completed
        before consent.
        """
        model_cls = django_apps.get_model(self.subject_screening_model)
        return model_cls.objects.get(
            screening_identifier=self.screening_identifier)

    @property
    def registration_unique_field(self):
        """Required for UpdatesOrCreatesRegistrationModelMixin.
        """
        return "subject_identifier"

    class Meta(ConsentModelMixin.Meta):
        unique_together = (
            ("subject_identifier", "version"),
            ("subject_identifier", "screening_identifier"),
            ("first_name", "dob", "initials", "version"),
        )
Ejemplo n.º 3
0
class SubjectConsent(ConsentModelMixin, SiteModelMixin,
                     UpdatesOrCreatesRegistrationModelMixin,
                     NonUniqueSubjectIdentifierModelMixin, IdentityFieldsMixin,
                     ReviewFieldsMixin, PersonalFieldsMixin, CitizenFieldsMixin,
                     VulnerabilityFieldsMixin, SearchSlugModelMixin, BaseUuidModel):
    """ A model completed by the user on the mother's consent. """

    subject_screening_model = 'flourish_caregiver.subjectscreening'

    caregiver_locator_model = 'flourish_caregiver.caregiverlocator'

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

    screening_identifier = models.CharField(
        verbose_name='Screening identifier',
        max_length=50)

    gender = models.CharField(
        verbose_name='Gender',
        choices=GENDER,
        max_length=1,
        default=FEMALE)

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

    recruit_source = models.CharField(
        max_length=75,
        choices=RECRUIT_SOURCE,
        verbose_name="The caregiver first learned about the flourish "
                     "study from ")

    recruit_source_other = OtherCharField(
        max_length=35,
        verbose_name="if other recruitment source, specify...",
        blank=True,
        null=True)

    recruitment_clinic = models.CharField(
        max_length=100,
        verbose_name="The caregiver was recruited from",
        choices=RECRUIT_CLINIC)

    recruitment_clinic_other = models.CharField(
        max_length=100,
        verbose_name="if other recruitment, specify...",
        blank=True,
        null=True,)

    remain_in_study = models.CharField(
        max_length=3,
        verbose_name='Are you willing to remain in the study area until 2025?',
        choices=YES_NO,
        help_text='If no, participant is not eligible.')

    biological_caregiver = models.CharField(
        max_length=3,
        verbose_name='Are you the biological mother to the child or children?',
        choices=YES_NO,
        blank=True)

    hiv_testing = models.CharField(
        max_length=3,
        verbose_name=('If HIV status not known, are you willing to undergo HIV'
                      ' testing and counseling?'),
        choices=YES_NO_NA,
        help_text='If ‘No’ ineligible for study participation')

    breastfeed_intent = models.CharField(
        max_length=3,
        verbose_name='Do you intend on breast feeding your infant?',
        choices=YES_NO_NA,
        help_text='If ‘No’ ineligible for study participation')

    future_contact = models.CharField(
        max_length=3,
        verbose_name='Do you give us permission to be contacted for future studies?',
        choices=YES_NO)

    child_consent = models.CharField(
        max_length=3,
        verbose_name='Are you willing to consent for your child’s participation in FLOURISH?',
        choices=YES_NO_NA,
        help_text='If ‘No’ ineligible for study participation')

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

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

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

    objects = SubjectConsentManager()

    consent = ConsentManager()

    history = HistoricalRecords()

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

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

        consent_version_cls = django_apps.get_model(
            'flourish_caregiver.flourishconsentversion')
        try:
            consent_version_obj = consent_version_cls.objects.get(
                screening_identifier=self.screening_identifier)
        except consent_version_cls.DoesNotExist:
            self.version = '2'
        else:
            self.version = consent_version_obj.version

        self.biological_caregiver = self.is_biological_mother()
        eligibility_criteria = ConsentEligibility(
            self.remain_in_study, self.hiv_testing, self.breastfeed_intent,
            self.consent_reviewed, self.citizen, self.study_questions,
            self.assessment_score, self.consent_signature, self.consent_copy,
            self.child_consent)
        self.is_eligible = eligibility_criteria.is_eligible
        self.ineligibility = eligibility_criteria.error_message
        if self.multiple_births in ['twins', 'triplets']:
            self.multiple_birth = True
        if self.is_eligible:

            if self.created and not self.subject_identifier:
                self.subject_identifier = self.update_subject_identifier_on_save()

            self.update_dataset_identifier()
            self.update_locator_subject_identifier()

        if self.caregiver_locator_obj:
            if not self.caregiver_locator_obj.first_name and not self.caregiver_locator_obj.last_name:
                self.caregiver_locator_obj.first_name = self.first_name
                self.caregiver_locator_obj.last_name = self.last_name
                self.caregiver_locator_obj.save()

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

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

    @property
    def multiple_births(self):
        """Returns value of births if the mother has twins/triplets.
        """
        dataset_cls = django_apps.get_model('flourish_caregiver.maternaldataset')

        try:
            dataset_obj = dataset_cls.objects.get(
                screening_identifier=self.screening_identifier)
        except dataset_cls.DoesNotExist:
            pass
        else:
            child_dataset_cls = django_apps.get_model('flourish_child.childdataset')
            children = child_dataset_cls.objects.filter(
                study_maternal_identifier=dataset_obj.study_maternal_identifier)
            if children.count() == 2:
                return 'twins'
            elif children.count() == 3:
                return 'triplets'
            elif children.count() > 3:
                raise ValidationError(
                    'We do not expect more than triplets to exist.')
        return None

    @property
    def caregiver_type(self):
        """Return the letter that represents the caregiver type.
        """
        if self.biological_caregiver == 'Yes':
            return 'B'
        elif self.biological_caregiver == 'No':
            return 'C'
        return None

    def make_new_identifier(self):
        """Returns a new and unique identifier.

        Override this if needed.
        """
        if not self.is_eligible:
            return None
        subject_identifier = SubjectIdentifier(
            caregiver_type=self.caregiver_type,
            identifier_type='subject',
            requesting_model=self._meta.label_lower,
            site=self.site)
        return subject_identifier.identifier

    def update_dataset_identifier(self):
        dataset_cls = django_apps.get_model('flourish_caregiver.maternaldataset')

        try:
            dataset_obj = dataset_cls.objects.get(
                screening_identifier=self.screening_identifier)
        except dataset_cls.DoesNotExist:
            pass
        else:
            dataset_obj.subject_identifier = self.subject_identifier
            dataset_obj.save()

    def update_locator_subject_identifier(self):
        locator_cls = django_apps.get_model('flourish_caregiver.caregiverlocator')
        try:
            locator_obj = locator_cls.objects.get(
                screening_identifier=self.screening_identifier)
        except locator_cls.DoesNotExist:
            pass
        else:
            locator_obj.subject_identifier = self.subject_identifier
            locator_obj.save()

    def is_biological_mother(self):
        # To refactor to include new enrollees !!
        prior_screening_cls = django_apps.get_model(
            'flourish_caregiver.screeningpriorbhpparticipants')
        preg_women_screening_cls = django_apps.get_model(
            'flourish_caregiver.screeningpregwomen')
        screening = None
        is_biological_mother = NO
        try:
            screening = prior_screening_cls.objects.get(
                screening_identifier=self.screening_identifier)
        except prior_screening_cls.DoesNotExist:
            try:
                screening = preg_women_screening_cls.objects.get(
                    screening_identifier=self.screening_identifier)
            except preg_women_screening_cls.DoesNotExist:
                is_biological_mother = NO
            else:
                is_biological_mother = YES
        else:
            if (screening.mother_alive == YES and
                    screening.flourish_participation == 'interested'):
                is_biological_mother = YES
        return is_biological_mother

    @property
    def consent_version(self):
        return self.version

    def registration_update_or_create(self):
        """Creates or Updates the registration model with attributes
        from this instance.

        Called from the signal
        """
        if self.is_eligible:
            return super().registration_update_or_create()

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

    @property
    def caregiver_locator_model_cls(self):
        return django_apps.get_model(self.caregiver_locator_model)

    @property
    def caregiver_locator_obj(self):
        try:
            caregiver_locator = self.caregiver_locator_model_cls.objects.get(
                screening_identifier=self.screening_identifier)
        except self.caregiver_locator_model_cls.DoesNotExist:
            return None
        else:
            return caregiver_locator

    class Meta(ConsentModelMixin.Meta):
        app_label = 'flourish_caregiver'
        verbose_name = 'Adult Participation Consent'
        unique_together = (('subject_identifier', 'version'),
                           ('screening_identifier', 'version'),
                           ('subject_identifier', 'screening_identifier', 'version'),
                           ('first_name', 'dob', 'initials', 'version'))
Ejemplo n.º 4
0
class SubjectConsent(ConsentModelMixin, SiteModelMixin,
                     UpdatesOrCreatesRegistrationModelMixin,
                     NonUniqueSubjectIdentifierModelMixin, IdentityFieldsMixin,
                     ReviewFieldsMixin, PersonalFieldsMixin,
                     CitizenFieldsMixin, VulnerabilityFieldsMixin,
                     SearchSlugModelMixin, BaseUuidModel):
    """ A model completed by the user on the mother's consent. """

    subject_screening_model = 'td_maternal.subjectscreening'

    screening_identifier = models.CharField(
        verbose_name='Screening identifier', max_length=50)

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

    recruit_source = models.CharField(
        max_length=75,
        choices=RECRUIT_SOURCE,
        verbose_name="The mother first learned about the tshilo "
        "dikotla study from ")

    recruit_source_other = OtherCharField(
        max_length=35,
        verbose_name="if other recruitment source, specify...",
        blank=True,
        null=True)

    recruitment_clinic = models.CharField(
        max_length=100,
        verbose_name="The mother was recruited from",
        choices=RECRUIT_CLINIC)

    recruitment_clinic_other = models.CharField(
        max_length=100,
        verbose_name="if other recruitment clinic, specify...",
        blank=True,
        null=True,
    )

    objects = SubjectConsentManager()

    consent = ConsentManager()

    history = HistoricalRecords()

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

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

    def save(self, *args, **kwargs):
        consent_version_cls = django_apps.get_model(
            'td_maternal.tdconsentversion')
        try:
            consent_version_obj = consent_version_cls.objects.get(
                screening_identifier=self.screening_identifier)
        except consent_version_cls.DoesNotExist:
            raise ValidationError(
                'Missing Consent Version form. Please complete '
                'it before proceeding.')
        self.version = consent_version_obj.version
        super().save(*args, **kwargs)

    def make_new_identifier(self):
        """Returns a new and unique identifier.

        Override this if needed.
        """
        subject_identifier = SubjectIdentifier(
            identifier_type='subject',
            requesting_model=self._meta.label_lower,
            site=self.site)
        return subject_identifier.identifier

    @property
    def consent_version(self):
        return self.version

    class Meta(ConsentModelMixin.Meta):
        app_label = 'td_maternal'
        verbose_name = 'Maternal Consent'
        unique_together = (('subject_identifier', 'version'),
                           ('subject_identifier', 'screening_identifier',
                            'version'), ('first_name', 'dob', 'initials',
                                         'version'))
Ejemplo n.º 5
0
class SubjectConsent(
        ConsentModelMixin,
        SiteModelMixin,
        UpdatesOrCreatesRegistrationModelMixin,
        NonUniqueSubjectIdentifierModelMixin,
        IdentityFieldsMixin,
        ReviewFieldsMixin,
        PersonalFieldsMixin,
        SampleCollectionFieldsMixin,
        CitizenFieldsMixin,
        VulnerabilityFieldsMixin,
        SearchSlugModelMixin,
        BaseUuidModel,
):
    """ A model completed by the user that captures the ICF.
    """

    subject_identifier_cls = SubjectIdentifier

    subject_screening_model = "meta_screening.subjectscreening"

    screening_identifier = models.CharField(
        verbose_name="Screening identifier", max_length=50, unique=True)

    screening_datetime = models.DateTimeField(
        verbose_name="Screening datetime", null=True, editable=False)

    completed_by_next_of_kin = models.CharField(max_length=10,
                                                default=NO,
                                                choices=YES_NO,
                                                editable=False)

    on_site = CurrentSiteManager()

    objects = SubjectConsentManager()

    consent = ConsentManager()

    history = HistoricalRecords()

    def __str__(self):
        return f"{self.subject_identifier} V{self.version}"

    def save(self, *args, **kwargs):
        subject_screening = self.get_subject_screening()
        self.screening_datetime = subject_screening.report_datetime
        self.subject_type = "subject"
        self.citizen = NOT_APPLICABLE
        super().save(*args, **kwargs)

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

    def get_subject_screening(self):
        """Returns the subject screening model instance.

        Instance must exist since SubjectScreening is completed
        before consent.
        """
        model_cls = django_apps.get_model(self.subject_screening_model)
        return model_cls.objects.get(
            screening_identifier=self.screening_identifier)

    @property
    def registration_unique_field(self):
        """Required for UpdatesOrCreatesRegistrationModelMixin.
        """
        return "subject_identifier"

    class Meta(ConsentModelMixin.Meta):
        unique_together = (
            ("subject_identifier", "version"),
            ("subject_identifier", "screening_identifier"),
            ("first_name", "dob", "initials", "version"),
        )
class TbInformedConsent(ConsentModelMixin, SiteModelMixin,
                        UpdatesOrCreatesRegistrationModelMixin,
                        NonUniqueSubjectIdentifierModelMixin,
                        IdentityFieldsMixin, PersonalFieldsMixin,
                        VulnerabilityFieldsMixin, SearchSlugModelMixin,
                        BaseUuidModel):
    subject_screening_model = 'flourish_caregiver.subjectscreening'

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

    consent_datetime = models.DateTimeField(
        verbose_name='Consent date and time',
        default=get_utcnow,
        help_text='Date and time of consent.')

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

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

    optional_sample_collection = models.CharField(
        verbose_name='Do you consent to optional sample collection?',
        choices=YES_NO,
        max_length=3,
    )

    consent_to_participate = models.CharField(
        verbose_name='Do you consent to participate in the study?',
        choices=YES_NO,
        max_length=3,
        validators=[
            eligible_if_yes,
        ],
        help_text='Participant is not eligible if no')

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

    gender_other = OtherCharField()

    objects = InformedConsentManager()

    consent = ConsentManager()

    on_site = CurrentSiteManager()

    history = HistoricalRecords()

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

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

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

    @property
    def consent_version(self):
        return self.version

    class Meta(ConsentModelMixin.Meta):
        app_label = 'flourish_caregiver'
        verbose_name = 'TB Informed Consent'
        verbose_name_plural = 'TB Informed Consent'
        unique_together = (('subject_identifier', 'version'),
                           ('first_name', 'dob', 'initials', 'version'))
Ejemplo n.º 7
0
class PreFlourishConsent(ConsentModelMixin, SiteModelMixin,
                         UpdatesOrCreatesRegistrationModelMixin,
                         NonUniqueSubjectIdentifierModelMixin,
                         IdentityFieldsMixin, ReviewFieldsMixin,
                         PersonalFieldsMixin, CitizenFieldsMixin,
                         VulnerabilityFieldsMixin, SearchSlugModelMixin,
                         BaseUuidModel):

    subject_screening_model = 'pre_flourish.preflourishsubjectscreening'

    screening_identifier = models.CharField(
        verbose_name='Screening identifier', max_length=50)

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

    recruit_source = models.CharField(
        max_length=75,
        choices=RECRUIT_SOURCE,
        verbose_name="The caregiver first learned about the flourish "
        "study from ")

    recruit_source_other = OtherCharField(
        max_length=35,
        verbose_name="if other recruitment source, specify...",
        blank=True,
        null=True)

    recruitment_clinic = models.CharField(
        max_length=100,
        verbose_name="The caregiver was recruited from",
        choices=RECRUIT_CLINIC)

    recruitment_clinic_other = models.CharField(
        max_length=100,
        verbose_name="if other recruitment clinic, specify...",
        blank=True,
        null=True,
    )

    objects = PreFlourishConsentManager()

    consent = ConsentManager()

    history = HistoricalRecords()

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

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

    def make_new_identifier(self):
        """Returns a new and unique identifier.

        Override this if needed.
        """
        subject_identifier = SubjectIdentifier(
            identifier_type='subject',
            requesting_model=self._meta.label_lower,
            site=self.site)
        return subject_identifier.identifier

    @property
    def consent_version(self):
        return self.version

    class Meta(ConsentModelMixin.Meta):
        app_label = 'pre_flourish'
        verbose_name = 'Caregiver Consent'
        verbose_name_plural = 'Caregiver Consent'
        unique_together = (('subject_identifier', 'version'),
                           ('subject_identifier', 'screening_identifier',
                            'version'), ('first_name', 'dob', 'initials',
                                         'version'))
Ejemplo n.º 8
0
class SubjectConsent(ConsentModelMixin, UpdatesOrCreatesRegistrationModelMixin,
                     NonUniqueSubjectIdentifierModelMixin,
                     SurveyScheduleModelMixin, IdentityFieldsMixin,
                     ReviewFieldsMixin, PersonalFieldsMixin,
                     SampleCollectionFieldsMixin, CitizenFieldsMixin,
                     VulnerabilityFieldsMixin, SearchSlugModelMixin,
                     BaseUuidModel):
    """ A model completed by the user that captures the ICF.
    """

    clinic_member_updater_cls = ClinicMemberUpdater

    household_member = models.ForeignKey(HouseholdMember,
                                         on_delete=models.PROTECT)

    is_minor = models.CharField(
        verbose_name=("Is subject a minor?"),
        max_length=10,
        choices=YES_NO,
        null=True,
        blank=False,
        help_text=('Subject is a minor if aged 16-17. A guardian must '
                   'be present for consent. HIV status may NOT be '
                   'revealed in the household.'),
        editable=False)

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

    objects = Manager()

    consent = ConsentManager()

    history = HistoricalRecords()

    def __str__(self):
        return '{0} ({1}) V{2}'.format(self.subject_identifier,
                                       self.survey_schedule_object.name,
                                       self.version)

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

        self.clinic_member_updater_cls(model_obj=self)

        if not self.id:
            self.survey_schedule = self.household_member.survey_schedule_object.field_value
            if re.match(subject_identifier,
                        self.household_member.subject_identifier):
                self.subject_identifier = self.household_member.subject_identifier

        self.study_site = site_mappers.current_map_code
        self.is_minor = YES if is_minor(self.dob,
                                        self.consent_datetime) else NO
        super().save(*args, **kwargs)

    def natural_key(self):
        return ((
            self.subject_identifier,
            self.version,
        ) + self.household_member.natural_key())

    natural_key.dependencies = ['bcpp_subject.household_member']

    @property
    def visit_code(self):
        """Returns a value for edc_reference.
        """
        return 'CONSENT'

    @property
    def internal_identifier(self):
        return self.household_member.internal_identifier

    class Meta(ConsentModelMixin.Meta):
        app_label = 'bcpp_subject'
        get_latest_by = 'consent_datetime'
        unique_together = (('subject_identifier', 'version'),
                           ('first_name', 'dob', 'initials', 'version'))
        ordering = ('-created', )
Ejemplo n.º 9
0
class SubjectConsent(ConsentModelMixin, SiteModelMixin,
                     UpdatesOrCreatesRegistrationModelMixin,
                     NonUniqueSubjectIdentifierModelMixin, IdentityFieldsMixin,
                     ReviewFieldsMixin, PersonalFieldsMixin,
                     SampleCollectionFieldsMixin, CitizenFieldsMixin,
                     VulnerabilityFieldsMixin, SearchSlugModelMixin,
                     BaseUuidModel):
    """ A model completed by the user that captures the ICF.
    """

    subject_screening_model = 'ambition_screening.subjectscreening'

    screening_identifier = models.CharField(
        verbose_name='Screening identifier', max_length=50)

    completed_by_next_of_kin = models.CharField(max_length=10,
                                                default=NO,
                                                choices=YES_NO,
                                                editable=False)

    on_site = CurrentSiteManager()

    objects = SubjectConsentManager()

    consent = ConsentManager()

    history = HistoricalRecords()

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

    def save(self, *args, **kwargs):
        subject_screening = self.get_subject_screening()
        self.completed_by_next_of_kin = (YES if subject_screening.mental_status
                                         == ABNORMAL else NO)
        self.gender = subject_screening.gender
        self.subject_type = 'subject'
        self.citizen = NOT_APPLICABLE
        super().save(*args, **kwargs)

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

    def get_subject_screening(self):
        """Returns the subject screening model instance.

        Instance must exist since SubjectScreening is completed
        before consent.
        """
        model_cls = django_apps.get_model(self.subject_screening_model)
        return model_cls.objects.get(
            screening_identifier=self.screening_identifier)

    @property
    def registration_unique_field(self):
        """Required for UpdatesOrCreatesRegistrationModelMixin.
        """
        return 'subject_identifier'

    class Meta(ConsentModelMixin.Meta):
        unique_together = (('subject_identifier', 'version'),
                           ('subject_identifier', 'screening_identifier'),
                           ('first_name', 'dob', 'initials', 'version'))
class AnonymousConsent(ConsentModelMixin, ReferenceModelMixin,
                       UpdatesOrCreatesRegistrationModelMixin,
                       NonUniqueSubjectIdentifierModelMixin, SurveyModelMixin,
                       IdentityFieldsMixin, PersonalFieldsMixin,
                       SampleCollectionFieldsMixin, SearchSlugModelMixin,
                       BaseUuidModel):
    """ A model completed by the user that captures the ICF.
    """

    household_member = models.ForeignKey(HouseholdMember,
                                         on_delete=models.PROTECT)

    citizen = models.CharField(
        verbose_name="Are you a Botswana citizen? ",
        max_length=3,
        choices=YES_NO,
        help_text="",
    )

    is_minor = models.CharField(
        verbose_name=("Is subject a minor?"),
        max_length=10,
        null=True,
        blank=False,
        default='-',
        choices=YES_NO,
        help_text=('Subject is a minor if aged 16-17. A guardian must '
                   'be present for consent. '
                   'HIV status may NOT be revealed in the household.'),
        editable=False)

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

    objects = Manager()

    consent = ConsentManager()

    history = HistoricalRecords()

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

    def __str__(self):
        return '{0} ({1}) V{2}'.format(self.subject_identifier, self.survey,
                                       self.version)

    def save(self, *args, **kwargs):
        if not self.id:
            self.survey_schedule = self.household_member.survey_schedule_object.field_value
            self.survey = S(self.survey_schedule_object.field_value,
                            survey_name=ANONYMOUS_SURVEY).survey_field_value
        super().save(*args, **kwargs)

    @property
    def visit_code(self):
        """Returns a value for edc_reference.
        """
        return 'E0'

    @property
    def internal_identifier(self):
        return self.household_member.internal_identifier

    class Meta(ConsentModelMixin.Meta):
        app_label = 'bcpp_subject'
        consent_group = settings.ANONYMOUS_CONSENT_GROUP
        get_latest_by = 'consent_datetime'
        unique_together = (('subject_identifier', 'version'),
                           ('first_name', 'dob', 'initials', 'version'))
        ordering = ('-created', )