Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

4541 Introduced clean_up_docket_judges command to clean up assigned_to and referred_to #4555

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions cl/recap/management/commands/clean_up_docket_judges.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# !/usr/bin/python
# -*- coding: utf-8 -*-
import time

from asgiref.sync import async_to_sync
from django.db.models import Q

from cl.lib.command_utils import VerboseCommand, logger
from cl.people_db.lookup_utils import lookup_judge_by_full_name
from cl.search.models import Docket


def find_and_fix_docket_judges(
iteration_wait: float, testing_mode: bool
) -> None:
"""Find and fix Dockets referred_to and assigned_to judges.

:param iteration_wait: A float that indicates the time to wait between iterations.
:param testing_mode: True if testing mode is enabled to avoid wait between
iterations.
:return: None
"""

logger.info("Finding dockets with judges.")
dockets_with_judges = Docket.objects.filter(
Q(referred_to__isnull=False) | Q(assigned_to__isnull=False)
)
total_dockets = dockets_with_judges.count()
logger.info(f"Total dockets to process: {total_dockets}")

fixed_dockets = 0
for iteration, d in enumerate(dockets_with_judges.iterator(), start=1):
new_referred = (
async_to_sync(lookup_judge_by_full_name)(
d.referred_to_str, d.court_id, d.date_filed
)
if d.referred_to_str
else None
)
new_assigned = (
async_to_sync(lookup_judge_by_full_name)(
d.assigned_to_str, d.court_id, d.date_filed
)
if d.assigned_to_str
else None
Comment on lines +34 to +45
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use lru_cache here to avoid zillions of DB lookups? Maybe set a maxsize of, say 30k so that we catch most judge names?

)

if d.referred_to != new_referred or d.assigned_to != new_assigned:
logger.info("Fixing Docket with ID %s", d.pk)
d.referred_to = new_referred
d.assigned_to = new_assigned
d.save()
fixed_dockets += 1
if not testing_mode:
# This will hit ES. So better to do it slowly.
time.sleep(iteration_wait)
mlissner marked this conversation as resolved.
Show resolved Hide resolved

# Log progress every 100 items.
if iteration % 100 == 0 or iteration == total_dockets:
progress_percentage = (iteration / total_dockets) * 100
logger.info(
f"Progress: {iteration}/{total_dockets} ({progress_percentage:.2f}%) dockets processed. Fixed: {fixed_dockets}"
)

logger.info(
f"Completed. Total dockets processed: {total_dockets}, Fixed: {fixed_dockets} Dockets"
)


class Command(VerboseCommand):
help = "Find and fix Dockets referred and assigned judges."

def add_arguments(self, parser):
parser.add_argument(
"--iteration-wait",
type=float,
default="0.1",
help="The time to wait between each iteration.",
)
parser.add_argument(
"--testing-mode",
action="store_true",
help="Use this flag only when running the command in tests based on TestCase",
)

def handle(self, *args, **options):
testing_mode = options.get("testing_mode", False)
iteration_wait = options.get("iteration_wait", 0.1)
find_and_fix_docket_judges(iteration_wait, testing_mode)
107 changes: 80 additions & 27 deletions cl/recap/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from django.core import mail
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.management import call_command
from django.test import RequestFactory, override_settings
from django.urls import reverse
from django.utils.timezone import now
Expand Down Expand Up @@ -2298,6 +2299,28 @@ class RecapDocketTaskTest(TestCase):
@classmethod
def setUpTestData(cls) -> None:
cls.court = CourtFactory(id="scotus", jurisdiction="F")
cls.judge = PersonFactory.create(name_first="John", name_last="Miller")
PositionFactory.create(
date_granularity_start="%Y-%m-%d",
court_id=cls.court.pk,
date_start=date(2020, 11, 10),
position_type="c-jud",
person=cls.judge,
how_selected="a_legis",
nomination_process="fed_senate",
)
cls.judge_2 = PersonFactory.create(
name_first="Debbie", name_last="Roe"
)
PositionFactory.create(
date_granularity_start="%Y-%m-%d",
court_id=cls.court.pk,
date_start=date(2019, 11, 10),
position_type="c-jud",
person=cls.judge_2,
how_selected="a_legis",
nomination_process="fed_senate",
)

def setUp(self) -> None:
self.user = User.objects.get(username="recap")
Expand Down Expand Up @@ -2680,26 +2703,6 @@ def test_clean_up_docket_judge_fields(
date_filed=date(2022, 12, 14),
),
)
judge = PersonFactory.create(name_first="John", name_last="Miller")
PositionFactory.create(
date_granularity_start="%Y-%m-%d",
court_id=self.court.pk,
date_start=date(2020, 11, 10),
position_type="c-jud",
person=judge,
how_selected="a_legis",
nomination_process="fed_senate",
)
judge_2 = PersonFactory.create(name_first="Debbie", name_last="Roe")
PositionFactory.create(
date_granularity_start="%Y-%m-%d",
court_id=self.court.pk,
date_start=date(2019, 11, 10),
position_type="c-jud",
person=judge_2,
how_selected="a_legis",
nomination_process="fed_senate",
)

