def test_balance_due_getter_setter(self): case_args = [("John Doe", "1990"), "", "", ("1/1/2019", ""), ("", ""), ""] case_1 = CaseCreator.create(*case_args, "123.45") # type: ignore assert case_1.get_balance_due() == 123.45 case_2 = CaseCreator.create(*case_args, "2,345.67") # type: ignore assert case_2.get_balance_due() == 2345.67 case_3 = CaseCreator.create(*case_args, "0") # type: ignore assert case_3.get_balance_due() == 0
def __record_case(self): self.cases.append( CaseCreator.create( self.info, self.case_number, self.citation_number, self.date_location, self.type_status, self.case_detail_link, ))
def __record_case(self): self.cases.append( CaseCreator.create( self.info, self.case_number, "", # district_attorney_number "", # sid self.citation_number, self.date_location, self.type_status, self.case_detail_link, ))
def create( info=["John Doe", "1990"], case_number="1", citation_number=None, date_location=["1/1/1995", "Multnomah"], type_status=["Offense Misdemeanor", "Closed"], case_detail_link="?404", balance="0", ) -> CaseSummary: return CaseCreator.create(info, case_number, citation_number, date_location, type_status, case_detail_link, balance)
def _read_case(session: Session, case_summary: CaseSummary) -> OeciCase: case_parser_data = Crawler._parse_case(session, case_summary) balance_due_in_cents = CaseCreator.compute_balance_due_in_cents( case_parser_data.balance_due) charges: List[OeciCharge] = [] for charge_id, charge_dict in case_parser_data.hashed_charge_data.items( ): ambiguous_charge_id = f"{case_summary.case_number}-{charge_id}" charge = Crawler._build_oeci_charge(charge_id, ambiguous_charge_id, charge_dict, case_parser_data, balance_due_in_cents) charges.append(charge) updated_case_summary = replace( case_summary, balance_due_in_cents=balance_due_in_cents) return OeciCase(updated_case_summary, charges=tuple(charges))
class CaseFactory: @staticmethod def create( info=["John Doe", "1990"], case_number="1", citation_number=None, date_location=["1/1/1995", "Multnomah"], type_status=["Offense Misdemeanor", "Closed"], charges=[], case_detail_link="?404", balance="0", ) -> Case: case = CaseCreator.create( info, case_number, citation_number, date_location, type_status, charges, case_detail_link, balance ) return case
class RecordEditor: @staticmethod def edit_search_results(search_result_cases: List[OeciCase], edits) -> Tuple[List[OeciCase], List[Charge]]: edited_cases: List[OeciCase] = [] new_charges_acc: List[Charge] = [] for case in search_result_cases: case_number = case.summary.case_number if case_number in edits.keys(): if edits[case_number]["action"] == "edit": edited_case, new_charges = RecordEditor._edit_case( case, edits[case_number]) edited_cases.append(edited_case) new_charges_acc += new_charges # else: if the action name for this case_number isn't "edit", assume it is "delete" and skip it else: edited_cases.append(case) return edited_cases, new_charges_acc @staticmethod def _edit_case(case: OeciCase, case_edits) -> Tuple[OeciCase, List[Charge]]: if "summary" in case_edits.keys(): case_summary_edits: Dict[str, Any] = {} for key, value in case_edits["summary"].items(): if key == "date": case_summary_edits["date"] = date_class.fromdatetime( datetime.strptime(value, "%m/%d/%Y")) elif key == "balance_due": case_summary_edits[ "balance_due_in_cents"] = CaseCreator.compute_balance_due_in_cents( value) elif key == "birth_year": case_summary_edits["birth_year"] = int(value) else: case_summary_edits[key] = value edited_summary = replace(case.summary, **case_summary_edits) else: edited_summary = case.summary new_charges: List[Charge] = [] if "charges" in case_edits.keys(): edited_charges, new_charges = RecordEditor._edit_charges( case.summary.case_number, case.charges, case_edits["charges"]) else: edited_charges = case.charges return OeciCase(edited_summary, edited_charges), new_charges
def _read_case(session: Session, case_summary: CaseSummary) -> OeciCase: case_parser_data = Crawler._parse_case(session, case_summary) district_attorney_number = case_parser_data.district_attorney_number sid = case_parser_data.sid balance_due_in_cents = CaseCreator.compute_balance_due_in_cents(case_parser_data.balance_due) charges: List[OeciCharge] = [] for charge_id, charge_dict in case_parser_data.hashed_charge_data.items(): ambiguous_charge_id = f"{case_summary.case_number}-{charge_id}" charge = Crawler._build_oeci_charge( charge_id, ambiguous_charge_id, charge_dict, case_parser_data, balance_due_in_cents ) charges.append(charge) updated_case_summary = replace( case_summary, district_attorney_number=district_attorney_number, sid=sid, balance_due_in_cents=balance_due_in_cents, edit_status=EditStatus.UNCHANGED, ) return OeciCase(updated_case_summary, charges=tuple(charges))
def __build_case(self, case) -> Tuple[AmbiguousCase, List[Question]]: case_parser_data = self.__parse_case(case) balance_due_in_cents = CaseCreator.compute_balance_due_in_cents( case_parser_data.balance_due) updated_case = replace( case, balance_due_in_cents=balance_due_in_cents, probation_revoked=case_parser_data.probation_revoked) ambiguous_charges: List[AmbiguousCharge] = [] questions: List[Question] = [] for charge_id, charge_dict in case_parser_data.hashed_charge_data.items( ): charge_dict["case_number"] = updated_case.case_number charge_dict["violation_type"] = updated_case.violation_type ambiguous_charge, question = Crawler.__build_charge( charge_id, charge_dict, case_parser_data) ambiguous_charges.append(ambiguous_charge) if question: questions.append(question) ambiguous_case = [] for charges in product(*ambiguous_charges): possible_case = replace(updated_case, charges=tuple(charges)) ambiguous_case.append(possible_case) return ambiguous_case, questions
new_charges_accumulator += new_charges return edited_cases, new_charges_accumulator @staticmethod def _edit_case(case: OeciCase, case_edits) -> Tuple[OeciCase, List[Charge]]: case_summary_edits: Dict[str, Any] = {} for key, value in case_edits["summary"].items(): if key == "edit_status": case_summary_edits["edit_status"] = EditStatus(value) if key == "date": case_summary_edits["date"] = date_class.fromdatetime( datetime.strptime(value, "%m/%d/%Y")) elif key == "balance_due": case_summary_edits[ "balance_due_in_cents"] = CaseCreator.compute_balance_due_in_cents( value) elif key == "birth_year": case_summary_edits["birth_year"] = int(value) else: case_summary_edits[key] = value edited_summary = replace(case.summary, **case_summary_edits) new_charges: List[Charge] = [] if case_summary_edits["edit_status"] == EditStatus.DELETE: edited_charges = RecordEditor._mark_charges_as_deleted( case.charges) elif "charges" in case_edits.keys(): edited_charges, new_charges = RecordEditor._edit_charges( case.summary.case_number, case.charges, case_edits["charges"]) else: edited_charges = case.charges return OeciCase(edited_summary, edited_charges), new_charges
class RecordCreator: @staticmethod 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 @staticmethod @lru_cache(maxsize=4) def build_search_results( username: str, password: str, aliases: Tuple[Alias, ...]) -> Tuple[List[OeciCase], List[str]]: errors = [] search_results: List[OeciCase] = [] for alias in aliases: session = requests.Session() try: login_response = Crawler.attempt_login(session, username, password) alias_search_result = Crawler.search( session, login_response, alias.first_name, alias.last_name, alias.middle_name, alias.birth_date, ) search_results += alias_search_result except InvalidOECIUsernamePassword as e: error(401, str(e)) except OECIUnavailable as e: error(404, str(e)) except Exception as e: errors.append(str(e)) finally: session.close() return search_results, errors @staticmethod 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 @staticmethod def analyze_ambiguous_record(ambiguous_record: AmbiguousRecord): charge_id_to_time_eligibilities = [] ambiguous_record_with_errors = [] for record in ambiguous_record: record_with_errors = replace(record, errors=tuple( ErrorChecker.check(record))) charge_id_to_time_eligibility = Expunger.run(record_with_errors) charge_id_to_time_eligibilities.append( charge_id_to_time_eligibility) ambiguous_record_with_errors.append(record_with_errors) record = RecordMerger.merge(ambiguous_record_with_errors, charge_id_to_time_eligibilities) sorted_record = RecordCreator.sort_record_by_case_date(record) return sorted_record @staticmethod def sort_record_by_case_date(record): sorted_cases = sorted(record.cases, key=lambda case: case.summary.date, reverse=True) return replace(record, cases=tuple(sorted_cases)) @staticmethod def _build_case( oeci_case: OeciCase) -> Tuple[AmbiguousCase, List[Question]]: ambiguous_charges: List[AmbiguousCharge] = [] questions: List[Question] = [] for oeci_charge in oeci_case.charges: ambiguous_charge_id = oeci_charge.ambiguous_charge_id charge_dict = { "name": oeci_charge.name, "statute": oeci_charge.statute, "level": oeci_charge.level, "date": oeci_charge.date, "disposition": oeci_charge.disposition, "probation_revoked": oeci_charge.probation_revoked, "case_number": oeci_case.summary.case_number, "violation_type": oeci_case.summary.violation_type, "birth_year": oeci_case.summary.birth_year, } ambiguous_charge, question = ChargeCreator.create( ambiguous_charge_id, **charge_dict) ambiguous_charges.append(ambiguous_charge) if question: questions.append(question) ambiguous_case: AmbiguousCase = [] for charges in product(*ambiguous_charges): possible_case = Case(oeci_case.summary, charges=tuple(charges)) ambiguous_case.append(possible_case) return ambiguous_case, questions @staticmethod def _edit_search_results(search_result_cases: List[OeciCase], edits) -> List[OeciCase]: edited_cases: List[OeciCase] = [] for case in search_result_cases: case_number = case.summary.case_number if case_number in edits.keys(): if edits[case_number]["action"] == "edit": edited_cases.append( RecordCreator._edit_case(case, edits[case_number])) # else: if the action name for this case_number isn't "edit", assume it is "delete" and skip it else: edited_cases.append(case) return edited_cases @staticmethod def _edit_case(case: OeciCase, edits): if "summary" in edits.keys(): case_summary_edits: Dict[str, Any] = {} for key, value in edits["summary"].items(): if key == "date": case_summary_edits["date"] = datetime.date( datetime.strptime(value, "%m/%d/%Y")) elif key == "balance_due": case_summary_edits[ "balance_due_in_cents"] = CaseCreator.compute_balance_due_in_cents( value) elif key == "birth_year": case_summary_edits["birth_year"] = int(value) else: case_summary_edits[key] = value edited_summary = replace(case.summary, **case_summary_edits) else: edited_summary = case.summary if "charges" in edits.keys(): edited_charges = RecordCreator._edit_charges( case.charges, edits["charges"]) else: edited_charges = case.charges return OeciCase(edited_summary, edited_charges)