Skip to content

Commit 29b5cec

Browse files
committed
Add flex fields grouping
1 parent b3116ec commit 29b5cec

File tree

4 files changed

+56
-11
lines changed

4 files changed

+56
-11
lines changed

src/country_workspace/contrib/hope/push.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from collections.abc import Callable, Iterator
22
from dataclasses import dataclass, field
3+
from functools import cached_property
34
from itertools import batched
45
from json import JSONDecodeError
56
from typing import Any, TypedDict, ReadOnly
@@ -12,9 +13,8 @@
1213

1314
from country_workspace.contrib.hope.client import HopeClient
1415
from country_workspace.exceptions import RemoteError
15-
from country_workspace.models import AsyncJob, Rdp
16+
from country_workspace.models import AsyncJob, Rdp, Program
1617
from country_workspace.workspaces.models import CountryHousehold, CountryIndividual
17-
from country_workspace.utils.fields import map_fields
1818

1919

2020
type Beneficiary = CountryHousehold | CountryIndividual
@@ -189,17 +189,24 @@ def safe_post(self, path: str, data: Any, error_msg: str) -> dict[str, Any] | No
189189
self.total["errors"].append(f"{error_msg}: {e}")
190190
return None
191191

192+
@cached_property
193+
def program(self) -> Program:
194+
return Program.objects.get(hope_id=self.program_hope_id)
195+
192196
def prepare_batch(self) -> tuple[list[int], list[dict]]:
193197
"""Prepare a batch of household/individual|people data for API submission."""
194198
ids, data = [], []
195199
for item in self.queryset:
196200
ids.append(item.id)
197-
data.append(
198-
{**map_fields(item.flex_fields), "members": [map_fields(m.flex_fields) for m in item.members.all()]}
199-
if self.master_detail
200-
else map_fields(item.flex_fields)
201-
)
202-
return ids, data
201+
flex_fields = item.apply_grouping()
202+
if self.master_detail:
203+
flex_fields["members"] = []
204+
for member in item.members.all():
205+
flex_fields["members"].append(member.apply_grouping())
206+
data.append(flex_fields)
207+
else:
208+
data.append(flex_fields)
209+
return ids, self.program.serialize(data)
203210

204211
def process_batch_response(self, response: dict | None, batch_ids: list[int]) -> list[int]:
205212
"""Process the API response for a batch push operation."""
@@ -279,7 +286,7 @@ def push_to_hope_core(job: AsyncJob) -> dict[str, Any]:
279286

280287
def steps() -> Iterator[Callable[[], None]]:
281288
"""Yield steps for pushing beneficiaries data in batches."""
282-
yield processor.rdi_create
289+
# yield processor.rdi_create
283290
for batch_pks in batched(config["pks"], config["batch_size"]):
284291
processor.set_queryset(batch_pks)
285292
yield from (processor.check_beneficiaries_validity, processor.rdi_push)

src/country_workspace/models/household.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from django.utils import timezone
77

88
from .base import BaseModel, Validable
9+
from .mixins import FlexFieldGroupingMixin
910

1011
if TYPE_CHECKING:
1112
from django.db.models import QuerySet
@@ -24,7 +25,7 @@
2425

2526

2627
@pghistory.track(pghistory.UpdateEvent(condition=pghistory.AnyChange("flex_fields", "flex_files", "removed")))
27-
class Household(Validable, BaseModel):
28+
class Household(FlexFieldGroupingMixin, Validable, BaseModel):
2829
system_fields = models.JSONField(default=dict, blank=True)
2930
members: "QuerySet[Individual]"
3031

src/country_workspace/models/individual.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,14 @@
66

77
from .base import BaseModel, Validable
88
from .household import Household
9+
from .mixins import FlexFieldGroupingMixin
910

1011
if TYPE_CHECKING:
1112
from hope_flex_fields.models import DataChecker
1213

1314

1415
@pghistory.track(pghistory.UpdateEvent(condition=pghistory.AnyChange("flex_fields", "flex_files", "removed")))
15-
class Individual(Validable, BaseModel):
16+
class Individual(FlexFieldGroupingMixin, Validable, BaseModel):
1617
household = models.ForeignKey(Household, on_delete=models.CASCADE, null=True, blank=True, related_name="members")
1718
system_fields = models.JSONField(default=dict, blank=True)
1819

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
from collections import defaultdict
2+
3+
4+
class FlexFieldGroupingMixin:
5+
def get_grouping_info(self) -> dict[str, list[str]]:
6+
grouping_info = defaultdict(list)
7+
for member in self.checker.members.select_related("fieldset").all():
8+
if not member.prefix:
9+
continue
10+
if member.group == "":
11+
continue
12+
if member.group is None:
13+
grouping_key = member.fieldset.group
14+
else:
15+
grouping_key = member.group
16+
17+
if grouping_key:
18+
grouping_info[grouping_key].append(member.prefix)
19+
20+
return grouping_info
21+
22+
def apply_grouping(self) -> dict:
23+
grouping_info = self.get_grouping_info()
24+
grouped_data = {}
25+
flex_fields = dict(self.flex_fields)
26+
for grouping_key, prefixes in grouping_info.items():
27+
grouped_data[grouping_key] = []
28+
for prefix in prefixes:
29+
_data = {}
30+
for field_name in self.flex_fields:
31+
if field_name.startswith(prefix):
32+
_data[field_name.removeprefix(prefix)] = flex_fields.pop(field_name)
33+
grouped_data[grouping_key].append(_data)
34+
grouped_data.update(flex_fields)
35+
36+
return grouped_data

0 commit comments

Comments
 (0)