Skip to content

Commit 62b8ce5

Browse files
committed
On Recipients, store count of funders
ThreeSixtyGiving/grantnav#940 Must switch test to TestCase or database is somehow not in correct state from another test, and tests fail
1 parent 02b96cd commit 62b8ce5

File tree

2 files changed

+54
-2
lines changed

2 files changed

+54
-2
lines changed

datastore/db/models.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
from django.db.utils import DataError
99
from django.utils import timezone
1010

11+
from additional_data.sources.find_that_charity import non_primary_org_ids_lookup_maps
12+
1113

1214
class Latest(models.Model):
1315
"""Latest best data we have"""
@@ -277,6 +279,8 @@ def update_aggregate(self, grant):
277279
# "GBP": { "grants": 0, "total": 0, "avg": 0, min: 0, max: 0 } },
278280
# ...
279281
# },
282+
# This only covers common stats.
283+
# See classes that inherit this - they may override update_aggregate() and add more.
280284

281285
amount = grant["amountAwarded"]
282286
currency = grant["currency"]
@@ -373,6 +377,49 @@ class Meta:
373377

374378
non_primary_org_ids = ArrayField(models.TextField())
375379

380+
"""While collecting aggregate info on funders, we need to store some data temporarily that we don't want to store in the database.
381+
This stores all primary ids so we can count unique funders."""
382+
_aggregate_funders_primary_ids = set()
383+
"""While collecting aggregate info on funders, we need to store some data temporarily that we don't want to store in the database.
384+
This stores information by currency."""
385+
_aggregate_funders_currencies = {}
386+
387+
def update_aggregate(self, grant):
388+
# Step 1: Call parent
389+
super().update_aggregate(grant)
390+
391+
# Step 2: update _aggregate_funders_* vars with info from this grant
392+
# This function is called repeatedly from datastore/db/management/commands/manage_entities_data.py
393+
# and it's inefficient to call non_primary_org_ids_lookup_maps every time.
394+
# But after discussion with MW that is ok.
395+
(
396+
non_primary_to_primary_org_ids_lookup,
397+
primary_to_non_primary_org_ids_lookup,
398+
) = non_primary_org_ids_lookup_maps()
399+
currency = grant["currency"]
400+
if currency not in self._aggregate_funders_currencies:
401+
self._aggregate_funders_currencies[currency] = {
402+
"funders_primary_ids": set(),
403+
}
404+
for funder in grant["fundingOrganization"]:
405+
# If the org-id provided is a non-primary org-id return the primary
406+
# otherwise return the specified org-id
407+
funder_primary_id = non_primary_to_primary_org_ids_lookup.get(
408+
funder["id"], funder["id"]
409+
)
410+
self._aggregate_funders_primary_ids.add(funder_primary_id)
411+
self._aggregate_funders_currencies[currency]["funders_primary_ids"].add(
412+
funder_primary_id
413+
)
414+
415+
# Step 3: copy info from _aggregate_funders_* vars to aggregate for saving to the database
416+
self.aggregate["funders"] = len(self._aggregate_funders_primary_ids)
417+
418+
for currency_id, currency_data in self._aggregate_funders_currencies.items():
419+
self.aggregate["currencies"][currency_id]["funders"] = len(
420+
self._aggregate_funders_currencies[currency_id]["funders_primary_ids"]
421+
)
422+
376423

377424
class Funder(Entity):
378425
class Meta:

datastore/tests/test_latest_data.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
from tempfile import TemporaryDirectory
55

66
from django.core.management import call_command
7-
from django.test import TransactionTestCase
7+
from django.test import TestCase
88

99
import db.models as db
1010
from tests.generate_testdata import generate_data
1111

1212

13-
class LatestDataTest(TransactionTestCase):
13+
class LatestDataTest(TestCase):
1414
def break_the_data(self, tmpdir):
1515
data_all_path = os.path.join(tmpdir, "data_all.json")
1616
dataset = None
@@ -43,6 +43,11 @@ def test_latest_data(self):
4343
self.assertEqual(
4444
db.Latest.objects.get(series=db.Latest.CURRENT).grant_set.count(), 50
4545
)
46+
# Test some specific data
47+
recipient = db.Recipient.objects.get(org_id="360G-example-a")
48+
self.assertEqual(1, recipient.aggregate["funders"])
49+
self.assertEqual(1, recipient.aggregate["currencies"]["GBP"]["funders"])
50+
4651
# Load broken data - This should trigger fall back mechanism
4752
print("Breaking the data")
4853
self.break_the_data(tmpdir)

0 commit comments

Comments
 (0)