def onschedule_or_raise(self, subject_identifier=None, report_datetime=None,
                            compare_as_datetimes=None):
        try:
            history_obj = self.history_model_cls.objects.get(
                subject_identifier=subject_identifier,
                visit_schedule_name=self.visit_schedule_name,
                schedule_name=self.schedule_name)
        except ObjectDoesNotExist:
            raise NotOnScheduleError(
                f'Subject is not been put on schedule {self.schedule_name}. '
                f'Got {subject_identifier}.')
        offschedule_datetime = history_obj.offschedule_datetime or get_utcnow()
        if compare_as_datetimes:
            in_date_range = (history_obj.onschedule_datetime
                             <= report_datetime
                             <= offschedule_datetime)
        else:
            in_date_range = (history_obj.onschedule_datetime.date()
                             <= report_datetime.date()
                             <= offschedule_datetime.date())

        if not in_date_range:
            formatted_date = report_datetime.strftime(
                convert_php_dateformat(settings.SHORT_DATE_FORMAT))
            raise NotOnScheduleForDateError(
                f'Subject not on schedule {self.schedule_name} on '
                f'{formatted_date}. Got {subject_identifier}.')
 def validate_assay_datetime(self, assay_datetime, requisition, field):
     if assay_datetime:
         assay_datetime = Arrow.fromdatetime(
             assay_datetime, assay_datetime.tzinfo).to('utc').datetime
         if assay_datetime < requisition.requisition_datetime:
             formatted = timezone.localtime(requisition.requisition_datetime).strftime(
                 convert_php_dateformat(settings.SHORT_DATETIME_FORMAT))
             raise forms.ValidationError({
                 field: (f'Invalid. Cannot be before date of '
                         f'requisition {formatted}.')})
 def validate_requisition_datetime(self):
     requisition_datetime = self.cleaned_data.get('requisition_datetime')
     subject_visit = self.cleaned_data.get('subject_visit')
     if requisition_datetime:
         requisition_datetime = Arrow.fromdatetime(
             requisition_datetime, requisition_datetime.tzinfo).to('utc').datetime
         if requisition_datetime < subject_visit.report_datetime:
             formatted = timezone.localtime(subject_visit.report_datetime).strftime(
                 convert_php_dateformat(settings.SHORT_DATETIME_FORMAT))
             raise forms.ValidationError({
                 'requisition_datetime':
                 f'Invalid. Cannot be before date of visit {formatted}.'})
 def validate_requisition_datetime(self):
     requisition_datetime = self.cleaned_data.get('requisition_datetime')
     maternal_visit = self.cleaned_data.get('maternal_visit')
     if requisition_datetime:
         requisition_datetime = Arrow.fromdatetime(
             requisition_datetime, requisition_datetime.tzinfo).to('utc').datetime
         if requisition_datetime < maternal_visit.report_datetime:
             formatted = timezone.localtime(maternal_visit.report_datetime).strftime(
                 convert_php_dateformat(settings.SHORT_DATETIME_FORMAT))
             raise forms.ValidationError({
                 'requisition_datetime':
                 f'Invalid. Cannot be before date of visit {formatted}.'})
