-
-
Notifications
You must be signed in to change notification settings - Fork 153
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4729 from freelawproject/4054-add-nested-results-…
…filtering feat(api): Adds logic to filter nested results
- Loading branch information
Showing
5 changed files
with
541 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,7 +64,13 @@ | |
SchoolViewSet, | ||
SourceViewSet, | ||
) | ||
from cl.people_db.factories import PartyFactory, PartyTypeFactory | ||
from cl.people_db.factories import ( | ||
AttorneyFactory, | ||
AttorneyOrganizationFactory, | ||
PartyFactory, | ||
PartyTypeFactory, | ||
RoleFactory, | ||
) | ||
from cl.people_db.models import Attorney | ||
from cl.recap.factories import ProcessingQueueFactory | ||
from cl.recap.views import ( | ||
|
@@ -1110,10 +1116,7 @@ async def test_exclusion_filters(self) -> None: | |
|
||
|
||
class DRFRecapApiFilterTests(TestCase, FilteringCountTestCase): | ||
fixtures = [ | ||
"recap_docs.json", | ||
"attorney_party.json", | ||
] | ||
fixtures = ["recap_docs.json"] | ||
|
||
@classmethod | ||
def setUpTestData(cls) -> None: | ||
|
@@ -1125,6 +1128,40 @@ def setUpTestData(cls) -> None: | |
ps = Permission.objects.filter(codename="has_recap_api_access") | ||
up.user.user_permissions.add(*ps) | ||
|
||
cls.docket = Docket.objects.get(pk=1) | ||
cls.docket_2 = DocketFactory() | ||
firm = AttorneyOrganizationFactory( | ||
name="Lawyers LLP", lookup_key="6201in816" | ||
) | ||
cls.attorney = AttorneyFactory( | ||
name="Juneau", | ||
contact_raw="Juneau\r\nAlaska", | ||
phone="555-555-5555", | ||
fax="555-555-5555", | ||
email="[email protected]", | ||
date_created="2017-04-25T23:52:43.497Z", | ||
date_modified="2017-04-25T23:52:43.497Z", | ||
organizations=[firm], | ||
docket=cls.docket, | ||
) | ||
cls.attorney_2 = AttorneyFactory( | ||
organizations=[firm], docket=cls.docket_2 | ||
) | ||
cls.party = PartyFactory( | ||
name="Honker", | ||
extra_info="", | ||
docket=cls.docket, | ||
attorneys=[cls.attorney], | ||
date_created="2017-04-25T23:53:11.745Z", | ||
date_modified="2017-04-25T23:53:11.745Z", | ||
) | ||
PartyTypeFactory.create( | ||
party=cls.party, | ||
name="Defendant", | ||
extra_info="Klaxon", | ||
docket=cls.docket, | ||
) | ||
|
||
@async_to_sync | ||
async def setUp(self) -> None: | ||
self.assertTrue( | ||
|
@@ -1215,19 +1252,19 @@ async def test_recap_document_filters(self) -> None: | |
async def test_attorney_filters(self) -> None: | ||
self.path = reverse("attorney-list", kwargs={"version": "v3"}) | ||
|
||
self.q["id"] = 1 | ||
self.q["id"] = self.attorney.pk | ||
await self.assertCountInResults(1) | ||
self.q["id"] = self.attorney_2.pk | ||
await self.assertCountInResults(1) | ||
self.q["id"] = 2 | ||
await self.assertCountInResults(0) | ||
|
||
self.q = {"docket__id": 1} | ||
self.q = {"docket__id": self.docket.pk} | ||
await self.assertCountInResults(1) | ||
self.q = {"docket__id": 2} | ||
self.q = {"docket__id": self.docket_2.pk} | ||
await self.assertCountInResults(0) | ||
|
||
self.q = {"parties_represented__id": 1} | ||
self.q = {"parties_represented__id": self.party.pk} | ||
await self.assertCountInResults(1) | ||
self.q = {"parties_represented__id": 2} | ||
self.q = {"parties_represented__id": 9999} | ||
await self.assertCountInResults(0) | ||
self.q = {"parties_represented__name__contains": "Honker"} | ||
await self.assertCountInResults(1) | ||
|
@@ -1237,40 +1274,119 @@ async def test_attorney_filters(self) -> None: | |
# Adds extra role to the existing attorney | ||
docket = await Docket.objects.afirst() | ||
attorney = await Attorney.objects.afirst() | ||
party = await sync_to_async(PartyFactory)( | ||
docket=self.docket_2, | ||
attorneys=[attorney], | ||
) | ||
await sync_to_async(PartyTypeFactory.create)( | ||
party=await sync_to_async(PartyFactory)( | ||
docket=docket, | ||
attorneys=[attorney], | ||
), | ||
docket=docket, | ||
party=party, | ||
docket=self.docket_2, | ||
) | ||
self.q = {"docket__date_created__range": "2017-04-14,2017-04-15"} | ||
await self.assertCountInResults(1) | ||
self.q = {"docket__date_created__range": "2017-04-15,2017-04-16"} | ||
await self.assertCountInResults(0) | ||
|
||
# Initial request: Fetch all related records | ||
self.q = {"docket__id": self.docket.pk} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify record has expected number of parties | ||
self.assertEqual( | ||
len(results[0]["parties_represented"]), | ||
2, | ||
msg=f"Expected 2, but got {len(results[0]['parties_represented'])}.\n\nr.data was: {r.data}", | ||
) | ||
|
||
# Fetch attorney records for docket (repeat request with "filter_nested_results") | ||
self.q = {"docket__id": self.docket.pk, "filter_nested_results": True} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify top-level record has single party (due to filter) | ||
self.assertEqual( | ||
len(results[0]["parties_represented"]), | ||
1, | ||
msg=f"Expected 1, but got {len(results[0]['parties_represented'])}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify expected party is present in the parties_represented list | ||
self.assertIn( | ||
str(self.party.pk), results[0]["parties_represented"][0]["party"] | ||
) | ||
|
||
# Request using parties_represented lookup: Fetch all related records | ||
self.q = {"parties_represented__docket__id": self.docket_2.pk} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify record has expected number of parties | ||
self.assertEqual( | ||
len(results[0]["parties_represented"]), | ||
2, | ||
msg=f"Expected 2, but got {len(results[0]['parties_represented'])}.\n\nr.data was: {r.data}", | ||
) | ||
|
||
# Fetch attorney records for parties associated with docket_2 (repeat with "filter_nested_results") | ||
self.q = { | ||
"parties_represented__docket__id": self.docket_2.pk, | ||
"filter_nested_results": True, | ||
} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify record has expected number of parties | ||
self.assertEqual( | ||
len(results[0]["parties_represented"]), | ||
1, | ||
msg=f"Expected 1, but got {len(results[0]['parties_represented'])}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify expected party is present in the parties_represented list | ||
self.assertIn( | ||
str(party.pk), results[0]["parties_represented"][0]["party"] | ||
) | ||
|
||
async def test_party_filters(self) -> None: | ||
self.path = reverse("party-list", kwargs={"version": "v3"}) | ||
|
||
self.q["id"] = 1 | ||
self.q["id"] = self.party.pk | ||
await self.assertCountInResults(1) | ||
self.q["id"] = 2 | ||
self.q["id"] = 999_999 | ||
await self.assertCountInResults(0) | ||
|
||
# This represents dockets that the party was a part of. | ||
self.q = {"docket__id": 1} | ||
self.q = {"docket__id": self.docket.id} | ||
await self.assertCountInResults(1) | ||
self.q = {"docket__id": 2} | ||
self.q = {"docket__id": self.docket_2.id} | ||
await self.assertCountInResults(0) | ||
|
||
# Contrasted with this, which joins based on their attorney. | ||
self.q = {"attorney__docket__id": 1} | ||
self.q = {"attorney__docket__id": self.docket.pk} | ||
await self.assertCountInResults(1) | ||
self.q = {"attorney__docket__id": 2} | ||
self.q = {"attorney__docket__id": self.docket_2.pk} | ||
await self.assertCountInResults(0) | ||
|
||
self.q = {"name": "Honker"} | ||
await self.assertCountInResults(1) | ||
self.q = {"name__icontains": "Honk"} | ||
await self.assertCountInResults(1) | ||
|
||
self.q = {"name": "Cardinal Bonds"} | ||
await self.assertCountInResults(0) | ||
|
||
|
@@ -1279,6 +1395,137 @@ async def test_party_filters(self) -> None: | |
self.q = {"attorney__name__icontains": "Juno"} | ||
await self.assertCountInResults(0) | ||
|
||
# Add another attorney to the party record but linked to another docket | ||
await sync_to_async(RoleFactory.create)( | ||
party=self.party, docket=self.docket_2, attorney=self.attorney_2 | ||
) | ||
|
||
# Fetch all party records for docket | ||
self.q = {"docket__id": self.docket.pk} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify record has expected number of attorneys | ||
self.assertEqual( | ||
len(results[0]["attorneys"]), | ||
2, | ||
msg=f"Expected 2, but got {len(results[0]['attorneys'])}.\n\nr.data was: {r.data}", | ||
) | ||
|
||
# Fetch top-level record for docket (repeat with "filter_nested_results") | ||
self.q = {"docket__id": self.docket.pk, "filter_nested_results": True} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify the record has only one attorney (due to filter) | ||
self.assertEqual( | ||
len(results[0]["attorneys"]), | ||
1, | ||
msg=f"Expected 1, but got {len(results[0]['attorneys'])}.\n\nr.data was: {r.data}", | ||
) | ||
# Check if retrieved attorney matches expected record | ||
self.assertEqual( | ||
results[0]["attorneys"][0]["attorney_id"], self.attorney.pk | ||
) | ||
|
||
# Add another party type to the party record but linked to a different docket | ||
await sync_to_async(PartyTypeFactory.create)( | ||
party=self.party, docket=self.docket_2 | ||
) | ||
|
||
# Fetch all party records for docket | ||
self.q = {"docket__id": self.docket.pk} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify record has expected number of attorneys | ||
self.assertEqual( | ||
len(results[0]["attorneys"]), | ||
2, | ||
msg=f"Expected 2, but got {len(results[0]['attorneys'])}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify record has expected number of party types | ||
self.assertEqual( | ||
len(results[0]["party_types"]), | ||
2, | ||
msg=f"Expected 2, but got {len(results[0]['party_types'])}.\n\nr.data was: {r.data}", | ||
) | ||
|
||
# Fetch top-level record for docket (repeat with "filter_nested_results") | ||
self.q = {"docket__id": self.docket.pk, "filter_nested_results": True} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify the record has only one attorney and one party type (due to filter) | ||
self.assertEqual( | ||
len(results[0]["attorneys"]), | ||
1, | ||
msg=f"Expected 1, but got {len(results[0]['attorneys'])}.\n\nr.data was: {r.data}", | ||
) | ||
self.assertEqual( | ||
len(results[0]["party_types"]), | ||
1, | ||
msg=f"Expected 1, but got {len(results[0]['party_types'])}.\n\nr.data was: {r.data}", | ||
) | ||
# Check if retrieved party type matches expected record | ||
self.assertNotEqual( | ||
results[0]["party_types"][0]["docket_id"], self.docket_2.pk | ||
) | ||
|
||
# Fetch party details based on attorney lookup | ||
self.q = {"attorney__docket__id": self.docket_2.pk} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Verify record has expected number of attorneys | ||
self.assertEqual( | ||
len(results[0]["attorneys"]), | ||
2, | ||
msg=f"Expected 2, but got {len(results[0]['attorneys'])}.\n\nr.data was: {r.data}", | ||
) | ||
|
||
# Apply additional filter to refine previous request | ||
self.q = { | ||
"attorney__docket__id": self.docket_2.pk, | ||
"filter_nested_results": True, | ||
} | ||
r = await self.async_client.get(self.path, self.q) | ||
results = r.data["results"] | ||
self.assertEqual( | ||
len(results), | ||
1, | ||
msg=f"Expected 1, but got {len(results)}.\n\nr.data was: {r.data}", | ||
) | ||
# Ensure only attorney_2 is associated with the filtered party | ||
self.assertEqual( | ||
len(results[0]["attorneys"]), | ||
1, | ||
msg=f"Expected 1, but got {len(results[0]['attorneys'])}.\n\nr.data was: {r.data}", | ||
) | ||
self.assertEqual( | ||
results[0]["attorneys"][0]["attorney_id"], self.attorney_2.pk | ||
) | ||
|
||
|
||
class DRFSearchAppAndAudioAppApiFilterTest( | ||
TestCase, AudioTestCase, FilteringCountTestCase | ||
|
Oops, something went wrong.