44
55from country_workspace .contrib .aurora .client import AuroraClient
66from country_workspace .models import AsyncJob , Batch , Household , Individual
7- from country_workspace .utils .config import BatchNameConfig , FailIfAlienConfig
8- from country_workspace .utils .fields import uppercase_field_value , clean_field_names
7+ from country_workspace .utils .config import BatchNameConfig
8+ from country_workspace .utils .fields import clean_field_names
99
1010
11- class Config (BatchNameConfig , FailIfAlienConfig ):
11+ class Config (BatchNameConfig ):
1212 registration_reference_pk : str | None
1313 master_detail : bool
1414 household_column_prefix : NotRequired [str ]
@@ -70,12 +70,11 @@ def create_household(batch: Batch, data: dict[str, Any], prefix: str) -> Househo
7070 ValueError: If multiple household entries are found in the provided data.
7171
7272 """
73- flex_fields = _collect_by_prefix (data , prefix )
74- if len (flex_fields ) > 1 :
73+ hh_data = _collect_by_prefix (data , prefix )
74+ if len (hh_data ) > 1 :
7575 raise ValueError ("Multiple households found" )
76- flex_fields = next (iter (flex_fields .values ()), {})
77- return batch .program .households .create (batch = batch , flex_fields = clean_field_names (flex_fields ))
78- # return batch.program.households.create(batch=batch, flex_fields=flex_fields)
76+ flex_fields = clean_field_names (next (iter (hh_data .values ()), {}))
77+ return batch .program .households .create (batch = batch , flex_fields = flex_fields )
7978
8079
8180def create_individuals (
@@ -97,24 +96,21 @@ def create_individuals(
9796 household , individuals = None , []
9897 head_found = False
9998
100- # for raw_individual in data.values():
101- # individual = clean_field_names(raw_individual)
102- # if not head_found:
10399 inds_data = _collect_by_prefix (data , cfg .get ("individuals_column_prefix" ))
104100
105101 if inds_data and cfg ["master_detail" ] and (hh_prefix := cfg .get ("household_column_prefix" )):
106102 household = create_household (batch , data , hh_prefix )
107103
108- for individual in inds_data .values ():
109- household_label_column = cfg . get ( "household_label_column" )
110- if household and household_label_column and not head_found :
111- head_found = _update_household_label_from_individual (household , individual , household_label_column )
104+ for ind_data in inds_data .values ():
105+ flex_fields = clean_field_names ( ind_data )
106+ if household and ( hh_label := cfg . get ( " household_label_column" )) and not head_found :
107+ head_found = _update_household_label_from_individual (household , flex_fields , hh_label )
112108 individuals .append (
113109 Individual (
114110 batch = batch ,
115111 household_id = household .pk if household else None ,
116- name = individual .get ("given_name" , "" ),
117- flex_fields = individual ,
112+ name = flex_fields .get ("given_name" , "" ),
113+ flex_fields = flex_fields ,
118114 )
119115 )
120116 return batch .program .individuals .bulk_create (individuals , batch_size = 1000 )
@@ -133,6 +129,9 @@ def _collect_by_prefix(data: dict[str, Any], prefix: str) -> dict[str, dict[str,
133129 and, for specific fields, values converted to uppercase. Returns an empty dictionary if no
134130 matching keys are found.
135131
132+ Raises:
133+ ValueError: If a key with the specified prefix does not contain an underscore after the prefix.
134+
136135 Examples:
137136 >>> data = {"user_0_relationship": "head", "user_0_gender": "male", "user_1_gender": "female"}
138137 >>> _collect_by_prefix(data, "user_")
@@ -144,25 +143,22 @@ def _collect_by_prefix(data: dict[str, Any], prefix: str) -> dict[str, dict[str,
144143 result = {}
145144 for k , v in data .items ():
146145 if (stripped := k .removeprefix (prefix )) != k :
147- index , field = stripped .split ("_" , 1 )
148- result .setdefault (index , {})[field ] = uppercase_field_value (field , v )
149- # for key, value in data.items():
150- # if not key.startswith(prefix):
151- # continue
152- # index, field = key.removeprefix(prefix).split("_", 1)
153- # clean_field = clean_field_name(field)
154- # result.setdefault(index, {})[clean_field] = uppercase_field_value(clean_field, value)
155- # return result
146+ try :
147+ index , field = stripped .split ("_" , 1 )
148+ result .setdefault (index , {})[field ] = v
149+ except ValueError :
150+ raise ValueError (f"Field name '{ k } ' after removing prefix '{ prefix } ' must contain an underscore." )
151+ return result
156152
157153
158154def _update_household_label_from_individual (
159- household : Household , individual : Mapping [str , Any ], household_label_column : str
155+ household : Household , ind_data : Mapping [str , Any ], household_label_column : str
160156) -> bool :
161157 """Update the household's name based on an individual's role and specified name field.
162158
163159 Args:
164160 household (Household): The household instance to update.
165- individual (dict[str, Any]): A dictionary containing the individual's data,
161+ ind_data (dict[str, Any]): A dictionary containing the individual's data,
166162 including relationship status and potential household name.
167163 household_label_column (str): The key in the individual's data that stores
168164 the name to assign to the household.
@@ -171,8 +167,8 @@ def _update_household_label_from_individual(
171167 bool: True if the household name was updated (individual is head and name provided), False otherwise.
172168
173169 """
174- is_head = any (individual .get (k ) == RELATIONSHIP_HEAD for k in individual if k . startswith ( RELATIONSHIP_FIELDNAME ) )
175- name = individual .get (household_label_column )
170+ is_head = any (ind_data .get (k ) == RELATIONSHIP_HEAD for k in ind_data if k == RELATIONSHIP_FIELDNAME )
171+ name = ind_data .get (household_label_column )
176172 if is_head and name :
177173 household .name = name
178174 household .save (update_fields = ["name" ])
0 commit comments