11from typing import Any , TypedDict , cast
22
3- from constance import config
3+ from constance import config as constance_config
44from django .core .cache import cache
55
66from country_workspace .contrib .kobo .api .client .main import Client
77from country_workspace .contrib .kobo .api .data .asset import Asset
88from country_workspace .contrib .kobo .api .data .submission import Submission
99from country_workspace .contrib .kobo .models import KoboSubmission
10- from country_workspace .models import AsyncJob , Batch , Household , Individual
11- from country_workspace .utils .fields import clean_field_name
10+ from country_workspace .models import AsyncJob , Batch , Household , Individual , Program
11+ from country_workspace .utils .config import FailIfAlienConfig , BatchNameConfig
12+ from country_workspace .utils .fields import create_json_record_preprocessor , RecordPreprocessor
13+
14+
15+ class Config (BatchNameConfig , FailIfAlienConfig ):
16+ project_id : str
17+ individual_records_field : str
1218
1319
1420def make_client (country_code : str | None ) -> Client :
15- token = config .KOBO_MASTER_API_TOKEN or config .KOBO_API_TOKEN
16- project_view_id = config .KOBO_PROJECT_VIEW_ID if config .KOBO_MASTER_API_TOKEN else None
21+ token = constance_config .KOBO_MASTER_API_TOKEN or constance_config .KOBO_API_TOKEN
22+ project_view_id = constance_config .KOBO_PROJECT_VIEW_ID if constance_config .KOBO_MASTER_API_TOKEN else None
1723 return Client (
18- base_url = config .KOBO_KF_URL ,
24+ base_url = constance_config .KOBO_KF_URL ,
1925 token = token ,
2026 country_code = country_code ,
2127 project_view_id = project_view_id ,
@@ -27,30 +33,35 @@ def extract_household_data(submission: Submission, individual_records_field: str
2733
2834
2935def create_individuals (
30- batch : Batch , household : Household , submission : Submission , individual_records_field : str
36+ batch : Batch , household : Household , submission : Submission , config : Config , preprocess_record : RecordPreprocessor
3137) -> int :
3238 individuals = []
33- for raw_individual in submission .get (individual_records_field , []):
34- individual = {key .lstrip (f"{ individual_records_field } /" ): value for key , value in raw_individual .items ()}
39+ for raw_individual in submission .get (config ["individual_records_field" ], []):
40+ individual = {
41+ key .lstrip (f"{ config ['individual_records_field' ]} /" ): value for key , value in raw_individual .items ()
42+ }
3543 fullname = next ((key for key in individual if key .startswith ("full_name" )), None )
3644 individuals .append (
3745 Individual (
3846 batch = batch ,
3947 household = household ,
4048 name = individual .get (fullname , "" ),
41- flex_fields = { clean_field_name ( key ): value for key , value in individual . items ()} ,
49+ flex_fields = preprocess_record ( individual ) ,
4250 ),
4351 )
4452 household .program .individuals .bulk_create (individuals )
4553 return len (individuals )
4654
4755
48- def create_household (batch : Batch , submission : Submission , individual_records_field : str ) -> Household :
49- household_fields = extract_household_data (submission , individual_records_field )
56+ def create_household (
57+ batch : Batch , submission : Submission , config : Config , preprocess_record : RecordPreprocessor
58+ ) -> Household :
59+ household_fields = extract_household_data (submission , config ["individual_records_field" ])
5060 return cast (
5161 Household ,
5262 batch .program .households .create (
53- batch = batch , flex_fields = {clean_field_name (key ): value for key , value in household_fields .items ()}
63+ batch = batch ,
64+ flex_fields = preprocess_record (household_fields ),
5465 ),
5566 )
5667
@@ -63,40 +74,44 @@ class ImportResult(TypedDict):
6374 individuals : int
6475
6576
66- def import_asset (batch : Batch , asset : Asset , individual_records_field : str ) -> ImportResult :
77+ def import_asset (batch : Batch , asset : Asset , config : Config , program : Program ) -> ImportResult :
6778 household_counter = 0
6879 individual_counter = 0
6980
81+ individual_preprocessor = create_json_record_preprocessor (config , program .individual_checker )
82+ household_preprocessor = create_json_record_preprocessor (config , program .household_checker )
83+
7084 with cache .lock (ASSET_CACHE_KEY .format (asset_id = asset .uid )):
7185 submission_ids = set (KoboSubmission .objects .filter (asset_uid = asset .uid ).values_list ("submission_id" , flat = True ))
7286 for submission in asset .submissions :
7387 if submission .id in submission_ids :
7488 continue
75- household = create_household (batch , submission , individual_records_field )
89+ household = create_household (batch , submission , config , household_preprocessor )
7690 household_counter += 1
77- individual_counter += create_individuals (batch , household , submission , individual_records_field )
91+ individual_counter += create_individuals (batch , household , submission , config , individual_preprocessor )
7892
7993 return ImportResult (households = household_counter , individuals = individual_counter )
8094
8195
8296def import_data (job : AsyncJob ) -> ImportResult :
97+ config : Config = job .config
98+
8399 batch = Batch .objects .create (
84- name = job . config ["batch_name" ],
100+ name = config ["batch_name" ],
85101 program = job .program ,
86102 country_office = job .program .country_office ,
87103 imported_by = job .owner ,
88104 source = Batch .BatchSource .KOBO ,
89105 )
90- individual_records_field = job .config ["individual_records_field" ]
91106 client = make_client (job .program .country_office .kobo_country_code )
92107
93108 household_counter = 0
94109 individual_counter = 0
95110
96111 for asset in client .assets :
97112 # TODO: fetch specific asset
98- if job . config ["project_id" ] == asset .uid :
99- import_result = import_asset (batch , asset , individual_records_field )
113+ if config ["project_id" ] == asset .uid :
114+ import_result = import_asset (batch , asset , config , job . program )
100115 household_counter += import_result ["households" ]
101116 individual_counter += import_result ["individuals" ]
102117
0 commit comments