Skip to content

Commit 69b378d

Browse files
authored
Merge pull request #124 from cfpb/cache-total-accts
Save total accounts per event, provide to API
2 parents add0d04 + f1e5794 commit 69b378d

8 files changed

Lines changed: 54 additions & 7 deletions

File tree

‎django/evaluate_m2/tests/test_views.py‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ def create_activity_data(self, create_zero_hit:bool=False):
116116
id=1, name='test_exam', portfolio='credit cards',
117117
directory='Enforcement/Huyndai2025', eid_or_matter_num='123-456789',
118118
other_descriptor='',date_range_start='2023-11-30',
119-
date_range_end='2023-12-31', total_tradelines=1234)
119+
date_range_end='2023-12-31', total_tradelines=1234,
120+
total_accounts=321)
120121
self.data_file = M2DataFile.objects.create(
121122
event=self.event, file_name='file.txt'
122123
)
@@ -437,6 +438,7 @@ def test_events_view(self):
437438
'date_range_start': '2023-11-30',
438439
'date_range_end': '2023-12-31',
439440
'total_tradelines': 1234,
441+
'total_accounts': 321,
440442
'evaluators': [{
441443
'hits': 2,
442444
'accounts_affected': 1,

‎django/evaluate_m2/views.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@ def events_view(request, event_id):
198198
"date_range_start": event.date_range_start,
199199
"date_range_end": event.date_range_end,
200200
"total_tradelines": event.total_tradelines,
201+
"total_accounts": event.total_accounts,
201202
"evaluators": evaluator_metadata_serializer.data,
202203
}
203204
return Response(result)

‎django/parse_m2/admin.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ class Metro2EventAdmin(Metro2AdminPermissions):
5252
'date_range_start',
5353
'date_range_end',
5454
'total_tradelines',
55+
'total_accounts',
5556
'prior_records_associated',
5657
]
5758
fields = [
@@ -64,6 +65,7 @@ class Metro2EventAdmin(Metro2AdminPermissions):
6465
'date_range_start',
6566
'date_range_end',
6667
'total_tradelines',
68+
'total_accounts',
6769
'prior_records_associated',
6870
]
6971
list_display = [
@@ -74,7 +76,6 @@ class Metro2EventAdmin(Metro2AdminPermissions):
7476
'date_range_start',
7577
'date_range_end',
7678
'total_tradelines',
77-
'prior_records_associated',
7879
]
7980
filter_horizontal = ['members']
8081

‎django/parse_m2/initiate_post_parsing.py‎

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ def post_parse(event: Metro2Event, strategy:str = 'chunk') -> None:
1212
logger.info("Calculating total records.")
1313
save_total_records(event)
1414
if event.total_tradelines > 0:
15+
logger.info("Calculating total accounts.")
16+
save_total_accts(event)
1517
logger.info("Calculating event date range.")
1618
save_date_range(event)
1719
logger.info("Beginning progressive evaluator query.")
@@ -27,6 +29,11 @@ def save_date_range(event: Metro2Event):
2729
event.date_range_end = date_range['latest']
2830
event.save()
2931

32+
def save_total_accts(event: Metro2Event):
33+
event.total_accounts = event.accountactivity_set.values(
34+
'cons_acct_num').distinct().count()
35+
event.save()
36+
3037
def save_total_records(event: Metro2Event):
3138
event.total_tradelines = event.calculate_total_tradelines()
3239
event.save()
@@ -54,7 +61,7 @@ def associate_previous_records(event: Metro2Event, strategy: str = 'chunk'):
5461
except ValueError:
5562
chunk_method_associate_prior_records(event)
5663
elif strategy == 'skip':
57-
logger.info("'Skip' option, was used; skipping prior records step.")
64+
logger.info("'Skip' option selected; skipping prior records step.")
5865
else:
5966
logger.info(
6067
f"Invalid strategy input: {strategy}. "
@@ -66,12 +73,12 @@ def report_on_prior_record_outcome(event: Metro2Event):
6673
record_set = event.get_all_account_activity()
6774
total_updated = record_set.filter(previous_values_id__isnull=False).count()
6875
logger.info(f"Records with a previous record associated: {total_updated:,}")
69-
total_not_updated = record_set.filter(previous_values_id__isnull=True).count()
70-
logger.info(f"Records with NO previous record associated: {total_not_updated:,}")
71-
7276
event.prior_records_associated = total_updated
7377
event.save()
7478

79+
total_not_updated = record_set.filter(previous_values_id__isnull=True).count()
80+
logger.info(f"Records with NO previous record associated: {total_not_updated:,}")
81+
7582

7683
# Chunk strategy for associating prior records
7784
##########################################################################
@@ -84,7 +91,11 @@ def report_on_prior_record_outcome(event: Metro2Event):
8491
def chunk_method_associate_prior_records(event: Metro2Event, chunk_size = 100_000):
8592
logger = logging.getLogger('parse_m2.chunk_method_associate_prior_records')
8693
# Count the number of distinct account numbers
87-
total_accts = event.accountactivity_set.values('cons_acct_num').distinct().count()
94+
if event.total_accounts:
95+
total_accts = event.total_accounts
96+
else:
97+
total_accts = event.accountactivity_set.values(
98+
'cons_acct_num').distinct().count()
8899

89100
# Use that to decide number of chunks
90101
q,r = divmod(total_accts, chunk_size)

‎django/parse_m2/management/commands/delete_event_data.py‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ def handle(self, *args, **options):
6363
logger.info(f"Deleting {parsed_files.count()} existing files.")
6464
parsed_files.delete()
6565

66+
logger.info("Deleting any cached summary data for event")
67+
event.date_range_start = None
68+
event.date_range_end = None
69+
event.total_tradelines = 0
70+
event.total_accounts = 0
71+
event.prior_records_associated = 0
72+
event.save()
73+
6674
logger.info(
6775
self.style.SUCCESS(f"Finished deleting data for event: {event_id}.")
6876
)
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 5.2.17 on 2026-10-13 21:10
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('parse_m2', '0006_metro2event_prior_records_associated'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='metro2event',
15+
name='total_accounts',
16+
field=models.IntegerField(default=0),
17+
),
18+
]

‎django/parse_m2/models.py‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class Meta:
2424
date_range_start = models.DateField(null=True)
2525
date_range_end = models.DateField(null=True)
2626
total_tradelines = models.IntegerField(default=0)
27+
total_accounts = models.IntegerField(default=0)
2728
prior_records_associated = models.IntegerField(default=0)
2829

2930
def __str__(self) -> str:

‎django/parse_m2/tests/test_post_parsing.py‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ def test_post_parse_total_tradelines(self):
4141
# post_parse updates total_tradelines value
4242
self.assertEqual(self.event.total_tradelines, 6)
4343

44+
def test_post_parse_total_accounts(self):
45+
self.assertEqual(self.event.total_accounts, 0)
46+
post_parse(self.event)
47+
self.assertEqual(self.event.total_accounts, 2)
48+
4449
def test_associate_previous_records_no_previous_records(self):
4550
associate_previous_records(self.event)
4651
# Retrieve any record with activity_date 2018-01-31

0 commit comments

Comments
 (0)