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
def _build_case_strategy(draw: Callable[[SearchStrategy], Any], min_charges_size=0) -> Case:
    case_summary = draw(builds(CaseSummary))
    charge_classes = get_charge_classes()
    charge_strategy_choices = list(
        map(lambda charge_class: _build_charge_strategy(charge_class, case_summary), charge_classes)
    )
    charge_strategy = one_of(charge_strategy_choices)
    charges = draw(lists(charge_strategy, min_charges_size))
    return Case(case_summary, charges=tuple(charges))
    def create(info=['John Doe', '1990'],
               case_number='C0000',
               citation_number=None,
               date_location=['1/1/1995', 'Multnomah'],
               type_status=['Offense Misdemeanor', 'Closed'],
               charges=[],
               case_detail_link='?404'):

        return Case(info, case_number, citation_number, date_location, type_status, charges, case_detail_link)
Exemple #4
0
 def __record_case(self):
     self.cases.append(
         Case.create(
             self.info,
             self.case_number,
             self.citation_number,
             self.date_location,
             self.type_status,
             [],
             self.case_detail_link,
         ))
Exemple #5
0
class CaseFactory:
    @staticmethod
    def create(info=['John Doe', '1990'],
               case_number='C0000',
               citation_number=None,
               date_location=['1/1/1995', 'Multnomah'],
               type_status=['Offense Misdemeanor', 'Closed'],
               charges=[],
               case_detail_link='?404',
               balance='0'):
        case = Case.create(info, case_number, citation_number, date_location,
                           type_status, charges, case_detail_link)
        case.set_balance_due(balance)
        return case
