|
8 | 8 | from django.db.utils import DataError
|
9 | 9 | from django.utils import timezone
|
10 | 10 |
|
| 11 | +from additional_data.sources.find_that_charity import non_primary_org_ids_lookup_maps |
| 12 | + |
11 | 13 |
|
12 | 14 | class Latest(models.Model):
|
13 | 15 | """Latest best data we have"""
|
@@ -277,6 +279,8 @@ def update_aggregate(self, grant):
|
277 | 279 | # "GBP": { "grants": 0, "total": 0, "avg": 0, min: 0, max: 0 } },
|
278 | 280 | # ...
|
279 | 281 | # },
|
| 282 | + # This only covers common stats. |
| 283 | + # See classes that inherit this - they may override update_aggregate() and add more. |
280 | 284 |
|
281 | 285 | amount = grant["amountAwarded"]
|
282 | 286 | currency = grant["currency"]
|
@@ -373,6 +377,49 @@ class Meta:
|
373 | 377 |
|
374 | 378 | non_primary_org_ids = ArrayField(models.TextField())
|
375 | 379 |
|
| 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 | + |
376 | 423 |
|
377 | 424 | class Funder(Entity):
|
378 | 425 | class Meta:
|
|
0 commit comments