Example #1
0
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'
Example #2
0
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
Example #6
0
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')
Example #8
0
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'
Example #9
0
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
Example #11
0
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}&nbsp;{two}'.format(one=one, two=two)

    report.allow_tags = True

    class Meta:
        app_label = 'td_lab'
        ordering = ['result_identifier']
Example #12
0
class LogEntry(SyncModelMixin, LogEntryModelMixin, BaseUuidModel):

    log = models.ForeignKey(Log)

    history = SyncHistoricalRecords()

    objects = LogEntryManager()

    class Meta:
        app_label = 'call_manager'
Example #13
0
class Log(SyncModelMixin, LogModelMixin, BaseUuidModel):

    call = models.ForeignKey(Call)

    history = SyncHistoricalRecords()

    objects = LogManager()

    class Meta:
        app_label = 'call_manager'
Example #14
0
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'
Example #16
0
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"
Example #18
0
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', ]
Example #19
0
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')
Example #20
0
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', )
Example #22
0
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'
Example #30
0
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'), )