示例#5
0
    def available_rdate(self,
                        suggested_datetime=None,
                        forward_delta=None,
                        reverse_delta=None,
                        taken_datetimes=None,
                        include_holidays=None):
        """Returns an arrow object for a datetime equal to or
        close to the suggested datetime.

        To exclude datetimes other than holidays, pass a list of
        datetimes in UTC to `taken_datetimes`.
        """
        available_rdate = None
        forward_delta = forward_delta or relativedelta(months=1)
        reverse_delta = reverse_delta or relativedelta(months=0)
        if suggested_datetime:
            suggested_rdate = arrow.Arrow.fromdatetime(suggested_datetime)
        else:
            suggested_rdate = arrow.Arrow.fromdatetime(get_utcnow())
        minimum = self.to_arrow_utc(suggested_rdate.datetime - reverse_delta)
        maximum = self.to_arrow_utc(suggested_rdate.datetime + forward_delta)
        rtaken = [self.to_arrow_utc(dt) for dt in taken_datetimes or []]
        for r in arrow.Arrow.span_range('day', minimum.datetime,
                                        maximum.datetime):
            # add back time to arrow object, r
            r = arrow.Arrow.fromdatetime(
                datetime.combine(r[0].date(), suggested_rdate.time()))
            if (r.datetime.weekday() in self.weekdays
                    and (minimum.date() <= r.date() < maximum.date())):
                if include_holidays:
                    is_holiday = False
                else:
                    is_holiday = self.is_holiday(r)
                if (not is_holiday
                        and r.date() not in [r.date() for r in rtaken]
                        and self.open_slot_on(r)):
                    available_rdate = r
                    break
        if not available_rdate:
            if self.best_effort_available_datetime:
                available_rdate = r
            else:
                formatted_date = suggested_datetime.strftime(
                    convert_php_dateformat(settings.SHORT_DATE_FORMAT))
                raise FacilityError(
                    f'No available appointment dates at facility for period. '
                    f'Got no available dates within {reverse_delta.days}-'
                    f'{forward_delta.days} days of {formatted_date}. '
                    f'Facility is {repr(self)}.')
        return available_rdate
 def get_consent(self, model=None, report_datetime=None,
                 version=None, consent_group=None, **kwargs):
     """Return consent object valid for the datetime.
     """
     app_config = django_apps.get_app_config('edc_consent')
     consent_group = consent_group or app_config.default_consent_group
     registered_consents = self.registry.values()
     if consent_group:
         registered_consents = [
             c for c in registered_consents if c.group == consent_group]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. '
             f'Got consent_group={consent_group}.')
     if version:
         registered_consents = [
             c for c in registered_consents if c.version == version]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. '
             f'Got consent_group={consent_group}, version={version}.')
     if model:
         registered_consents = [
             c for c in registered_consents if c.model == model]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. '
             f'Got consent_group={consent_group}, version={version}, '
             f'model={model}.')
     registered_consents = [
         c for c in registered_consents if c.start <= report_datetime <= c.end]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. '
             f'Got consent_group={consent_group}, version={version}, '
             f'model={model}, report_datetime={report_datetime}.')
     elif len(registered_consents) > 1:
         consents = list(set([c.name for c in registered_consents]))
         formatted_report_datetime = report_datetime.strftime(
             convert_php_dateformat(settings.SHORT_DATE_FORMAT))
         raise ConsentError(
             f'Multiple consents found, using consent model={model}, '
             f'date={formatted_report_datetime}, '
             f'consent_group={consent_group}, version={version}. '
             f'Got {consents}')
     return registered_consents[0]
示例#7
0
 def get_consent(self, model=None, report_datetime=None,
                 version=None, consent_group=None, **kwargs):
     """Return consent object valid for the datetime.
     """
     app_config = django_apps.get_app_config('edc_consent')
     consent_group = consent_group or app_config.default_consent_group
     registered_consents = self.registry.values()
     if consent_group:
         registered_consents = [
             c for c in registered_consents if c.group == consent_group]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. Got consent_group={consent_group}.')
     if version:
         registered_consents = [
             c for c in registered_consents if c.version == version]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. '
             f'Got consent_group={consent_group}, version={version}.')
     if model:
         registered_consents = [
             c for c in registered_consents if c.model == model]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. '
             f'Got consent_group={consent_group}, version={version}, '
             f'model={model}.')
     registered_consents = [
         c for c in registered_consents if c.start <= report_datetime <= c.end]
     if not registered_consents:
         raise ConsentObjectDoesNotExist(
             f'No matching consent in site consents. '
             f'Got consent_group={consent_group}, version={version}, '
             f'model={model}, report_datetime={report_datetime}.')
     elif len(registered_consents) > 1:
         consents = list(set([c.name for c in registered_consents]))
         formatted_report_datetime = report_datetime.strftime(
             convert_php_dateformat(settings.SHORT_DATE_FORMAT))
         raise ConsentError(
             f'Multiple consents found, using consent model={model}, '
             f'date={formatted_report_datetime}, '
             f'consent_group={consent_group}, version={version}. '
             f'Got {consents}')
     return registered_consents[0]
    def validate_study_day_with_datetime(self,
                                         subject_identifier=None,
                                         study_day=None,
                                         compare_date=None,
                                         study_day_field=None):
        """Raises an exception if study day does not match
        calculation against import pytz.

        Note: study-day is 1-based.
        """
        if study_day is not None and compare_date is not None:
            try:
                compare_date = compare_date.date()
            except AttributeError:
                pass
            subject_identifier = subject_identifier or self.cleaned_data.get(
                'subject_identifier') or self.instance.subject_identifier
            if not subject_identifier:
                raise ValueError(
                    f'Subject identifier cannot be None. See {repr(self)}')
            registered_subject_model_cls = django_apps.get_model(
                'edc_registration.registeredsubject')
            randomization_datetime = registered_subject_model_cls.objects.get(
                subject_identifier=subject_identifier).randomization_datetime
            days_on_study = (compare_date - randomization_datetime.date()).days
            if study_day - 1 != days_on_study:
                tz = pytz.timezone(settings.TIME_ZONE)
                formatted_date = Arrow.fromdatetime(randomization_datetime).to(
                    tz).strftime(
                        convert_php_dateformat(settings.DATETIME_FORMAT))
                message = {
                    study_day_field:
                    (f'Invalid. Expected {days_on_study + 1}. '
                     f'Subject was registered on {formatted_date}')
                }
                self._errors.update(message)
                self._error_codes.append(INVALID_ERROR)
                raise forms.ValidationError(message, code=INVALID_ERROR)
