def test_get_violation_and_response_history_no_violations(self): supervision_violation_response = ( StateSupervisionViolationResponse.new_with_defaults( state_code="US_XX", supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, response_date=datetime.date(2009, 1, 7), supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_XX", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, ) ], ) ) revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [supervision_violation_response], UsXxViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=None, most_severe_violation_type_subtype=None, most_severe_response_decision=StateSupervisionViolationResponseDecision.CONTINUANCE, response_count=1, violation_history_description=None, violation_type_frequency_counter=None, ) self.assertEqual(expected_output, violation_history)
def test_get_violation_and_response_history_us_mo_handle_law_technicals(self): """Tests that a US_MO violation report with a TECHNICAL type and a LAW condition is not treated like a citation with a LAW condition.""" supervision_violation = StateSupervisionViolation.new_with_defaults( supervision_violation_id=123455, state_code="US_MO", violation_date=datetime.date(2009, 1, 7), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_MO", violation_type=StateSupervisionViolationType.TECHNICAL, ), ], supervision_violated_conditions=[ StateSupervisionViolatedConditionEntry.new_with_defaults( state_code="US_MO", condition="LAW" ), ], ) supervision_violation_response = StateSupervisionViolationResponse.new_with_defaults( state_code="US_MO", supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, response_subtype="ITR", response_date=datetime.date(2009, 1, 7), is_draft=False, supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_MO", decision=StateSupervisionViolationResponseDecision.REVOCATION, revocation_type=StateSupervisionViolationResponseRevocationType.REINCARCERATION, ), StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_MO", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, revocation_type=StateSupervisionViolationResponseRevocationType.SHOCK_INCARCERATION, ), ], supervision_violation=supervision_violation, ) revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [supervision_violation_response], UsMoViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=StateSupervisionViolationType.TECHNICAL, most_severe_violation_type_subtype=StateSupervisionViolationType.TECHNICAL.value, most_severe_response_decision=StateSupervisionViolationResponseDecision.REVOCATION, response_count=1, violation_history_description="1tech", violation_type_frequency_counter=[["LAW", "TECHNICAL"]], ) self.assertEqual(expected_output, violation_history)
def test_get_violation_and_response_history_with_us_mo_subtype(self): supervision_violation = StateSupervisionViolation.new_with_defaults( supervision_violation_id=123455, state_code="US_MO", violation_date=datetime.date(2009, 1, 3), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_MO", violation_type=StateSupervisionViolationType.TECHNICAL, ), ], supervision_violated_conditions=[ StateSupervisionViolatedConditionEntry.new_with_defaults( state_code="US_MO", condition="DRG" ), StateSupervisionViolatedConditionEntry.new_with_defaults( state_code="US_MO", condition="OTHER" ), ], ) supervision_violation_response = StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, response_subtype="INI", state_code="US_MO", response_date=datetime.date(2009, 1, 7), supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_MO", decision=StateSupervisionViolationResponseDecision.REVOCATION, revocation_type=StateSupervisionViolationResponseRevocationType.REINCARCERATION, ), StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_MO", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, ), ], supervision_violation=supervision_violation, ) revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [supervision_violation_response], UsMoViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=StateSupervisionViolationType.TECHNICAL, most_severe_violation_type_subtype="SUBSTANCE_ABUSE", most_severe_response_decision=StateSupervisionViolationResponseDecision.REVOCATION, response_count=1, violation_history_description="1subs", violation_type_frequency_counter=[["SUBSTANCE_ABUSE", "OTHER"]], ) self.assertEqual(expected_output, violation_history)
def test_get_violation_and_response_history(self): supervision_violation = StateSupervisionViolation.new_with_defaults( supervision_violation_id=123455, state_code="US_XX", violation_date=datetime.date(2009, 1, 3), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.TECHNICAL, ), StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.FELONY, ), StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.ABSCONDED, ), ], ) supervision_violation_response = StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, state_code="US_XX", response_date=datetime.date(2009, 1, 7), supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_XX", decision=StateSupervisionViolationResponseDecision.REVOCATION, revocation_type=StateSupervisionViolationResponseRevocationType.REINCARCERATION, ), StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_XX", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, ), ], supervision_violation=supervision_violation, ) revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [supervision_violation_response], UsXxViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=StateSupervisionViolationType.FELONY, most_severe_violation_type_subtype=StateSupervisionViolationType.FELONY.value, most_severe_response_decision=StateSupervisionViolationResponseDecision.REVOCATION, response_count=1, violation_history_description="1felony", violation_type_frequency_counter=[["TECHNICAL", "FELONY", "ABSCONDED"]], ) self.assertEqual(expected_output, violation_history)
def test_get_violation_and_response_history_with_us_pa_subtype_high_technical(self): supervision_violation = StateSupervisionViolation.new_with_defaults( supervision_violation_id=123455, state_code="US_PA", violation_date=datetime.date(2009, 1, 3), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_PA", violation_type=StateSupervisionViolationType.ABSCONDED, violation_type_raw_text="H09", ), StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_PA", violation_type=StateSupervisionViolationType.TECHNICAL, violation_type_raw_text="H08", # High Technical ), ], ) supervision_violation_response = StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, state_code="US_PA", response_date=datetime.date(2009, 1, 7), supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_PA", decision=StateSupervisionViolationResponseDecision.REVOCATION, revocation_type=StateSupervisionViolationResponseRevocationType.REINCARCERATION, ), StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_PA", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, revocation_type=StateSupervisionViolationResponseRevocationType.SHOCK_INCARCERATION, ), ], supervision_violation=supervision_violation, ) revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [supervision_violation_response], UsPaViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=StateSupervisionViolationType.TECHNICAL, most_severe_violation_type_subtype="HIGH_TECH", most_severe_response_decision=StateSupervisionViolationResponseDecision.REVOCATION, response_count=1, violation_history_description="1high_tech", violation_type_frequency_counter=[["ABSCONDED", "HIGH_TECH"]], ) self.assertEqual(expected_output, violation_history)
def test_get_violation_and_response_history_citation_date(self): supervision_violation = StateSupervisionViolation.new_with_defaults( supervision_violation_id=123455, state_code="US_XX", supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.ABSCONDED, ), StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.MISDEMEANOR, ), ], ) supervision_violation_response = StateSupervisionViolationResponse.new_with_defaults( state_code="US_XX", supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.CITATION, response_date=datetime.date(2009, 1, 7), supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_XX", decision=StateSupervisionViolationResponseDecision.REVOCATION, revocation_type=StateSupervisionViolationResponseRevocationType.REINCARCERATION, ), StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_XX", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, revocation_type=StateSupervisionViolationResponseRevocationType.SHOCK_INCARCERATION, ), ], supervision_violation=supervision_violation, ) revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [supervision_violation_response], UsXxViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=StateSupervisionViolationType.MISDEMEANOR, most_severe_violation_type_subtype=StateSupervisionViolationType.MISDEMEANOR.value, most_severe_response_decision=StateSupervisionViolationResponseDecision.REVOCATION, response_count=1, violation_history_description="1misdemeanor", violation_type_frequency_counter=[["ABSCONDED", "MISDEMEANOR"]], ) self.assertEqual(expected_output, violation_history)
def test_get_violation_and_response_history_no_responses(self): revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [], UsXxViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=None, most_severe_violation_type_subtype=None, most_severe_response_decision=None, response_count=0, violation_history_description=None, violation_type_frequency_counter=None, ) self.assertEqual(expected_output, violation_history)
def _commitment_from_supervision_event_for_period( self, incarceration_sentences: List[StateIncarcerationSentence], supervision_sentences: List[StateSupervisionSentence], incarceration_period: StateIncarcerationPeriod, incarceration_period_index: PreProcessedIncarcerationPeriodIndex, supervision_period_index: PreProcessedSupervisionPeriodIndex, assessments: List[StateAssessment], sorted_violation_responses: List[StateSupervisionViolationResponse], supervision_period_to_agent_associations: Dict[int, Dict[Any, Any]], county_of_residence: Optional[str], commitment_from_supervision_delegate: StateSpecificCommitmentFromSupervisionDelegate, violation_delegate: StateSpecificViolationDelegate, ) -> IncarcerationCommitmentFromSupervisionAdmissionEvent: """ Returns the IncarcerationCommitmentFromSupervisionAdmissionEvent corresponding to the admission to the |incarceration_period| that qualifies as a commitment from supervision admission. Includes details about the period of supervision that preceded the admission. """ admission_date = incarceration_period.admission_date admission_reason = incarceration_period.admission_reason state_code = incarceration_period.state_code if not admission_date or not admission_reason: raise ValueError( "Should only be calling this function with a set " "admission_date and admission_reason." ) ( assessment_score, assessment_level, assessment_type, ) = assessment_utils.most_recent_applicable_assessment_attributes_for_class( admission_date, assessments, assessment_class=StateAssessmentClass.RISK, state_code=incarceration_period.state_code, ) violation_responses_for_history = ( filter_violation_responses_for_violation_history( violation_delegate, violation_responses=sorted_violation_responses, include_follow_up_responses=False, ) ) violation_history_window = commitment_from_supervision_delegate.violation_history_window_pre_commitment_from_supervision( admission_date=admission_date, sorted_and_filtered_violation_responses=violation_responses_for_history, default_violation_history_window_months=VIOLATION_HISTORY_WINDOW_MONTHS, ) # Get details about the violation and response history leading up to the # admission to incarceration violation_history = get_violation_and_response_history( upper_bound_exclusive_date=violation_history_window.upper_bound_exclusive_date, lower_bound_inclusive_date_override=violation_history_window.lower_bound_inclusive_date, violation_responses_for_history=violation_responses_for_history, violation_delegate=violation_delegate, incarceration_period=incarceration_period, ) responses_for_decision_evaluation = violation_responses_for_history if ( violation_delegate.include_decisions_on_follow_up_responses_for_most_severe_response() ): # Get a new state-specific list of violation responses that includes follow-up # responses responses_for_decision_evaluation = ( filter_violation_responses_for_violation_history( violation_delegate=violation_delegate, violation_responses=sorted_violation_responses, include_follow_up_responses=True, ) ) responses_in_window_for_decision_evaluation = violation_responses_in_window( violation_responses=responses_for_decision_evaluation, upper_bound_exclusive=(admission_date + relativedelta(days=1)), # We're just looking for the most recent response lower_bound_inclusive=None, ) # Find the most severe decision on the most recent response decisions most_recent_responses = responses_on_most_recent_response_date( responses_in_window_for_decision_evaluation ) most_recent_response_decision = get_most_severe_response_decision( most_recent_responses ) commitment_details = get_commitment_from_supervision_details( incarceration_period=incarceration_period, incarceration_period_index=incarceration_period_index, supervision_period_index=supervision_period_index, incarceration_sentences=incarceration_sentences, supervision_sentences=supervision_sentences, commitment_from_supervision_delegate=commitment_from_supervision_delegate, supervision_period_to_agent_associations=supervision_period_to_agent_associations, state_specific_officer_and_location_info_from_supervision_period_fn=get_state_specific_supervising_officer_and_location_info_function( state_code ), ) deprecated_supervising_district_external_id = ( commitment_details.level_2_supervision_location_external_id or commitment_details.level_1_supervision_location_external_id ) return IncarcerationCommitmentFromSupervisionAdmissionEvent( state_code=incarceration_period.state_code, event_date=admission_date, facility=incarceration_period.facility, admission_reason=admission_reason, admission_reason_raw_text=incarceration_period.admission_reason_raw_text, supervision_type=commitment_details.supervision_type, specialized_purpose_for_incarceration=commitment_details.purpose_for_incarceration, purpose_for_incarceration_subtype=commitment_details.purpose_for_incarceration_subtype, county_of_residence=county_of_residence, case_type=commitment_details.case_type, supervision_level=commitment_details.supervision_level, supervision_level_raw_text=commitment_details.supervision_level_raw_text, assessment_score=assessment_score, assessment_level=assessment_level, assessment_type=assessment_type, most_severe_violation_type=violation_history.most_severe_violation_type, most_severe_violation_type_subtype=violation_history.most_severe_violation_type_subtype, most_severe_response_decision=violation_history.most_severe_response_decision, most_recent_response_decision=most_recent_response_decision, response_count=violation_history.response_count, violation_history_description=violation_history.violation_history_description, violation_type_frequency_counter=violation_history.violation_type_frequency_counter, supervising_officer_external_id=commitment_details.supervising_officer_external_id, supervising_district_external_id=deprecated_supervising_district_external_id, level_1_supervision_location_external_id=( commitment_details.level_1_supervision_location_external_id ), level_2_supervision_location_external_id=( commitment_details.level_2_supervision_location_external_id ), )
def test_get_violation_and_response_history_with_us_pa_subtype_multiple_types(self): supervision_violation_1 = StateSupervisionViolation.new_with_defaults( supervision_violation_id=12345, state_code="US_PA", violation_date=datetime.date(2009, 1, 3), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_PA", violation_type=StateSupervisionViolationType.TECHNICAL, violation_type_raw_text="M05", # MED_TECH ), ], ) supervision_violation_2 = StateSupervisionViolation.new_with_defaults( supervision_violation_id=123456, state_code="US_PA", violation_date=datetime.date(2009, 1, 3), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_PA", violation_type=StateSupervisionViolationType.TECHNICAL, violation_type_raw_text="M05", # MED_TECH ), ], ) supervision_violation_3 = StateSupervisionViolation.new_with_defaults( supervision_violation_id=1234567, state_code="US_PA", violation_date=datetime.date(2009, 1, 3), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_PA", violation_type=StateSupervisionViolationType.TECHNICAL, violation_type_raw_text="M14", # SUBSTANCE_ABUSE ), ], ) supervision_violation_response_1 = StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, state_code="US_PA", response_date=datetime.date(2009, 1, 7), supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_PA", decision=StateSupervisionViolationResponseDecision.REVOCATION, revocation_type=StateSupervisionViolationResponseRevocationType.REINCARCERATION, ), StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_PA", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, revocation_type=StateSupervisionViolationResponseRevocationType.SHOCK_INCARCERATION, ), ], supervision_violation=supervision_violation_1, ) supervision_violation_response_2 = ( StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=1234567, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, state_code="US_PA", response_date=datetime.date(2009, 1, 6), supervision_violation=supervision_violation_2, ) ) supervision_violation_response_3 = ( StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=1234567, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, state_code="US_PA", response_date=datetime.date(2009, 1, 5), supervision_violation=supervision_violation_3, ) ) revocation_date = datetime.date(2009, 2, 13) violation_history = violation_utils.get_violation_and_response_history( revocation_date, [ supervision_violation_response_3, supervision_violation_response_2, supervision_violation_response_1, ], UsPaViolationDelegate(), ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=StateSupervisionViolationType.TECHNICAL, most_severe_violation_type_subtype="SUBSTANCE_ABUSE", most_severe_response_decision=StateSupervisionViolationResponseDecision.REVOCATION, response_count=3, violation_history_description="1subs;2med_tech", violation_type_frequency_counter=[ ["SUBSTANCE_ABUSE"], ["MED_TECH"], ["MED_TECH"], ], ) self.assertEqual(expected_output, violation_history)
def test_get_violation_and_response_history_outside_lookback(self): supervision_violation = StateSupervisionViolation.new_with_defaults( supervision_violation_id=123455, state_code="US_XX", violation_date=datetime.date(2009, 1, 3), supervision_violation_types=[ StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.TECHNICAL, ), StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.FELONY, ), StateSupervisionViolationTypeEntry.new_with_defaults( state_code="US_XX", violation_type=StateSupervisionViolationType.ABSCONDED, ), ], ) # This is outside of the lookback window supervision_violation_response_before_look_back = ( StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, state_code="US_XX", response_date=datetime.date(2018, 7, 25), ) ) supervision_violation_response = StateSupervisionViolationResponse.new_with_defaults( supervision_violation_response_id=_DEFAULT_SSVR_ID, response_type=StateSupervisionViolationResponseType.VIOLATION_REPORT, state_code="US_XX", response_date=datetime.date(2019, 1, 20), supervision_violation_response_decisions=[ StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_XX", decision=StateSupervisionViolationResponseDecision.REVOCATION, revocation_type=StateSupervisionViolationResponseRevocationType.REINCARCERATION, ), StateSupervisionViolationResponseDecisionEntry.new_with_defaults( state_code="US_XX", decision=StateSupervisionViolationResponseDecision.CONTINUANCE, revocation_type=StateSupervisionViolationResponseRevocationType.SHOCK_INCARCERATION, ), ], supervision_violation=supervision_violation, ) violation_responses = [ supervision_violation_response_before_look_back, supervision_violation_response, ] end_date = datetime.date(2019, 9, 5) violation_history = violation_utils.get_violation_and_response_history( end_date, violation_responses, UsXxViolationDelegate() ) expected_output = violation_utils.ViolationHistory( most_severe_violation_type=StateSupervisionViolationType.FELONY, most_severe_violation_type_subtype=StateSupervisionViolationType.FELONY.value, most_severe_response_decision=StateSupervisionViolationResponseDecision.REVOCATION, response_count=1, violation_history_description="1felony", violation_type_frequency_counter=[["TECHNICAL", "FELONY", "ABSCONDED"]], ) self.assertEqual(expected_output, violation_history)