def test_very_old_needs_more_analysis_mrc_with_single_arrest(): eligible_charge, ineligible_charge = ChargeFactory.create_ambiguous_charge( name="Assault in the third degree", statute="163.165", level="Felony Class C", disposition=DispositionCreator.create(ruling="Convicted", date=Time.TWENTY_YEARS_AGO), ) arrest = ChargeFactory.create(disposition=DispositionCreator.create(ruling="Dismissed", date=Time.THREE_YEARS_AGO)) case_a = CaseFactory.create(charges=tuple([eligible_charge, arrest])) case_b = CaseFactory.create(charges=tuple([ineligible_charge, arrest])) record_a = Record(tuple([case_a])) record_b = Record(tuple([case_b])) expunger_result_a = Expunger.run(record_a) expunger_result_b = Expunger.run(record_b) three_years_from_mrc = eligible_charge.disposition.date + Time.THREE_YEARS assert expunger_result_a[arrest.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert ( expunger_result_a[arrest.ambiguous_charge_id].reason == 'Time eligibility of the arrest matches conviction on the same case (the "friendly" rule)' ) assert expunger_result_a[arrest.ambiguous_charge_id].date_will_be_eligible == three_years_from_mrc assert expunger_result_b[arrest.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result_b[arrest.ambiguous_charge_id].reason == "Eligible now" assert expunger_result_b[arrest.ambiguous_charge_id].date_will_be_eligible == arrest.disposition.date
def test_doubly_eligible_b_felony_gets_normal_eligibility_rule(): # This charge is both ManufactureDelivery and also a class B felony. ManufactureDelivery classification takes precedence and the B felony time rule does not apply. manudel_charges = ChargeFactory.create_ambiguous_charge( case_number="1", name="Manufacture/Delivery 1", statute="4759922b", level="Felony Class B", date=Time.LESS_THAN_TWENTY_YEARS_AGO, disposition=DispositionCreator.create(ruling="Convicted", date=Time.LESS_THAN_TWENTY_YEARS_AGO), ) manudel_type_eligilibility = RecordMerger.merge_type_eligibilities(manudel_charges) case_1a = CaseFactory.create(case_number="1", charges=tuple([manudel_charges[0]])) case_1b = CaseFactory.create(case_number="1", charges=tuple([manudel_charges[1]])) subsequent_charge = ChargeFactory.create( case_number="2", disposition=DispositionCreator.create(ruling="Convicted", date=Time.TEN_YEARS_AGO), ) case_2 = CaseFactory.create(case_number="2", charges=tuple([subsequent_charge])) possible_record_1 = Record(tuple([case_1a, case_2])) possible_record_2 = Record(tuple([case_1b, case_2])) expunger_result_1 = Expunger.run(possible_record_1) expunger_result_2 = Expunger.run(possible_record_2) assert manudel_type_eligilibility.status is EligibilityStatus.ELIGIBLE assert expunger_result_1[manudel_charges[0].ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result_2[manudel_charges[1].ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE
def test_felony_class_b_with_subsequent_conviction(): b_felony_charge = create_class_b_felony_charge("1", Time.TWENTY_YEARS_AGO) case_1 = CaseFactory.create(case_number="1", charges=tuple([b_felony_charge])) subsequent_charge = ChargeFactory.create( disposition=DispositionCreator.create(ruling="Convicted", date=Time.TEN_YEARS_AGO)) case_2 = CaseFactory.create(case_number="2", charges=tuple([subsequent_charge])) expunger_result = Expunger.run(Record(tuple([case_1, case_2]))) assert expunger_result[ b_felony_charge. ambiguous_charge_id].status is EligibilityStatus.INELIGIBLE assert ( expunger_result[b_felony_charge.ambiguous_charge_id].reason == "Never. Class B felony can have no subsequent arrests or convictions (137.225(5)(a)(A)(ii))" ) assert expunger_result[ b_felony_charge.ambiguous_charge_id].date_will_be_eligible == date.max # The Class B felony does not affect eligibility of another charge that is otherwise eligible assert expunger_result[ subsequent_charge. ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert subsequent_charge.type_eligibility.status is EligibilityStatus.ELIGIBLE
def test_all_mrd_case_related_dismissals_are_expungeable(self): case_related_dismissal = ChargeFactory.create_dismissed_charge( case_number=self.case_1.case_number, date=Time.TWO_YEARS_AGO, violation_type=self.case_1.violation_type) self.case_1.charges.append(case_related_dismissal) record = Record([self.case_1]) expunger = Expunger(record) expunger_result = expunger.run() assert expunger_result[ self.recent_dismissal. ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[ self.recent_dismissal.ambiguous_charge_id].reason == "Eligible now" assert expunger_result[ self.recent_dismissal. ambiguous_charge_id].date_will_be_eligible == Time.TWO_YEARS_AGO assert expunger_result[ case_related_dismissal. ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[case_related_dismissal. ambiguous_charge_id].reason == "Eligible now" assert expunger_result[ case_related_dismissal. ambiguous_charge_id].date_will_be_eligible == Time.TWO_YEARS_AGO
def test_marijuana_violation_eligible_with_prior_conviction(): marijuana_violation = ChargeFactory.create( case_number="1", name="Possession of Marijuana < 1 Ounce", statute="4758643", level="Violation Unclassified", date=date.today(), disposition=DispositionCreator.create(ruling="Convicted", date=date.today() + relativedelta(days=-1)), ) case_1 = CaseFactory.create(case_number="1", charges=tuple([marijuana_violation])) prior_conviction = ChargeFactory.create( case_number="2", name="Identity Theft", statute="165.800", level="Felony Class C", date=Time.FIVE_YEARS_AGO, disposition=DispositionCreator.create(ruling="Convicted", date=Time.ONE_YEAR_AGO), ) case_2 = CaseFactory.create(case_number="2", charges=tuple([prior_conviction])) expunger_result = Expunger.run(Record(tuple([case_1, case_2]))) assert isinstance(marijuana_violation.charge_type, MarijuanaViolation) assert expunger_result[marijuana_violation.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[prior_conviction.ambiguous_charge_id].status is EligibilityStatus.INELIGIBLE
def test_all_mrd_case_related_dismissals_are_expungeable(self): case_related_dismissal = ChargeFactory.create_dismissed_charge( case_number=self.case_1.case_number, date=Time.TWO_YEARS_AGO) updated_case_1 = replace( self.case_1, charges=tuple([*self.case_1.charges, case_related_dismissal])) record = Record(tuple([updated_case_1])) expunger_result = Expunger.run(record) assert expunger_result[ self.recent_dismissal. ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[ self.recent_dismissal.ambiguous_charge_id].reason == "Eligible now" assert expunger_result[ self.recent_dismissal. ambiguous_charge_id].date_will_be_eligible == Time.TWO_YEARS_AGO assert expunger_result[ case_related_dismissal. ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[case_related_dismissal. ambiguous_charge_id].reason == "Eligible now" assert expunger_result[ case_related_dismissal. ambiguous_charge_id].date_will_be_eligible == Time.TWO_YEARS_AGO
def test_record_with_only_an_mrd_is_time_eligible(self): record = Record(tuple([self.case_1])) expunger_result = Expunger.run(record) assert expunger_result[self.recent_dismissal.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[self.recent_dismissal.ambiguous_charge_id].reason == "Eligible now" assert expunger_result[self.recent_dismissal.ambiguous_charge_id].date_will_be_eligible == Time.TWO_YEARS_AGO
def build_record( search: Callable, username: str, password: str, aliases: Tuple[Alias, ...], edits: Dict[str, Dict[str, Any]], ) -> Tuple[Record, AmbiguousRecord, Dict[str, Question], List[str]]: search_results, errors = search(username, password, aliases) if errors: record = Record((), tuple(errors)) ambiguous_record = [record] return record, ambiguous_record, {}, [] else: cases_with_unique_case_number: List[OeciCase] = [ list(group)[0] for key, group in groupby( sorted(search_results, key=lambda case: case.summary.case_number), lambda case: case.summary.case_number, ) ] unknown_dispositions = RecordCreator._find_unknown_dispositions( cases_with_unique_case_number) user_edited_search_results = RecordCreator._edit_search_results( cases_with_unique_case_number, edits) ambiguous_record, questions = RecordCreator.build_ambiguous_record( user_edited_search_results) record = RecordCreator.analyze_ambiguous_record(ambiguous_record) questions_as_dict = dict( list(map(lambda q: (q.ambiguous_charge_id, q), questions))) return record, ambiguous_record, questions_as_dict, unknown_dispositions
def test_print_balance_in_cents(self): recordTest = Record([ CaseFactory.create(balance="123.00"), CaseFactory.create(balance="246.00") ]) assert recordTest.total_balance_due == 369.00
def test_record_with_only_an_mrd_is_time_eligible(self): record = Record([self.case_1]) expunger = Expunger(record) expunger.run() assert self.recent_dismissal.expungement_result.time_eligibility.status is EligibilityStatus.ELIGIBLE assert self.recent_dismissal.expungement_result.time_eligibility.reason == "" assert self.recent_dismissal.expungement_result.time_eligibility.date_will_be_eligible == Time.TWO_YEARS_AGO
def test_record_with_only_an_mrd_is_time_eligible(self): record = Record([self.case_1]) expunger = Expunger(record) expunger.run() assert self.recent_dismissal.expungement_result.time_eligibility.status is True assert self.recent_dismissal.expungement_result.time_eligibility.reason == '' assert self.recent_dismissal.expungement_result.time_eligibility.date_will_be_eligible is None
def build_record( username: str, password: str, aliases: List[Dict[str, str]] ) -> Tuple[Record, AmbiguousRecord, Dict[str, Question]]: ambiguous_cases_accumulator: List[AmbiguousCase] = [] questions_accumulator: List[Question] = [] errors = [] for alias in aliases: crawler = Crawler() login_result = crawler.login(username, password, close_session=False) if login_result is False: error(401, "Attempted login to OECI failed") try: search_result = crawler.search( alias["first_name"], alias["last_name"], alias["middle_name"], alias["birth_date"], ) ambiguous_cases, questions = search_result ambiguous_cases_accumulator += ambiguous_cases questions_accumulator += questions except Exception as e: errors.append(str(e)) if errors: record = Record((), tuple(errors)) ambiguous_record = [record] return record, ambiguous_record, {} else: ambiguous_record: AmbiguousRecord = [] # type: ignore for cases in product(*ambiguous_cases_accumulator): cases_with_unique_case_number: List[Case] = [ list(group)[0] for key, group in groupby( sorted(list(cases), key=lambda case: case.case_number), lambda case: case.case_number) ] ambiguous_record.append( Record(tuple(cases_with_unique_case_number))) record = RecordCreator.analyze_ambiguous_record(ambiguous_record) questions_as_dict = dict( list( map(lambda q: (q.ambiguous_charge_id, q), questions_accumulator))) return record, ambiguous_record, questions_as_dict
def test_record_summarizer_no_cases(): record = Record(tuple([])) record_summary = RecordSummarizer.summarize(record, {}) assert record_summary.total_fines_due == 0.00 assert record_summary.total_cases == 0 assert record_summary.total_charges == 0 assert record_summary.county_fines == [] assert record_summary.charges_grouped_by_eligibility_and_case == {}
def setUp(self): self.charge_zero = ChargeFactory.create(case_number="1") self.case_1 = CaseFactory.create(case_number="1", charges=tuple([self.charge_zero])) self.charge_one = ChargeFactory.create(case_number="2") self.charge_two = ChargeFactory.create(case_number="2") self.case_2 = CaseFactory.create(case_number="2", charges=tuple([self.charge_one, self.charge_two])) self.record = Record(tuple([self.case_1, self.case_2]))
def test_record_summarizer_no_cases(): record = Record(tuple([])) record_summary = RecordSummarizer.summarize(record, {}) assert record_summary.total_balance_due == 0.00 assert record_summary.total_cases == 0 assert record_summary.total_charges == 0 assert record_summary.county_balances == [] assert record_summary.eligible_charges_by_date == {}
def post(self): request_data = request.get_json() if request_data is None or not request_data.get("names"): error(400, "No json data in request body") for alias in request_data["names"]: check_data_fields( alias, ["first_name", "last_name", "middle_name", "birth_date"]) cipher = DataCipher(key=current_app.config.get("SECRET_KEY")) if not "oeci_token" in request.cookies.keys(): error(401, "Missing login credentials to OECI.") decrypted_credentials = cipher.decrypt(request.cookies["oeci_token"]) crawler = Crawler() login_result = crawler.login(decrypted_credentials["oeci_username"], decrypted_credentials["oeci_password"], close_session=False) if login_result is False: error(401, "Attempted login to OECI failed") cases: List[Case] = [] for alias in request_data["names"]: cases += crawler.search( alias["first_name"], alias["last_name"], alias["middle_name"], alias["birth_date"], ).cases cases_with_unique_case_number = [ list(group)[0] for key, group in groupby(cases, lambda case: case.case_number) ] record = Record(cases_with_unique_case_number) expunger = Expunger(record) expunger.run() try: save_result(request_data, record) except Exception as ex: logging.error("Saving search result failed with exception: %s" % ex, stack_info=True) record_summary = RecordSummarizer.summarize(record) response_data = {"data": {"record": record_summary}} current_app.json_encoder = ExpungeModelEncoder return response_data # Json-encoding happens automatically here
def test_mrd_blocks_dismissals_in_unrelated_cases(self): unrelated_dismissal = ChargeFactory.create_dismissed_charge(case=self.case_2, date=Time.TEN_YEARS_AGO) self.case_2.charges = [unrelated_dismissal] record = Record([self.case_1, self.case_2]) expunger = Expunger(record) expunger.run() assert unrelated_dismissal.expungement_result.time_eligibility.status is False assert unrelated_dismissal.expungement_result.time_eligibility.reason == 'Recommend sequential expungement' assert unrelated_dismissal.expungement_result.time_eligibility.date_will_be_eligible == Time.ONE_YEARS_FROM_NOW
def test_delete_case(): record, questions = RecordCreator.build_record( search("single_case_two_charges"), "username", "password", (), {"X0001": { "action": "delete" }}, ) assert record == Record((), ())
def test_record_summarizer_no_cases(): record = Record(tuple([])) record_summary = RecordSummarizer.summarize(record, {}) assert record_summary.total_fines_due == 0.00 assert record_summary.total_cases == 0 assert record_summary.total_charges == 0 assert record_summary.county_fines == [] assert record_summary.eligible_charges_by_date == {} assert record_summary.county_filing_fees == [] assert record_summary.no_fees_reason == "None"
def build_record( search: Callable, username: str, password: str, aliases: Tuple[Alias, ...], edits: Dict[str, Dict[str, Any]], today: date_class, search_cache: LRUCache, ) -> Tuple[Record, Dict[str, QuestionSummary]]: search_results, errors = search(username, password, aliases, search_cache) if errors: record = Record((), tuple(errors)) return record, {} else: cases_with_unique_case_number: List[OeciCase] = [ list(group)[0] for key, group in groupby( sorted(search_results, key=lambda case: case.summary.case_number), lambda case: case.summary.case_number, ) ] user_edited_search_results, new_charges = RecordEditor.edit_search_results( cases_with_unique_case_number, edits) ambiguous_cases, questions = RecordCreator._build_ambiguous_cases( user_edited_search_results, new_charges) ambiguous_record, overflow_error = RecordCreator._build_ambiguous_record( ambiguous_cases) if overflow_error: return Record((), tuple(overflow_error)), {} else: charge_ids_with_question = [ question.ambiguous_charge_id for question in questions ] record = RecordCreator._analyze_ambiguous_record( ambiguous_record, charge_ids_with_question, today) questions_as_dict = dict( list(map(lambda q: (q.ambiguous_charge_id, q), questions))) return record, questions_as_dict
def test_mrd_does_not_block_other_dismissals(self): unrelated_dismissal = ChargeFactory.create_dismissed_charge( case_number="2", date=Time.TEN_YEARS_AGO, violation_type="Offense Misdemeanor" ) case_2 = CaseFactory.create(case_number="2", charges=tuple([unrelated_dismissal])) record = Record(tuple([self.case_1, case_2])) expunger_result = Expunger.run(record) assert expunger_result[unrelated_dismissal.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert expunger_result[unrelated_dismissal.ambiguous_charge_id].reason == "Eligible now" assert expunger_result[unrelated_dismissal.ambiguous_charge_id].date_will_be_eligible == Time.TEN_YEARS_AGO
def build_ambiguous_record( search_result: List[OeciCase] ) -> Tuple[AmbiguousRecord, List[Question]]: ambiguous_record: AmbiguousRecord = [] questions_accumulator: List[Question] = [] ambiguous_cases: List[AmbiguousCase] = [] for oeci_case in search_result: ambiguous_case, questions = RecordCreator._build_case(oeci_case) questions_accumulator += questions ambiguous_cases.append(ambiguous_case) for cases in product(*ambiguous_cases): ambiguous_record.append(Record(tuple(cases))) return ambiguous_record, questions_accumulator
def test_mrd_blocks_dismissals_in_unrelated_cases(self): unrelated_dismissal = ChargeFactory.create_dismissed_charge( case=self.case_2, date=Time.TEN_YEARS_AGO) self.case_2.charges = [unrelated_dismissal] record = Record([self.case_1, self.case_2]) expunger = Expunger(record) expunger.run() assert unrelated_dismissal.expungement_result.time_eligibility.status is EligibilityStatus.INELIGIBLE assert (unrelated_dismissal.expungement_result.time_eligibility.reason == "Three years from most recent other arrest (137.225(8)(a))") assert unrelated_dismissal.expungement_result.time_eligibility.date_will_be_eligible == Time.ONE_YEARS_FROM_NOW
def test_record_summarizer_no_cases(): record = Record([]) record_summary = RecordSummarizer.summarize(record, {}) assert record_summary.total_balance_due == 0.00 assert record_summary.total_cases == 0 assert record_summary.total_charges == 0 assert record_summary.cases_sorted["fully_eligible"] == [] assert record_summary.cases_sorted["fully_ineligible"] == [] assert record_summary.cases_sorted["partially_eligible"] == [] assert record_summary.cases_sorted["other"] == [] assert record_summary.county_balances == [] assert record_summary.eligible_charges_by_date == [("now", [])]
def test_dismissed_felony_class_b_with_subsequent_conviction(): b_felony_charge = create_class_b_felony_charge("1", Time.LESS_THAN_TWENTY_YEARS_AGO, "Dismissed") case_1 = CaseFactory.create(case_number="1", charges=tuple([b_felony_charge])) subsequent_charge = ChargeFactory.create( case_number="2", disposition=DispositionCreator.create(ruling="Convicted", date=Time.TEN_YEARS_AGO), ) case_2 = CaseFactory.create(case_number="2", charges=tuple([subsequent_charge])) expunger_result = Expunger.run(Record(tuple([case_1, case_2]))) assert b_felony_charge.type_eligibility.status is EligibilityStatus.ELIGIBLE assert expunger_result[b_felony_charge.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE
def setUp(self): self.case_1 = CaseFactory.create(case_number="1") self.charge_zero = ChargeFactory.create( case_number=self.case_1.case_number) self.case_1.charges = [self.charge_zero] self.case_2 = CaseFactory.create(case_number="2") self.charge_one = ChargeFactory.create( case_number=self.case_2.case_number) self.charge_two = ChargeFactory.create( case_number=self.case_2.case_number) self.case_2.charges = [self.charge_one, self.charge_two] self.record = Record([self.case_1, self.case_2])
def test_sort_if_all_dates_are_same(): case1 = CaseFactory.create(case_number="1") case2 = CaseFactory.create(case_number="2") case3 = CaseFactory.create(case_number="3") record = Record(tuple([case1, case2, case3])) assert record.cases[0].summary.case_number == "1" assert record.cases[1].summary.case_number == "2" assert record.cases[2].summary.case_number == "3" sorted_record = RecordCreator.sort_record_by_case_date(record) assert sorted_record.cases[0].summary.case_number == "1" assert sorted_record.cases[1].summary.case_number == "2" assert sorted_record.cases[2].summary.case_number == "3"
def test_dismissed_felony_class_b_with_subsequent_conviction(): b_felony_charge = create_class_b_felony_charge( Time.LESS_THAN_TWENTY_YEARS_AGO, "Dismissed") case_1 = CaseFactory.create() case_1.charges = [b_felony_charge] subsequent_charge = ChargeFactory.create( disposition=Disposition(ruling="Convicted", date=Time.TEN_YEARS_AGO)) case_2 = CaseFactory.create() case_2.charges = [subsequent_charge] expunger = Expunger(Record([case_1, case_2])) expunger.run() assert b_felony_charge.expungement_result.type_eligibility.status is EligibilityStatus.ELIGIBLE assert b_felony_charge.expungement_result.time_eligibility.status is EligibilityStatus.ELIGIBLE
def test_all_mrd_case_related_dismissals_are_expungeable(self): case_related_dismissal = ChargeFactory.create_dismissed_charge(case=self.case_1, date=Time.TWO_YEARS_AGO) self.case_1.charges.append(case_related_dismissal) record = Record([self.case_1]) expunger = Expunger(record) expunger.run() assert self.recent_dismissal.expungement_result.time_eligibility.status is True assert self.recent_dismissal.expungement_result.time_eligibility.reason == '' assert self.recent_dismissal.expungement_result.time_eligibility.date_will_be_eligible is None assert case_related_dismissal.expungement_result.time_eligibility.status is True assert case_related_dismissal.expungement_result.time_eligibility.reason == '' assert case_related_dismissal.expungement_result.time_eligibility.date_will_be_eligible is None
def test_needs_more_analysis_mrc_with_single_arrest(): eligible_charge, ineligible_charge = ChargeFactory.create_ambiguous_charge( name="Assault in the third degree", statute="163.165", level="Felony Class C", disposition=DispositionCreator.create(ruling="Convicted", date=Time.THREE_YEARS_AGO), ) arrest = ChargeFactory.create(disposition=DispositionCreator.create( ruling="Dismissed", date=Time.THREE_YEARS_AGO)) case_a = CaseFactory.create(charges=tuple([eligible_charge, arrest])) case_b = CaseFactory.create(charges=tuple([ineligible_charge, arrest])) record_a = Record(tuple([case_a])) record_b = Record(tuple([case_b])) expunger_result_a = Expunger.run(record_a) expunger_result_b = Expunger.run(record_b) ten_years_from_mrc = eligible_charge.disposition.date + Time.TEN_YEARS assert expunger_result_a[ arrest.ambiguous_charge_id].status is EligibilityStatus.ELIGIBLE assert ( expunger_result_a[arrest.ambiguous_charge_id].reason == 'Time eligibility of the arrest matches conviction on the same case (the "friendly" rule)' ) assert expunger_result_a[ arrest.ambiguous_charge_id].date_will_be_eligible == date.today() assert expunger_result_b[ arrest.ambiguous_charge_id].status is EligibilityStatus.INELIGIBLE assert ( expunger_result_b[arrest.ambiguous_charge_id].reason == f"137.225(7)(b) – Ten years from most recent conviction from case [{case_a.summary.case_number}]." ) assert expunger_result_b[ arrest.ambiguous_charge_id].date_will_be_eligible == ten_years_from_mrc