Esempio n. 1
0
def _move_periods_onto_sentences_for_sentence_group(
        sentence_group: schema.StateSentenceGroup,
        period_type: Type[schema.SchemaPeriodType]):
    """Looks at all SupervisionPeriods in the provided |sentence_group|, and attempts to match them to any
    corresponding sentences, based on date.
    """
    sentences = sentence_group.supervision_sentences + sentence_group.incarceration_sentences

    # Get all periods from sentence group
    periods = get_all_entities_of_cls([sentence_group], period_type)

    # Clear non-placeholder links from sentence to period. We will re-add/update these relationships below.
    for sentence in sentences:
        _only_keep_placeholder_periods_on_sentence(sentence, period_type)

    unmatched_periods = []
    matchable_sentences = _get_date_matchable_sentences(sentences)

    non_placeholder_periods = [p for p in periods if not is_placeholder(p)]

    # Match periods to non_placeholder_sentences by date.
    for p in non_placeholder_periods:
        matched = False
        p_start_date = _get_period_start_date(p)
        p_end_date = _get_period_end_date(p)

        for s in matchable_sentences:
            s_start_date = s.start_date
            if not s_start_date:
                continue

            s_completion_date = s.completion_date if s.completion_date else datetime.date.max

            if date_spans_overlap_exclusive(start_1=p_start_date,
                                            end_1=p_end_date,
                                            start_2=s_start_date,
                                            end_2=s_completion_date):
                matched = True
                _add_period_to_sentence(p, s)

        # Unmatched periods will be re-added to a placeholder sentence at the end.
        if not matched:
            unmatched_periods.append(p)

    # Add unmatched periods to a placeholder sentence
    if unmatched_periods:
        placeholder_sentences = [s for s in sentences if is_placeholder(s)]
        if not placeholder_sentences:
            placeholder_sentence = get_or_create_placeholder_child(
                sentence_group,
                'supervision_sentences',
                schema.StateSupervisionSentence,
                state_code=sentence_group.state_code,
                status=StateSentenceStatus.PRESENT_WITHOUT_INFO.value,
                person=sentence_group.person)
        else:
            placeholder_sentence = placeholder_sentences[0]
        for unmatched_period in unmatched_periods:
            _add_period_to_sentence(unmatched_period, placeholder_sentence)
def us_id_get_most_recent_supervision_period_supervision_type_before_upper_bound_day(
    upper_bound_exclusive_date: date,
    lower_bound_inclusive_date: Optional[date],
    supervision_periods: List[StateSupervisionPeriod],
) -> Optional[StateSupervisionPeriodSupervisionType]:
    """Finds the most recent nonnull supervision period supervision type on the supervision periods, preceding or
    overlapping the provided date. An optional lower bound may be provided to limit the lookback window.

    Returns the most recent StateSupervisionPeriodSupervisionType. If there is no valid supervision
    type found (e.g. the person has only been incarcerated for the time window), returns None. In the case where
    multiple SupervisionPeriodSupervisionTypes end on the same day, this returns only the most relevant
    SupervisionPeriodSupervisionType based on our own ranking.
    """
    supervision_types_by_end_date: Dict[
        date, Set[StateSupervisionPeriodSupervisionType]] = defaultdict(set)

    lower_bound_exclusive_date = (lower_bound_inclusive_date -
                                  relativedelta(days=1)
                                  if lower_bound_inclusive_date else date.min)

    for supervision_period in supervision_periods:
        start_date = supervision_period.start_date

        if not start_date:
            continue

        termination_date = (supervision_period.termination_date
                            if supervision_period.termination_date else
                            date.today())

        supervision_period_supervision_type = (
            supervision_period.supervision_period_supervision_type)

        if not supervision_period_supervision_type:
            continue

        if not date_spans_overlap_exclusive(
                start_1=lower_bound_exclusive_date,
                end_1=upper_bound_exclusive_date,
                start_2=start_date,
                end_2=termination_date,
        ):
            continue

        supervision_types_by_end_date[termination_date].add(
            supervision_period_supervision_type)

    if not supervision_types_by_end_date:
        return None

    max_end_date = max(supervision_types_by_end_date.keys())

    return get_most_relevant_supervision_type(
        supervision_types_by_end_date[max_end_date])
Esempio n. 3
0
    def test_dateSpansOverlapExclusive(self) -> None:
        # Spans intersect partially
        self.assertTrue(
            date_spans_overlap_exclusive(start_1=_DATE_1,
                                         end_1=_DATE_3,
                                         start_2=_DATE_2,
                                         end_2=_DATE_4))
        # One span completely overshadows the other
        self.assertTrue(
            date_spans_overlap_exclusive(start_1=_DATE_1,
                                         end_1=_DATE_5,
                                         start_2=_DATE_2,
                                         end_2=_DATE_4))
        # Single day span start date
        self.assertTrue(
            date_spans_overlap_exclusive(start_1=_DATE_2,
                                         end_1=_DATE_2,
                                         start_2=_DATE_2,
                                         end_2=_DATE_4))
        # Single day span middle
        self.assertTrue(
            date_spans_overlap_exclusive(start_1=_DATE_3,
                                         end_1=_DATE_3,
                                         start_2=_DATE_2,
                                         end_2=_DATE_4))

        # Spans are distinct
        self.assertFalse(
            date_spans_overlap_exclusive(start_1=_DATE_5,
                                         end_1=_DATE_6,
                                         start_2=_DATE_2,
                                         end_2=_DATE_4))
        # Span end span start
        self.assertFalse(
            date_spans_overlap_exclusive(start_1=_DATE_1,
                                         end_1=_DATE_2,
                                         start_2=_DATE_2,
                                         end_2=_DATE_4))
        # Single day span end date
        self.assertFalse(
            date_spans_overlap_exclusive(start_1=_DATE_4,
                                         end_1=_DATE_4,
                                         start_2=_DATE_2,
                                         end_2=_DATE_4))