Esempio n. 1
0
    def test_find_last_terminated_period_before_date_overlapping_no_termination(
        self, ):
        supervision_period_older = StateSupervisionPeriod.new_with_defaults(
            state_code="US_XX",
            start_date=date(2000, 1, 1),
            termination_date=date(2007, 9, 20),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        # Overlapping supervision period that should have been found in the other identifier code
        supervision_period_recent = StateSupervisionPeriod.new_with_defaults(
            state_code="US_XX",
            start_date=date(2006, 3, 1),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        most_recently_terminated_period = find_last_terminated_period_before_date(
            upper_bound_date=date(2007, 10, 1),
            periods=[
                supervision_period_older,
                supervision_period_recent,
            ],
            maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
        )

        self.assertEqual(supervision_period_older,
                         most_recently_terminated_period)
Esempio n. 2
0
    def test_find_last_terminated_period_before_date_none(self):
        supervision_period_older = StateSupervisionPeriod.new_with_defaults(
            state_code="US_XX",
            start_date=date(2000, 1, 1),
            termination_date=date(2005, 1, 1),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        supervision_period_recent = StateSupervisionPeriod.new_with_defaults(
            state_code="US_XX",
            start_date=date(2006, 3, 1),
            termination_date=date(2010, 1, 1),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        most_recently_terminated_period = find_last_terminated_period_before_date(
            upper_bound_date=date(1990, 10, 1),
            periods=[
                supervision_period_older,
                supervision_period_recent,
            ],
            maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
        )

        self.assertIsNone(most_recently_terminated_period)
Esempio n. 3
0
    def test_find_last_terminated_period_before_date_same_termination_date(
        self, ):
        supervision_period_a = StateSupervisionPeriod.new_with_defaults(
            external_id="a",
            state_code="US_XX",
            start_date=date(2006, 1, 1),
            termination_date=date(2007, 12, 31),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        supervision_period_b = StateSupervisionPeriod.new_with_defaults(
            external_id="b",
            state_code="US_XX",
            start_date=date(2006, 1, 1),
            termination_date=date(2007, 12, 31),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        most_recently_terminated_period = find_last_terminated_period_before_date(
            upper_bound_date=date(2008, 1, 10),
            periods=[supervision_period_a, supervision_period_b],
            maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
        )

        self.assertEqual(supervision_period_a, most_recently_terminated_period)
Esempio n. 4
0
    def test_find_last_terminated_period_before_date_ends_on_cutoff_date(self):
        supervision_period_older = StateSupervisionPeriod.new_with_defaults(
            state_code="US_XX",
            start_date=date(2000, 1, 1),
            termination_date=date(2005, 1, 1),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        supervision_period_recent = StateSupervisionPeriod.new_with_defaults(
            state_code="US_XX",
            start_date=date(2006, 3, 1),
            termination_date=date(2010, 1, 1),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        # Set the admission date to be on the last day of the cut-off for how close a supervision period termination
        # has to be to a revocation admission to be counted as a proximal supervision period
        admission_date = supervision_period_recent.termination_date + relativedelta(
            days=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT)

        most_recently_terminated_period = find_last_terminated_period_before_date(
            upper_bound_date=admission_date,
            periods=[
                supervision_period_older,
                supervision_period_recent,
            ],
            maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
        )

        self.assertEqual(supervision_period_recent,
                         most_recently_terminated_period)
Esempio n. 5
0
    def test_find_last_terminated_period_before_date_no_periods(self):
        most_recently_terminated_period = find_last_terminated_period_before_date(
            upper_bound_date=date(1990, 10, 1),
            periods=[],
            maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
        )

        self.assertIsNone(most_recently_terminated_period)
Esempio n. 6
0
    def test_find_last_terminated_period_before_date_month_boundary(self):
        supervision_period = StateSupervisionPeriod.new_with_defaults(
            state_code="US_XX",
            start_date=date(2000, 1, 1),
            termination_date=date(2005, 3, 31),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
        )

        most_recently_terminated_period = find_last_terminated_period_before_date(
            upper_bound_date=date(2005, 4, 1),
            periods=[supervision_period],
            maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
        )

        self.assertEqual(supervision_period, most_recently_terminated_period)
Esempio n. 7
0
    def test_find_last_terminated_period_before_date_same_termination_date_override(
        self, ):
        """Tests the find_last_terminated_period_before_date function when a
        same_date_sort_fn function is included.
        """
        supervision_period_a = StateSupervisionPeriod.new_with_defaults(
            external_id="a",
            state_code="US_XX",
            start_date=date(2006, 1, 1),
            termination_date=date(2007, 12, 31),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
            termination_reason=StateSupervisionPeriodTerminationReason.
            DISCHARGE,
        )

        supervision_period_b = StateSupervisionPeriod.new_with_defaults(
            external_id="b",
            state_code="US_XX",
            start_date=date(2006, 1, 1),
            termination_date=date(2007, 12, 31),
            status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO,
            termination_reason=StateSupervisionPeriodTerminationReason.
            ABSCONSION,
        )

        def _same_date_sort_override(period_a: StateSupervisionPeriod,
                                     period_b: StateSupervisionPeriod) -> int:
            prioritized_termination_reasons = [
                StateSupervisionPeriodTerminationReason.ABSCONSION,
                StateSupervisionPeriodTerminationReason.EXPIRATION,
            ]
            prioritize_a = (period_a.termination_reason
                            in prioritized_termination_reasons)
            prioritize_b = (period_b.termination_reason
                            in prioritized_termination_reasons)

            if prioritize_a and prioritize_b:
                return 0
            return -1 if prioritize_a else 1

        most_recently_terminated_period = find_last_terminated_period_before_date(
            upper_bound_date=date(2008, 1, 10),
            periods=[supervision_period_a, supervision_period_b],
            maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
            same_date_sort_fn=_same_date_sort_override,
        )

        self.assertEqual(supervision_period_b, most_recently_terminated_period)
Esempio n. 8
0
def _get_commitment_from_supervision_supervision_period(
    incarceration_period: StateIncarcerationPeriod,
    commitment_from_supervision_delegate:
    StateSpecificCommitmentFromSupervisionDelegate,
    supervision_period_index: PreProcessedSupervisionPeriodIndex,
    incarceration_period_index: PreProcessedIncarcerationPeriodIndex,
) -> Optional[StateSupervisionPeriod]:
    """Identifies the supervision period associated with the commitment to supervision
    admission on the given |admission_date|.

    If |prioritize_overlapping_periods| is True, prioritizes supervision periods that
    are overlapping with the |admission_date|. Else, prioritizes the period that has
    most recently terminated within SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT months of
    the |admission_date|.
    """
    if not supervision_period_index.supervision_periods:
        return None

    if not incarceration_period.admission_date:
        raise ValueError(
            "Unexpected missing admission_date on incarceration period: "
            f"[{incarceration_period}]")
    if not incarceration_period.admission_reason:
        raise ValueError(
            "Unexpected missing admission_reason on incarceration period: "
            f"[{incarceration_period}]")

    admission_date = incarceration_period.admission_date
    admission_reason = incarceration_period.admission_reason

    if not is_commitment_from_supervision(admission_reason):
        raise ValueError(
            "This function should only be called with an "
            "incarceration_period that is a commitment from supervision. "
            "Found an incarceration period with an admission_reason that "
            "is not a valid commitment from supervision admission: "
            f"{admission_reason}.")

    preceding_incarceration_period = (
        incarceration_period_index.preceding_incarceration_period_in_index(
            incarceration_period))

    if period_is_commitment_from_supervision_admission_from_parole_board_hold(
            incarceration_period=incarceration_period,
            preceding_incarceration_period=preceding_incarceration_period,
    ):
        if not preceding_incarceration_period:
            raise ValueError(
                "This should never happen, since the determination of "
                "whether the commitment came from a board hold requires "
                "the preceding_incarceration_period to be a board hold.")

        if not preceding_incarceration_period.admission_date:
            raise ValueError(
                "Unexpected missing admission_date on incarceration period: "
                f"[{preceding_incarceration_period}]")

        # If this person was a commitment from supervision from a parole board hold,
        # then the date that they entered prison was the date of the preceding
        # incarceration period.
        admission_date = preceding_incarceration_period.admission_date

    relevant_periods = _get_relevant_sps_for_pre_commitment_sp_search(
        admission_reason=admission_reason,
        supervision_periods=supervision_period_index.supervision_periods,
        commitment_from_supervision_delegate=
        commitment_from_supervision_delegate,
    )

    overlapping_periods = _supervision_periods_overlapping_with_date(
        admission_date, relevant_periods)

    # If there's more than one recently terminated period with the same
    # termination_date, prioritize the ones with REVOCATION or RETURN_TO_INCARCERATION
    # termination_reasons
    def _same_date_sort_override(period_a: StateSupervisionPeriod,
                                 period_b: StateSupervisionPeriod) -> int:
        prioritized_termination_reasons = [
            StateSupervisionPeriodTerminationReason.REVOCATION,
            StateSupervisionPeriodTerminationReason.RETURN_TO_INCARCERATION,
        ]
        prioritize_a = period_a.termination_reason in prioritized_termination_reasons
        prioritize_b = period_b.termination_reason in prioritized_termination_reasons

        if prioritize_a and prioritize_b:
            return sort_period_by_external_id(period_a, period_b)
        return -1 if prioritize_a else 1

    most_recent_terminated_period = find_last_terminated_period_before_date(
        upper_bound_date=admission_date,
        periods=relevant_periods,
        maximum_months_proximity=SUPERVISION_PERIOD_PROXIMITY_MONTH_LIMIT,
        same_date_sort_fn=_same_date_sort_override,
    )

    terminated_periods = ([most_recent_terminated_period]
                          if most_recent_terminated_period else [])

    if (admission_reason in commitment_from_supervision_delegate.
            admission_reasons_that_should_prioritize_overlaps_in_pre_commitment_sp_search(
            )):
        valid_pre_commitment_periods = (
            overlapping_periods if overlapping_periods else terminated_periods)
    else:
        valid_pre_commitment_periods = (
            terminated_periods if terminated_periods else overlapping_periods)

    if not valid_pre_commitment_periods:
        return None

    # In the case where there are multiple relevant SPs at this point, sort and return
    # the first one
    return min(
        valid_pre_commitment_periods,
        key=lambda e: (
            # Prioritize terminated periods with a termination_reason of REVOCATION
            # (False sorts before True)
            e.termination_reason != StateSupervisionPeriodTerminationReason.
            REVOCATION,
            # Prioritize termination_date closest to the admission_date
            abs(((e.termination_date or datetime.date.today()) - admission_date
                 ).days),
            # Deterministically sort by external_id in the case where there
            # are two REVOKED periods with the same termination_date
            e.external_id,
        ),
    )
def us_nd_infer_supervision_period_admission(
    supervision_period: StateSupervisionPeriod,
    supervision_period_index: PreProcessedSupervisionPeriodIndex,
    incarceration_period_index: PreProcessedIncarcerationPeriodIndex,
) -> Optional[StateSupervisionPeriodAdmissionReason]:
    """Looks at the provided |supervision_period|, all supervision periods for this person via the
    |supervision_period_index|, and all incarceration periods via |incarceration_period_index| and returns the
    admission reason for this |supervision_period|.
    This is necessary because we do not currently have a way to ingest ND admission reasons for supervision periods.
    """
    if not supervision_period.start_date:
        raise ValueError(
            "Found null supervision_period.start_date while inferring admission reason."
        )

    all_periods: List[Union[StateIncarcerationPeriod,
                            StateSupervisionPeriod]] = []
    all_periods.extend(supervision_period_index.supervision_periods)
    all_periods.extend(incarceration_period_index.incarceration_periods)

    most_recent_previous_period = find_last_terminated_period_before_date(
        upper_bound_date=supervision_period.start_date,
        periods=all_periods,
        maximum_months_proximity=LOOKBACK_MONTHS_LIMIT,
    )

    if not most_recent_previous_period:
        if supervision_period.supervision_type == StateSupervisionType.PAROLE:
            # If there was not a previous period and the person is under parole supervision, the current admission
            # reason should be CONDITIONAL_RELEASE
            return StateSupervisionPeriodAdmissionReason.CONDITIONAL_RELEASE
        if supervision_period.supervision_type == StateSupervisionType.PROBATION:
            # If there was not a previous period and the person is under PROBATION supervision, the current admission
            # reason should be COURT_SENTENCE
            return StateSupervisionPeriodAdmissionReason.COURT_SENTENCE

    if isinstance(most_recent_previous_period, StateIncarcerationPeriod):
        if (most_recent_previous_period.release_reason ==
                StateIncarcerationPeriodReleaseReason.CONDITIONAL_RELEASE):
            # If the most recent previous incarceration period terminated in CONDITIONAL_RELEASE, set that as the
            # admission reason.
            return StateSupervisionPeriodAdmissionReason.CONDITIONAL_RELEASE
    if isinstance(most_recent_previous_period, StateSupervisionPeriod):
        if (most_recent_previous_period.termination_reason ==
                StateSupervisionPeriodTerminationReason.ABSCONSION):
            # If the most recent previous supervision period was an absconsion, the current supervision period's
            # admission reason should be ABSCONSION.
            return StateSupervisionPeriodAdmissionReason.RETURN_FROM_ABSCONSION
        if (most_recent_previous_period.termination_reason ==
                StateSupervisionPeriodTerminationReason.REVOCATION):
            # If the most recent previous supervision period was a REVOCATION, the current supervision period's
            # admission reason should be COURT_SENTENCE.
            return StateSupervisionPeriodAdmissionReason.COURT_SENTENCE
        if (most_recent_previous_period.supervision_type
                == StateSupervisionType.HALFWAY_HOUSE
                and supervision_period.supervision_type
                == StateSupervisionType.PAROLE):
            # If the supervision type transitioned from HALFWAY_HOUSE to PAROLE, the current supervision period's
            # admission reason should be TRANSFER_WITHIN_STATE.
            return StateSupervisionPeriodAdmissionReason.TRANSFER_WITHIN_STATE
        if (most_recent_previous_period.supervision_type
                == StateSupervisionType.PAROLE
                and supervision_period.supervision_type
                == StateSupervisionType.PROBATION):
            # If the supervision type transitioned from PAROLE to PROBATION, the admission reason should be
            # COURT_SENTENCE.
            return StateSupervisionPeriodAdmissionReason.COURT_SENTENCE
        if (most_recent_previous_period.supervising_officer
                and supervision_period.supervising_officer
                and most_recent_previous_period.supervising_officer !=
                supervision_period.supervising_officer):
            # If the supervision officer changed between the previous and current supervision period, the admission
            # reason should be TRANSFER_WITHIN_STATE.
            return StateSupervisionPeriodAdmissionReason.TRANSFER_WITHIN_STATE
        if (most_recent_previous_period.supervision_type
                == StateSupervisionType.PROBATION
                and supervision_period.supervision_type
                == StateSupervisionType.PAROLE):
            # If the supervision type transitioned from PROBATION to PAROLE, the admission reason should be
            # INTERNAL_UNKNOWN, since this should be extremely rare.
            return StateSupervisionPeriodAdmissionReason.INTERNAL_UNKNOWN

    return None
def _us_nd_normalize_period_if_commitment_from_supervision(
    incarceration_period_list_index: int,
    sorted_incarceration_periods: List[StateIncarcerationPeriod],
    supervision_period_index: Optional[PreProcessedSupervisionPeriodIndex],
) -> StateIncarcerationPeriod:
    """Returns an updated version of the specified incarceration period if it is a
    commitment from supervision admission.

    Updates the admission_reason to be a PROBATION_REVOCATION or a PAROLE_REVOCATION
    for the following scenarios:
        - The person was admitted to a state prison due to a NEW_ADMISSION (not a period
      of TEMPORARY_CUSTODY in a county jail) and was previously in a PAROLE or
          PROBATION supervision period that terminated due to a REVOCATION.

    Also note that in this case, we also ensure that there was not an intermediate
    period of incarceration in a state prison between the supervision REVOCATION and
    this incarceration period under examination, to make sure we do not mistakenly
    re-classify what is truly a NEW_ADMISSION as a REVOCATION.
    """
    if supervision_period_index is None:
        raise ValueError(
            "IP pre-processing relies on supervision periods for US_ND. "
            "Expected non-null supervision_period_index.")

    incarceration_period = sorted_incarceration_periods[
        incarceration_period_list_index]

    admission_date = incarceration_period.admission_date

    if not admission_date:
        raise ValueError(f"Admission date for null for {incarceration_period}")

    admission_reason = incarceration_period.admission_reason
    if admission_reason == StateIncarcerationPeriodAdmissionReason.NEW_ADMISSION:

        most_recent_supervision_period = find_last_terminated_period_before_date(
            upper_bound_date=admission_date,
            periods=supervision_period_index.supervision_periods,
            maximum_months_proximity=
            _NEW_ADMISSION_PROBATION_COMMITMENT_LOOKBACK_MONTHS,
        )

        if (most_recent_supervision_period
                and most_recent_supervision_period.termination_reason
                == StateSupervisionPeriodTerminationReason.REVOCATION
                and most_recent_supervision_period.supervision_type
                in (StateSupervisionType.PAROLE,
                    StateSupervisionType.PROBATION)):
            was_intermediate_state_prison_admission = (
                _intermediate_state_prison_admission(
                    most_recent_supervision_period,
                    incarceration_period,
                    sorted_incarceration_periods,
                ))

            # If there was a separate admission to a state prison after the revocation
            # and before this admission, then it is not accurate to describe *this*
            # admission as being due to a revocation
            if was_intermediate_state_prison_admission:
                return incarceration_period

            return attr.evolve(
                incarceration_period,
                admission_reason=(
                    StateIncarcerationPeriodAdmissionReason.
                    PROBATION_REVOCATION
                    if most_recent_supervision_period.supervision_type
                    == StateSupervisionType.PROBATION else
                    StateIncarcerationPeriodAdmissionReason.PAROLE_REVOCATION),
            )

    # This period does not require any updated values
    return incarceration_period