示例#9
0
def action_item_with_popover(action_item_model_wrapper, tabindex):
    strike_thru = None
    action_item = action_item_model_wrapper.object
    href = action_item_model_wrapper.href
    date_format = convert_php_dateformat(settings.SHORT_DATE_FORMAT)

    if action_item.last_updated:
        last_updated = action_item.last_updated.strftime(date_format)
        user_last_updated = action_item.user_last_updated
        last_updated_text = (
            f'Last updated on {last_updated} by {user_last_updated}.')
    else:
        last_updated_text = 'This action item has not been updated.'

    # this reference model and url
    reference_model_cls = django_apps.get_model(action_item.action_type.model)
    query_dict = dict(parse_qsl(urlparse(href).query))
    model_fk_dict = model_fk(action_item_obj=action_item)
    if model_fk_dict:
        query_dict.update(model_fk_dict)
    parent_reference_model_url = None
    parent_reference_model_name = None
    action_item_reason = None
    parent_action_identifier = None
    # reference_model and url
    action_cls = site_action_items.get(reference_model_cls.action_name)
    try:
        reference_model_obj = reference_model_cls.objects.get(
            action_identifier=action_item.action_identifier)
    except ObjectDoesNotExist:
        reference_model_obj = None
    try:
        subject_visit = reference_model_obj.visit
    except (AttributeError, ObjectDoesNotExist):
        pass
    else:
        # reference model is a CRF, add visit to querystring
        query_dict.update({
            reference_model_obj.visit_model_attr():
            str(subject_visit.pk),
            'appointment':
            str(subject_visit.appointment.pk)
        })
    try:
        reference_model_url = action_cls.reference_model_url(
            action_item=action_item,
            action_identifier=action_item.action_identifier,
            reference_model_obj=reference_model_obj,
            **query_dict)
    except ObjectDoesNotExist:
        reference_model_url = None
        # object wont exist if an action item was deleted
        # that was created by another action item.
        strike_thru = True
    else:
        if action_item.parent_action_item:

            # parent action item
            parent_reference_model_cls = django_apps.get_model(
                action_item.parent_action_item.action_type.model)

            # parent reference model and url
            try:
                parent_reference_model_obj = parent_reference_model_cls.objects.get(
                    tracking_identifier=action_item.parent_action_item.
                    reference_identifier)

            except ObjectDoesNotExist:
                pass
            else:
                try:
                    subject_visit = parent_reference_model_obj.visit
                except (AttributeError, ObjectDoesNotExist):
                    pass
                else:
                    # parent reference model is a CRF, add visit to querystring
                    query_dict.update({
                        parent_reference_model_obj.visit_model_attr():
                        str(subject_visit.pk),
                        'appointment':
                        str(subject_visit.appointment.pk)
                    })
                parent_reference_model_url = (action_cls.reference_model_url(
                    reference_model_obj=parent_reference_model_obj,
                    action_item=action_item,
                    action_identifier=action_item.action_identifier,
                    **query_dict))

                parent_reference_model_name = (
                    f'{parent_reference_model_cls._meta.verbose_name} '
                    f'{parent_reference_model_obj.tracking_identifier}')
                action_item_reason = parent_reference_model_obj.action_item_reason
            parent_action_identifier = action_item.parent_action_item.action_identifier

    open_display = [c[1] for c in ACTION_STATUS if c[0] == OPEN][0]

    return dict(HIGH_PRIORITY=HIGH_PRIORITY,
                OPEN=open_display,
                action_instructions=action_item.instructions,
                action_item_reason=action_item_reason,
                report_datetime=action_item.report_datetime,
                display_name=action_item.action_type.display_name,
                action_identifier=action_item.action_identifier,
                parent_action_identifier=parent_action_identifier,
                parent_action_item=action_item.parent_action_item,
                href=href,
                last_updated_text=last_updated_text,
                name=action_item.action_type.name,
                reference_model_name=reference_model_cls._meta.verbose_name,
                reference_model_url=reference_model_url,
                reference_model_obj=reference_model_obj,
                action_item_color=action_cls.color_style,
                parent_model_name=parent_reference_model_name,
                parent_model_url=parent_reference_model_url,
                priority=action_item.priority or '',
                status=action_item.get_status_display(),
                tabindex=tabindex,
                strike_thru=strike_thru)