# Test for district docket. Related judges exist in the people_db
async_to_sync(update_docket_metadata)(d, docket_data)
Expand All @@ -2708,8 +2711,8 @@ def test_clean_up_docket_judge_fields(

self.assertEqual(d.referred_to_str, "John Miller")
self.assertEqual(d.assigned_to_str, "Debbie Roe")
self.assertEqual(d.referred_to_id, judge.pk)
self.assertEqual(d.assigned_to_id, judge_2.pk)
self.assertEqual(d.referred_to_id, self.judge.pk)
self.assertEqual(d.assigned_to_id, self.judge_2.pk)

# Confirm that related judges are not removed if no referred_to_str or
# assigned_to_str are available in the docket metadata.
Expand All @@ -2726,8 +2729,8 @@ def test_clean_up_docket_judge_fields(
d.refresh_from_db()
self.assertEqual(d.referred_to_str, "John Miller")
self.assertEqual(d.assigned_to_str, "Debbie Roe")
self.assertEqual(d.referred_to_id, judge.pk)
self.assertEqual(d.assigned_to_id, judge_2.pk)
self.assertEqual(d.referred_to_id, self.judge.pk)
self.assertEqual(d.assigned_to_id, self.judge_2.pk)

# Judges have changed from the source. Confirm that referred_to_str and
# assigned_to_str are updated, while referred_to_id and assigned_to_id
Expand Down Expand Up @@ -2762,10 +2765,10 @@ def test_clean_up_docket_judge_fields(
d_a.originating_court_information.assigned_to_str, "Debbie Roe"
)
self.assertEqual(
d_a.originating_court_information.ordering_judge_id, judge.pk
d_a.originating_court_information.ordering_judge_id, self.judge.pk
)
self.assertEqual(
d_a.originating_court_information.assigned_to_id, judge_2.pk
d_a.originating_court_information.assigned_to_id, self.judge_2.pk
)

# Clean up judges in originating_court_information
Expand Down Expand Up @@ -2800,10 +2803,60 @@ def test_clean_up_docket_judge_fields(
self.assertEqual(
d_a.originating_court_information.assigned_to_id, None
)

d.delete()
d_a.delete()

def test_clean_up_docket_judge_fields_command(
self,
) -> None:
"""Ensure the command clean_up_docket_judges works correct.
The referred_to or assigned_to fields are cleared if the
referred_to_str or assigned_to_str judges don't exist in people_db.
"""

d = DocketFactory.create(
source=Docket.DEFAULT,
pacer_case_id="12345",
court_id=self.court.pk,
date_filed=date(2023, 12, 14),
referred_to_str="Marcus Carter",
assigned_to_str="Evelyn Whitfield",
referred_to_id=self.judge.pk,
assigned_to_id=self.judge_2.pk,
)

d_a = DocketFactory.create(
source=Docket.DEFAULT,
pacer_case_id="123421",
court_id=self.court.pk,
date_filed=date(2023, 12, 14),
appeal_from=self.court,
referred_to_str="Marcus Carter",
assigned_to_str="John Miller",
referred_to_id=self.judge.pk,
assigned_to_id=self.judge_2.pk,
)

self.assertEqual(d.referred_to_str, "Marcus Carter")
self.assertEqual(d.assigned_to_str, "Evelyn Whitfield")
self.assertEqual(d.referred_to_id, self.judge.pk)
self.assertEqual(d.assigned_to_id, self.judge_2.pk)

call_command("clean_up_docket_judges", testing_mode=True)

d.refresh_from_db()
self.assertEqual(d.referred_to_str, "Marcus Carter")
self.assertEqual(d.assigned_to_str, "Evelyn Whitfield")
self.assertEqual(d.referred_to_id, None)
self.assertEqual(d.assigned_to_id, None)

# Only one Judge should be cleaned up.
d_a.refresh_from_db()
self.assertEqual(d_a.referred_to_str, "Marcus Carter")
self.assertEqual(d_a.assigned_to_str, "John Miller")
self.assertEqual(d_a.referred_to_id, None)
self.assertEqual(d_a.assigned_to_id, self.judge.pk)


@mock.patch("cl.recap.tasks.add_items_to_solr")
class RecapDocketAttachmentTaskTest(TestCase):
Expand Down
Loading