def test_associateSvrsWithIps_dontAssociateTheSameSvr(self): # Arrange svr_1 = StateSupervisionViolationResponse.new_with_defaults( response_date=_DATE_1, revocation_type=StateSupervisionViolationResponseRevocationType. REINCARCERATION) placeholder_sv = StateSupervisionViolation.new_with_defaults( supervision_violation_responses=[svr_1]) placeholder_sp = StateSupervisionPeriod.new_with_defaults( supervision_violation_entries=[placeholder_sv]) placeholder_ss = StateSupervisionSentence.new_with_defaults( supervision_periods=[placeholder_sp]) ip_1 = StateIncarcerationPeriod.new_with_defaults( admission_date=_DATE_2, admission_reason=StateIncarcerationPeriodAdmissionReason. PROBATION_REVOCATION) ip_2 = StateIncarcerationPeriod.new_with_defaults( admission_date=_DATE_4, admission_reason=StateIncarcerationPeriodAdmissionReason. PROBATION_REVOCATION) placeholder_is = StateIncarcerationSentence.new_with_defaults( incarceration_periods=[ip_1, ip_2]) placeholder_sg = StateSentenceGroup.new_with_defaults( incarceration_sentences=[placeholder_is], supervision_sentences=[placeholder_ss]) placeholder_person = StatePerson.new_with_defaults( sentence_groups=[placeholder_sg]) expected_svr_1 = attr.evolve(svr_1) expected_placeholder_sv = attr.evolve( placeholder_sv, supervision_violation_responses=[expected_svr_1]) expected_placeholder_sp = attr.evolve( placeholder_sp, supervision_violation_entries=[expected_placeholder_sv]) expected_placeholder_ss = attr.evolve( placeholder_ss, supervision_periods=[expected_placeholder_sp]) expected_ip_1 = attr.evolve( ip_1, source_supervision_violation_response=expected_svr_1) expected_ip_2 = attr.evolve(ip_2) expected_placeholder_is = attr.evolve( placeholder_is, incarceration_periods=[expected_ip_1, expected_ip_2]) expected_placeholder_sg = attr.evolve( placeholder_sg, supervision_sentences=[expected_placeholder_ss], incarceration_sentences=[expected_placeholder_is]) expected_placeholder_person = attr.evolve( placeholder_person, sentence_groups=[expected_placeholder_sg]) # Act input_people = \ converter.convert_entity_people_to_schema_people( [placeholder_person]) associate_revocation_svrs_with_ips(input_people) # Assert self.assert_people_match([expected_placeholder_person], input_people)
def test_identify_months_fully_incarcerated_two_consecutive_periods_do_not_cover( self): incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=111, external_id='ip1', state_code='US_XX', admission_date=date(2005, 3, 1), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2005, 3, 15) ) incarceration_period_index = IncarcerationPeriodIndex( [incarceration_period]) self.assertEqual(incarceration_period_index.months_fully_incarcerated, set()) incarceration_period_2 = \ StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id='ip2', state_code='US_XX', admission_date=date(2005, 3, 15), admission_reason=AdmissionReason.TRANSFER, release_date=date(2005, 3, 20) ) incarceration_period_index = IncarcerationPeriodIndex( [incarceration_period, incarceration_period_2]) self.assertEqual(incarceration_period_index.months_fully_incarcerated, set())
def test_index_incarceration_periods_by_admission_date_multiple_in_day( self): """Tests the index_incarceration_periods_by_admission_date function when there are multiple incarceration periods with the same admission dates.""" first_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, incarceration_period_id=111, external_id='ip1', state_code='US_XX', admission_date=date(2018, 6, 1), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2018, 6, 21) ) second_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( status=StateIncarcerationPeriodStatus.IN_CUSTODY, incarceration_period_id=111, external_id='ip2', state_code='US_XX', admission_date=date(2018, 6, 1), admission_reason=AdmissionReason.NEW_ADMISSION ) incarceration_period_index = IncarcerationPeriodIndex( [first_incarceration_period, second_incarceration_period]) self.assertEqual( incarceration_period_index.incarceration_periods_by_admission_date, { first_incarceration_period.admission_date: [first_incarceration_period, second_incarceration_period] })
def test_incarceration_periods_not_under_supervision_authority(self): incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=444, external_id="ip4", state_code="US_XX", admission_date=date(2007, 12, 1), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2008, 2, 2), release_reason=ReleaseReason.SENTENCE_SERVED, custodial_authority=StateCustodialAuthority.STATE_PRISON, status=StateIncarcerationPeriodStatus.PRESENT_WITHOUT_INFO, ) # This period has a supervision custodial authority incarceration_period_2 = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=555, external_id="ip5", state_code="US_XX", admission_date=date(2008, 2, 4), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2008, 4, 5), release_reason=ReleaseReason.SENTENCE_SERVED, custodial_authority=StateCustodialAuthority.SUPERVISION_AUTHORITY, status=StateIncarcerationPeriodStatus.PRESENT_WITHOUT_INFO, ) index = IncarcerationPeriodIndex([incarceration_period, incarceration_period_2]) self.assertEqual( [incarceration_period], index.incarceration_periods_not_under_supervision_authority, )
def test_ip_is_nested_in_previous_period_bad_sort(self): # This period should not have been sorted before ip previous_ip = StateIncarcerationPeriod.new_with_defaults( external_id="1", incarceration_period_id=1111, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code="US_XX", admission_date=date(2002, 2, 5), admission_reason=StateIncarcerationPeriodAdmissionReason.NEW_ADMISSION, release_date=date(2002, 9, 11), release_reason=StateIncarcerationPeriodReleaseReason.SENTENCE_SERVED, ) ip = StateIncarcerationPeriod.new_with_defaults( external_id="2", incarceration_period_id=2222, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code="US_XX", admission_date=date(2002, 1, 1), admission_reason=StateIncarcerationPeriodAdmissionReason.TRANSFER, release_date=date(2002, 5, 22), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, ) with pytest.raises(ValueError): ip_is_nested_in_previous_period(ip, previous_ip)
def test_period_is_commitment_from_parole_board_hold_not_adjacent(self): ip_1 = StateIncarcerationPeriod.new_with_defaults( external_id="1", incarceration_period_id=1111, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code="US_XX", admission_date=date(2002, 2, 5), admission_reason=StateIncarcerationPeriodAdmissionReason. TEMPORARY_CUSTODY, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD, release_date=date(2002, 9, 11), release_reason=StateIncarcerationPeriodReleaseReason. RELEASED_FROM_TEMPORARY_CUSTODY, ) ip_2 = StateIncarcerationPeriod.new_with_defaults( external_id="1", incarceration_period_id=1111, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code="US_XX", admission_date=date(2010, 3, 31), admission_reason=StateIncarcerationPeriodAdmissionReason. PAROLE_REVOCATION, release_date=date(2012, 9, 19), release_reason=StateIncarcerationPeriodReleaseReason. SENTENCE_SERVED, ) self.assertFalse( period_is_commitment_from_supervision_admission_from_parole_board_hold( incarceration_period=ip_2, preceding_incarceration_period=ip_1))
def test_us_id_revoked_supervision_period_if_revocation_occurred_regular_transfer( self): board_hold_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id='ip2', state_code='US_ID', incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 17), admission_reason=StateIncarcerationPeriodAdmissionReason. RETURN_FROM_SUPERVISION, release_date=date(2017, 5, 29), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL) incarceration_revocation_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id='ip2', state_code='US_ID', incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 29), admission_reason=StateIncarcerationPeriodAdmissionReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL) admission_is_revocation, revoked_period = us_id_revoked_supervision_period_if_revocation_occurred( incarceration_revocation_period, [], board_hold_period) self.assertFalse(admission_is_revocation) self.assertIsNone(revoked_period)
def test_set_missing_admission_data_all_valid(self): """Tests that no information is changed when all incarceration periods have valid data.""" first_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( external_id='99983-1|99983-2', incarceration_period_id=1111, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='US_ND', admission_date=date(2004, 1, 3), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2008, 4, 14), release_reason=ReleaseReason.SENTENCE_SERVED) second_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( external_id='99983-3', incarceration_period_id=2222, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='US_ND', admission_date=date(2009, 3, 19), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2010, 4, 14), release_reason=ReleaseReason.SENTENCE_SERVED) incarceration_periods = [first_incarceration_period, second_incarceration_period] updated_incarceration_periods = \ set_missing_admission_data(incarceration_periods) assert updated_incarceration_periods == incarceration_periods
def test_find_release_events_by_cohort_year_invalid_open_period(self): """Tests the find_release_events_by_cohort_year function where the person has an open IN_CUSTODY period that is invalid because the person was released elsewhere after the admission to the period.""" invalid_open_incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.IN_CUSTODY, state_code='TX', admission_date=date(2008, 11, 20), admission_reason=AdmissionReason.NEW_ADMISSION) closed_incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='TX', admission_date=date(2008, 11, 20), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2009, 3, 14), release_reason=ReleaseReason.SENTENCE_SERVED) release_events_by_cohort = \ identifier.find_release_events_by_cohort_year( [invalid_open_incarceration_period, closed_incarceration_period], _COUNTY_OF_RESIDENCE) assert release_events_by_cohort[2009] == [ NonRecidivismReleaseEvent( state_code='TX', county_of_residence=_COUNTY_OF_RESIDENCE, original_admission_date=closed_incarceration_period.admission_date, release_date=closed_incarceration_period.release_date, release_facility=None)]
def test_find_earliest_period_ending_in_death_no_end_date(self): supervision_period_death = StateSupervisionPeriod.new_with_defaults( state_code="US_XX", start_date=date(2000, 1, 1), termination_reason=StateSupervisionPeriodTerminationReason.DEATH, status=StateSupervisionPeriodStatus.TERMINATED, ) incarceration_period = StateIncarcerationPeriod.new_with_defaults( state_code="US_XX", admission_date=date(2003, 1, 3), release_date=date(2004, 1, 3), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, ) incarceration_period_death = StateIncarcerationPeriod.new_with_defaults( state_code="US_XX", admission_date=date(2004, 1, 3), release_reason=StateIncarcerationPeriodReleaseReason.DEATH, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, ) earliest_period_ending_in_death = find_earliest_date_of_period_ending_in_death( periods=[ supervision_period_death, incarceration_period, incarceration_period_death, ], ) self.assertIsNone(earliest_period_ending_in_death)
def test_mergeFlatFields_incompleteIncarcerationPeriods(self): ingested_entity = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=_ID, external_id=_EXTERNAL_ID, status=StateIncarcerationPeriodStatus.IN_CUSTODY, facility=_FACILITY, admission_date=_DATE_1, admission_reason=StateIncarcerationPeriodAdmissionReason. NEW_ADMISSION) db_entity = StateIncarcerationPeriod.new_with_defaults( external_id=_EXTERNAL_ID_2, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, facility=_FACILITY, release_date=_DATE_2, release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER) expected_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=_ID, external_id=_EXTERNAL_ID + '|' + _EXTERNAL_ID_2, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, facility=_FACILITY, admission_date=_DATE_1, admission_reason= StateIncarcerationPeriodAdmissionReason.NEW_ADMISSION, release_date=_DATE_2, release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER) self.assertEqual( expected_incarceration_period, merge_flat_fields(new_entity=ingested_entity, old_entity=db_entity))
def test_sort_periods_by_set_dates_and_statuses_ips_empty_release_dates( self): state_code = "US_XX" ip_1 = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2008, 11, 20), admission_reason=StateIncarcerationPeriodAdmissionReason. NEW_ADMISSION, release_date=date(2010, 12, 4), release_reason=StateIncarcerationPeriodReleaseReason. SENTENCE_SERVED, ) ip_2 = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=2222, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2011, 3, 4), admission_reason=StateIncarcerationPeriodAdmissionReason. NEW_ADMISSION, release_date=date(2014, 4, 14), release_reason=StateIncarcerationPeriodReleaseReason. SENTENCE_SERVED, ) ip_3 = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=3333, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.IN_CUSTODY, state_code=state_code, admission_date=date(2012, 2, 4), admission_reason=StateIncarcerationPeriodAdmissionReason. NEW_ADMISSION, ) incarceration_periods = [ ip_1, ip_3, ip_2, ] for ip_order_combo in permutations(incarceration_periods): ips_for_test = [attr.evolve(ip) for ip in ip_order_combo] sort_periods_by_set_dates_and_statuses( ips_for_test, incarceration_period_utils._is_active_period, incarceration_period_utils._is_transfer_start, incarceration_period_utils._is_transfer_end, ) self.assertEqual( [ip_1, ip_2, ip_3], ips_for_test, )
def test_pre_processed_incarceration_periods_different_pfi_do_not_collapse( self, ) -> None: """Tests the pre-processing function does not collapse two adjacent TRANSFER edges in US_ID when they have different specialized_purpose_for_incarceration values. """ state_code = "US_ID" initial_incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2008, 11, 20), admission_reason=StateIncarcerationPeriodAdmissionReason. NEW_ADMISSION, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.TREATMENT_IN_PRISON, release_date=date(2012, 12, 4), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, ) second_incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=3333, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2012, 12, 4), admission_reason=StateIncarcerationPeriodAdmissionReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL, release_date=date(2014, 4, 14), release_reason=StateIncarcerationPeriodReleaseReason. SENTENCE_SERVED, ) incarceration_periods = [ initial_incarceration_period, second_incarceration_period, ] updated_periods = [ attr.evolve( initial_incarceration_period, release_reason=StateIncarcerationPeriodReleaseReason. STATUS_CHANGE, ), attr.evolve( second_incarceration_period, admission_reason=StateIncarcerationPeriodAdmissionReason. STATUS_CHANGE, ), ] validated_incarceration_periods = ( self._pre_processed_incarceration_periods_for_calculations( incarceration_periods=incarceration_periods, collapse_transfers=True, )) self.assertEqual(updated_periods, validated_incarceration_periods)
def testFindReleaseEventsByCohortYear_collapseTemporaryCustodyAndRevocation(self): """Tests the find_release_events_by_cohort_year function where a temporary custody incarceration period is followed by a revocation period. In this test case the person did recidivate. """ initial_incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, external_id='1', incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='TX', admission_date=date(2008, 11, 20), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2010, 12, 4), release_reason=ReleaseReason.SENTENCE_SERVED) temporary_custody_reincarceration = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=2222, external_id='2', incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='TX', admission_date=date(2011, 4, 5), admission_reason=AdmissionReason.TEMPORARY_CUSTODY, release_date=date(2014, 4, 14), release_reason=ReleaseReason.RELEASED_FROM_TEMPORARY_CUSTODY) revocation_incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=3333, external_id='3', incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.IN_CUSTODY, state_code='TX', admission_date=date(2014, 4, 14), admission_reason=AdmissionReason.PROBATION_REVOCATION) incarceration_periods = [ initial_incarceration_period, temporary_custody_reincarceration, revocation_incarceration_period] release_events_by_cohort = identifier.find_release_events_by_cohort_year( incarceration_periods, _COUNTY_OF_RESIDENCE) self.assertEqual(1, len(release_events_by_cohort)) self.assertCountEqual( [RecidivismReleaseEvent( state_code='TX', original_admission_date=initial_incarceration_period.admission_date, release_date=initial_incarceration_period.release_date, release_facility=None, reincarceration_date=temporary_custody_reincarceration.admission_date, reincarceration_facility=None, county_of_residence=_COUNTY_OF_RESIDENCE, from_supervision_type=StateSupervisionPeriodSupervisionType.PROBATION, return_type=ReincarcerationReturnType.REVOCATION)], release_events_by_cohort[2010])
def test_find_release_events_by_cohort_year_sentence_served_prob_rev(self): """Tests the find_release_events_by_cohort_year function path where the person served their first sentence, then later returned on a probation revocation.""" initial_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='TX', admission_date=date(2008, 11, 20), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2010, 12, 4), release_reason=ReleaseReason.SENTENCE_SERVED) first_reincarceration_period = \ StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=2222, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='TX', admission_date=date(2011, 4, 5), admission_reason=AdmissionReason.PROBATION_REVOCATION, release_date=date(2014, 4, 14), release_reason=ReleaseReason.SENTENCE_SERVED) incarceration_periods = [initial_incarceration_period, first_reincarceration_period] release_events_by_cohort = \ identifier.find_release_events_by_cohort_year( incarceration_periods=incarceration_periods, county_of_residence=_COUNTY_OF_RESIDENCE) assert len(release_events_by_cohort) == 2 assert release_events_by_cohort[2010] == [RecidivismReleaseEvent( state_code='TX', original_admission_date=initial_incarceration_period.admission_date, release_date=initial_incarceration_period.release_date, release_facility=None, reincarceration_date=first_reincarceration_period.admission_date, reincarceration_facility=None, county_of_residence=_COUNTY_OF_RESIDENCE, return_type=ReincarcerationReturnType.REVOCATION, from_supervision_type=StateSupervisionPeriodSupervisionType. PROBATION)] assert release_events_by_cohort[2014] == [ NonRecidivismReleaseEvent( state_code='TX', original_admission_date=first_reincarceration_period. admission_date, release_date=first_reincarceration_period.release_date, county_of_residence=_COUNTY_OF_RESIDENCE, release_facility=None)]
def test_sort_periods_by_set_dates_and_statuses_ips_two_same_day_zero_day_periods_release( self, ): state_code = "US_XX" ip_1 = StateIncarcerationPeriod.new_with_defaults( external_id="X", incarceration_period_id=1111, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2008, 11, 20), admission_reason=StateIncarcerationPeriodAdmissionReason. ADMITTED_FROM_SUPERVISION, release_date=date(2009, 1, 1), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, ) ip_2 = StateIncarcerationPeriod.new_with_defaults( external_id="Z", incarceration_period_id=2222, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2009, 1, 1), admission_reason=StateIncarcerationPeriodAdmissionReason.TRANSFER, release_date=date(2009, 1, 1), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, ) ip_3 = StateIncarcerationPeriod.new_with_defaults( external_id="Y", incarceration_period_id=3333, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2009, 1, 1), admission_reason=StateIncarcerationPeriodAdmissionReason.TRANSFER, release_date=date(2009, 1, 1), release_reason=StateIncarcerationPeriodReleaseReason. CONDITIONAL_RELEASE, ) incarceration_periods = [ip_1, ip_2, ip_3] for ip_order_combo in permutations(incarceration_periods): ips_for_test = [attr.evolve(ip) for ip in ip_order_combo] sort_periods_by_set_dates_and_statuses( ips_for_test, incarceration_period_utils._is_active_period, incarceration_period_utils._is_transfer_start, incarceration_period_utils._is_transfer_end, ) self.assertEqual( [ip_1, ip_2, ip_3], ips_for_test, )
def test_prepare_incarceration_periods_for_calculations_irregular_board_hold( self, ) -> None: state_code = "US_MO" board_hold = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=111, external_id="111", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2017, 11, 20), admission_reason=StateIncarcerationPeriodAdmissionReason. PAROLE_REVOCATION, admission_reason_raw_text="50N1010", release_date=date(2017, 12, 4), release_reason=StateIncarcerationPeriodReleaseReason. RELEASED_FROM_TEMPORARY_CUSTODY, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL, ) revocation_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id="222", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2017, 12, 4), admission_reason=StateIncarcerationPeriodAdmissionReason. PAROLE_REVOCATION, admission_reason_raw_text="50N1050", release_date=date(2020, 1, 14), release_reason=StateIncarcerationPeriodReleaseReason. CONDITIONAL_RELEASE, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL, ) updated_period = attr.evolve( board_hold, admission_reason=StateIncarcerationPeriodAdmissionReason. TEMPORARY_CUSTODY, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD, ) incarceration_periods = [board_hold, revocation_period] for ip_order_combo in permutations(incarceration_periods): ips_for_test = [attr.evolve(ip) for ip in ip_order_combo] validated_incarceration_periods = ( self._pre_processed_incarceration_periods_for_calculations( incarceration_periods=ips_for_test, )) self.assertEqual([updated_period, revocation_period], validated_incarceration_periods)
def test_pre_processed_incarceration_periods_for_calculations_multiple_temporary_and_valid( self, ) -> None: state_code = "US_ND" temporary_custody_1 = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=111, external_id="111", incarceration_type=StateIncarcerationType.COUNTY_JAIL, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2008, 11, 20), admission_reason=AdmissionReason.TEMPORARY_CUSTODY, release_date=date(2010, 12, 4), release_reason=ReleaseReason.RELEASED_FROM_TEMPORARY_CUSTODY, ) temporary_custody_2 = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=112, external_id="222", incarceration_type=StateIncarcerationType.COUNTY_JAIL, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2008, 12, 20), admission_reason=AdmissionReason.TEMPORARY_CUSTODY, release_date=date(2008, 12, 24), release_reason=ReleaseReason.RELEASED_FROM_TEMPORARY_CUSTODY, ) valid_incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, external_id="333", incarceration_type=StateIncarcerationType.COUNTY_JAIL, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code=state_code, admission_date=date(2016, 11, 20), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2017, 12, 4), release_reason=ReleaseReason.SENTENCE_SERVED, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL, ) incarceration_periods = [ temporary_custody_1, temporary_custody_2, valid_incarceration_period, ] for ip_order_combo in permutations(incarceration_periods): ips_for_test = [attr.evolve(ip) for ip in ip_order_combo] validated_incarceration_periods = ( self._pre_processed_incarceration_periods_for_calculations( incarceration_periods=ips_for_test, )) self.assertEqual([valid_incarceration_period], validated_incarceration_periods)
def test_set_missing_admission_data_unsorted_periods(self): """Tests that the admission data on an incarceration period is set when there's an empty admission_date and admission_reason following a transfer out, and the incarceration periods are not sent in a sorted order. """ first_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( external_id='99983-1|99983-2', incarceration_period_id=1111, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='US_ND', admission_date=date(2004, 1, 3), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2008, 4, 14), release_reason=ReleaseReason.TRANSFER) second_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( external_id='99983-3', incarceration_period_id=2222, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='US_ND', admission_date=None, admission_reason=None, release_date=date(2010, 4, 14), release_reason=ReleaseReason.SENTENCE_SERVED) incarceration_periods = [ second_incarceration_period, first_incarceration_period ] updated_incarceration_periods = \ set_missing_admission_data(incarceration_periods) assert updated_incarceration_periods == [ StateIncarcerationPeriod.new_with_defaults( external_id='99983-1|99983-2', incarceration_period_id=1111, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='US_ND', admission_date=date(2004, 1, 3), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2008, 4, 14), release_reason=ReleaseReason.TRANSFER), StateIncarcerationPeriod.new_with_defaults( external_id='99983-3', incarceration_period_id=2222, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='US_ND', admission_date=date(2008, 4, 14), admission_reason=AdmissionReason.TRANSFER, release_date=date(2010, 4, 14), release_reason=ReleaseReason.SENTENCE_SERVED) ]
def test_find_release_events_by_cohort_year_cond_release_new_admit(self): """Tests the find_release_events_by_cohort_year function path where the person was conditionally released on parole but returned as a new admission.""" initial_incarceration_period = \ StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1111, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='TX', admission_date=date(2008, 11, 20), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2010, 12, 4), release_reason=ReleaseReason.CONDITIONAL_RELEASE) first_reincarceration_period = \ StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=2222, incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code='TX', admission_date=date(2011, 4, 5), admission_reason=AdmissionReason.NEW_ADMISSION, release_date=date(2014, 4, 14), release_reason=ReleaseReason.SENTENCE_SERVED) incarceration_periods = [initial_incarceration_period, first_reincarceration_period] release_events_by_cohort = \ identifier.find_release_events_by_cohort_year( incarceration_periods=incarceration_periods, county_of_residence=_COUNTY_OF_RESIDENCE) assert len(release_events_by_cohort) == 2 assert release_events_by_cohort[2010] == [RecidivismReleaseEvent( state_code='TX', original_admission_date=initial_incarceration_period.admission_date, release_date=initial_incarceration_period.release_date, release_facility=None, reincarceration_date=first_reincarceration_period.admission_date, reincarceration_facility=None, county_of_residence=_COUNTY_OF_RESIDENCE, return_type=ReincarcerationReturnType.NEW_ADMISSION)] assert release_events_by_cohort[2014] == [ NonRecidivismReleaseEvent( state_code='TX', original_admission_date=first_reincarceration_period. admission_date, release_date=first_reincarceration_period.release_date, county_of_residence=_COUNTY_OF_RESIDENCE, release_facility=None)]
def test_revoked_supervision_periods_if_revocation_did_not_occur_with_treatment_transfer_US_ID( self, ) -> None: supervision_period = StateSupervisionPeriod.new_with_defaults( state_code="US_ID", start_date=date(2017, 1, 1), termination_date=date(2017, 5, 17), supervision_period_supervision_type= StateSupervisionPeriodSupervisionType.PAROLE, status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO, ) treatment_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id="ip2", state_code="US_ID", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 17), admission_reason=AdmissionReason.RETURN_FROM_SUPERVISION, release_date=date(2017, 5, 29), release_reason=ReleaseReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.TREATMENT_IN_PRISON, ) incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id="ip2", state_code="US_ID", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 29), admission_reason=AdmissionReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL, ) supervision_periods = [supervision_period] ( admission_is_revocation, revoked_periods, ) = state_calculation_config_manager.revoked_supervision_periods_if_revocation_occurred( incarceration_period.state_code, incarceration_period, supervision_periods, treatment_period, ) self.assertFalse(admission_is_revocation) self.assertEqual([], revoked_periods)
def test_us_id_revoked_supervision_period_if_revocation_occurred_parole_board_to_treatment_revocation( self, ): supervision_period = StateSupervisionPeriod.new_with_defaults( state_code="US_ID", start_date=date(2017, 1, 1), termination_date=date(2017, 5, 17), supervision_period_supervision_type= StateSupervisionPeriodSupervisionType.PAROLE, status=StateSupervisionPeriodStatus.PRESENT_WITHOUT_INFO, ) board_hold_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id="ip2", state_code="US_ID", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 17), admission_reason=StateIncarcerationPeriodAdmissionReason. RETURN_FROM_SUPERVISION, release_date=date(2017, 5, 29), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.PAROLE_BOARD_HOLD, ) incarceration_revocation_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id="ip2", state_code="US_ID", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 29), admission_reason=StateIncarcerationPeriodAdmissionReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.TREATMENT_IN_PRISON, ) supervision_periods = [supervision_period] ( admission_is_revocation, revoked_period, ) = us_id_revoked_supervision_period_if_revocation_occurred( incarceration_revocation_period, supervision_periods, board_hold_period) self.assertTrue(admission_is_revocation) self.assertEqual(revoked_period, supervision_period)
def test_revoked_supervision_periods_if_revocation_occurred_with_general_purpose_US_ID( self, ) -> None: incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id="ip2", state_code="US_ID", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 17), admission_reason=StateIncarcerationPeriodAdmissionReason. RETURN_FROM_SUPERVISION, release_date=date(2019, 5, 29), release_reason=ReleaseReason.SENTENCE_SERVED, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL, ) supervision_periods: List[StateSupervisionPeriod] = [] ( admission_is_revocation, revoked_periods, ) = state_calculation_config_manager.revoked_supervision_periods_if_revocation_occurred( incarceration_period.state_code, incarceration_period, supervision_periods, None, ) self.assertTrue(admission_is_revocation) self.assertEqual([], revoked_periods)
def test_usMo_getPreIncarcerationSupervisionType_ignoreOutOfDateSentences( self): incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1, admission_reason=StateIncarcerationPeriodAdmissionReason. PAROLE_REVOCATION, external_id='ip1', state_code='US_MO', admission_date=self.REVOCATION_DATE) supervision_sentence_parole = FakeUsMoSupervisionSentence.fake_sentence_from_sentence( StateSupervisionSentence.new_with_defaults( supervision_sentence_id=1, external_id=self.PAROLE_SENTENCE_EXTERNAL_ID, start_date=datetime.date(2017, 2, 1), supervision_type=StateSupervisionType.PROBATION), supervision_type=StateSupervisionType.PAROLE) old_incarceration_sentence = FakeUsMoIncarcerationSentence.fake_sentence_from_sentence( StateIncarcerationSentence.new_with_defaults( incarceration_sentence_id=1, external_id='US_MO', start_date=datetime.date(2017, 2, 1), completion_date=datetime.date(2017, 3, 4), status=StateSentenceStatus.COMPLETED), supervision_type=None # Terminated already ) self.assertEqual( StateSupervisionPeriodSupervisionType.PAROLE, us_mo_get_pre_incarceration_supervision_type( [old_incarceration_sentence], [supervision_sentence_parole], incarceration_period))
def test_usId_getPreIncarcerationSupervisionType_ignoreOutOfDatePeriods_Before( self): incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1, admission_reason=StateIncarcerationPeriodAdmissionReason. RETURN_FROM_SUPERVISION, external_id='ip1', state_code='US_ID', admission_date=date(2019, 9, 13)) preceding_supervision_period = StateSupervisionPeriod.new_with_defaults( supervision_period_id=1, start_date=incarceration_period.admission_date - relativedelta( days=INCARCERATION_SUPERVISION_TYPE_DAYS_LIMIT + 100), termination_date=incarceration_period.admission_date - relativedelta(days=INCARCERATION_SUPERVISION_TYPE_DAYS_LIMIT + 10), supervision_period_supervision_type= StateSupervisionPeriodSupervisionType.PAROLE) supervision_sentence = StateSupervisionSentence.new_with_defaults( supervision_sentence_id=1, external_id='XXX', supervision_periods=[preceding_supervision_period]) self.assertIsNone( us_id_get_pre_incarceration_supervision_type( incarceration_sentences=[], supervision_sentences=[supervision_sentence], incarceration_period=incarceration_period))
def test_usMo_getPreIncarcerationSupervisionType(self): incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1, admission_reason=StateIncarcerationPeriodAdmissionReason. PAROLE_REVOCATION, external_id='ip1', state_code='US_MO', admission_date=self.REVOCATION_DATE) supervision_sentence_parole = FakeUsMoSupervisionSentence.fake_sentence_from_sentence( StateSupervisionSentence.new_with_defaults( supervision_sentence_id=1, external_id=self.PAROLE_SENTENCE_EXTERNAL_ID, start_date=datetime.date(2017, 2, 1), supervision_type=StateSupervisionType.PROBATION), supervision_type=StateSupervisionType.PAROLE) # Even though the supervision type of the sentence is PROBATION, we find that it's actually a PAROLE # sentence from the statuses. self.assertEqual( StateSupervisionPeriodSupervisionType.PAROLE, us_mo_get_pre_incarceration_supervision_type( incarceration_sentences=[], supervision_sentences=[supervision_sentence_parole], incarceration_period=incarceration_period))
def test_usMo_getPreIncarcerationSupervisionType_noSupervisionPeriod(self): incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1, admission_reason=StateIncarcerationPeriodAdmissionReason. PAROLE_REVOCATION, external_id='ip1', state_code='US_MO', admission_date=date(2018, 3, 5)) supervision_sentence_prob = StateSupervisionSentence.new_with_defaults( supervision_sentence_id=1, external_id='US_MO', start_date=date(2018, 2, 1), completion_date=date(2018, 3, 6), status=StateSentenceStatus.COMPLETED, projected_completion_date=date(2018, 5, 19), supervision_type=StateSupervisionType.PROBATION) invalid_incarceration_sentence = StateIncarcerationSentence.new_with_defaults( incarceration_sentence_id=1, external_id='US_MO', start_date=date(2018, 2, 1), completion_date=date(2018, 3, 4), status=StateSentenceStatus.COMPLETED) self.assertEqual( StateSupervisionPeriodSupervisionType.PAROLE, get_pre_incarceration_supervision_type( [invalid_incarceration_sentence], [supervision_sentence_prob], incarceration_period, []))
def test_us_nd_get_pre_commitment_supervision_type_default(self) -> None: incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=1112, external_id="2", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, state_code="US_ND", facility="NDSP", admission_date=date(2008, 12, 20), admission_reason=StateIncarcerationPeriodAdmissionReason. PAROLE_REVOCATION, admission_reason_raw_text="ADMN", release_date=date(2010, 12, 21), release_reason=StateIncarcerationPeriodReleaseReason. CONDITIONAL_RELEASE, ) supervision_type_pre_commitment = ( self._test_get_commitment_from_supervision_supervision_type( incarceration_period=incarceration_period)) self.assertEqual( StateSupervisionPeriodSupervisionType.PAROLE, supervision_type_pre_commitment, )
def _test_us_nd_pre_commitment_supervision_period( admission_date: date, admission_reason: StateIncarcerationPeriodAdmissionReason, supervision_periods: List[StateSupervisionPeriod], ) -> Optional[StateSupervisionPeriod]: ip = StateIncarcerationPeriod.new_with_defaults( state_code="US_ND", incarceration_period_id=111, status=StateIncarcerationPeriodStatus.IN_CUSTODY, admission_date=admission_date, admission_reason=admission_reason, ) incarceration_periods = [ip] return _get_commitment_from_supervision_supervision_period( incarceration_period=ip, commitment_from_supervision_delegate= UsNdCommitmentFromSupervisionDelegate(), supervision_period_index=PreProcessedSupervisionPeriodIndex( supervision_periods), incarceration_period_index=PreProcessedIncarcerationPeriodIndex( incarceration_periods=incarceration_periods, ip_id_to_pfi_subtype={ ip.incarceration_period_id: None for ip in incarceration_periods if ip.incarceration_period_id }, ), )
def test_us_id_revoked_supervision_period_if_revocation_occurred_no_revocation( self, ): incarceration_period = StateIncarcerationPeriod.new_with_defaults( incarceration_period_id=222, external_id="ip2", state_code="US_ID", incarceration_type=StateIncarcerationType.STATE_PRISON, status=StateIncarcerationPeriodStatus.NOT_IN_CUSTODY, admission_date=date(2017, 5, 17), admission_reason=StateIncarcerationPeriodAdmissionReason. NEW_ADMISSION, release_date=date(2019, 5, 29), release_reason=StateIncarcerationPeriodReleaseReason.TRANSFER, specialized_purpose_for_incarceration= StateSpecializedPurposeForIncarceration.GENERAL, ) ( admission_is_revocation, revoked_period, ) = us_id_revoked_supervision_period_if_revocation_occurred( incarceration_period, [], None) self.assertFalse(admission_is_revocation) self.assertIsNone(revoked_period)