|
1 | 1 | import logging |
| 2 | +from typing import List, Optional, Tuple |
2 | 3 |
|
3 | 4 | import requests |
4 | 5 | from django.conf import settings |
|
85 | 86 | ("KPI_PStaff_Tot_age_18_29", CO.fdrs_staff_age_18_29), |
86 | 87 | ) |
87 | 88 | FDRS_INDICATORS = ( |
88 | | - [indicator for indicator in FDRS_INDICATORS_FIELD_MAP.keys()] |
| 89 | + list(FDRS_INDICATORS_FIELD_MAP.keys()) |
89 | 90 | + [indicator for indicator, _ in FDRS_VOLUNTEERS_DISAGGREGATION_INDICATORS_FIELD_MAP] |
90 | 91 | + [indicator for indicator, _ in FDRS_STAFF_DISAGGREGATION_INDICATORS_FIELD_MAP] |
91 | 92 | ) |
|
100 | 101 | ) |
101 | 102 |
|
102 | 103 |
|
103 | | -@catch_error("Error occured while fetching from FDRS API.") |
| 104 | +@catch_error("Error occurred while fetching from FDRS API.") |
104 | 105 | def prefetch(): |
105 | | - fdrs_entities = requests.get(FDRS_NS_API_ENDPOINT) |
106 | | - if fdrs_entities.status_code != 200: |
107 | | - return |
108 | | - fdrs_entities.raise_for_status() |
109 | | - fdrs_entities = fdrs_entities.json() |
110 | | - |
111 | | - ns_iso_map = { |
112 | | - # ISO3 are missing for some in FDRS & IFRC-GO only have ISO2 for countries |
113 | | - ns["KPI_DON_code"]: ns["iso_2"] |
114 | | - for ns in fdrs_entities |
115 | | - } |
116 | | - |
117 | | - return ( |
118 | | - { |
119 | | - # KEY <ISO2>-<Indicator_ID>: {year: '', value: ''} |
120 | | - # NOTE: We are fetching the latest data for each indicators |
121 | | - f"{ns_iso_map[ns_data['id']].upper()}-{indicator_data['id']}": ( |
122 | | - max(ns_data["data"], key=lambda x: x["year"]) if (ns_data["data"] and len(ns_data["data"]) > 0) else None |
123 | | - ) |
124 | | - for indicator_data in requests.get(FDRS_DATA_API_ENDPOINT).json()["data"] |
125 | | - for ns_data in indicator_data["data"] |
126 | | - }, |
127 | | - len(ns_iso_map), |
128 | | - FDRS_DATA_API_ENDPOINT, |
| 106 | + response = requests.get(FDRS_NS_API_ENDPOINT) |
| 107 | + response.raise_for_status() |
| 108 | + fdrs_entities = response.json() |
| 109 | + |
| 110 | + ns_iso_map = {ns["KPI_DON_code"]: ns["iso_2"] for ns in fdrs_entities} |
| 111 | + |
| 112 | + fdrs_data_response = requests.get(FDRS_DATA_API_ENDPOINT) |
| 113 | + fdrs_data_response.raise_for_status() |
| 114 | + fdrs_data = fdrs_data_response.json()["data"] |
| 115 | + |
| 116 | + # Getting the latest available data for the indicators |
| 117 | + processed_fdrs_data = {} |
| 118 | + |
| 119 | + for indictor_data in fdrs_data: |
| 120 | + indicator_id = indictor_data["id"] |
| 121 | + |
| 122 | + for ns_data in indictor_data["data"]: |
| 123 | + ns_id = ns_data["id"] |
| 124 | + iso_code = ns_iso_map.get(ns_id) |
| 125 | + |
| 126 | + if not iso_code: |
| 127 | + continue |
| 128 | + |
| 129 | + latest_data_with_value = None |
| 130 | + for data in ns_data["data"]: |
| 131 | + if data.get("value"): |
| 132 | + if latest_data_with_value is None or int(data["year"]) > int(latest_data_with_value["year"]): |
| 133 | + latest_data_with_value = data |
| 134 | + |
| 135 | + if latest_data_with_value: |
| 136 | + processed_fdrs_data[f"{iso_code}-{indicator_id}"] = latest_data_with_value |
| 137 | + |
| 138 | + return (processed_fdrs_data, len(ns_iso_map), FDRS_DATA_API_ENDPOINT) |
| 139 | + |
| 140 | + |
| 141 | +def set_latest_year_data( |
| 142 | + disaggregation_map: List[Tuple[str, CO]], |
| 143 | + data_year_field: CO, |
| 144 | + latest_year: int, |
| 145 | + fdrs_data: dict, |
| 146 | + country_iso: str, |
| 147 | + overview: CO, |
| 148 | +) -> None: |
| 149 | + """ |
| 150 | + Set only the latest year data for volunteers or staff for the provided year |
| 151 | + """ |
| 152 | + for indicator, field in disaggregation_map: |
| 153 | + data = fdrs_data.get(f"{country_iso}-{indicator}") |
| 154 | + if data and int(data.get("year")) == latest_year: |
| 155 | + setattr(overview, field.field.name, data.get("value")) |
| 156 | + |
| 157 | + # Set the year field for the data |
| 158 | + setattr(overview, data_year_field.field.name, latest_year) |
| 159 | + |
| 160 | + |
| 161 | +def get_latest_year_from_indicators(disaggregation_map: List[Tuple[str, CO]], fdrs_data: dict, country_iso: str) -> Optional[int]: |
| 162 | + """ |
| 163 | + Get the latest year across all indicators where the value field exists |
| 164 | + """ |
| 165 | + return max( |
| 166 | + ( |
| 167 | + int(data["year"]) |
| 168 | + for indicator, _ in disaggregation_map |
| 169 | + if (data := fdrs_data.get(f"{country_iso}-{indicator}")) and data.get("value") |
| 170 | + ), |
| 171 | + default=None, |
129 | 172 | ) |
130 | 173 |
|
131 | 174 |
|
132 | | -@catch_error() |
| 175 | +@catch_error("Error occurred while loading FDRS data.") |
133 | 176 | def load(country, overview, fdrs_data): |
134 | | - if country.iso is None or fdrs_data is None: |
| 177 | + if not country.iso or not fdrs_data: |
135 | 178 | return |
136 | 179 |
|
| 180 | + country_iso = country.iso.upper() |
| 181 | + |
| 182 | + # Country Key Indicators |
137 | 183 | for indicator, (field, year_field) in FDRS_INDICATORS_FIELD_MAP.items(): |
138 | | - data = fdrs_data.get(f"{country.iso.upper()}-{indicator}") |
| 184 | + data = fdrs_data.get(f"{country_iso}-{indicator}") |
139 | 185 | if data: |
140 | 186 | setattr(overview, field.field.name, data.get("value")) |
141 | 187 | setattr(overview, year_field.field.name, data.get("year")) |
142 | 188 |
|
143 | | - def set_disaggregation_data(disaggregation_map, data_year_field): |
144 | | - """ |
145 | | - Set disaggregation data for volunteers or staff for the latest year |
146 | | - """ |
147 | | - latest_year = None |
148 | | - for indicator, field in disaggregation_map: |
149 | | - data = fdrs_data.get(f"{country.iso.upper()}-{indicator}") |
150 | | - if data: |
151 | | - year = data.get("year") |
152 | | - if latest_year is None or (year and int(year) > latest_year): |
153 | | - latest_year = int(year) |
154 | | - setattr(overview, field.field.name, data.get("value")) |
155 | | - setattr(overview, data_year_field.field.name, latest_year) |
156 | | - |
157 | | - # Volunteer disaggregation |
158 | | - set_disaggregation_data(FDRS_VOLUNTEERS_DISAGGREGATION_INDICATORS_FIELD_MAP, CO.fdrs_volunteer_data_year) |
159 | | - # Staff disaggregation |
160 | | - set_disaggregation_data(FDRS_STAFF_DISAGGREGATION_INDICATORS_FIELD_MAP, CO.fdrs_staff_data_year) |
| 189 | + # Volunteer disaggregation data |
| 190 | + latest_year = get_latest_year_from_indicators( |
| 191 | + disaggregation_map=FDRS_VOLUNTEERS_DISAGGREGATION_INDICATORS_FIELD_MAP, fdrs_data=fdrs_data, country_iso=country_iso |
| 192 | + ) |
| 193 | + if latest_year: |
| 194 | + set_latest_year_data( |
| 195 | + disaggregation_map=FDRS_VOLUNTEERS_DISAGGREGATION_INDICATORS_FIELD_MAP, |
| 196 | + data_year_field=CO.fdrs_volunteer_data_year, |
| 197 | + latest_year=latest_year, |
| 198 | + fdrs_data=fdrs_data, |
| 199 | + country_iso=country_iso, |
| 200 | + overview=overview, |
| 201 | + ) |
| 202 | + |
| 203 | + # Staff disaggregation data |
| 204 | + latest_year = get_latest_year_from_indicators( |
| 205 | + disaggregation_map=FDRS_STAFF_DISAGGREGATION_INDICATORS_FIELD_MAP, fdrs_data=fdrs_data, country_iso=country_iso |
| 206 | + ) |
| 207 | + if latest_year: |
| 208 | + set_latest_year_data( |
| 209 | + disaggregation_map=FDRS_STAFF_DISAGGREGATION_INDICATORS_FIELD_MAP, |
| 210 | + data_year_field=CO.fdrs_staff_data_year, |
| 211 | + latest_year=latest_year, |
| 212 | + fdrs_data=fdrs_data, |
| 213 | + country_iso=country_iso, |
| 214 | + overview=overview, |
| 215 | + ) |
161 | 216 |
|
162 | 217 | overview.save() |
0 commit comments