class DeathReport(UniqueSubjectIdentifierFieldMixin, SiteModelMixin, BaseUuidModel): objects = SubjectIdentifierManager() def natural_key(self): return (self.subject_identifier, )
class SubjectConsent( UniqueSubjectIdentifierModelMixin, PersonalFieldsMixin, UpdatesOrCreatesRegistrationModelMixin, SiteModelMixin, BaseUuidModel, ): consent_datetime = models.DateTimeField(default=get_utcnow) version = models.CharField(max_length=25, default="1") screening_identifier = models.CharField(max_length=25, null=True) identity = models.CharField(max_length=25, default="111111111") confirm_identity = models.CharField(max_length=25, default="111111111") dob = models.DateField(default=date(1995, 1, 1)) gender = models.CharField(max_length=25, default=MALE) objects = SubjectIdentifierManager() def natural_key(self): return tuple(self.subject_identifier, ) class Meta(BaseUuidModel.Meta): verbose_name = "Subject Consent" verbose_name_plural = "Subject Consents"
class PreFlourishOffStudy(OffScheduleModelMixin, ActionModelMixin, BaseUuidModel): tracking_identifier_prefix = 'MO' 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.')) reason = models.CharField( verbose_name=('Please code the primary reason participant taken' ' off-study'), max_length=115) objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): pass class Meta: app_label = 'pre_flourish' verbose_name = 'Off Study' verbose_name_plural = 'Off Studies'
class InfantOffSchedule(ConsentVersionModelModelMixin, OffScheduleModelMixin, BaseUuidModel): schedule_name = models.CharField(max_length=25, blank=True, null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): pass def get_consent_version(self): subject_consent_cls = django_apps.get_model( 'td_infant.infantdummysubjectconsent') subject_consent_objs = subject_consent_cls.objects.filter( subject_identifier=self.subject_identifier).order_by( '-consent_datetime') if subject_consent_objs: return subject_consent_objs.first().version else: raise ValidationError( 'Missing Infant Dummy Consent form. Cannot proceed.') class Meta: unique_together = ('subject_identifier', 'schedule_name')
class ClinicalNote( NonUniqueSubjectIdentifierFieldMixin, TrackingModelMixin, SiteModelMixin, BaseUuidModel, ): tracking_identifier_prefix = "CN" report_datetime = models.DateTimeField(verbose_name="Report Date and Time", default=get_utcnow) subjective = models.TextField( verbose_name="Subjective / Pertinant history", ) note = EncryptedTextField(verbose_name="Clinical Note") on_site = CurrentSiteManager() objects = SubjectIdentifierManager() def natural_key(self): return (self.tracking_identifier, ) class Meta(BaseUuidModel.Meta): verbose_name = "Clinical Note" verbose_name_plural = "Clinical Notes" indexes = [models.Index(fields=["tracking_identifier", "site", "id"])]
class CaregiverOffSchedule(OffScheduleModelMixin, BaseUuidModel): schedule_name = models.CharField(max_length=25, blank=True, null=True) objects = SubjectIdentifierManager() on_site = CurrentSiteManager() history = HistoricalRecords() def take_off_schedule(self): pass @property def latest_consent_obj_version(self): caregiver_consent_cls = django_apps.get_model( 'flourish_caregiver.subjectconsent') subject_consents = caregiver_consent_cls.objects.filter( subject_identifier=self.subject_identifier, ) if subject_consents: latest_consent = subject_consents.latest('consent_datetime') return latest_consent.version else: raise forms.ValidationError( 'Missing Subject Consent form, cannot proceed.') def save(self, *args, **kwargs): self.consent_version = self.latest_consent_obj_version super().save(*args, **kwargs) class Meta: unique_together = ('subject_identifier', 'schedule_name')
class OnSchedulePreFlourish(OnScheduleModelMixin, BaseUuidModel): """A model used by the system. Auto-completed by enrollment model. """ subject_identifier = models.CharField( verbose_name="Subject Identifier", max_length=50) schedule_name = models.CharField(max_length=25, blank=True, null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords() def put_on_schedule(self): pass def save(self, *args, **kwargs): self.consent_version = '1' super().save(*args, **kwargs) class Meta: unique_together = ('subject_identifier', 'schedule_name')
class OnSchedule(OnScheduleModelMixin, BaseUuidModel): """A model used by the system. Auto-completed by subject_consent. """ on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords()
class SubjectOffStudy(UniqueSubjectIdentifierFieldMixin, SiteModelFormMixin, BaseUuidModel): """A model completed by the user that completed when the subject is taken off-study. """ offstudy_date = models.DateField( verbose_name="Off-study Date", null=True, default=get_utcnow, validators=[ date_not_before_study_start, date_not_future]) report_datetime = models.DateTimeField( verbose_name="Report Date", validators=[ datetime_not_before_study_start, datetime_not_future], null=True, default=get_utcnow, help_text=('If reporting today, use today\'s date/time, otherwise use ' 'the date/time this information was reported.')) last_contact = models.DateField( verbose_name='Date of last contact', default=get_utcnow, validators=[ date_not_before_study_start, date_not_future]) reason = models.TextField( verbose_name='Describe the primary reason for going offstudy', max_length=500, null=True) reason_code = models.CharField( verbose_name=('Based on the description above code the primary reason ' 'for the participant to be going offstudy'), max_length=150, choices=OFF_STUDY_REASON, null=True) reason_code_other = OtherCharField() comment = models.TextField( max_length=250, verbose_name="Comment", blank=True, null=True) objects = SubjectIdentifierManager() history = HistoricalRecords() class Meta: app_label = 'motheo_call_manager' verbose_name_plural = 'Subject Off Study'
class UnblindingRequest( NonUniqueSubjectIdentifierFieldMixin, SiteModelMixin, ActionModelMixin, TrackingModelMixin, BaseUuidModel, ): action_name = UNBLINDING_REQUEST_ACTION tracking_identifier_prefix = "UB" report_datetime = models.DateTimeField(verbose_name="Report Date and Time", default=get_utcnow) initials = models.CharField( verbose_name="Subject's initials", max_length=3, validators=[ RegexValidator("[A-Z]{1,3}", "Invalid format"), MinLengthValidator(2), MaxLengthValidator(3), ], help_text="Use UPPERCASE letters only. May be 2 or 3 letters.", ) requestor = models.ForeignKey( UnblindingRequestorUser, related_name="+", on_delete=models.PROTECT, verbose_name="Unblinding requested by", help_text="Select a name from the list", ) unblinding_reason = models.TextField(verbose_name="Reason for unblinding") approved = models.CharField(max_length=15, default=TBD, choices=YES_NO_TBD) approved_datetime = models.DateTimeField(null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() def natural_key(self): return (self.action_identifier, ) class Meta: verbose_name = "Unblinding Request" verbose_name_plural = "Unblinding Requests" indexes = [ models.Index(fields=[ "subject_identifier", "action_identifier", "site", "id" ]) ]
class ChildOffSchedule(OffScheduleModelMixin, BaseUuidModel): schedule_name = models.CharField(max_length=25, blank=True, null=True) objects = SubjectIdentifierManager() on_site = CurrentSiteManager() history = HistoricalRecords() def take_off_schedule(self): pass def get_consent_version(self): preg_subject_screening_cls = django_apps.get_model( 'flourish_caregiver.screeningpregwomen') prior_subject_screening_cls = django_apps.get_model( 'flourish_caregiver.screeningpriorbhpparticipants') consent_version_cls = django_apps.get_model( 'flourish_caregiver.flourishconsentversion') subject_screening_obj = None try: subject_screening_obj = preg_subject_screening_cls.objects.get( subject_identifier=self.subject_identifier[:-3]) except preg_subject_screening_cls.DoesNotExist: try: subject_screening_obj = prior_subject_screening_cls.objects.get( subject_identifier=self.subject_identifier[:-3]) except prior_subject_screening_cls.DoesNotExist: raise ValidationError( 'Missing Subject Screening form. Please complete ' 'it before proceeding.') if subject_screening_obj: try: consent_version_obj = consent_version_cls.objects.get( screening_identifier=subject_screening_obj. screening_identifier) except consent_version_cls.DoesNotExist: raise ValidationError( 'Missing Consent Version form. Please complete ' 'it before proceeding.') return consent_version_obj.version def save(self, *args, **kwargs): self.consent_version = self.get_consent_version() super().save(*args, **kwargs) class Meta: unique_together = ('subject_identifier', 'schedule_name')
class OnScheduleW10(OnScheduleModelMixin, BaseUuidModel): """A model used by the system. Auto-completed by the signal. """ on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords() class Meta(OnScheduleModelMixin.Meta): pass
class MaternalOffStudy(OffStudyModelMixin, OffScheduleModelMixin, ActionModelMixin, BaseUuidModel): tracking_identifier_prefix = 'MO' action_name = MATERNALOFF_STUDY_ACTION 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.')) reason = models.CharField( verbose_name=('Please code the primary reason participant taken' ' off-study'), max_length=115, choices=MATERNAL_OFF_STUDY_REASON) objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): maternal_labour_del_schedule = django_apps.get_model( 'td_maternal.onschedulematernallabourdel') antenatal_visit_membership_schedule = django_apps.get_model( 'td_maternal.onscheduleantenatalvisitmembership') antenatal_enrollment_schedule = django_apps.get_model( 'td_maternal.onscheduleantenatalenrollment') maternal_schedules = [ maternal_labour_del_schedule, antenatal_visit_membership_schedule, antenatal_enrollment_schedule ] for on_schedule in maternal_schedules: on_schedule_objs = on_schedule.objects.filter( subject_identifier=self.subject_identifier) if on_schedule_objs: for on_schedule_obj in on_schedule_objs: _, schedule = \ site_visit_schedules.get_by_onschedule_model_schedule_name( onschedule_model=on_schedule._meta.label_lower, name=on_schedule_obj.schedule_name) schedule.take_off_schedule(offschedule_model_obj=self) class Meta: app_label = 'td_prn' verbose_name = 'Maternal Off Study' verbose_name_plural = 'Maternal Off Studies'
class CaregiverOffStudy(OffStudyModelMixin, OffScheduleModelMixin, ActionModelMixin, BaseUuidModel): tracking_identifier_prefix = 'MO' action_name = CAREGIVEROFF_STUDY_ACTION 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.')) reason = models.CharField( verbose_name=('Please code the primary reason participant taken' ' off-study'), max_length=115, choices=CAREGIVER_OFF_STUDY_REASON) offstudy_point = models.CharField( verbose_name='At what point did the mother go off study', choices=OFFSTUDY_POINT, max_length=50, blank=True, null=True, help_text='For pregnant women enrolled in Cohort A') objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): history_model = 'edc_visit_schedule.subjectschedulehistory' history_cls = django_apps.get_model(history_model) onschedules = history_cls.objects.onschedules( subject_identifier=self.subject_identifier) if onschedules: for onschedule in onschedules: _, schedule = \ site_visit_schedules.get_by_onschedule_model_schedule_name( onschedule_model=onschedule._meta.label_lower, name=onschedule.schedule_name) schedule.take_off_schedule( subject_identifier=self.subject_identifier) class Meta: app_label = 'flourish_prn' verbose_name = 'Caregiver Off Study' verbose_name_plural = 'Caregiver Off Study'
class SubjectConsent( ConsentModelMixin, PersonalFieldsMixin, IdentityFieldsMixin, UniqueSubjectIdentifierFieldMixin, UpdatesOrCreatesRegistrationModelMixin, SiteModelMixin, BaseUuidModel, ): objects = SubjectIdentifierManager() def natural_key(self): return (self.subject_identifier, )
class OnScheduleModelMixin(BaseOnScheduleModelMixin, BaseUuidModel): """A model used by the system. Auto-completed by enrollment model. """ subject_identifier = models.CharField( verbose_name="Subject Identifier", max_length=50) schedule_name = models.CharField(max_length=25, blank=True, null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords() def put_on_schedule(self): pass def save(self, *args, **kwargs): self.consent_version = self.latest_consent_obj_version super().save(*args, **kwargs) @property def consent_version_cls(self): return django_apps.get_model('flourish_caregiver.flourishconsentversion') @property def subject_consent_cls(self): return django_apps.get_model('flourish_caregiver.subjectconsent') @property def latest_consent_obj_version(self): child_consent_cls = django_apps.get_model( 'flourish_child.childdummysubjectconsent') subject_consents = child_consent_cls.objects.filter( subject_identifier=self.subject_identifier,) if subject_consents: latest_consent = subject_consents.latest('consent_datetime') return latest_consent.version else: raise forms.ValidationError('Missing dummy consent obj, cannot proceed.') class Meta: unique_together = ('subject_identifier', 'schedule_name') abstract = True
class CaregiverOffSchedule(OffScheduleModelMixin, BaseUuidModel): schedule_name = models.CharField(max_length=25, blank=True, null=True) objects = SubjectIdentifierManager() on_site = CurrentSiteManager() history = HistoricalRecords() def take_off_schedule(self): pass class Meta: unique_together = ('subject_identifier', 'schedule_name')
class PreFlourishDeathReport(ActionModelMixin, SiteModelMixin, SearchSlugModelMixin, BaseUuidModel): objects = SubjectIdentifierManager() history = HistoricalRecords() def natural_key(self): return (self.subject_identifier, ) natural_key.dependencies = ['sites.Site'] class Meta: app_label = 'pre_flourish' verbose_name = 'Death Report'
class ChildOffStudy(OffStudyModelMixin, OffScheduleModelMixin, ActionModelMixin, BaseUuidModel): """ A model completed by the user when the child is taken off study. """ tracking_identifier_prefix = 'CO' action_name = CHILDOFF_STUDY_ACTION 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.')) reason = models.CharField( verbose_name=('Please code the primary reason the participant is' ' being taken off the study'), max_length=115, choices=CHILD_OFF_STUDY_REASON) objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): history_model = 'edc_visit_schedule.subjectschedulehistory' history_cls = django_apps.get_model(history_model) onschedules = history_cls.objects.onschedules( subject_identifier=self.subject_identifier) if onschedules: for onschedule in onschedules: _, schedule = \ site_visit_schedules.get_by_onschedule_model_schedule_name( onschedule_model=onschedule._meta.label_lower, name=onschedule.schedule_name) schedule.take_off_schedule( subject_identifier=self.subject_identifier) class Meta: app_label = 'flourish_prn' verbose_name = "Child Off-Study" verbose_name_plural = "Child Off-Study"
class MaternalDeathReport(DeathReportModelMixin, ActionModelMixin, SiteModelMixin, SearchSlugModelMixin, BaseUuidModel): tracking_identifier_prefix = 'MD' action_name = MATERNAL_DEATH_REPORT_ACTION objects = SubjectIdentifierManager() history = HistoricalRecords() def natural_key(self): return (self.subject_identifier, ) natural_key.dependencies = ['sites.Site'] class Meta: app_label = 'td_prn' verbose_name = 'Maternal Death Report'
class UnblindingReview( NonUniqueSubjectIdentifierFieldMixin, SiteModelMixin, ActionModelMixin, TrackingModelMixin, BaseUuidModel, ): action_name = UNBLINDING_REVIEW_ACTION tracking_identifier_prefix = "UR" report_datetime = models.DateTimeField(verbose_name="Report Date and Time", default=get_utcnow) reviewer = models.ForeignKey( UnblindingReviewerUser, related_name="+", on_delete=models.PROTECT, verbose_name="Unblinding request reviewed by", help_text="Select a name from the list", ) approved = models.CharField(max_length=15, default=TBD, choices=YES_NO_TBD) comment = models.TextField(verbose_name="Comment", null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() def natural_key(self): return (self.action_identifier, ) class Meta(BaseUuidModel.Meta): verbose_name = "Unblinding Review" verbose_name_plural = "Unblinding Reviews" indexes = [ models.Index(fields=[ "subject_identifier", "action_identifier", "site", "id" ]) ]
class StudyTerminationConclusionW10(OffScheduleModelMixin, ActionItemModelMixin, TrackingIdentifierModelMixin, BaseUuidModel): action_cls = StudyTerminationConclusionW10Action tracking_identifier_prefix = 'ST' last_study_fu_date = models.DateField( verbose_name='Date of last research follow up (if different):', validators=[date_not_future], blank=True, null=True) termination_reason = models.CharField( verbose_name='Reason for study termination', max_length=75, choices=REASON_STUDY_TERMINATED_W10, help_text=( 'If included in error, be sure to fill in protocol deviation form.' )) death_date = models.DateField(verbose_name='Date of Death', validators=[date_not_future], blank=True, null=True) consent_withdrawal_reason = models.CharField( verbose_name='Reason for withdrawing consent', max_length=75, blank=True, null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords() class Meta: verbose_name = 'W10 Study Termination/Conclusion' verbose_name_plural = 'W10 Study Terminations/Conclusions'
class OnScheduleMaternalLabourDel(ConsentVersionModelModelMixin, OnScheduleModelMixin, BaseUuidModel): """A model used by the system. Auto-completed by subject_consent. """ subject_identifier = models.CharField(verbose_name="Subject Identifier", max_length=50) schedule_name = models.CharField(max_length=25, blank=True, null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords() def put_on_schedule(self): pass class Meta: unique_together = ('subject_identifier', 'schedule_name')
class ScheduleModelMixin(UniqueSubjectIdentifierFieldMixin, SiteModelMixin, models.Model): """A model mixin for a schedule's on/off schedule models.""" report_datetime = models.DateTimeField(editable=False) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() def __str__(self): formatted_date = timezone.localtime(self.report_datetime).strftime( convert_php_dateformat(settings.SHORT_DATE_FORMAT) ) return f"{self.subject_identifier} {formatted_date}" def natural_key(self): return (self.subject_identifier,) class Meta: abstract = True
class OnScheduleInfantBirth(OnScheduleModelMixin, BaseUuidModel): """A model used by the system. Auto-completed by infant birth. """ subject_identifier = models.CharField(verbose_name="Subject Identifier", max_length=50) schedule_name = models.CharField(max_length=25, blank=True, null=True) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() history = HistoricalRecords() def put_on_schedule(self): pass def save(self, *args, **kwargs): self.consent_version = self.get_consent_version() super(OnScheduleInfantBirth, self).save(*args, **kwargs) def get_consent_version(self): subject_consent_cls = django_apps.get_model( 'td_infant.infantdummysubjectconsent') subject_consent_objs = subject_consent_cls.objects.filter( subject_identifier=self.subject_identifier).order_by( '-consent_datetime') if subject_consent_objs: return subject_consent_objs.first().version else: raise ValidationError( 'Missing Infant Dummy Consent form. Cannot proceed.') class Meta: unique_together = ('subject_identifier', 'schedule_name')
class KaraboOffstudy(InfantCrfModelMixin): """ A model completed by the user when the infant is taken off study. """ 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.')) offschedule_datetime = models.DateTimeField( verbose_name="Date and time subject taken off schedule", validators=[ datetime_not_before_study_start, datetime_not_future], default=get_utcnow) reason = models.CharField( verbose_name=('Please code the primary reason participant taken' ' off-study'), max_length=115, choices=KARABO_OFF_STUDY_REASON) offstudy_date = models.DateField( verbose_name="Off-study Date", validators=[ date_not_before_study_start, date_not_future]) reason_other = OtherCharField() comment = models.TextField( max_length=250, verbose_name="Comment", blank=True, null=True) objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): pass def get_consent_version(self): subject_consent_cls = django_apps.get_model( 'td_infant.infantdummysubjectconsent') subject_consent_objs = subject_consent_cls.objects.filter( subject_identifier=self.infant_visit.subject_identifier).order_by( '-consent_datetime') if subject_consent_objs: return subject_consent_objs.first().version else: raise ValidationError( 'Missing Infant Dummy Consent form. Cannot proceed.') def save(self, *args, **kwargs): super().save(*args, **kwargs) class Meta: app_label = 'td_infant' verbose_name = "Karabo Off-Study" verbose_name_plural = "Karabo Off-Study"
class CoordinatorExit(OffScheduleModelMixin, ActionModelMixin, BaseUuidModel): action_name = COORDINATOR_EXIT_ACTION tracking_identifier_prefix = 'CE' report_datetime = models.DateTimeField( verbose_name='Report datetime', validators=[datetime_not_before_study_start, datetime_not_future], null=True, default=get_utcnow,) components_rec = models.ManyToManyField( ComponentsReceived, verbose_name='Potlako components received (or potentially received)',) components_rec_other = OtherCharField( verbose_name='Other Potlako component received:', max_length=50,) cancer_stage = models.CharField( verbose_name='If cancer, stage of cancer', choices=CANCER_STAGES, max_length=20, blank=True, null=True) cancer_treatment_rec = models.CharField( verbose_name='Was any cancer specific treatment received?', choices=YES_NO_UNKNOWN, max_length=7, help_text='(Example: radiation, surgery (beyond biopsy), chemotherapy,' ' ART for KS, esophageal stenting)',) cancer_treatment = models.CharField( verbose_name='What specific cancer treatment was received?', choices=CANCER_TREATMENT, max_length=25, blank=True, null=True,) cancer_treatment_other = OtherCharField() date_therapy_started = models.DateField( verbose_name='Date started cancer specific therapy', validators=[date_not_future, ], blank=True, null=True,) date_therapy_started_estimated = models.CharField( verbose_name='Is the above therapy start date estimated?', choices=YES_NO, max_length=3, blank=True, null=True,) date_therapy_started_estimation = models.CharField( verbose_name='If yes, which part of the therapy start date was estimated?', choices=DATE_ESTIMATION, max_length=15, blank=True, null=True,) treatment_intent = models.CharField( verbose_name='At time of exit, what was treatment intent?', choices=TREATMENT_INTENT, max_length=10,) patient_disposition = models.CharField( verbose_name='What is the patient\'s final disposition?', choices=DISPOSITION, default='exit', max_length=15) patient_contact_date = models.DateField( verbose_name='If call/visit above, date for patient call/visit ', validators=[date_is_future, ], blank=True, null=True,) objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): on_schedule = django_apps.get_model( 'potlako_subject.onschedule') _, schedule = site_visit_schedules.get_by_onschedule_model( onschedule_model=on_schedule._meta.label_lower) schedule.take_off_schedule(offschedule_model_obj=self) def save(self, *args, **kwargs): self.consent_version = None super().save(*args, **kwargs) class Meta: app_label = 'potlako_prn' verbose_name = 'Coordinator Exit' verbose_name_plural = 'Coordinator Exit'
class SubjectReconsent( UniqueSubjectIdentifierModelMixin, SiteModelMixin, ReviewFieldsMixin, SearchSlugModelMixin, ActionModelMixin, TrackingModelMixin, BaseUuidModel, ): """ A model completed by the user that updates the consent for those originally consented by next of kin. """ subject_identifier_cls = None subject_screening_model = "meta_screening.subjectscreening" subject_consent_model = "meta_consent.subjectconsent" tracking_identifier_prefix = "SR" action_name = RECONSENT_ACTION site = models.ForeignKey(Site, on_delete=models.PROTECT, null=True, editable=False) report_datetime = models.DateTimeField(default=get_utcnow) identity = IdentityField( verbose_name="Identity number", help_text=( "Provide the same identity number provided on the original " "consent complete by the next of kin." ), ) on_site = CurrentSiteManager() objects = SubjectIdentifierManager() def __str__(self): return self.subject_identifier def save(self, *args, **kwargs): subject_screening = self.get_subject_screening() if subject_screening.mental_status != ABNORMAL: raise ValidationError("Reconsent is not required.") try: self.get_subject_consent( screening_identifier=subject_screening.screening_identifier ) except ObjectDoesNotExist: raise ValidationError("Previous consent does not exist.") super().save(*args, **kwargs) def natural_key(self): return (self.subject_identifier, self.version) def get_subject_consent(self, screening_identifier=None): """Returns the first subject consent model instance. """ if not screening_identifier: screening_identifier = self.get_subject_screening().screening_identifier model_cls = django_apps.get_model(self.subject_consent_model) return model_cls.objects.get( screening_identifier=screening_identifier, subject_identifier=self.subject_identifier, identity=self.identity, ) def get_subject_screening(self): """Returns the subject screening model instance. """ rs = RegisteredSubject.objects.get(subject_identifier=self.subject_identifier) model_cls = django_apps.get_model(self.subject_screening_model) return model_cls.objects.get(screening_identifier=rs.screening_identifier) @property def registration_unique_field(self): """Required for UpdatesOrCreatesRegistrationModelMixin. """ return "subject_identifier" class Meta: verbose_name = "Subject re-consent"
class InfantOffStudy(OffStudyModelMixin, OffScheduleModelMixin, ActionModelMixin, BaseUuidModel): """ A model completed by the user when the infant is taken off study. """ tracking_identifier_prefix = 'IO' action_name = INFANTOFF_STUDY_ACTION 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.')) reason = models.CharField( verbose_name=('Please code the primary reason participant taken' ' off-study'), max_length=115, choices=INFANT_OFF_STUDY_REASON) objects = SubjectIdentifierManager() history = HistoricalRecords() def take_off_schedule(self): infant_schedule_model = django_apps.get_model( 'td_infant.onscheduleinfantbirth') on_schedule_objs = infant_schedule_model.objects.filter( subject_identifier=self.subject_identifier) if on_schedule_objs: for on_schedule_obj in on_schedule_objs: _, schedule = \ site_visit_schedules.get_by_onschedule_model_schedule_name( onschedule_model='td_infant.onscheduleinfantbirth', name=on_schedule_obj.schedule_name) schedule.take_off_schedule(offschedule_model_obj=self) def get_consent_version(self): subject_screening_cls = django_apps.get_model( 'td_maternal.subjectscreening') consent_version_cls = django_apps.get_model( 'td_maternal.tdconsentversion') try: subject_screening_obj = subject_screening_cls.objects.get( subject_identifier=self.subject_identifier[:-3]) except subject_screening_cls.DoesNotExist: raise ValidationError( 'Missing Subject Screening form. Please complete ' 'it before proceeding.') else: try: consent_version_obj = consent_version_cls.objects.get( screening_identifier=subject_screening_obj. screening_identifier) except consent_version_cls.DoesNotExist: raise ValidationError( 'Missing Consent Version form. Please complete ' 'it before proceeding.') return consent_version_obj.version class Meta: app_label = 'td_prn' verbose_name = "Infant Off-Study" verbose_name_plural = "Infant Off-Study"
class SubjectOffstudy(OffScheduleModelMixin, ActionModelMixin, BaseUuidModel): """A model completed by the user that completed when the subject is taken off-study. """ tracking_identifier_prefix = 'OS' action_name = SUBJECT_OFFSTUDY_ACTION offstudy_date = models.DateField( verbose_name="Off-study Date", null=True, default=get_utcnow, validators=[date_not_before_study_start, date_not_future]) report_datetime = models.DateTimeField( verbose_name="Report Date", validators=[datetime_not_before_study_start, datetime_not_future], null=True, default=get_utcnow, help_text=('If reporting today, use today\'s date/time, otherwise use ' 'the date/time this information was reported.')) reason = models.CharField(verbose_name="Please code the primary" " reason participant taken off-study", max_length=115, choices=OFF_STUDY_REASON, null=True) reason_other = OtherCharField() schedule = models.CharField( verbose_name='Are scheduled data being submitted' ' on the off-study date?', max_length=3, choices=YES_NO) comment = models.TextField(max_length=250, verbose_name="Comment", blank=True, null=True) objects = SubjectIdentifierManager() history = HistoricalRecords() def save(self, *args, **kwargs): self.consent_version = None super(SubjectOffstudy, self).save(*args, **kwargs) def take_off_schedule(self): on_schedule = OnSchedule try: on_schedule_obj = on_schedule.objects.get( subject_identifier=self.subject_identifier) except on_schedule.DoesNotExist: pass else: _, schedule = site_visit_schedules.get_by_onschedule_model( onschedule_model=on_schedule._meta.label_lower) schedule.take_off_schedule(offschedule_model_obj=self) class Meta: app_label = "trainee_prn" verbose_name_plural = "Subject Off Study"