示例#10
0
 def formatted_date(self):
     return self.local_date.strftime(
         convert_php_dateformat(settings.SHORT_DATE_FORMAT))
    def clean(self):

        try:
            death_report = self.death_report_model_cls.objects.get(
                subject_identifier=self.cleaned_data.get('subject_identifier'))
        except ObjectDoesNotExist:
            if self.cleaned_data.get('termination_reason') == DEAD:
                raise forms.ValidationError({
                    'termination_reason':
                    'Patient is deceased, please complete death report form first.'
                })
        else:
            if self.cleaned_data.get('death_date'):
                try:
                    self.death_report_model_cls.objects.get(
                        subject_identifier=self.cleaned_data.get(
                            'subject_identifier'),
                        death_datetime__date=self.cleaned_data.get(
                            'death_date'))
                except ObjectDoesNotExist:
                    formatted_date = death_report.death_datetime.strftime(
                        convert_php_dateformat(settings.SHORT_DATE_FORMAT))
                    raise forms.ValidationError({
                        'death_date':
                        'Date does not match Death Report. '
                        f'Expected {formatted_date}.'
                    })

        self.required_if(YES,
                         field='discharged_after_initial_admission',
                         field_required='initial_discharge_date')

        self.applicable_if(
            YES,
            field='discharged_after_initial_admission',
            field_applicable='readmission_after_initial_discharge')

        self.required_if(YES,
                         field='readmission_after_initial_discharge',
                         field_required='readmission_date')

        self.required_if(DEAD,
                         field='termination_reason',
                         field_required='death_date')

        self.required_if(CONSENT_WITHDRAWAL,
                         field='termination_reason',
                         field_required='consent_withdrawal_reason')

        self.applicable_if(CONSENT_WITHDRAWAL,
                           field='termination_reason',
                           field_applicable='willing_to_complete_10w')

        self.applicable_if('care_transferred_to_another_institution',
                           field='termination_reason',
                           field_applicable='willing_to_complete_centre')

        self.required_if_true(
            condition=(self.cleaned_data.get('willing_to_complete_10w') == YES
                       or self.cleaned_data.get('willing_to_complete_centre')
                       == YES),
            field_required='willing_to_complete_date')

        self.applicable_if('late_exclusion_criteria_met',
                           field='termination_reason',
                           field_applicable='protocol_exclusion_criterion')

        self.required_if('included_in_error',
                         field='termination_reason',
                         field_required='included_in_error')

        self.required_if('included_in_error',
                         field='termination_reason',
                         field_required='included_in_error_date')

        self.validate_other_specify(field='first_line_regimen')

        self.validate_other_specify(field='second_line_regimen')

        self.not_applicable_if(NOT_APPLICABLE,
                               field='first_line_regimen',
                               field_applicable='first_line_choice')