Exemple #6
0
 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_summary = CaseSummaryFactory.create(info, case_number,
                                              citation_number,
                                              date_location, type_status,
                                              case_detail_link, balance)
     return Case(case_summary, 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 = Case.create(info, case_number, citation_number, date_location,
                           type_status, charges, case_detail_link)
        case.set_balance_due(balance)
        return case
 def setUp(self):
     self.case = Case.create(("John Doe", "1990"), "", "", ("1/1/2019", ""),
                             ("", ""), "", "")
class TestCaseBalanceDue(unittest.TestCase):
    def setUp(self):
        self.case = Case(("John Doe", "1990"), "", "", ("1/1/2019", ""),
                         ("", ""), "", "")

    def test_balance_due_getter_setter(self):

        self.case.set_balance_due("123.45")
        assert self.case.get_balance_due() == 123.45

        self.case.set_balance_due("2,345.67")
        assert self.case.get_balance_due() == 2345.67

        self.case.set_balance_due(12345.67)
        assert self.case.get_balance_due() == 12345.67

        self.case.set_balance_due("0")
        assert self.case.get_balance_due() == 0
Exemple #10
0
def test_expunger_categorizes_charges(record_with_various_categories):
    dismissals, convictions = Case.categorize_charges(
        record_with_various_categories.charges)

    assert len(dismissals) == 5
    assert len(convictions) == 4
Exemple #11
0
    def run(record: Record) -> Dict[str, TimeEligibility]:
        """
        Evaluates the expungement eligibility of a record.
        """
        analyzable_record = Expunger._without_skippable_charges(record)
        ambiguous_charge_id_to_time_eligibility = {}
        cases = analyzable_record.cases
        for charge in analyzable_record.charges:
            eligibility_dates: List[Tuple[date, str]] = []

            other_charges = [
                c for c in analyzable_record.charges
                if c.id != charge.id and c.edit_status != EditStatus.DELETE
            ]

            other_blocking_charges = [
                c for c in other_charges if c.charge_type.blocks_other_charges
            ]

            _, convictions = Case.categorize_charges(other_charges)
            blocking_dismissals, blocking_convictions = Case.categorize_charges(
                other_blocking_charges)

            most_recent_blocking_dismissal = Expunger._most_recent_different_case_dismissal(
                charge, blocking_dismissals)
            most_recent_blocking_conviction = Expunger._most_recent_convictions(
                blocking_convictions)

            other_convictions_all_traffic = Expunger._is_other_convictions_all_traffic(
                convictions)

            if charge.convicted():
                if isinstance(
                        charge.charge_type,
                        MarijuanaUnder21) and other_convictions_all_traffic:
                    eligibility_dates.append((
                        charge.disposition.date + relativedelta(years=1),
                        "One year from date of conviction (137.226)",
                    ))
                else:
                    eligibility_dates.append((
                        charge.disposition.date + relativedelta(years=3),
                        "Three years from date of conviction (137.225(1)(a))",
                    ))
            elif charge.dismissed():
                eligibility_dates.append(
                    (charge.date, "Eligible immediately (137.225(1)(b))"))
            else:
                raise ValueError(
                    "Charge should always convicted or dismissed at this point."
                )

            if charge.type_eligibility.status == EligibilityStatus.INELIGIBLE:
                eligibility_dates.append((date.max(
                ), "Never. Type ineligible charges are always time ineligible."
                                          ))

            if charge.disposition.status == DispositionStatus.NO_COMPLAINT:
                eligibility_dates.append((
                    charge.date + relativedelta(years=1),
                    "One year from date of no-complaint arrest (137.225(1)(b))",
                ))

            if charge.convicted() and charge.probation_revoked:
                eligibility_dates.append((
                    charge.probation_revoked + relativedelta(years=10),
                    "Time-ineligible under 137.225(1)(c) (Probation Revoked). Inspect further if the case has multiple convictions on the case.",
                ))

            if most_recent_blocking_conviction:
                conviction_string = "other conviction" if charge.convicted(
                ) else "conviction"
                summary = most_recent_blocking_conviction.case(cases).summary
                potential = "potential " if not summary.closed() else ""
                eligibility_dates.append((
                    most_recent_blocking_conviction.disposition.date +
                    relativedelta(years=10),
                    f"137.225(7)(b) – Ten years from most recent {potential}{conviction_string} from case [{summary.case_number}].",
                ))

            if charge.dismissed() and most_recent_blocking_dismissal:
                eligibility_dates.append((
                    most_recent_blocking_dismissal.date +
                    relativedelta(years=3),
                    "Three years from most recent other arrest (137.225(8)(a))",
                ))

            if charge.convicted() and isinstance(charge.charge_type,
                                                 FelonyClassB):
                if Expunger._calculate_has_subsequent_charge(
                        charge, other_blocking_charges):
                    eligibility_dates.append((
                        date.max(),
                        "Never. Class B felony can have no subsequent arrests or convictions (137.225(5)(a)(A)(ii))",
                    ))
                else:
                    eligibility_dates.append((
                        charge.disposition.date + relativedelta(years=20),
                        "Twenty years from date of class B felony conviction (137.225(5)(a)(A)(i))",
                    ))

            if isinstance(charge.charge_type, MarijuanaViolation):
                date_will_be_eligible = charge.disposition.date
                reason = "Eligible immediately (475B.401)"
            else:
                date_will_be_eligible, reason = max(eligibility_dates)

            if date_will_be_eligible and date.today() >= date_will_be_eligible:
                time_eligibility = TimeEligibility(
                    status=EligibilityStatus.ELIGIBLE,
                    reason="Eligible now",
                    date_will_be_eligible=date_will_be_eligible,
                )
            else:
                time_eligibility = TimeEligibility(
                    status=EligibilityStatus.INELIGIBLE,
                    reason=reason,
                    date_will_be_eligible=date_will_be_eligible)
            ambiguous_charge_id_to_time_eligibility[
                charge.ambiguous_charge_id] = time_eligibility
        for case in cases:
            non_violation_convictions_in_case = []
            violations_in_case = []
            for charge in case.charges:
                if charge.convicted():
                    if "violation" in charge.level.lower():
                        violations_in_case.append(charge)
                    else:
                        non_violation_convictions_in_case.append(charge)
            violations_in_case.sort(key=lambda charge: charge.disposition.date,
                                    reverse=True)
            if len(non_violation_convictions_in_case
                   ) == 1 and len(violations_in_case) <= 1:
                attractor = non_violation_convictions_in_case[0]
            elif len(violations_in_case) == 1:
                attractor = violations_in_case[0]
            elif len(violations_in_case) in [2, 3]:
                attractor = violations_in_case[1]
            else:
                attractor = None

            if attractor:
                for charge in case.charges:
                    if (charge.type_eligibility.status !=
                            EligibilityStatus.INELIGIBLE
                            and charge.dismissed()
                            and ambiguous_charge_id_to_time_eligibility[
                                charge.
                                ambiguous_charge_id].date_will_be_eligible >
                            ambiguous_charge_id_to_time_eligibility[
                                attractor.
                                ambiguous_charge_id].date_will_be_eligible):
                        time_eligibility = TimeEligibility(
                            status=ambiguous_charge_id_to_time_eligibility[
                                attractor.ambiguous_charge_id].status,
                            reason=
                            'Time eligibility of the arrest matches conviction on the same case (the "friendly" rule)',
                            date_will_be_eligible=
                            ambiguous_charge_id_to_time_eligibility[
                                attractor.
                                ambiguous_charge_id].date_will_be_eligible,
                        )
                        ambiguous_charge_id_to_time_eligibility[
                            charge.ambiguous_charge_id] = time_eligibility
        return ambiguous_charge_id_to_time_eligibility
 def _build_case(
     oeci_case: OeciCase, new_charges: List[Charge]
 ) -> Tuple[AmbiguousCase, List[QuestionSummary]]:
     ambiguous_charges: List[AmbiguousCharge] = []
     questions: List[QuestionSummary] = []
     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,
             "balance_due_in_cents": oeci_charge.balance_due_in_cents,
             "case_number": oeci_case.summary.case_number,
             "violation_type": oeci_case.summary.violation_type,
             "birth_year": oeci_case.summary.birth_year,
             "edit_status": EditStatus(oeci_charge.edit_status),
         }
         if oeci_charge.disposition.status == DispositionStatus.UNKNOWN:
             charge_dict.pop("disposition")
             ambiguous_charge_dismissed, question_dismissed = ChargeCreator.create(
                 ambiguous_charge_id,
                 **charge_dict,
                 disposition=DispositionCreator.create(
                     date_class.today(), "dismissed"),
             )
             ambiguous_charge_convicted, question_convicted = ChargeCreator.create(
                 ambiguous_charge_id,
                 **charge_dict,
                 disposition=DispositionCreator.create(
                     date_class.future(), "convicted"),
             )
             if RecordCreator._disposition_question_is_irrelevant(
                     ambiguous_charge_convicted,
                     ambiguous_charge_dismissed):
                 ambiguous_charges.append(ambiguous_charge_dismissed)
                 question = RecordCreator._append_ambiguous_charge_id_to_question_id(
                     question_dismissed, ambiguous_charge_id
                 ) if question_dismissed else None  # type: ignore # TODO: Fix type
             else:
                 ambiguous_charges.append(ambiguous_charge_dismissed +
                                          ambiguous_charge_convicted)
                 disposition_question_text = "Choose the disposition"
                 question_id_prefix = ambiguous_charge_id + disposition_question_text
                 dismissed_option = RecordCreator._build_option(
                     question_dismissed, "Dismissed",
                     f"{question_id_prefix}-dismissed")
                 convicted_option = RecordCreator._build_option(
                     question_convicted, "Convicted",
                     f"{question_id_prefix}-convicted")
                 probation_revoked_option = RecordCreator._build_probation_revoked_option(
                     question_convicted, f"{question_id_prefix}-revoked")
                 unknown_option = {"Unknown": Answer()}
                 question = Question(
                     question_id_prefix,
                     disposition_question_text,
                     {
                         **dismissed_option,
                         **convicted_option,
                         **probation_revoked_option,
                         **unknown_option
                     },
                 )
         else:
             ambiguous_charge, maybe_question = ChargeCreator.create(
                 ambiguous_charge_id, **charge_dict)
             ambiguous_charges.append(ambiguous_charge)
             question = RecordCreator._append_ambiguous_charge_id_to_question_id(
                 maybe_question, ambiguous_charge_id
             ) if maybe_question else None  # type: ignore # TODO: Fix type
         if question:
             question_summary = QuestionSummary(
                 ambiguous_charge_id, oeci_case.summary.case_number,
                 question)
             questions.append(question_summary)
     ambiguous_charges += [[charge] for charge in new_charges]
     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
 def save(case):
     return Case(**case)
                )
            return pdf, warnings
        else:
            return None

    @staticmethod
    def _build_pdf_for_eligible_case(
            case: Case, eligible_charges: List[Charge],
            user_information: Dict[str, str],
            case_number_with_comments: str) -> Tuple[PdfReader, List[str]]:
        warnings: List[str] = []
        charges = case.charges
        charge_names = [charge.name.title() for charge in charges]
        arrest_dates_all = list(
            set([charge.date.strftime("%b %-d, %Y") for charge in charges]))
        dismissals, convictions = Case.categorize_charges(eligible_charges)
        dismissed_names = [charge.name.title() for charge in dismissals]
        dismissed_arrest_dates = list(
            set([charge.date.strftime("%b %-d, %Y") for charge in dismissals]))
        dismissed_dates = list(
            set([
                charge.disposition.date.strftime("%b %-d, %Y")
                for charge in dismissals
            ]))
        conviction_names = [charge.name.title() for charge in convictions]
        conviction_arrest_dates = list(
            set([charge.date.strftime("%b %-d, %Y")
                 for charge in convictions]))
        conviction_dates = list(
            set([
                charge.disposition.date.strftime("%b %-d, %Y")
Exemple #15
0
 def save(case):
     return Case.create(**case)