class PackingList(PackingListMixin, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): objects = PackingListManager() history = SyncHistoricalRecords() @property def item_models(self): item_m = [] item_m.append(apps.get_model('td_lab', 'InfantRequisition')) item_m.append(apps.get_model('td_lab', 'MaternalRequisition')) item_m.append(apps.get_model('td_lab', 'Aliquot')) return item_m @property def packing_list_item_model(self): return apps.get_model('td_lab', 'PackingListItem') def specimen_count(self): lst = self.list_items.replace('\r', '').split('\n') return len(lst) def view_list_items(self): return '<a href="/admin/{app_label}/{object_name}item/?q={reference}">{count} items</a>'.format( app_label=self._meta.app_label, object_name=self._meta.object_name.lower(), reference=self.timestamp, count=self.specimen_count()) view_list_items.allow_tags = True class Meta: app_label = 'td_lab' verbose_name = 'Packing List'
class InfantFuDxItems(CrfInlineModelMixin, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): infant_fu_dx = models.ForeignKey(InfantFuDx) fu_dx = models.CharField(verbose_name="Diagnosis", max_length=150, choices=DX_INFANT) fu_dx_specify = models.CharField(verbose_name="Diagnosis specification", max_length=50, blank=True, null=True) health_facility = models.CharField( verbose_name="Seen at health facility for Dx", choices=YES_NO, max_length=3) was_hospitalized = models.CharField(verbose_name="Hospitalized?", choices=YES_NO, max_length=3) objects = InfantFuDxItemsManager() history = SyncHistoricalRecords() def natural_key(self): return (self.fu_dx, ) + self.infant_fu_dx.natural_key() class Meta: app_label = 'td_infant' verbose_name = "Infant FollowUp: Dx" unique_together = ('fu_dx', 'infant_fu_dx')
class MaternalEligibilityLoss(SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model triggered and completed by system when a mother is in-eligible. """ maternal_eligibility = models.OneToOneField(MaternalEligibility) report_datetime = models.DateTimeField( verbose_name="Report Date and Time", default=timezone.now, help_text='Date and time of report.') reason_ineligible = models.TextField( verbose_name='Reason not eligible', max_length=500, help_text='Gets reasons from Maternal Eligibility.ineligibility') objects = MaternalEligibilityLossManager() history = SyncHistoricalRecords() def __str__(self): return "{0}".format(self.maternal_eligibility.eligibility_id) def natural_key(self): return self.maternal_eligibility.natural_key() def ineligibility(self): return self.reason_ineligible or [] reason_ineligible.allow_tags = True class Meta: app_label = 'td_maternal' verbose_name = 'Maternal Eligibility Loss' verbose_name_plural = 'Maternal Eligibility Loss'
class InfantRequisition(CrfModelMixin, SyncModelMixin, RequisitionModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): aliquot_model = Aliquot infant_visit = models.ForeignKey(InfantVisit) packing_list = models.ForeignKey(PackingList, null=True, blank=True) aliquot_type = models.ForeignKey(AliquotType) panel = models.ForeignKey(Panel) reason_not_drawn_other = OtherCharField( max_length=35, verbose_name="if (other) specify...", blank=True, null=True) objects = InfantRequisitionManager() history = SyncHistoricalRecords() entry_meta_data_manager = RequisitionMetaDataManager(InfantVisit) def get_visit(self): return self.infant_visit class Meta: app_label = 'td_lab' verbose_name = 'Infant Laboratory Requisition' verbose_name_plural = 'Infant Laboratory Requisition' unique_together = ('infant_visit', 'panel', 'is_drawn')
class InfantCrfModel(CrfModelMixin, SyncModelMixin, OffStudyMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user on the infant's scheduled visit. """ off_study_model = ('td_infant', 'InfantOffStudy') infant_visit = models.OneToOneField(InfantVisit) history = SyncHistoricalRecords() objects = InfantVisitCrfManager() entry_meta_data_manager = CrfMetaDataManager(InfantVisit) def __str__(self): return "{}: {}".format( self.__class__._meta.model_name, self.infant_visit.appointment. registered_subject.subject_identifier) def get_consenting_subject_identifier(self): """Returns mother's identifier.""" return self.get_visit( ).appointment.registered_subject.relative_identifier class Meta: abstract = True
class MaternalCrfModel(SyncModelMixin, CrfModelMixin, ExportTrackingFieldsMixin, OffStudyMixin, RequiresConsentMixin, BaseUuidModel): """ Base model for all scheduled models (adds key to :class:`MaternalVisit`). """ consent_model = MaternalConsent visit_model_attr = 'maternal_visit' off_study_model = ('td_maternal', 'MaternalOffStudy') maternal_visit = models.OneToOneField(MaternalVisit) history = SyncHistoricalRecords() objects = VisitCrfModelManager() entry_meta_data_manager = CrfMetaDataManager(MaternalVisit) def __str__(self): return "{}: {}".format( self.__class__._meta.model_name, self.maternal_visit.appointment. registered_subject.subject_identifier) def natural_key(self): return self.maternal_visit.natural_key() class Meta: abstract = True
class InfantVaccines(CrfInlineModelMixin, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): infant_birth_feed_vaccine = models.ForeignKey(InfantBirthFeedingVaccine) vaccination = models.CharField( choices=INFANT_VACCINATIONS, verbose_name="Since delivery, did the child receive any of the following vaccinations", max_length=100) vaccine_date = models.DateField( verbose_name='Date Vaccine was given', null=True, blank=True) objects = InfantVaccinesManager() history = SyncHistoricalRecords() def natural_key(self): return (self.vaccination, ) + self.infant_birth_feed_vaccine.natural_key() class Meta: app_label = 'td_infant' verbose_name = "Infant Vaccines" verbose_name_plural = "Infant Vaccines" unique_together = ( 'infant_birth_feed_vaccine', 'vaccination', 'vaccine_date')
class AliquotProcessing(BaseProcessing, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): aliquot = models.ForeignKey(Aliquot, verbose_name='Source Aliquot', help_text='Create aliquots from this one.') profile = models.ForeignKey( AliquotProfile, verbose_name='Profile', help_text='Create aliquots according to this profile.') objects = AliquotProcessingManager() history = SyncHistoricalRecords() def natural_key(self): return self.aliquot.natural_key() + self.profile.natural_key() def deserialize_get_missing_fk(self, attrname): retval = None return retval class Meta: app_label = 'td_lab' db_table = 'td_lab_processing'
class Order(SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): order_datetime = models.DateTimeField(default=timezone.now) objects = OrderManager() history = SyncHistoricalRecords() def natural_key(self): return (self.order_datetime, ) def items(self): change_list_url = reverse("admin:{}_{}_changelist".format( self._meta.app_label, 'orderitem')) return '<a href="{change_list_url}?q={pk}">{count} items</a>'.format( change_list_url=change_list_url, pk=self.id, count=self.order_items.count()) items.allow_tags = True # @property # def order_items(self): # OrderItem = models.get_model('mb_lab', 'orderitem') # return OrderItem.objects.filter(order__pk=self.pk) class Meta: app_label = 'td_lab'
class BaseCnsItem(CrfInlineModelMixin, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): congenital_anomalies = models.ForeignKey(InfantCongenitalAnomalies) history = SyncHistoricalRecords() class Meta: abstract = True
class Result(BaseResult, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): """Stores result information in a one-to-many relation with :class:`ResultItem`.""" order_item = models.ForeignKey(OrderItem) subject_identifier = models.CharField( max_length=50, null=True, editable=False, db_index=True, help_text="non-user helper field to simplify search and filtering") objects = ResultManager() history = SyncHistoricalRecords() def save(self, *args, **kwargs): self.subject_identifier = self.order.aliquot.receive.registered_subject.subject_identifier super(Result, self).save(*args, **kwargs) def __str__(self): return "{}: {}: order: {}".format(self.__class__._meta.model_name, self.subject_identifier, self.order_item.order_identifier) def panel(self): try: return str(self.order_item.panel.edc_name) except AttributeError: return None def natural_key(self): return (self.result_identifier, self.subject_identifier) def report(self): url = reverse('view_result_report', kwargs={'result_identifier': self.result_identifier}) url_review = reverse('admin:lab_clinic_api_review_add') two = '' if self.review: label = 'comment' url_review = self.review.get_absolute_url() two = ('<a href="{url}" class="add-another" id="add_id_review" ' 'onclick="return showAddAnotherPopup(this);"> {label}</a>' ).format(url=url_review, label=label) one = ( '<a href="{url}" class="add-another" id="add_id_report" ' 'onclick="return showAddAnotherPopup(this);"> <img src="/static/admin/img/icon_addlink.gif" ' 'width="10" height="10" alt="View report"/></a>').format(url=url) return '{one} {two}'.format(one=one, two=two) report.allow_tags = True class Meta: app_label = 'td_lab' ordering = ['result_identifier']
class LogEntry(SyncModelMixin, LogEntryModelMixin, BaseUuidModel): log = models.ForeignKey(Log) history = SyncHistoricalRecords() objects = LogEntryManager() class Meta: app_label = 'call_manager'
class Log(SyncModelMixin, LogModelMixin, BaseUuidModel): call = models.ForeignKey(Call) history = SyncHistoricalRecords() objects = LogManager() class Meta: app_label = 'call_manager'
class InfantOffStudy(CrfModelMixin, OffStudyModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user when the infant is taken off study. """ infant_visit = models.OneToOneField(InfantVisit) entry_meta_data_manager = CrfMetaDataManager(InfantVisit) history = SyncHistoricalRecords() class Meta: app_label = 'td_infant' verbose_name = "Infant Off-Study" verbose_name_plural = "Infant Off-Study"
class SpecimenConsent(BaseSpecimenConsent, SampleCollectionFieldsMixin, RequiresConsentMixin, VulnerabilityFieldsMixin, TdAppointmentMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user when a mother gives consent for specimen storage. """ consent_model = MaternalConsent registered_subject = models.OneToOneField(RegisteredSubject, null=True) objects = SpecimenConsentManager() history = SyncHistoricalRecords() def __str__(self): return "{0}".format(self.registered_subject.subject_identifier) def natural_key(self): return self.registered_subject.natural_key() def prepare_appointments(self, using): """Overrides so that the signal does not attempt to prepare appointments.""" pass @property def group_names(self): return ['Specimen Consent'] def get_subject_identifier(self): return self.registered_subject.subject_identifier def get_report_datetime(self): return self.consent_datetime @property def subject_identifier(self): return self.get_subject_identifier() # subject_identifier.allow_tags = True @property def report_datetime(self): return self.consent_datetime class Meta: app_label = 'td_maternal' verbose_name = 'Specimen Consent' verbose_name_plural = 'Specimen Consent'
class InfantArvProphMod(CrfInlineModelMixin, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user on the infant's nvp or azt prophylaxis modifications. """ infant_arv_proph = models.ForeignKey(InfantArvProph) arv_code = models.CharField( verbose_name="ARV Code", max_length=25, choices=ARV_DRUG_LIST, ) dose_status = models.CharField( max_length=25, choices=DOSE_STATUS, verbose_name="Dose Status", ) modification_date = models.DateField(verbose_name="Date ARV Modified", ) modification_code = models.CharField( max_length=50, choices=ARV_MODIFICATION_REASON, verbose_name="Reason for Modification", ) other_reason = models.CharField(verbose_name="Specify Other", max_length=100, null=True, blank=True) objects = InfantArvProphModManager() history = SyncHistoricalRecords() def natural_key(self): return (self.arv_code, ) + self.infant_arv_proph.natural_key() class Meta: app_label = 'td_infant' verbose_name = 'Infant NVP or AZT Proph: Mods' verbose_name_plural = 'Infant NVP or AZT Proph: Mods' unique_together = ('infant_arv_proph', 'arv_code', 'dose_status', 'modification_date')
class InfantFuNewMedItems(CrfInlineModelMixin, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): """A model completed by the user on the infant's follow up medication items.""" infant_fu_med = models.ForeignKey(InfantFuNewMed) medication = models.CharField( max_length=100, choices=MEDICATIONS, verbose_name="Medication", ) other_medication = OtherCharField() date_first_medication = models.DateField( verbose_name="Date of first medication use", ) stop_date = models.DateField( verbose_name="Date medication was stopped", blank=True, null=True, ) drug_route = models.CharField( max_length=20, choices=DRUG_ROUTE, verbose_name="Drug route", ) objects = InfantFuNewMedItemsManager() history = SyncHistoricalRecords() def natural_key(self): return (self.medication, ) + self.infant_fu_med.natural_key() class Meta: app_label = 'td_infant' verbose_name = "Infant FollowUp: New Med Items" verbose_name_plural = "Infant FollowUp: New Med Items"
class OrderItem(SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): order = models.ForeignKey(Order) aliquot = models.ForeignKey(Aliquot) panel = models.ForeignKey( Panel, null=True, blank=False, ) order_identifier = models.CharField( max_length=25, null=True, help_text='', ) order_datetime = models.DateTimeField( default=timezone.now ) subject_identifier = models.CharField( max_length=50, null=True, help_text="non-user helper field to simplify search and filtering") objects = OrderItemManager() history = SyncHistoricalRecords() def save(self, *args, **kwargs): self.subject_identifier = self.aliquot.receive.registered_subject.subject_identifier super(OrderItem, self).save(*args, **kwargs) def natural_key(self): return (self.order_identifier, ) class Meta: app_label = 'td_lab' ordering = ['-order_datetime', ]
class VaccinesReceived(CrfInlineModelMixin, SyncModelMixin, BaseUuidModel): """ALL possible vaccines given to infant""" infant_fu_immunizations = models.ForeignKey(InfantFuImmunizations) received_vaccine_name = models.CharField( verbose_name="Received vaccine name", choices=IMMUNIZATIONS, max_length=100, null=True, blank=True) date_given = models.DateField(verbose_name="Date Given", validators=[ date_not_future, ], null=True, blank=True) infant_age = models.CharField(verbose_name="Infant age when vaccine given", choices=INFANT_AGE_VACCINE_GIVEN, null=True, blank=True, max_length=35) objects = VaccinesReceivedManager() history = SyncHistoricalRecords() def natural_key(self): return (self.received_vaccine_name, ) + self.infant_fu_immunizations.natural_key() class Meta: app_label = 'td_infant' verbose_name = 'Received Vaccines' verbose_name_plural = 'Received Vaccines' unique_together = ('received_vaccine_name', 'infant_fu_immunizations', 'infant_age')
class Call(SyncModelMixin, CallModelMixin, BaseUuidModel): registered_subject = models.ForeignKey(RegisteredSubject) # subject_identifier = models.CharField( # verbose_name="Subject Identifier", # max_length=50, # blank=True, # db_index=True, # unique=True) call_datetime = models.DateTimeField(default=timezone.now, verbose_name='Date of this call') history = SyncHistoricalRecords() objects = CallManager() def __str__(self): return self.registered_subject.subject_identifier @property def subject(self): return self def get_gender_display(self): return self.registered_subject.gender @property def dob(self): return self.registered_subject.dob @property def last_name(self): return self.registered_subject.last_name class Meta: app_label = 'call_manager'
class MaternalRequisition(CrfModelMixin, SyncModelMixin, RequisitionModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): aliquot_model = Aliquot maternal_visit = models.ForeignKey(MaternalVisit) packing_list = models.ForeignKey(PackingList, null=True, blank=True) aliquot_type = models.ForeignKey(AliquotType) panel = models.ForeignKey(Panel) reason_not_drawn_other = OtherCharField( max_length=35, verbose_name="if (other) specify...", blank=True, null=True) objects = MaternalRequisitionManager() history = SyncHistoricalRecords() entry_meta_data_manager = RequisitionMetaDataManager(MaternalVisit) def __str__(self): return '{0} {1}'.format(str(self.panel), self.requisition_identifier) def natural_key(self): return (self.requisition_identifier, ) class Meta: app_label = 'td_lab' verbose_name = 'Maternal Requisition' verbose_name_plural = 'Maternal Requisition' unique_together = ('maternal_visit', 'panel', 'is_drawn') ordering = ('-created', )
class VaccinesMissed(CrfInlineModelMixin, SyncModelMixin, BaseUuidModel): """ALL vaccines missed by infant""" parent_model_attr = 'infant_fu_immunizations' infant_fu_immunizations = models.ForeignKey(InfantFuImmunizations) missed_vaccine_name = models.CharField(verbose_name="Missed vaccine name", choices=IMMUNIZATIONS, max_length=100, null=True, blank=True) reason_missed = models.CharField( verbose_name="Reasons infant missed vaccines", choices=REASONS_VACCINES_MISSED, max_length=100, null=True, blank=True) reason_missed_other = OtherCharField() objects = VaccinesMissedManager() history = SyncHistoricalRecords() def natural_key(self): return (self.missed_vaccine_name, ) + self.infant_fu_immunizations.natural_key() class Meta: app_label = 'td_infant' verbose_name = 'Missed Vaccines' verbose_name_plural = 'Missed Vaccines' unique_together = ('missed_vaccine_name', 'infant_fu_immunizations', 'reason_missed')
class InfantVisit(CrfMetaDataMixin, SyncModelMixin, TdPreviousVisitMixin, OffStudyMixin, VisitModelMixin, CaretakerFieldsMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user on the infant visits. """ off_study_model = ('td_infant', 'InfantOffStudy') death_report_model = ('td_infant', 'InfantDeathReport') consent_model = InfantBirth # a bit weird, see visit_form_mixin clean() history = SyncHistoricalRecords() def __str__(self): return '{} {} {}'.format( self.appointment.registered_subject.subject_identifier, self.appointment.registered_subject.first_name, self.appointment.visit_definition.code) def custom_post_update_crf_meta_data(self): """Calls custom methods that manipulate meta data on the post save. This method is called in a post-save signal in edc_meta_data.""" if self.survival_status == DEAD: self.require_death_report() elif self.reason == COMPLETED_PROTOCOL_VISIT: self.require_off_study_report() elif self.reason == UNSCHEDULED: self.change_to_unscheduled_visit(self.appointment) elif self.reason == SCHEDULED: pass # if self.postnatal_enrollment.enrollment_hiv_status: # self.requires_infant_birth_arv_on_maternal_pos() # self.requires_dna_pcr_on_maternal_pos() # self.requires_circumcision_for_male_at_2030_or_2060() return self # def requires_infant_birth_arv_on_maternal_pos(self): # PostnatalEnrollment = get_model('mb_maternal', 'PostnatalEnrollment') # maternal_registered_subject = RegisteredSubject.objects.get( # subject_identifier=self.appointment.registered_subject.relative_identifier) # postnatal_enrollment = PostnatalEnrollment.objects.get( # registered_subject=maternal_registered_subject) # if postnatal_enrollment.enrollment_hiv_status == POS: # if self.appointment.visit_definition.code == '2000': # self.crf_is_required(self.appointment, 'td_infant', 'infantbirtharv') # def requires_dna_pcr_on_maternal_pos(self): # PostnatalEnrollment = get_model('td_maternal', 'PostnatalEnrollment') # maternal_registered_subject = RegisteredSubject.objects.get( # subject_identifier=self.appointment.registered_subject.relative_identifier) # postnatal_enrollment = PostnatalEnrollment.objects.get( # registered_subject=maternal_registered_subject) # if postnatal_enrollment.enrollment_hiv_status == POS: # if self.appointment.visit_definition.code in [ # '2000', '2010', '2030', '2060', '2090', '2120']: # self.requisition_is_required( # self.appointment, 'td_lab', 'infantrequisition', 'DNA PCR') def requires_circumcision_for_male_at_2030_or_2060(self): infant_birth = InfantBirth.objects.get( registered_subject=self.appointment.registered_subject) if infant_birth.gender == MALE: if self.appointment.visit_definition.code == '2030': self.crf_is_required(self.appointment, 'td_infant', 'infantcircumcision') if self.appointment.visit_definition.code == '2060': appointment = Appointment.objects.get( visit_definition__code='2030', registered_subject=self.appointment.registered_subject) if appointment: infant_visit = InfantVisit.objects.get( appointment=appointment) if infant_visit.reason == MISSED_VISIT: self.crf_is_required(self.appointment, 'td_infant', 'infantcircumcision') def natural_key(self): return self.appointment.natural_key() natural_key.dependencies = ['edc_appointment.appointment'] def get_visit_reason_choices(self): return VISIT_REASON def get_visit_reason_no_follow_up_choices(self): """Returns the visit reasons that do not imply any data collection; that is, the subject is not available.""" dct = {} for item in VISIT_REASON_NO_FOLLOW_UP_CHOICES: if item not in [COMPLETED_PROTOCOL_VISIT, LOST_VISIT]: dct.update({item: item}) return dct class Meta: app_label = 'td_infant' verbose_name = "Infant Visit" verbose_name_plural = "Infant Visit"
class MaternalLabourDel(SyncModelMixin, RequiresConsentMixin, TdAppointmentMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user on Maternal Labor and Delivery which triggers registration of infants. """ consent_model = MaternalConsent registered_subject = models.OneToOneField(RegisteredSubject, null=True) report_datetime = models.DateTimeField(verbose_name="Report date", validators=[ datetime_not_before_study_start, datetime_not_future, ], help_text='') delivery_datetime = models.DateTimeField( verbose_name="Date and time of delivery :", help_text="If TIME unknown, estimate", validators=[ datetime_not_future, ]) delivery_time_estimated = models.CharField( verbose_name="Is the delivery TIME estimated?", max_length=3, choices=YES_NO) delivery_hospital = models.CharField(verbose_name="Place of delivery? ", max_length=65, choices=DELIVERY_HEALTH_FACILITY, help_text="If 'OTHER', specify below") delivery_hospital_other = OtherCharField() labour_hrs = models.CharField( verbose_name= "How long prior to to delivery, in HRS, did labour begin? ", max_length=10) mode_delivery = models.CharField( verbose_name="What was the mode of delivery?", max_length=100, choices=DELIVERY_MODE, help_text="If 'OTHER', specify below") mode_delivery_other = OtherCharField() csection_reason = models.CharField( verbose_name="If C-section was performed, indicate reason below", max_length=100, choices=CSECTION_REASON, help_text="If 'OTHER', specify below") csection_reason_other = OtherCharField() delivery_complications = models.ManyToManyField( DeliveryComplications, verbose_name= "Were any of the following complications present at delivery? ", help_text="If 'OTHER', specify below") delivery_complications_other = OtherCharField() live_infants_to_register = models.IntegerField( verbose_name="How many babies are you registering to the study? ") still_births = models.IntegerField( default=0, verbose_name="How many still births or miscarriages?") valid_regiment_duration = models.CharField( verbose_name= "(Interviewer) If HIV+ve, has the participant been on the ART " "regimen for at least 4 weeks in pregnancy?", choices=YES_NO_NA, null=True, blank=False, max_length=15, help_text=( "If not 4 or more weeks then participant will go OFF STUDY.")) arv_initiation_date = models.DateField( verbose_name= "(Interviewer) If on ART, when did the participant initiate therapy for this pregnancy?", null=True, blank=True) delivery_comment = models.TextField( verbose_name= "List any additional information about the labour and delivery (mother only) ", max_length=250, blank=True, null=True) comment = models.TextField( verbose_name="Comment if any additional pertinent information ", max_length=250, blank=True, null=True) history = SyncHistoricalRecords() objects = MaternalLabourDelManager() def save(self, *args, **kwargs): # self.live_infants_to_register = 1 super(MaternalLabourDel, self).save(*args, **kwargs) def __str__(self): return "{0}".format(self.registered_subject.subject_identifier) def natural_key(self): return self.registered_subject.natural_key() natural_key.dependencies = ['edc_registration.registeredsubject'] def get_registration_datetime(self): return self.report_datetime @property def subject_identifier(self): return self.registered_subject.subject_identifier def get_subject_identifier(self): return self.registered_subject.subject_identifier @property def antenatal_enrollment(self): AntenatalEnrollment = apps.get_model('td_maternal', 'antenatalenrollment') return AntenatalEnrollment.objects.get( registered_subject=self.registered_subject) @property def group_names(self): return ['Follow Up Visit', 'Follow Up Visit v3'] def prepare_appointments(self, using): """Creates infant appointments relative to the date-of-delivery""" maternal_consent = MaternalConsent.objects.filter( subject_identifier=self.subject_identifier).order_by( 'version').last() instruction = 'V' + maternal_consent.version self.create_all(using=using, instruction=instruction) @property def keep_on_study(self): if self.antenatal_enrollment.enrollment_hiv_status == POS and self.valid_regiment_duration != YES: return False return True class Meta: app_label = 'td_maternal' verbose_name = "Delivery" verbose_name_plural = "Deliveries"
class MaternalEligibility(SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user to test and capture the result of the pre-consent eligibility checks. This model has no PII.""" registered_subject = models.OneToOneField(RegisteredSubject, null=True) eligibility_id = models.CharField(verbose_name="Eligibility Identifier", max_length=36, unique=True, editable=False) report_datetime = models.DateTimeField( verbose_name="Report Date and Time", validators=[datetime_not_before_study_start, datetime_not_future], help_text='Date and time of assessing eligibility') age_in_years = models.IntegerField( verbose_name='What is the age of the participant?') has_omang = models.CharField(verbose_name="Do you have an OMANG?", max_length=3, choices=YES_NO) ineligibility = models.TextField(verbose_name="Reason not eligible", max_length=150, null=True, editable=False) is_eligible = models.BooleanField(default=False, editable=False) # is updated via signal once subject is consented is_consented = models.BooleanField(default=False, editable=False) # updated by signal on saving consent, is determined by participant # citizenship has_passed_consent = models.BooleanField(default=False, editable=False) objects = MaternalEligibilityManager() history = SyncHistoricalRecords() def save(self, *args, **kwargs): self.set_uuid_for_eligibility_if_none() self.is_eligible, error_message = self.check_eligibility() # error_message not None if is_eligible is False self.ineligibility = error_message super(MaternalEligibility, self).save(*args, **kwargs) def check_eligibility(self): """Returns a tuple (True, None) if mother is eligible otherwise (False, error_messsage) where error message is the reason for eligibility test failed.""" error_message = [] if self.age_in_years < MIN_AGE_OF_CONSENT: error_message.append( 'Mother is under {}'.format(MIN_AGE_OF_CONSENT)) if self.age_in_years > MAX_AGE_OF_CONSENT: error_message.append( 'Mother is too old (>{})'.format(MAX_AGE_OF_CONSENT)) if self.has_omang == NO: error_message.append('Not a citizen') is_eligible = False if error_message else True return (is_eligible, ','.join(error_message)) def __str__(self): return "Screened, age ({})".format(self.age_in_years) def natural_key(self): return self.eligibility_id @property def maternal_eligibility_loss(self): MaternalEligibilityLoss = apps.get_model('td_maternal', 'MaternalEligibilityLoss') try: maternal_eligibility_loss = MaternalEligibilityLoss.objects.get( maternal_eligibility_id=self.id) except MaternalEligibilityLoss.DoesNotExist: maternal_eligibility_loss = None return maternal_eligibility_loss @property def have_latest_consent(self): MaternalConsent = apps.get_model('td_maternal', 'MaternalConsent') return (MaternalConsent.objects.filter( subject_identifier=self.registered_subject.subject_identifier). order_by('-version').first().version == site_consent_types.get_by_consent_datetime( MaternalConsent, timezone.now()).version) @property def previous_consents(self): MaternalConsent = apps.get_model('td_maternal', 'MaternalConsent') return MaternalConsent.objects.filter( subject_identifier=self.registered_subject.subject_identifier ).order_by('version') @property def latest_consent_version(self): MaternalConsent = apps.get_model('td_maternal', 'MaternalConsent') consent_type = site_consent_types.get_by_datetime_lastest_version( MaternalConsent, timezone.now()) return consent_type.version @property def re_consent(self): if self.previous_consents and self.td_consent_version: MaternalConsent = apps.get_model('td_maternal', 'MaternalConsent') try: maternal_consent = MaternalConsent.objects.get( subject_identifier=self.registered_subject. subject_identifier, version=settings.LASTEST_VERSION) except MaternalConsent.DoesNotExist: maternal_consent = None if self.td_consent_version.version == settings.LASTEST_VERSION and not maternal_consent: return True return False @property def td_consent_version(self): """Returns a td consent version instance. """ from td_maternal.models import TdConsentVersion try: td_consent_version = TdConsentVersion.objects.get( maternal_eligibility=self) except TdConsentVersion.DoesNotExist: td_consent_version = None return td_consent_version @property def create_td_consent_version(self): from td_maternal.models import TdConsentVersion try: TdConsentVersion.objects.get(maternal_eligibility=self) except TdConsentVersion.DoesNotExist: TdConsentVersion.objects.create(version='3', maternal_eligibility=self, report_datetime=datetime.now()) def set_uuid_for_eligibility_if_none(self): if not self.eligibility_id: self.eligibility_id = str(uuid4()) class Meta: app_label = 'td_maternal' verbose_name = "Maternal Eligibility" verbose_name_plural = "Maternal Eligibility"
class OrderIdentifierHistory(SyncModelMixin, BaseIdentifierModel, ExportTrackingFieldsMixin, BaseUuidModel): history = SyncHistoricalRecords() class Meta: app_label = 'td_lab'
class InfantBirth(SyncModelMixin, OffStudyMixin, TdAppointmentMixin, ExportTrackingFieldsMixin, BaseUuidModel): """ A model completed by the user on the infant's birth. """ off_study_model = ('td_infant', 'InfantOffStudy') registered_subject = models.OneToOneField(RegisteredSubject, null=True) maternal_labour_del = models.ForeignKey( MaternalLabourDel, verbose_name="Mother's delivery record") report_datetime = models.DateTimeField( verbose_name="Date and Time infant enrolled", validators=[ datetime_not_before_study_start, datetime_not_future, ], help_text='') first_name = models.CharField( 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'") initials = models.CharField(max_length=3) 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) objects = InfantBirthModelManager() history = SyncHistoricalRecords() def natural_key(self): return self.maternal_labour_del.natural_key() natural_key.dependencies = [ 'td_maternal.maternallabourdel', 'edc_registration.registered_subject' ] def __str__(self): return "{} ({}) {}".format(self.first_name, self.initials, self.gender) @property def group_names(self): return ['Infant Enrollment', 'Infant Enrollment v3'] @property def maternal_consents(self): return MaternalConsent.objects.filter( subject_identifier=self.registered_subject.relative_identifier) def prepare_appointments(self, using): """Creates infant appointments relative to the date-of-delivery""" relative_identifier = self.registered_subject.relative_identifier maternal_labour_del = MaternalLabourDel.objects.get( registered_subject__subject_identifier=relative_identifier) maternal_consent = MaternalConsent.objects.filter( subject_identifier=relative_identifier).order_by('version').last() instruction = 'V' + maternal_consent.version self.create_all( base_appt_datetime=maternal_labour_del.delivery_datetime, using=using, instruction=instruction) def get_subject_identifier(self): return self.registered_subject.subject_identifier class Meta: app_label = 'td_infant' verbose_name = "Infant Birth"
class MaternalContact(AppointmentMixin, SyncModelMixin, BaseUuidModel): consent_model = MaternalConsent report_datetime = models.DateTimeField( verbose_name='Report Date', validators=[ datetime_not_before_study_start, datetime_not_future, ], default=timezone.now, help_text=('If reporting today, use today\'s date/time, otherwise use ' 'the date/time this information was reported.')) registered_subject = models.ForeignKey(RegisteredSubject) contact_type = models.CharField( verbose_name='Type of contact', choices=CONTACT_TYPE, max_length=25, ) contact_datetime = models.DateTimeField( verbose_name='Contact datetime', help_text='This date can be modified.', null=True, blank=True) call_reason = models.CharField( verbose_name='Reason for call', max_length=30, choices=CALL_REASON, ) call_reason_other = models.CharField(verbose_name='Other, specify', max_length=70, null=True, blank=True) contact_success = models.CharField( verbose_name='Were you able to reach the participant?', max_length=5, choices=YES_NO, help_text='If Yes, please answer the next question.') contact_comment = models.TextField(verbose_name='Outcome of call', max_length=500, null=True, blank=True) history = SyncHistoricalRecords() objects = MaternalContactManager() def natural_key(self): return (self.registered_subject.subject_identifier, ) def prepare_appointments(self, using): """Overrides so that the signal does not attempt to prepare appointments.""" pass # @property # def subject_consent(self): # try: # subject_consent = MaternalConsent.objects.get(subject_identifier=self.subject_identifier) # except MaternalConsent.DoesNotExist: # return None # return subject_consent def __str__(self): try: name = self.registered_subject.first_name except MaternalConsent.DoesNotExist: name = 'not consented' return '{}. {}'.format(name, self.registered_subject.subject_identifier) class Meta: app_label = 'td_maternal' unique_together = ('registered_subject', 'contact_datetime')
class PackingListItem(BasePackingListItem, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): packing_list = models.ForeignKey(PackingList, null=True) panel = models.ForeignKey(Panel, null=True, blank=True) objects = PackingListItemManager() history = SyncHistoricalRecords() def get_subject_type(self): aliquot = Aliquot.objects.get(aliquot_identifier=self.item_reference) registered_subject = RegisteredSubject.objects.get( subject_identifier=aliquot.subject_identifier) return registered_subject.subject_type def save(self, *args, **kwargs): if self.item_reference: aliquot = Aliquot.objects.get( aliquot_identifier=self.item_reference) if self.get_subject_type() == INFANT: requisition = InfantRequisition.objects.get( requisition_identifier=aliquot.receive. requisition_identifier) else: requisition = MaternalRequisition.objects.get( requisition_identifier=aliquot.receive. requisition_identifier) self.panel = requisition.panel self.item_priority = requisition.priority super(PackingListItem, self).save(*args, **kwargs) def drawn_datetime(self): retval = NOT_APPLICABLE if self.item_reference: aliquot = Aliquot.objects.get( aliquot_identifier=self.item_reference) if self.get_subject_type() == INFANT: requisition = InfantRequisition.objects.get( requisition_identifier=aliquot.receive. requisition_identifier) else: requisition = MaternalRequisition.objects.get( requisition_identifier=aliquot.receive. requisition_identifier) retval = requisition.drawn_datetime return retval def clinician(self): retval = NOT_APPLICABLE if self.item_reference: aliquot = Aliquot.objects.get( aliquot_identifier=self.item_reference) if self.get_subject_type() == INFANT: requisition = InfantRequisition.objects.get( requisition_identifier=aliquot.receive. requisition_identifier) else: requisition = MaternalRequisition.objects.get( requisition_identifier=aliquot.receive. requisition_identifier) retval = requisition.user_created return retval def gender(self): retval = NOT_APPLICABLE if self.item_reference: aliquot = Aliquot.objects.get( aliquot_identifier=self.item_reference) registered_subject = RegisteredSubject.objects.get( subject_identifier=aliquot.subject_identifier) retval = registered_subject.gender return retval def natural_key(self): return (self.item_reference, ) class Meta: app_label = "td_lab" verbose_name = 'Packing List Item'
class Aliquot(BaseAliquot, SyncModelMixin, ExportTrackingFieldsMixin, BaseUuidModel): receive = models.ForeignKey(Receive, editable=False) aliquot_type = models.ForeignKey(AliquotType, verbose_name="Aliquot Type", null=True) aliquot_condition = models.ForeignKey(AliquotCondition, verbose_name="Aliquot Condition", null=True, blank=True) is_rejected = models.BooleanField(verbose_name='rejected', default=False) def __str__(self): return self.aliquot_type.name objects = AliquotManager() history = SyncHistoricalRecords() def save(self, *args, **kwargs): self.subject_identifier = self.receive.registered_subject.subject_identifier super(Aliquot, self).save(*args, **kwargs) @property def specimen_identifier(self): return self.aliquot_identifier[:-4] @property def registered_subject(self): return self.receive.registered_subject @property def visit_code(self): return self.receive.visit @property def subject_visit(self): MaternalVisit = apps.get_model('td_maternal', 'MaternalVisit') try: return MaternalVisit.objects.get( appointment__visit_definition__code=self.visit_code, appointment__registered_subject=self.registered_subject) except MaternalVisit.DoesNotExist: return None @property def subject_requisition(self): model = self.receive.requisition_model_name RequisitionModel = apps.get_model('td_lab', model) try: return RequisitionModel.objects.get( requisition_identifier=self.receive.requisition_identifier) except RequisitionModel.DoesNotExist: return None @property def optional_description(self): """See PackingListHelper.""" try: return self.subject_requisition.optional_description except AttributeError: return None def processing(self): url = reverse('admin:td_lab_aliquotprocessing_add') return '<a href="{0}?aliquot={1}">process</a>'.format(url, self.pk) processing.allow_tags = True # # def related(self): # url = reverse('admin:mb_lab_aliquot_changelist') # return '<a href="{0}?q={1}">related</a>'.format(url, self.receive.receive_identifier) # related.allow_tags = True class Meta: app_label = 'td_lab' unique_together = (('receive', 'count'), )