diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..23210b7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.venv/ +primero.cache +__pycache__ +*.pyc +primero/ +.egg-info/ +.pytest_cache/ +tmp*/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ef750d6 --- /dev/null +++ b/README.md @@ -0,0 +1,37 @@ +# magasin-primero-paquet - Unlock the Full Potential of Your Primero Data + +This repository contains the code to ingest, store, and analyze data from Primero using [magasin](https://unicef.github.io/magasin/). + +Magasin is a foundational toolset designed to help data analysis teams uncover valuable insights. It enables you to extract, analyze, and visualize data from multiple sources. As the only complete, open-source, cloud-based data and AI toolset, Magasin grows with your organization, empowering you to make better decisions with clear and impactful insights throughout your digital transformation journey. + +**[👉 Learn more about magasin](https://unicef.github.io/magasin/)** + +## Pre-requisites + +- magasin instance +- Primero instance + +## Installation + + + +```shell +# create the minio bucket + +mag minio add bucket --bucket-name primero +``` + + +## Repository Structure + +This repository is organized following the magasin data lifecycle, that is explained in the [magain getting started tutorial overview](https://unicef.github.io/magasin/get-started/tutorial-overview.html): + +- `explorations/`: Contains the code to analyze the data from Primero using Jupyter notebooks, it allows you to get a grasp of what does the dataset contain and play with it using python code.. +- `pipelines/`: Contains the code to ingest data from Primero into magasin using Dagster. Using Primero API it extracts data into a cloud storage (fi. S3 Bucket/MinIO or Azure Blob Storage). +- `dashboards/`: Contains the SuperSet dashboards to visualize the data from Primero. + +Additionally +- `primero_api/`: Contains the code to interact with the Primero API using Python. + +# LICENSE +This repository is licensed under the MIT License. diff --git a/explorations/primero copy.ipynb b/explorations/primero copy.ipynb new file mode 100644 index 0000000..244ce62 --- /dev/null +++ b/explorations/primero copy.ipynb @@ -0,0 +1,7587 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Primero Explorations\n", + "Using Magasin to explore the Primero API and datasets" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd \n", + "import requests\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "PRIMERO_USER='primero'\n", + "PRIMERO_PASSWORD='primer0!'\n", + "PRIMERO_SERVER_URL = 'http://localhost/'\n", + "PRIMERO_SERVER_API_URL='http://localhost/api/v2/'\n", + "\n", + "# \n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Authentication\n", + "\n", + "[https://github.com/primeroIMS/primero/blob/main/doc/api/tokens/post.md\n", + "](https://github.com/primeroIMS/primero/blob/main/doc/api/tokens/post.md\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "request to http://localhost/api/v2/tokens\n", + "{'user': {'user_name': 'primero', 'password': 'primer0!'}}\n", + "Failed to get token\n", + "{\"errors\":[{\"status\":403,\"resource\":\"/api/v2/tokens\",\"message\":\"ActionController::InvalidAuthenticityToken\"}]}\n" + ] + } + ], + "source": [ + "\n", + "def get_token():\n", + "\n", + " session = requests.Session()\n", + " url = PRIMERO_SERVER_URL + 'health'\n", + " url = PRIMERO_SERVER_API_URL + 'tokens'\n", + " \n", + " headers = {\n", + " 'Content-Type': 'application/json',\n", + " }\n", + " data = {\n", + " \"user\": {\n", + " \"user_name\": PRIMERO_USER,\n", + " \"password\": PRIMERO_PASSWORD\n", + " }\n", + " }\n", + " print(f\"request to {url}\")\n", + " print(f'{data}')\n", + " response = requests.post(url, json=data, headers=headers)\n", + " # check if response is successful\n", + " if response.status_code != 200:\n", + " print(\"Failed to get token\")\n", + " print(response.text)\n", + " return None\n", + " # Extract the Authorization Bearer token from the headers of the response\n", + " token = response.headers['Authorization Bearer']\n", + " print(\"Token: \" + token)\n", + "\n", + " return token\n", + "\n", + "get_token()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "http://localhost/api/v2/tokens\n", + "Failed to get token\n", + "{\"errors\":[{\"status\":403,\"resource\":\"/api/v2/tokens\",\"message\":\"ActionController::InvalidAuthenticityToken\"}]}\n", + "403\n", + "{'Date': 'Mon, 21 Oct 2024 12:54:13 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'X-Download-Options': 'noopen', 'X-Permitted-Cross-Domain-Policies': 'none', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'Vary': 'Accept-Encoding', 'Content-Encoding': 'gzip', 'Cache-Control': 'no-cache', 'Content-Security-Policy': \"default-src 'self' https:; font-src 'self' https: data: blob:; img-src 'self' https: data: blob:; media-src 'self' https: data: blob:; object-src 'none'; script-src 'self' https: 'strict-dynamic' 'nonce-n5XjcDUuWSlNiLTyHTENig=='; style-src 'self' https: 'nonce-n5XjcDUuWSlNiLTyHTENig=='; child-src 'self' https: blob:; frame-src 'none'; base-uri 'self'\", 'X-Request-Id': '2d04a04e-a8fa-4b07-972c-4a6a0ff74d1e', 'X-Runtime': '0.078985', 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains', 'NEL': '{\"max_age\":31536000,\"include_subdomains\":true,\"success_fraction\":0,\"failure_fraction\":1,\"report_to\":\"default\"}'}\n" + ] + } + ], + "source": [ + "def get_token_basic_auth():\n", + " url = PRIMERO_SERVER_API_URL + 'tokens'\n", + " print(url)\n", + " # Basic authentication with user and password\n", + " headers = {\n", + " 'Origin': 'http://localhost',\n", + " 'Content-Type': 'application/json',\n", + " 'Authorization': 'Basic ' + PRIMERO_USER + ':' + PRIMERO_PASSWORD\n", + " }\n", + " data = {\n", + " \"user\": {\n", + " \"user_name\": PRIMERO_USER,\n", + " \"password\": PRIMERO_PASSWORD\n", + " }\n", + " }\n", + " response = requests.post(url, json=data, headers=headers)\n", + " \n", + " # check if response is successful\n", + " if response.status_code != 200:\n", + " print(\"Failed to get token\")\n", + " print(response.text)\n", + " print(response.status_code)\n", + " print(response.headers)\n", + " return None\n", + " # Extract the cases from the response\n", + " print(\"Got 200\")\n", + " json = response.json()\n", + " print(json)\n", + " return (json)\n", + "\n", + "get_token_basic_auth()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CSRF Token: F6A4uaWAkohSIB-hOMyAk-5okvajH0Fj_D7cKhWW7oFg2kAxC-6RacuWABTLEhj5mwzZv7u6lIlSdRUS-ntm1Q\n", + "Failed: 403 {\"errors\":[{\"status\":403,\"resource\":\"/api/v2/tokens\",\"message\":\"ActionController::InvalidAuthenticityToken\"}]}\n" + ] + } + ], + "source": [ + "import requests\n", + "from bs4 import BeautifulSoup\n", + "\n", + "# Step 1: Make a GET request to the login page to fetch the CSRF token\n", + "login_url = 'http://localhost/v2/login'\n", + "session = requests.Session()\n", + "response = session.get(login_url)\n", + "\n", + "# Step 2: Parse the CSRF token from the HTML\n", + "soup = BeautifulSoup(response.text, 'html.parser')\n", + "csrf_token = soup.find('meta', {'name': 'csrf-token'})['content']\n", + "\n", + "print('CSRF Token:', csrf_token)\n", + "\n", + "# Step 3: Make a POST request to the API endpoint with the CSRF token\n", + "api_url = 'http://localhost/api/v2/tokens'\n", + "headers = {\n", + " 'Referrer': 'http://localhost/v2/login',\n", + " 'X-CSRF-Token': csrf_token,\n", + " 'Content-Type': 'application/json'\n", + "}\n", + "data = {\n", + " \"user\": {\n", + " \"user_name\": PRIMERO_USER,\n", + " \"password\": PRIMERO_PASSWORD\n", + " }\n", + " }\n", + "response = session.post(api_url, headers=headers, json=data)\n", + "\n", + "# Step 4: Check the response\n", + "if response.status_code == 200:\n", + " print('Success:', response.json())\n", + "else:\n", + " print('Failed:', response.status_code, response.text)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Getting Cases from Primero\n" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "URL: http://localhost/api/v2/cases\n", + "{'data': [{'id': '99c73a6c-cba0-4ce4-ab92-aa9a019ce10b', 'enabled': True, 'age': 1, 'sex': 'female', 'name': 'name 4 middle 4 surname 4', 'status': 'open', 'case_id': 'bcf8e253-eb28-425e-8c5c-9e32a50143d8', 'flagged': False, 'cpims_id': 'cpimsid4', 'owned_by': 'primero', 'short_id': '50143d8', 'workflow': 'care_plan', 'estimated': False, 'has_photo': False, 'module_id': 'primeromodule-cp', 'name_last': 'surname 4', 'created_at': '2024-10-17T11:07:58.125Z', 'created_by': 'primero', 'name_first': 'name 4', 'name_other': 'other name 4', 'occupation': 'Vago', 'name_middle': 'middle 4', 'nationality': ['australia'], 'record_state': True, 'date_of_birth': '2023-01-01', 'has_case_plan': False, 'has_incidents': False, 'name_nickname': 'nickname 4', 'notes_section': [{'note_date': '2024-10-21T08:54:48.746Z', 'note_text': 'note text', 'unique_id': '36715d79-2446-4bb8-bb80-a0d5ecbe1480', 'note_subject': 'note subject', 'note_created_by': 'primero'}], 'reopened_logs': [], 'followup_dates': ['2024-10-25'], 'national_id_no': 'natnum4', 'referred_users': [], 'address_current': 'sadflkjasdf', 'case_id_display': '50143d8', 'last_updated_at': '2024-10-21T08:58:06.636Z', 'last_updated_by': 'primero', 'maritial_status': 'married_cohabitating', 'owned_by_groups': ['usergroup-primero-cp', 'usergroup-primero-ftr', 'usergroup-primero-cp-families'], 'closure_approved': False, 'location_current': 'XX0101', 'services_section': [{'unique_id': 'd51c5928-b3de-4de4-89b3-aa442b2fbaaa', 'service_type': 'safehouse_service', 'service_location': 'service location', 'service_provider': 'service provider', 'service_implemented': 'not_implemented', 'service_response_type': 'care_plan', 'service_referral_notes': 'notes', 'service_appointment_date': '2024-10-16', 'service_delivery_location': 'XX0101', 'service_response_day_time': '2024-10-21T08:57:30.000Z', 'service_response_timeframe': '1_hour'}], 'consent_reporting': 'true', 'interview_subject': 'individual', 'registration_date': '2024-10-17', 'case_plan_approved': False, 'owned_by_agency_id': 'UNICEF', 'assessment_approved': False, 'assessment_due_date': '2024-10-31', 'consent_for_tracing': 'true', 'current_alert_types': [], 'not_edited_by_owner': False, 'protection_concerns': [], 'address_is_permanent': False, 'case_status_reopened': False, 'consent_for_services': True, 'created_organization': 'UNICEF', 'transferred_to_users': [], 'associated_user_names': ['primero'], 'disclosure_other_orgs': True, 'family_details_section': [{'relation': 'mother', 'unique_id': 'bf7a6961-118c-4278-ac22-bacf3e0d988d', 'relation_age': 44, 'relation_sex': 'female', 'relation_name': 'family details name', 'relation_is_alive': 'unknown', 'relation_language': ['language8'], 'relation_nickname': 'nickname family details', 'relation_religion': ['religion9'], 'relation_ethnicity': 'ethnicity9', 'relation_telephone': '0123', 'relation_nationality': ['australia'], 'relation_is_caregiver': True, 'relation_other_family': 'other persons well known to the child', 'relation_date_of_birth': '1980-01-01', 'relation_address_current': 'current address', 'relation_location_current': 'XX'}], 'referred_users_present': False, 'withholding_info_reason': ['fear'], 'followup_subform_section': [{'unique_id': '600c6af2-1d0c-4753-a1d4-ebd830c14d66', 'followup_date': '2024-10-25', 'followup_type': 'after_reunification', 'followup_comments': 'comment of follow up', 'followup_service_type': 'safehouse_service', 'followup_needed_by_date': '2024-10-08', 'followup_assessment_type': 'personal_intervention_assessment'}], 'care_arrangements_section': [{'unique_id': 'a06bf86e-5e5e-4baa-a473-ecb04a2be236', 'caregiver_age': 44, 'caregiver_dob': '2024-10-21', 'name_caregiver': 'name of current caregiver', 'nickname_caregiver': 'other names or spelings caregiver is known by', 'care_arrangements_type': 'parent_s', 'relationship_caregiver': 'father', 'care_arrangement_started_date': '2024-10-15', 'child_caregiver_reason_change': 'abuse_exploitation', 'care_arrangements_include_referral_form': True}], 'transferred_to_user_groups': [], 'service_implemented_day_times': [], 'record_in_scope': True, 'flag_count': 0, 'alert_count': 0, 'registry_record_id': None, 'family_id': None, 'family_member_id': None, 'family_number': None, 'photo': None, 'upload_bid_document': [], 'other_documents': [], 'photos': [], 'recorded_audio': [], 'incident_details': [], 'current_care_arrangements_type': 'parent_s', 'current_name_caregiver': 'name of current caregiver', 'current_care_arrangement_started_date': '2024-10-15'}, {'id': '30acff2d-85af-4cab-8205-7968bafab974', 'enabled': True, 'age': 9, 'sex': 'male', 'name': 'first 3 middle 3 surname 3', 'status': 'open', 'case_id': '323470a1-fbf2-4ab9-8461-02d445995b30', 'flagged': False, 'language': ['language5'], 'owned_by': 'primero', 'religion': ['religion4'], 'short_id': '5995b30', 'workflow': 'new', 'estimated': True, 'ethnicity': ['ethnicity6'], 'has_photo': False, 'module_id': 'primeromodule-cp', 'name_last': 'surname 3', 'created_at': '2024-10-17T02:59:30.067Z', 'created_by': 'primero', 'name_first': 'first 3', 'occupation': 'ocupied', 'risk_level': 'high', 'name_middle': 'middle 3', 'nationality': ['andorra'], 'other_id_no': 'askdlfj', 'record_state': True, 'date_of_birth': '2015-01-01', 'has_case_plan': False, 'has_incidents': False, 'location_last': 'XX', 'name_nickname': 'nickname 3', 'notes_section': [], 'other_id_type': 'aslkdfjasd', 'reopened_logs': [], 'national_id_no': 'asfkljaslkdfjasd', 'referred_users': [], 'case_id_display': '5995b30', 'disability_type': 'mental_disability', 'last_updated_at': '2024-10-17T02:59:43.655Z', 'last_updated_by': 'primero', 'maritial_status': 'married_cohabitating', 'other_agency_id': 'askdlfj', 'owned_by_groups': ['usergroup-primero-cp', 'usergroup-primero-ftr', 'usergroup-primero-cp-families'], 'sub_ethnicity_1': ['ethnicity5'], 'sub_ethnicity_2': ['ethnicity7'], 'closure_approved': False, 'location_current': 'XX01', 'country_of_origin': 'afghanistan', 'other_agency_name': 'asdlkfj', 'registration_date': '2024-10-17', 'unhcr_needs_codes': ['cr-lo'], 'case_plan_approved': False, 'owned_by_agency_id': 'UNICEF', 'assessment_approved': False, 'assessment_due_date': '2024-09-03', 'current_alert_types': [], 'displacement_status': 'refugee', 'not_edited_by_owner': False, 'protection_concerns': ['migrant'], 'address_is_permanent': True, 'case_status_reopened': False, 'consent_for_services': False, 'created_organization': 'UNICEF', 'transferred_to_users': [], 'associated_user_names': ['primero'], 'disclosure_other_orgs': False, 'referred_users_present': False, 'urgent_protection_concern': 'true', 'transferred_to_user_groups': [], 'record_in_scope': True, 'flag_count': 0, 'alert_count': 0, 'registry_record_id': None, 'family_id': None, 'family_member_id': None, 'family_number': None, 'family_details_section': [], 'photo': None, 'upload_bid_document': [], 'other_documents': [], 'photos': [], 'recorded_audio': [], 'incident_details': []}, {'id': 'e517088a-6ec6-40fa-85e3-32533bfa8f6f', 'enabled': True, 'age': 14, 'sex': 'male', 'name': 'first2 middle2 surname2', 'status': 'open', 'case_id': '18a4cdcf-d609-4712-9662-492e0bd0cc14', 'flagged': True, 'cpims_id': 'cpimsid2', 'owned_by': 'primero', 'short_id': 'bd0cc14', 'workflow': 'new', 'estimated': False, 'has_photo': False, 'module_id': 'primeromodule-cp', 'name_last': 'surname2', 'created_at': '2024-10-17T02:53:12.147Z', 'created_by': 'primero', 'name_first': 'first2', 'name_other': 'othername2', 'occupation': 'occupied2', 'name_middle': 'middle2', 'nationality': ['afghanistan'], 'record_state': True, 'date_of_birth': '2010-01-01', 'has_case_plan': True, 'has_incidents': False, 'name_nickname': 'nickname2', 'notes_section': [], 'reopened_logs': [], 'closure_reason': 'formal_closing', 'national_id_no': '122341234', 'referred_users': [], 'address_current': 'address 2', 'case_id_display': 'bd0cc14', 'last_updated_at': '2024-10-17T02:56:52.081Z', 'last_updated_by': 'primero', 'maritial_status': 'single', 'owned_by_groups': ['usergroup-primero-cp', 'usergroup-primero-ftr', 'usergroup-primero-cp-families'], 'closure_approved': False, 'location_current': 'XX', 'consent_reporting': 'true', 'interview_subject': 'individual', 'registration_date': '2024-10-17', 'telephone_current': '123456', 'case_plan_approved': False, 'owned_by_agency_id': 'UNICEF', 'assessment_approved': False, 'assessment_due_date': '0004-10-21', 'consent_for_tracing': 'true', 'current_alert_types': [], 'not_edited_by_owner': False, 'protection_concerns': [], 'address_is_permanent': False, 'case_status_reopened': False, 'closure_reason_other': 'asdfasdfa', 'consent_for_services': True, 'created_organization': 'UNICEF', 'transferred_to_users': [], 'associated_user_names': ['primero'], 'disclosure_other_orgs': True, 'referred_users_present': False, 'disclosure_deny_details': 'asdfasdfasdf', 'withholding_info_reason': ['fear'], 'care_arrangements_section': [{'unique_id': 'f3767312-20a8-42aa-9b22-cd0ab277482a', 'caregiver_dob': '2024-10-24', 'name_caregiver': 'asdfasdfasd', 'nickname_caregiver': 'adsfasdf', 'care_arrangements_type': 'step_parent', 'relationship_caregiver': 'uncle', 'care_arrangements_type_other': 'adfadfg', 'care_arrangement_started_date': '2024-10-24', 'child_caregiver_reason_change': 'abuse_exploitation', 'care_arrangements_include_referral_form': True}], 'transferred_to_user_groups': [], 'cp_case_plan_subform_case_plan_interventions': [{'unique_id': '3f95999a-825e-4786-a8fe-3f5bc50de768', 'case_plan_timeframe': '2024-10-14', 'intervention_service_goal': 'asdlkfjasdf', 'intervention_service_success': 'false', 'intervention_service_to_be_provided': 'aslkjasdfaf', 'case_plan_provider_and_contact_details': 'dsaflkjasdf'}, {'unique_id': 'a6bf8641-a1e6-4b2c-860b-bbffbf96c9e3', 'case_plan_timeframe': '2024-10-25', 'intervention_service_goal': 'goal', 'intervention_service_to_be_provided': 'service', 'case_plan_provider_and_contact_details': 'person'}], 'record_in_scope': True, 'flag_count': 1, 'alert_count': 0, 'registry_record_id': None, 'family_id': None, 'family_member_id': None, 'family_number': None, 'family_details_section': [], 'photo': None, 'upload_bid_document': [], 'other_documents': [], 'photos': [], 'recorded_audio': [], 'incident_details': [], 'current_care_arrangements_type': 'step_parent', 'current_name_caregiver': 'asdfasdfasd', 'current_care_arrangement_started_date': '2024-10-24'}, {'id': '84439496-7273-416b-a87e-cb0763161594', 'enabled': True, 'age': 11, 'sex': 'male', 'name': 'first name middle name surname', 'status': 'open', 'case_id': 'd753bd13-ad83-4d44-874b-67872cfaba47', 'flagged': False, 'owned_by': 'primero', 'short_id': 'cfaba47', 'workflow': 'new', 'estimated': False, 'has_photo': False, 'module_id': 'primeromodule-cp', 'name_last': 'surname', 'created_at': '2024-10-11T09:42:55.963Z', 'created_by': 'primero', 'name_first': 'first name', 'name_other': 'other name', 'occupation': 'ocupation', 'name_middle': 'middle name', 'nationality': ['antigua_and_barbuda'], 'record_state': True, 'date_of_birth': '2013-01-10', 'has_case_plan': False, 'has_incidents': False, 'name_nickname': 'nickname', 'notes_section': [], 'other_id_type': 'OTHERIDDOCUEMENT', 'reopened_logs': [], 'national_id_no': '100200300', 'referred_users': [], 'address_current': 'address', 'case_id_display': 'cfaba47', 'last_updated_at': '2024-10-11T09:42:55.966Z', 'last_updated_by': 'primero', 'maritial_status': 'single', 'other_agency_id': 'Agency ID', 'owned_by_groups': ['usergroup-primero-cp', 'usergroup-primero-ftr', 'usergroup-primero-cp-families'], 'closure_approved': False, 'other_agency_name': 'Other agency name', 'registration_date': '2024-10-11', 'telephone_current': '900100900', 'case_plan_approved': False, 'owned_by_agency_id': 'UNICEF', 'assessment_approved': False, 'current_alert_types': [], 'not_edited_by_owner': False, 'protection_concerns': [], 'address_is_permanent': False, 'case_status_reopened': False, 'consent_for_services': False, 'created_organization': 'UNICEF', 'transferred_to_users': [], 'associated_user_names': ['primero'], 'disclosure_other_orgs': False, 'referred_users_present': False, 'transferred_to_user_groups': [], 'record_in_scope': True, 'flag_count': 0, 'alert_count': 0, 'registry_record_id': None, 'family_id': None, 'family_member_id': None, 'family_number': None, 'family_details_section': [], 'photo': None, 'upload_bid_document': [], 'other_documents': [], 'photos': [], 'recorded_audio': [], 'incident_details': []}], 'metadata': {'total': 4, 'per': 20, 'page': 1}}\n" + ] + }, + { + "data": { + "text/plain": [ + "{'data': [{'id': '99c73a6c-cba0-4ce4-ab92-aa9a019ce10b',\n", + " 'enabled': True,\n", + " 'age': 1,\n", + " 'sex': 'female',\n", + " 'name': 'name 4 middle 4 surname 4',\n", + " 'status': 'open',\n", + " 'case_id': 'bcf8e253-eb28-425e-8c5c-9e32a50143d8',\n", + " 'flagged': False,\n", + " 'cpims_id': 'cpimsid4',\n", + " 'owned_by': 'primero',\n", + " 'short_id': '50143d8',\n", + " 'workflow': 'care_plan',\n", + " 'estimated': False,\n", + " 'has_photo': False,\n", + " 'module_id': 'primeromodule-cp',\n", + " 'name_last': 'surname 4',\n", + " 'created_at': '2024-10-17T11:07:58.125Z',\n", + " 'created_by': 'primero',\n", + " 'name_first': 'name 4',\n", + " 'name_other': 'other name 4',\n", + " 'occupation': 'Vago',\n", + " 'name_middle': 'middle 4',\n", + " 'nationality': ['australia'],\n", + " 'record_state': True,\n", + " 'date_of_birth': '2023-01-01',\n", + " 'has_case_plan': False,\n", + " 'has_incidents': False,\n", + " 'name_nickname': 'nickname 4',\n", + " 'notes_section': [{'note_date': '2024-10-21T08:54:48.746Z',\n", + " 'note_text': 'note text',\n", + " 'unique_id': '36715d79-2446-4bb8-bb80-a0d5ecbe1480',\n", + " 'note_subject': 'note subject',\n", + " 'note_created_by': 'primero'}],\n", + " 'reopened_logs': [],\n", + " 'followup_dates': ['2024-10-25'],\n", + " 'national_id_no': 'natnum4',\n", + " 'referred_users': [],\n", + " 'address_current': 'sadflkjasdf',\n", + " 'case_id_display': '50143d8',\n", + " 'last_updated_at': '2024-10-21T08:58:06.636Z',\n", + " 'last_updated_by': 'primero',\n", + " 'maritial_status': 'married_cohabitating',\n", + " 'owned_by_groups': ['usergroup-primero-cp',\n", + " 'usergroup-primero-ftr',\n", + " 'usergroup-primero-cp-families'],\n", + " 'closure_approved': False,\n", + " 'location_current': 'XX0101',\n", + " 'services_section': [{'unique_id': 'd51c5928-b3de-4de4-89b3-aa442b2fbaaa',\n", + " 'service_type': 'safehouse_service',\n", + " 'service_location': 'service location',\n", + " 'service_provider': 'service provider',\n", + " 'service_implemented': 'not_implemented',\n", + " 'service_response_type': 'care_plan',\n", + " 'service_referral_notes': 'notes',\n", + " 'service_appointment_date': '2024-10-16',\n", + " 'service_delivery_location': 'XX0101',\n", + " 'service_response_day_time': '2024-10-21T08:57:30.000Z',\n", + " 'service_response_timeframe': '1_hour'}],\n", + " 'consent_reporting': 'true',\n", + " 'interview_subject': 'individual',\n", + " 'registration_date': '2024-10-17',\n", + " 'case_plan_approved': False,\n", + " 'owned_by_agency_id': 'UNICEF',\n", + " 'assessment_approved': False,\n", + " 'assessment_due_date': '2024-10-31',\n", + " 'consent_for_tracing': 'true',\n", + " 'current_alert_types': [],\n", + " 'not_edited_by_owner': False,\n", + " 'protection_concerns': [],\n", + " 'address_is_permanent': False,\n", + " 'case_status_reopened': False,\n", + " 'consent_for_services': True,\n", + " 'created_organization': 'UNICEF',\n", + " 'transferred_to_users': [],\n", + " 'associated_user_names': ['primero'],\n", + " 'disclosure_other_orgs': True,\n", + " 'family_details_section': [{'relation': 'mother',\n", + " 'unique_id': 'bf7a6961-118c-4278-ac22-bacf3e0d988d',\n", + " 'relation_age': 44,\n", + " 'relation_sex': 'female',\n", + " 'relation_name': 'family details name',\n", + " 'relation_is_alive': 'unknown',\n", + " 'relation_language': ['language8'],\n", + " 'relation_nickname': 'nickname family details',\n", + " 'relation_religion': ['religion9'],\n", + " 'relation_ethnicity': 'ethnicity9',\n", + " 'relation_telephone': '0123',\n", + " 'relation_nationality': ['australia'],\n", + " 'relation_is_caregiver': True,\n", + " 'relation_other_family': 'other persons well known to the child',\n", + " 'relation_date_of_birth': '1980-01-01',\n", + " 'relation_address_current': 'current address',\n", + " 'relation_location_current': 'XX'}],\n", + " 'referred_users_present': False,\n", + " 'withholding_info_reason': ['fear'],\n", + " 'followup_subform_section': [{'unique_id': '600c6af2-1d0c-4753-a1d4-ebd830c14d66',\n", + " 'followup_date': '2024-10-25',\n", + " 'followup_type': 'after_reunification',\n", + " 'followup_comments': 'comment of follow up',\n", + " 'followup_service_type': 'safehouse_service',\n", + " 'followup_needed_by_date': '2024-10-08',\n", + " 'followup_assessment_type': 'personal_intervention_assessment'}],\n", + " 'care_arrangements_section': [{'unique_id': 'a06bf86e-5e5e-4baa-a473-ecb04a2be236',\n", + " 'caregiver_age': 44,\n", + " 'caregiver_dob': '2024-10-21',\n", + " 'name_caregiver': 'name of current caregiver',\n", + " 'nickname_caregiver': 'other names or spelings caregiver is known by',\n", + " 'care_arrangements_type': 'parent_s',\n", + " 'relationship_caregiver': 'father',\n", + " 'care_arrangement_started_date': '2024-10-15',\n", + " 'child_caregiver_reason_change': 'abuse_exploitation',\n", + " 'care_arrangements_include_referral_form': True}],\n", + " 'transferred_to_user_groups': [],\n", + " 'service_implemented_day_times': [],\n", + " 'record_in_scope': True,\n", + " 'flag_count': 0,\n", + " 'alert_count': 0,\n", + " 'registry_record_id': None,\n", + " 'family_id': None,\n", + " 'family_member_id': None,\n", + " 'family_number': None,\n", + " 'photo': None,\n", + " 'upload_bid_document': [],\n", + " 'other_documents': [],\n", + " 'photos': [],\n", + " 'recorded_audio': [],\n", + " 'incident_details': [],\n", + " 'current_care_arrangements_type': 'parent_s',\n", + " 'current_name_caregiver': 'name of current caregiver',\n", + " 'current_care_arrangement_started_date': '2024-10-15'},\n", + " {'id': '30acff2d-85af-4cab-8205-7968bafab974',\n", + " 'enabled': True,\n", + " 'age': 9,\n", + " 'sex': 'male',\n", + " 'name': 'first 3 middle 3 surname 3',\n", + " 'status': 'open',\n", + " 'case_id': '323470a1-fbf2-4ab9-8461-02d445995b30',\n", + " 'flagged': False,\n", + " 'language': ['language5'],\n", + " 'owned_by': 'primero',\n", + " 'religion': ['religion4'],\n", + " 'short_id': '5995b30',\n", + " 'workflow': 'new',\n", + " 'estimated': True,\n", + " 'ethnicity': ['ethnicity6'],\n", + " 'has_photo': False,\n", + " 'module_id': 'primeromodule-cp',\n", + " 'name_last': 'surname 3',\n", + " 'created_at': '2024-10-17T02:59:30.067Z',\n", + " 'created_by': 'primero',\n", + " 'name_first': 'first 3',\n", + " 'occupation': 'ocupied',\n", + " 'risk_level': 'high',\n", + " 'name_middle': 'middle 3',\n", + " 'nationality': ['andorra'],\n", + " 'other_id_no': 'askdlfj',\n", + " 'record_state': True,\n", + " 'date_of_birth': '2015-01-01',\n", + " 'has_case_plan': False,\n", + " 'has_incidents': False,\n", + " 'location_last': 'XX',\n", + " 'name_nickname': 'nickname 3',\n", + " 'notes_section': [],\n", + " 'other_id_type': 'aslkdfjasd',\n", + " 'reopened_logs': [],\n", + " 'national_id_no': 'asfkljaslkdfjasd',\n", + " 'referred_users': [],\n", + " 'case_id_display': '5995b30',\n", + " 'disability_type': 'mental_disability',\n", + " 'last_updated_at': '2024-10-17T02:59:43.655Z',\n", + " 'last_updated_by': 'primero',\n", + " 'maritial_status': 'married_cohabitating',\n", + " 'other_agency_id': 'askdlfj',\n", + " 'owned_by_groups': ['usergroup-primero-cp',\n", + " 'usergroup-primero-ftr',\n", + " 'usergroup-primero-cp-families'],\n", + " 'sub_ethnicity_1': ['ethnicity5'],\n", + " 'sub_ethnicity_2': ['ethnicity7'],\n", + " 'closure_approved': False,\n", + " 'location_current': 'XX01',\n", + " 'country_of_origin': 'afghanistan',\n", + " 'other_agency_name': 'asdlkfj',\n", + " 'registration_date': '2024-10-17',\n", + " 'unhcr_needs_codes': ['cr-lo'],\n", + " 'case_plan_approved': False,\n", + " 'owned_by_agency_id': 'UNICEF',\n", + " 'assessment_approved': False,\n", + " 'assessment_due_date': '2024-09-03',\n", + " 'current_alert_types': [],\n", + " 'displacement_status': 'refugee',\n", + " 'not_edited_by_owner': False,\n", + " 'protection_concerns': ['migrant'],\n", + " 'address_is_permanent': True,\n", + " 'case_status_reopened': False,\n", + " 'consent_for_services': False,\n", + " 'created_organization': 'UNICEF',\n", + " 'transferred_to_users': [],\n", + " 'associated_user_names': ['primero'],\n", + " 'disclosure_other_orgs': False,\n", + " 'referred_users_present': False,\n", + " 'urgent_protection_concern': 'true',\n", + " 'transferred_to_user_groups': [],\n", + " 'record_in_scope': True,\n", + " 'flag_count': 0,\n", + " 'alert_count': 0,\n", + " 'registry_record_id': None,\n", + " 'family_id': None,\n", + " 'family_member_id': None,\n", + " 'family_number': None,\n", + " 'family_details_section': [],\n", + " 'photo': None,\n", + " 'upload_bid_document': [],\n", + " 'other_documents': [],\n", + " 'photos': [],\n", + " 'recorded_audio': [],\n", + " 'incident_details': []},\n", + " {'id': 'e517088a-6ec6-40fa-85e3-32533bfa8f6f',\n", + " 'enabled': True,\n", + " 'age': 14,\n", + " 'sex': 'male',\n", + " 'name': 'first2 middle2 surname2',\n", + " 'status': 'open',\n", + " 'case_id': '18a4cdcf-d609-4712-9662-492e0bd0cc14',\n", + " 'flagged': True,\n", + " 'cpims_id': 'cpimsid2',\n", + " 'owned_by': 'primero',\n", + " 'short_id': 'bd0cc14',\n", + " 'workflow': 'new',\n", + " 'estimated': False,\n", + " 'has_photo': False,\n", + " 'module_id': 'primeromodule-cp',\n", + " 'name_last': 'surname2',\n", + " 'created_at': '2024-10-17T02:53:12.147Z',\n", + " 'created_by': 'primero',\n", + " 'name_first': 'first2',\n", + " 'name_other': 'othername2',\n", + " 'occupation': 'occupied2',\n", + " 'name_middle': 'middle2',\n", + " 'nationality': ['afghanistan'],\n", + " 'record_state': True,\n", + " 'date_of_birth': '2010-01-01',\n", + " 'has_case_plan': True,\n", + " 'has_incidents': False,\n", + " 'name_nickname': 'nickname2',\n", + " 'notes_section': [],\n", + " 'reopened_logs': [],\n", + " 'closure_reason': 'formal_closing',\n", + " 'national_id_no': '122341234',\n", + " 'referred_users': [],\n", + " 'address_current': 'address 2',\n", + " 'case_id_display': 'bd0cc14',\n", + " 'last_updated_at': '2024-10-17T02:56:52.081Z',\n", + " 'last_updated_by': 'primero',\n", + " 'maritial_status': 'single',\n", + " 'owned_by_groups': ['usergroup-primero-cp',\n", + " 'usergroup-primero-ftr',\n", + " 'usergroup-primero-cp-families'],\n", + " 'closure_approved': False,\n", + " 'location_current': 'XX',\n", + " 'consent_reporting': 'true',\n", + " 'interview_subject': 'individual',\n", + " 'registration_date': '2024-10-17',\n", + " 'telephone_current': '123456',\n", + " 'case_plan_approved': False,\n", + " 'owned_by_agency_id': 'UNICEF',\n", + " 'assessment_approved': False,\n", + " 'assessment_due_date': '0004-10-21',\n", + " 'consent_for_tracing': 'true',\n", + " 'current_alert_types': [],\n", + " 'not_edited_by_owner': False,\n", + " 'protection_concerns': [],\n", + " 'address_is_permanent': False,\n", + " 'case_status_reopened': False,\n", + " 'closure_reason_other': 'asdfasdfa',\n", + " 'consent_for_services': True,\n", + " 'created_organization': 'UNICEF',\n", + " 'transferred_to_users': [],\n", + " 'associated_user_names': ['primero'],\n", + " 'disclosure_other_orgs': True,\n", + " 'referred_users_present': False,\n", + " 'disclosure_deny_details': 'asdfasdfasdf',\n", + " 'withholding_info_reason': ['fear'],\n", + " 'care_arrangements_section': [{'unique_id': 'f3767312-20a8-42aa-9b22-cd0ab277482a',\n", + " 'caregiver_dob': '2024-10-24',\n", + " 'name_caregiver': 'asdfasdfasd',\n", + " 'nickname_caregiver': 'adsfasdf',\n", + " 'care_arrangements_type': 'step_parent',\n", + " 'relationship_caregiver': 'uncle',\n", + " 'care_arrangements_type_other': 'adfadfg',\n", + " 'care_arrangement_started_date': '2024-10-24',\n", + " 'child_caregiver_reason_change': 'abuse_exploitation',\n", + " 'care_arrangements_include_referral_form': True}],\n", + " 'transferred_to_user_groups': [],\n", + " 'cp_case_plan_subform_case_plan_interventions': [{'unique_id': '3f95999a-825e-4786-a8fe-3f5bc50de768',\n", + " 'case_plan_timeframe': '2024-10-14',\n", + " 'intervention_service_goal': 'asdlkfjasdf',\n", + " 'intervention_service_success': 'false',\n", + " 'intervention_service_to_be_provided': 'aslkjasdfaf',\n", + " 'case_plan_provider_and_contact_details': 'dsaflkjasdf'},\n", + " {'unique_id': 'a6bf8641-a1e6-4b2c-860b-bbffbf96c9e3',\n", + " 'case_plan_timeframe': '2024-10-25',\n", + " 'intervention_service_goal': 'goal',\n", + " 'intervention_service_to_be_provided': 'service',\n", + " 'case_plan_provider_and_contact_details': 'person'}],\n", + " 'record_in_scope': True,\n", + " 'flag_count': 1,\n", + " 'alert_count': 0,\n", + " 'registry_record_id': None,\n", + " 'family_id': None,\n", + " 'family_member_id': None,\n", + " 'family_number': None,\n", + " 'family_details_section': [],\n", + " 'photo': None,\n", + " 'upload_bid_document': [],\n", + " 'other_documents': [],\n", + " 'photos': [],\n", + " 'recorded_audio': [],\n", + " 'incident_details': [],\n", + " 'current_care_arrangements_type': 'step_parent',\n", + " 'current_name_caregiver': 'asdfasdfasd',\n", + " 'current_care_arrangement_started_date': '2024-10-24'},\n", + " {'id': '84439496-7273-416b-a87e-cb0763161594',\n", + " 'enabled': True,\n", + " 'age': 11,\n", + " 'sex': 'male',\n", + " 'name': 'first name middle name surname',\n", + " 'status': 'open',\n", + " 'case_id': 'd753bd13-ad83-4d44-874b-67872cfaba47',\n", + " 'flagged': False,\n", + " 'owned_by': 'primero',\n", + " 'short_id': 'cfaba47',\n", + " 'workflow': 'new',\n", + " 'estimated': False,\n", + " 'has_photo': False,\n", + " 'module_id': 'primeromodule-cp',\n", + " 'name_last': 'surname',\n", + " 'created_at': '2024-10-11T09:42:55.963Z',\n", + " 'created_by': 'primero',\n", + " 'name_first': 'first name',\n", + " 'name_other': 'other name',\n", + " 'occupation': 'ocupation',\n", + " 'name_middle': 'middle name',\n", + " 'nationality': ['antigua_and_barbuda'],\n", + " 'record_state': True,\n", + " 'date_of_birth': '2013-01-10',\n", + " 'has_case_plan': False,\n", + " 'has_incidents': False,\n", + " 'name_nickname': 'nickname',\n", + " 'notes_section': [],\n", + " 'other_id_type': 'OTHERIDDOCUEMENT',\n", + " 'reopened_logs': [],\n", + " 'national_id_no': '100200300',\n", + " 'referred_users': [],\n", + " 'address_current': 'address',\n", + " 'case_id_display': 'cfaba47',\n", + " 'last_updated_at': '2024-10-11T09:42:55.966Z',\n", + " 'last_updated_by': 'primero',\n", + " 'maritial_status': 'single',\n", + " 'other_agency_id': 'Agency ID',\n", + " 'owned_by_groups': ['usergroup-primero-cp',\n", + " 'usergroup-primero-ftr',\n", + " 'usergroup-primero-cp-families'],\n", + " 'closure_approved': False,\n", + " 'other_agency_name': 'Other agency name',\n", + " 'registration_date': '2024-10-11',\n", + " 'telephone_current': '900100900',\n", + " 'case_plan_approved': False,\n", + " 'owned_by_agency_id': 'UNICEF',\n", + " 'assessment_approved': False,\n", + " 'current_alert_types': [],\n", + " 'not_edited_by_owner': False,\n", + " 'protection_concerns': [],\n", + " 'address_is_permanent': False,\n", + " 'case_status_reopened': False,\n", + " 'consent_for_services': False,\n", + " 'created_organization': 'UNICEF',\n", + " 'transferred_to_users': [],\n", + " 'associated_user_names': ['primero'],\n", + " 'disclosure_other_orgs': False,\n", + " 'referred_users_present': False,\n", + " 'transferred_to_user_groups': [],\n", + " 'record_in_scope': True,\n", + " 'flag_count': 0,\n", + " 'alert_count': 0,\n", + " 'registry_record_id': None,\n", + " 'family_id': None,\n", + " 'family_member_id': None,\n", + " 'family_number': None,\n", + " 'family_details_section': [],\n", + " 'photo': None,\n", + " 'upload_bid_document': [],\n", + " 'other_documents': [],\n", + " 'photos': [],\n", + " 'recorded_audio': [],\n", + " 'incident_details': []}],\n", + " 'metadata': {'total': 4, 'per': 20, 'page': 1}}" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import requests\n", + "# Using basic authentication to get /api/v2/cases endpoint\n", + "from requests.auth import HTTPBasicAuth\n", + "\n", + "\n", + "def get_cases_basic_auth():\n", + " url = PRIMERO_SERVER_API_URL + 'cases'\n", + " # Basic authentication with user and password\n", + " \n", + " print(\"URL: \" + url)\n", + " response = requests.get(url, headers=headers, auth=HTTPBasicAuth(PRIMERO_USER, PRIMERO_PASSWORD))\n", + " # check if response is successful\n", + " if response.status_code != 200:\n", + " print(\"Failed to get cases\")\n", + " print(response.status_code)\n", + " print(response.headers)\n", + " print (response.text)\n", + " return None\n", + " # Extract the cases from the response\n", + " cases = response.json()\n", + " print(cases)\n", + " return cases\n", + "\n", + "get_cases_basic_auth()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Primero API Resource" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: requests-cache in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (1.2.1)\n", + "Requirement already satisfied: requests-ratelimiter in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (0.7.0)\n", + "Requirement already satisfied: attrs>=21.2 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests-cache) (23.2.0)\n", + "Requirement already satisfied: cattrs>=22.2 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests-cache) (24.1.2)\n", + "Requirement already satisfied: platformdirs>=2.5 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests-cache) (4.2.0)\n", + "Requirement already satisfied: requests>=2.22 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests-cache) (2.31.0)\n", + "Requirement already satisfied: url-normalize>=1.4 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests-cache) (1.4.3)\n", + "Requirement already satisfied: urllib3>=1.25.5 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests-cache) (2.2.1)\n", + "Requirement already satisfied: pyrate-limiter<3.0 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests-ratelimiter) (2.10.0)\n", + "Requirement already satisfied: charset-normalizer<4,>=2 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests>=2.22->requests-cache) (3.3.2)\n", + "Requirement already satisfied: idna<4,>=2.5 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests>=2.22->requests-cache) (3.6)\n", + "Requirement already satisfied: certifi>=2017.4.17 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from requests>=2.22->requests-cache) (2024.2.2)\n", + "Requirement already satisfied: six in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from url-normalize>=1.4->requests-cache) (1.16.0)\n" + ] + } + ], + "source": [ + "!pip install requests-cache requests-ratelimiter" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import requests\n", + "from requests.auth import HTTPBasicAuth\n", + "\n", + "# Limit the requests to prevent hitting the rate limit\n", + "from requests_cache import CacheMixin, SQLiteCache\n", + "from requests_ratelimiter import LimiterMixin, MemoryQueueBucket\n", + "from pyrate_limiter import Duration, RequestRate, Limiter\n", + "\n", + "class CachedLimiterSession(CacheMixin, LimiterMixin, requests.Session):\n", + " pass\n", + "\n", + "\n", + "class PrimeroAPI:\n", + "\n", + "\n", + " def __init__(self, user, password, api_url, page_size=1000, rate=2, duration=1, cache_expire=3600): \n", + " '''\n", + " Constructor\n", + " user: the user name\n", + " password: the password\n", + " api_url: the url of the api\n", + " page_size: the size of the page to use for pagination\n", + " rate: the rate of requests per duration (default 2 requests per 1 seconds)\n", + " duration: the duration in seconds of the rate limit (default 1 seconds)\n", + " cache_expire: the duration in seconds to expire the cache (default 3600 seconds)\n", + "\n", + " Note: In a pod the cache is removed when the pod is killed or restarted\n", + " '''\n", + " self.user = user\n", + " self.password = password\n", + " self.api_url = api_url\n", + " self.token = None\n", + " self.headers = {\n", + " 'Content-Type': 'application/json',\n", + " }\n", + " # Set a controlled rate limit to prevent hitting the rate limit\n", + " self.session = CachedLimiterSession(\n", + " limiter=Limiter(RequestRate(rate, Duration.SECOND*duration)), \n", + " bucket_class=MemoryQueueBucket,\n", + " backend=SQLiteCache(\"primero.cache\", expire_after=3600)\n", + " )\n", + " self.page_size = page_size\n", + "\n", + " def is_last_page(self, metadata):\n", + " '''\n", + " for a multi-page response, check if the current page is the last page\n", + " metadata is the metadata object from the response which contains the \n", + " page, total and per parameters.\n", + " '''\n", + "\n", + " page = metadata['page'] # current page\n", + " total = metadata['total'] # total number of items\n", + " per = metadata['per'] # number of items per page\n", + " return (page * per) >= total\n", + "\n", + " def call_paginated_api(self, url: str):\n", + " '''\n", + " Calls the api with the given url and page_size.\n", + " \n", + " URL should not have per and page parameters\n", + " Returns a list of data\n", + "\n", + " '''\n", + " page_size = self.page_size \n", + " page = 1\n", + " data = []\n", + " while True:\n", + " #Check if ? is present, add it if not \n", + " if '?' not in url:\n", + " url += '?' \n", + " # Add &per=page_size&page=page to the url.\n", + " url += f'&per={page_size}&page={page}'\n", + " print ('call_paginated_api: ' + url)\n", + " response = self.session.get(url, headers=self.headers, auth=HTTPBasicAuth(self.user, self.password)) \n", + "\n", + " # check if response is successful\n", + " if response.status_code != 200:\n", + " print(\"Failed to get paginated data\")\n", + " print(response.status_code)\n", + " print(response.headers)\n", + " print (response.text)\n", + "\n", + " continue \n", + " # The response is a JSON object that contains the data and metadata objects.\n", + " # data is an array of objects that contain the actual data\n", + " # metadata contains information about the pagination\n", + "\n", + " # Extract the data from the response\n", + " json_data = response.json()\n", + " # extend the existing list to include new data\n", + " data.extend(json_data['data'])\n", + " print(json_data)\n", + " # check if we are at the last page \n", + " if self.is_last_page(json_data['metadata']):\n", + " break \n", + " \n", + " page += 1\n", + " return data\n", + " \n", + " def get_cases(self):\n", + " url = self.api_url + 'cases'\n", + " return self.call_paginated_api(url)\n", + "\n", + " def get_incidents(self):\n", + " url = self.api_url + 'incidents'\n", + " return self.call_paginated_api(url)\n", + "\n", + " def get_report(self, id: int):\n", + " '''\n", + " Gets the report with the given id\n", + " returns a dictionary with the content of the report or None if there is an error.\n", + "\n", + " '''\n", + " url = self.api_url + 'reports/' + str(id)\n", + " print(url)\n", + " response = self.session.get(url, headers=self.headers, auth=HTTPBasicAuth(self.user, self.password)) \n", + " # check if response is successful\n", + " if response.status_code != 200:\n", + " print(\"Failed to get report\")\n", + " print(response.status_code)\n", + " print(response.headers)\n", + " print (response.text)\n", + " return None\n", + " return response.json()['data']\n", + " \n", + " \n", + " def get_report_list(self):\n", + " '''\n", + " Gets the list of reports for the given page and page_size. \n", + " Returns a dictionary with the id as key and the report as value\n", + " The content of the report is a dictionary\n", + " '''\n", + " url = self.api_url + 'reports'\n", + " return self.call_paginated_api(url)\n", + "\n", + " def get_reports(self):\n", + " '''\n", + " Gets the list of reports for the given page and page_size. \n", + " Returns a dictionary with the id as key and the report as value\n", + " The content of the report is a dictionary\n", + " '''\n", + " reports = []\n", + " report_list = self.get_report_list()\n", + " for report in report_list:\n", + " id = report['id']\n", + " report = self.get_report(id)\n", + " # report is None if there is an error\n", + " if report:\n", + " reports.append(report['data'])\n", + " return reports\n", + "\n", + " def get_lookups():\n", + " '''lookups are mapping between ids and human labels for the data'''\n", + " url = self.api_url + 'lookups'\n", + " return self.call_paginated_api(url)\n", + " \n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'PrimeroAPIResource' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[11], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m api \u001b[38;5;241m=\u001b[39m \u001b[43mPrimeroAPIResource\u001b[49m(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_SERVER_API_URL)\n\u001b[1;32m 2\u001b[0m api\u001b[38;5;241m.\u001b[39mget_cases()\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(api\u001b[38;5;241m.\u001b[39mget_report(\u001b[38;5;241m1\u001b[39m))\n", + "\u001b[0;31mNameError\u001b[0m: name 'PrimeroAPIResource' is not defined" + ] + } + ], + "source": [ + "api = PrimeroAPIResource(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_SERVER_API_URL)\n", + "api.get_cases()\n", + "print(api.get_report(1))\n", + "print(api.get_report_list())\n", + "print(api.get_reports())\n", + "print(api.get_incidents())\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!pip install python-slugify" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "call_paginated_api: http://localhost/api/v2/reports?&per=1000&page=1\n", + "{'data': [{'id': 1, 'name': {'en': 'Registration CP', 'fr': 'Registration CP', 'ar': 'Registration CP'}, 'description': {'en': 'Case registrations over time', 'fr': 'Case registrations over time', 'ar': 'Case registrations over time'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'month', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'registration_date', 'display_name': {'en': 'Date of Registration or Interview', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}]}, {'id': 2, 'name': {'en': 'Caseload Summary CP', 'fr': 'Caseload Summary CP', 'ar': 'Caseload Summary CP'}, 'description': {'en': 'Number of cases for each case worker', 'fr': 'Number of cases for each case worker', 'ar': 'Number of cases for each case worker'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'owned_by', 'display_name': {'en': 'Caseworker Code', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}]}, {'id': 3, 'name': {'en': 'Case status by case worker CP', 'fr': 'Case status by case worker CP', 'ar': 'Case status by case worker CP'}, 'description': {'en': 'Status of cases held by case workers', 'fr': 'Status of cases held by case workers', 'ar': 'Status of cases held by case workers'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'owned_by', 'display_name': {'en': 'Caseworker Code', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}, {'name': 'status', 'display_name': {'en': 'Case Status', 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}, 'option_labels': {'en': [{'id': 'open', 'display_text': 'Open'}, {'id': 'closed', 'display_text': 'Closed'}, {'id': 'transferred', 'display_text': 'Transferred'}, {'id': 'duplicate', 'display_text': 'Duplicate'}], 'fr': [], 'ar': []}}]}, {'id': 4, 'name': {'en': 'Cases by Agency CP', 'fr': 'Cases by Agency CP', 'ar': 'Cases by Agency CP'}, 'description': {'en': 'Number of cases broken down by agency', 'fr': 'Number of cases broken down by agency', 'ar': 'Number of cases broken down by agency'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'owned_by_agency_id', 'display_name': {'en': \"Record Owner's Agency\", 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}, 'option_strings_source': 'Agency'}]}, {'id': 5, 'name': {'en': 'Cases by Nationality', 'fr': 'Cases by Nationality', 'ar': 'Cases by Nationality'}, 'description': {'en': 'Number of cases broken down by nationality', 'fr': 'Number of cases broken down by nationality', 'ar': 'Number of cases broken down by nationality'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'nationality', 'display_name': {'en': 'Nationality', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}, 'option_labels': {'en': [{'id': 'afghanistan', 'display_text': 'Afghanistan'}, {'id': 'albania', 'display_text': 'Albania'}, {'id': 'algeria', 'display_text': 'Algeria'}, {'id': 'andorra', 'display_text': 'Andorra'}, {'id': 'angola', 'display_text': 'Angola'}, {'id': 'antigua_and_barbuda', 'display_text': 'Antigua and Barbuda'}, {'id': 'argentina', 'display_text': 'Argentina'}, {'id': 'armenia', 'display_text': 'Armenia'}, {'id': 'australia', 'display_text': 'Australia'}, {'id': 'austria', 'display_text': 'Austria'}, {'id': 'azerbaijan', 'display_text': 'Azerbaijan'}, {'id': 'bahamas', 'display_text': 'Bahamas'}, {'id': 'bahrain', 'display_text': 'Bahrain'}, {'id': 'bangladesh', 'display_text': 'Bangladesh'}, {'id': 'barbados', 'display_text': 'Barbados'}, {'id': 'belarus', 'display_text': 'Belarus'}, {'id': 'belgium', 'display_text': 'Belgium'}, {'id': 'belize', 'display_text': 'Belize'}, {'id': 'benin', 'display_text': 'Benin'}, {'id': 'bhutan', 'display_text': 'Bhutan'}, {'id': 'bolivia', 'display_text': 'Bolivia'}, {'id': 'bosnia_and_herzegovina', 'display_text': 'Bosnia and Herzegovina'}, {'id': 'botswana', 'display_text': 'Botswana'}, {'id': 'brazil', 'display_text': 'Brazil'}, {'id': 'brunei', 'display_text': 'Brunei'}, {'id': 'bulgaria', 'display_text': 'Bulgaria'}, {'id': 'burkina_faso', 'display_text': 'Burkina Faso'}, {'id': 'burundi', 'display_text': 'Burundi'}, {'id': 'cabo_verde', 'display_text': 'Cabo Verde'}, {'id': 'cambodia', 'display_text': 'Cambodia'}, {'id': 'cameroon', 'display_text': 'Cameroon'}, {'id': 'canada', 'display_text': 'Canada'}, {'id': 'central_african_republic', 'display_text': 'Central African Republic'}, {'id': 'chad', 'display_text': 'Chad'}, {'id': 'chile', 'display_text': 'Chile'}, {'id': 'china', 'display_text': 'China'}, {'id': 'colombia', 'display_text': 'Colombia'}, {'id': 'comoros', 'display_text': 'Comoros'}, {'id': 'congo', 'display_text': 'Congo, Republic of the'}, {'id': 'drc', 'display_text': 'Congo, Democratic Republic of the'}, {'id': 'costa_rica', 'display_text': 'Costa Rica'}, {'id': 'cote_divoire', 'display_text': \"Cote d'Ivoire\"}, {'id': 'croatia', 'display_text': 'Croatia'}, {'id': 'cuba', 'display_text': 'Cuba'}, {'id': 'cyprus', 'display_text': 'Cyprus'}, {'id': 'czech_republic', 'display_text': 'Czech Republic'}, {'id': 'denmark', 'display_text': 'Denmark'}, {'id': 'djibouti', 'display_text': 'Djibouti'}, {'id': 'dominica', 'display_text': 'Dominica'}, {'id': 'dominican_republic', 'display_text': 'Dominican Republic'}, {'id': 'ecuador', 'display_text': 'Ecuador'}, {'id': 'egypt', 'display_text': 'Egypt'}, {'id': 'el_salvador', 'display_text': 'El Salvador'}, {'id': 'equatorial_guinea', 'display_text': 'Equatorial Guinea'}, {'id': 'eritrea', 'display_text': 'Eritrea'}, {'id': 'estonia', 'display_text': 'Estonia'}, {'id': 'ethiopia', 'display_text': 'Ethiopia'}, {'id': 'fiji', 'display_text': 'Fiji'}, {'id': 'finland', 'display_text': 'Finland'}, {'id': 'france', 'display_text': 'France'}, {'id': 'gabon', 'display_text': 'Gabon'}, {'id': 'gambia', 'display_text': 'Gambia'}, {'id': 'georgia', 'display_text': 'Georgia'}, {'id': 'germany', 'display_text': 'Germany'}, {'id': 'ghana', 'display_text': 'Ghana'}, {'id': 'greece', 'display_text': 'Greece'}, {'id': 'grenada', 'display_text': 'Grenada'}, {'id': 'guatemala', 'display_text': 'Guatemala'}, {'id': 'guinea', 'display_text': 'Guinea'}, {'id': 'guinea_bissau', 'display_text': 'Guinea-Bissau'}, {'id': 'guyana', 'display_text': 'Guyana'}, {'id': 'haiti', 'display_text': 'Haiti'}, {'id': 'honduras', 'display_text': 'Honduras'}, {'id': 'hungary', 'display_text': 'Hungary'}, {'id': 'iceland', 'display_text': 'Iceland'}, {'id': 'india', 'display_text': 'India'}, {'id': 'indonesia', 'display_text': 'Indonesia'}, {'id': 'iran', 'display_text': 'Iran'}, {'id': 'iraq', 'display_text': 'Iraq'}, {'id': 'ireland', 'display_text': 'Ireland'}, {'id': 'israel', 'display_text': 'Israel'}, {'id': 'italy', 'display_text': 'Italy'}, {'id': 'jamaica', 'display_text': 'Jamaica'}, {'id': 'japan', 'display_text': 'Japan'}, {'id': 'jordan', 'display_text': 'Jordan'}, {'id': 'kazakhstan', 'display_text': 'Kazakhstan'}, {'id': 'kenya', 'display_text': 'Kenya'}, {'id': 'kiribati', 'display_text': 'Kiribati'}, {'id': 'kosovo', 'display_text': 'Kosovo'}, {'id': 'kuwait', 'display_text': 'Kuwait'}, {'id': 'kyrgyzstan', 'display_text': 'Kyrgyzstan'}, {'id': 'laos', 'display_text': 'Laos'}, {'id': 'latvia', 'display_text': 'Latvia'}, {'id': 'lebanon', 'display_text': 'Lebanon'}, {'id': 'lesotho', 'display_text': 'Lesotho'}, {'id': 'liberia', 'display_text': 'Liberia'}, {'id': 'libya', 'display_text': 'Libya'}, {'id': 'liechtenstein', 'display_text': 'Liechtenstein'}, {'id': 'lithuania', 'display_text': 'Lithuania'}, {'id': 'luxembourg', 'display_text': 'Luxembourg'}, {'id': 'macedonia', 'display_text': 'Macedonia'}, {'id': 'madagascar', 'display_text': 'Madagascar'}, {'id': 'malawi', 'display_text': 'Malawi'}, {'id': 'malaysia', 'display_text': 'Malaysia'}, {'id': 'maldives', 'display_text': 'Maldives'}, {'id': 'mali', 'display_text': 'Mali'}, {'id': 'malta', 'display_text': 'Malta'}, {'id': 'marshall_islands', 'display_text': 'Marshall Islands'}, {'id': 'mauritania', 'display_text': 'Mauritania'}, {'id': 'mauritius', 'display_text': 'Mauritius'}, {'id': 'mexico', 'display_text': 'Mexico'}, {'id': 'micronesia', 'display_text': 'Micronesia'}, {'id': 'moldova', 'display_text': 'Moldova'}, {'id': 'monaco', 'display_text': 'Monaco'}, {'id': 'mongolia', 'display_text': 'Mongolia'}, {'id': 'montenegro', 'display_text': 'Montenegro'}, {'id': 'morocco', 'display_text': 'Morocco'}, {'id': 'mozambique', 'display_text': 'Mozambique'}, {'id': 'myanmar', 'display_text': 'Myanmar'}, {'id': 'namibia', 'display_text': 'Namibia'}, {'id': 'nauru', 'display_text': 'Nauru'}, {'id': 'nepal', 'display_text': 'Nepal'}, {'id': 'netherlands', 'display_text': 'Netherlands'}, {'id': 'new_zealand', 'display_text': 'New Zealand'}, {'id': 'nicaragua', 'display_text': 'Nicaragua'}, {'id': 'niger', 'display_text': 'Niger'}, {'id': 'nigeria', 'display_text': 'Nigeria'}, {'id': 'north_korea', 'display_text': 'North Korea'}, {'id': 'norway', 'display_text': 'Norway'}, {'id': 'oman', 'display_text': 'Oman'}, {'id': 'pakistan', 'display_text': 'Pakistan'}, {'id': 'palau', 'display_text': 'Palau'}, {'id': 'palestine', 'display_text': 'Palestine'}, {'id': 'panama', 'display_text': 'Panama'}, {'id': 'papua_new_guinea', 'display_text': 'Papua New Guinea'}, {'id': 'paraguay', 'display_text': 'Paraguay'}, {'id': 'peru', 'display_text': 'Peru'}, {'id': 'philippines', 'display_text': 'Philippines'}, {'id': 'poland', 'display_text': 'Poland'}, {'id': 'portugal', 'display_text': 'Portugal'}, {'id': 'qatar', 'display_text': 'Qatar'}, {'id': 'romania', 'display_text': 'Romania'}, {'id': 'russia', 'display_text': 'Russia'}, {'id': 'rwanda', 'display_text': 'Rwanda'}, {'id': 'st_kitts_and_nevis', 'display_text': 'St. Kitts and Nevis'}, {'id': 'st_lucia', 'display_text': 'St. Lucia'}, {'id': 'st_vincent_and_the_grenadines', 'display_text': 'St. Vincent and The Grenadines'}, {'id': 'samoa', 'display_text': 'Samoa'}, {'id': 'san_marino', 'display_text': 'San Marino'}, {'id': 'sao_tome_and_principe', 'display_text': 'Sao Tome and Principe'}, {'id': 'saudi_arabia', 'display_text': 'Saudi Arabia'}, {'id': 'senegal', 'display_text': 'Senegal'}, {'id': 'serbia', 'display_text': 'Serbia'}, {'id': 'seychelles', 'display_text': 'Seychelles'}, {'id': 'sierra_leone', 'display_text': 'Sierra Leone'}, {'id': 'singapore', 'display_text': 'Singapore'}, {'id': 'slovakia', 'display_text': 'Slovakia'}, {'id': 'slovenia', 'display_text': 'Slovenia'}, {'id': 'solomon_islands', 'display_text': 'Solomon Islands'}, {'id': 'somalia', 'display_text': 'Somalia'}, {'id': 'south_africa', 'display_text': 'South Africa'}, {'id': 'south_korea', 'display_text': 'South Korea'}, {'id': 'south_sudan', 'display_text': 'South Sudan'}, {'id': 'spain', 'display_text': 'Spain'}, {'id': 'sri_lanka', 'display_text': 'Sri Lanka'}, {'id': 'sudan', 'display_text': 'Sudan'}, {'id': 'suriname', 'display_text': 'Suriname'}, {'id': 'swaziland', 'display_text': 'Swaziland'}, {'id': 'sweden', 'display_text': 'Sweden'}, {'id': 'switzerland', 'display_text': 'Switzerland'}, {'id': 'syria', 'display_text': 'Syria'}, {'id': 'taiwan', 'display_text': 'Taiwan'}, {'id': 'tajikistan', 'display_text': 'Tajikistan'}, {'id': 'tanzania', 'display_text': 'Tanzania'}, {'id': 'thailand', 'display_text': 'Thailand'}, {'id': 'timor_leste', 'display_text': 'Timor-Leste'}, {'id': 'togo', 'display_text': 'Togo'}, {'id': 'tonga', 'display_text': 'Tonga'}, {'id': 'trinidad_and_tobago', 'display_text': 'Trinidad and Tobago'}, {'id': 'tunisia', 'display_text': 'Tunisia'}, {'id': 'turkey', 'display_text': 'Turkey'}, {'id': 'turkmenistan', 'display_text': 'Turkmenistan'}, {'id': 'tuvalu', 'display_text': 'Tuvalu'}, {'id': 'uganda', 'display_text': 'Uganda'}, {'id': 'ukraine', 'display_text': 'Ukraine'}, {'id': 'united_arab_emirates', 'display_text': 'United Arab Emirates'}, {'id': 'uk', 'display_text': 'UK (United Kingdom)'}, {'id': 'usa', 'display_text': 'USA (United States of America)'}, {'id': 'uruguay', 'display_text': 'Uruguay'}, {'id': 'uzbekistan', 'display_text': 'Uzbekistan'}, {'id': 'vanuatu', 'display_text': 'Vanuatu'}, {'id': 'vatican', 'display_text': 'Vatican City (Holy See)'}, {'id': 'venezuela', 'display_text': 'Venezuela'}, {'id': 'vietnam', 'display_text': 'Vietnam'}, {'id': 'yemen', 'display_text': 'Yemen'}, {'id': 'zambia', 'display_text': 'Zambia'}, {'id': 'zimbabwe', 'display_text': 'Zimbabwe'}], 'fr': [], 'ar': []}}]}, {'id': 6, 'name': {'en': 'Cases by Age and Sex', 'fr': 'Cases by Age and Sex', 'ar': 'Cases by Age and Sex'}, 'description': {'en': 'Number of cases broken down by age and sex', 'fr': 'Number of cases broken down by age and sex', 'ar': 'Number of cases broken down by age and sex'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': True, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'age', 'display_name': {'en': 'Age', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}, {'name': 'sex', 'display_name': {'en': 'Sex', 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}, 'option_labels': {'en': [{'id': 'male', 'display_text': 'Male'}, {'id': 'female', 'display_text': 'Female'}], 'fr': [], 'ar': []}}]}, {'id': 7, 'name': {'en': 'Cases by Protection Concern', 'fr': 'Cases by Protection Concern', 'ar': 'Cases by Protection Concern'}, 'description': {'en': 'Number of cases broken down by protection concern and sex', 'fr': 'Number of cases broken down by protection concern and sex', 'ar': 'Number of cases broken down by protection concern and sex'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'protection_concerns', 'display_name': {'en': 'Protection Concerns', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}, 'option_labels': {'en': [{'id': 'sexually_exploited', 'display_text': 'Sexually Exploited'}, {'id': 'gbv_survivor', 'display_text': 'GBV survivor'}, {'id': 'trafficked_smuggled', 'display_text': 'Trafficked/smuggled'}, {'id': 'statelessness', 'display_text': 'Statelessness'}, {'id': 'arrested_detained', 'display_text': 'Arrested/Detained'}, {'id': 'migrant', 'display_text': 'Migrant'}, {'id': 'disabled', 'display_text': 'Disabled'}, {'id': 'serious_health_issue', 'display_text': 'Serious health issue'}, {'id': 'refugee', 'display_text': 'Refugee'}, {'id': 'caafag', 'display_text': 'CAAFAG'}, {'id': 'street_child', 'display_text': 'Street child'}, {'id': 'child_mother', 'display_text': 'Child Mother'}, {'id': 'physically_or_mentally_abused', 'display_text': 'Physically or Mentally Abused'}, {'id': 'living_with_vulnerable_person', 'display_text': 'Living with vulnerable person'}, {'id': 'worst_forms_of_child_labor', 'display_text': 'Worst Forms of Child Labor'}, {'id': 'child_headed_household', 'display_text': 'Child Headed Household'}, {'id': 'mentally_distressed', 'display_text': 'Mentally Distressed'}, {'id': 'other', 'display_text': 'Other'}], 'fr': [], 'ar': []}}, {'name': 'sex', 'display_name': {'en': 'Sex', 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}, 'option_labels': {'en': [{'id': 'male', 'display_text': 'Male'}, {'id': 'female', 'display_text': 'Female'}], 'fr': [], 'ar': []}}]}, {'id': 8, 'name': {'en': 'Current Care Arrangements', 'fr': 'Current Care Arrangements', 'ar': 'Current Care Arrangements'}, 'description': {'en': 'The care arrangements broken down by age and sex', 'fr': 'The care arrangements broken down by age and sex', 'ar': 'The care arrangements broken down by age and sex'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': True, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'care_arrangements_type', 'display_name': {'en': \"What are the child's current care arrangements?\", 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}, 'option_labels': {'en': [{'id': 'parent_s', 'display_text': 'Parent(s)'}, {'id': 'step_parent', 'display_text': 'Step parent'}, {'id': 'customary_caregiver_s', 'display_text': 'Customary caregiver(s)'}, {'id': 'adult_sibling', 'display_text': 'Adult sibling'}, {'id': 'kinship_care_extended_family', 'display_text': 'Kinship care / extended family'}, {'id': 'foster_care', 'display_text': 'Foster care'}, {'id': 'residential_care', 'display_text': 'Residential care'}, {'id': 'kafala', 'display_text': 'Kafala'}, {'id': 'independent_living', 'display_text': 'Independent living'}, {'id': 'child_headed_household', 'display_text': 'Child-headed household'}, {'id': 'unrelated_adult', 'display_text': 'Unrelated adult'}, {'id': 'no_care_arrangement', 'display_text': 'No care arrangement'}, {'id': 'other', 'display_text': 'Other'}], 'fr': [], 'ar': []}}, {'name': 'sex', 'display_name': {'en': 'Sex', 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}, 'option_labels': {'en': [{'id': 'male', 'display_text': 'Male'}, {'id': 'female', 'display_text': 'Female'}], 'fr': [], 'ar': []}}, {'name': 'age', 'display_name': {'en': 'Age', 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 1}}]}, {'id': 9, 'name': {'en': 'Workflow Status', 'fr': 'Workflow Status', 'ar': 'Workflow Status'}, 'description': {'en': 'Cases broken down by current workflow status', 'fr': 'Cases broken down by current workflow status', 'ar': 'Cases broken down by current workflow status'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': True, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': None, 'display_name': None, 'position': {'type': 'horizontal', 'order': 0}}]}, {'id': 10, 'name': {'en': 'Follow up by month by Agency', 'fr': 'Follow up by month by Agency', 'ar': 'Follow up by month by Agency'}, 'description': {'en': 'Number of followups broken down by month and agency', 'fr': 'Number of followups broken down by month and agency', 'ar': 'Number of followups broken down by month and agency'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'reportable_follow_up', 'module_id': 'primeromodule-cp', 'group_dates_by': 'month', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}, {'value': '', 'attribute': 'followup_date', 'constraint': 'not_null'}], 'fields': [{'name': 'followup_date', 'display_name': {'en': 'Follow up date', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}, {'name': 'owned_by_agency_id', 'display_name': {'en': \"Record Owner's Agency\", 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}, 'option_strings_source': 'Agency'}]}, {'id': 11, 'name': {'en': 'Follow up by week by Agency', 'fr': 'Follow up by week by Agency', 'ar': 'Follow up by week by Agency'}, 'description': {'en': 'Number of followups broken down by week and agency', 'fr': 'Number of followups broken down by week and agency', 'ar': 'Number of followups broken down by week and agency'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'reportable_follow_up', 'module_id': 'primeromodule-cp', 'group_dates_by': 'week', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}, {'value': '', 'attribute': 'followup_date', 'constraint': 'not_null'}], 'fields': [{'name': 'followup_date', 'display_name': {'en': 'Follow up date', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}, {'name': 'owned_by_agency_id', 'display_name': {'en': \"Record Owner's Agency\", 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}, 'option_strings_source': 'Agency'}]}, {'id': 12, 'name': {'en': 'Cases per Month', 'fr': 'Cases per Month', 'ar': 'Cases per Month'}, 'description': {'en': ' Number of newly registered cases per month per location ', 'fr': ' Number of newly registered cases per month per location ', 'ar': ' Number of newly registered cases per month per location '}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'month', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'owned_by_location', 'display_name': {'en': \"Record Owner's Location\", 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}, 'option_strings_source': 'Location'}, {'name': 'created_at', 'display_name': {'en': 'Date of referral or transfer', 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}}]}, {'id': 13, 'name': {'en': 'Cases with case plans', 'fr': 'Cases with case plans', 'ar': 'Cases with case plans'}, 'description': {'en': 'How many registered cases have case plans?', 'fr': 'How many registered cases have case plans?', 'ar': 'How many registered cases have case plans?'}, 'graph': False, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'has_case_plan', 'display_name': {'en': 'Does this case have a case plan?', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}]}], 'metadata': {'total': 13, 'per': 1000, 'page': 1}}\n", + "http://localhost/api/v2/reports/1\n", + "http://localhost/api/v2/reports/2\n", + "http://localhost/api/v2/reports/3\n", + "http://localhost/api/v2/reports/4\n", + "http://localhost/api/v2/reports/5\n", + "http://localhost/api/v2/reports/6\n", + "http://localhost/api/v2/reports/7\n", + "http://localhost/api/v2/reports/8\n", + "http://localhost/api/v2/reports/9\n", + "Failed to get report\n", + "500\n", + "{'Date': 'Thu, 17 Oct 2024 07:50:24 GMT', 'Content-Type': 'application/json; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'X-Frame-Options': 'SAMEORIGIN', 'X-XSS-Protection': '1; mode=block', 'X-Content-Type-Options': 'nosniff', 'X-Download-Options': 'noopen', 'X-Permitted-Cross-Domain-Policies': 'none', 'Referrer-Policy': 'strict-origin-when-cross-origin', 'Vary': 'Accept-Encoding', 'Content-Encoding': 'gzip', 'Cache-Control': 'no-cache', 'Content-Security-Policy': \"default-src 'self' https:; font-src 'self' https: data: blob:; img-src 'self' https: data: blob:; media-src 'self' https: data: blob:; object-src 'none'; script-src 'self' https: 'strict-dynamic' 'nonce-86/VIwPUA3goVkAQycM1Og=='; style-src 'self' https: 'nonce-86/VIwPUA3goVkAQycM1Og=='; child-src 'self' https: blob:; frame-src 'none'; base-uri 'self'\", 'Set-Cookie': '_session_id=QXsW8LNPIs%2BIvkgiUol8xfWFIQih2sJIzTLL9jx8K%2BznT0IWChnnhAl8YbWatnLabiyYKnyhXiaOwTDW3xSMPHTYl297XB%2Bl08cjOlrbkzbs4OPVZPzrr9OWRKXdHkEprTsyAlrXaTKxe8PYZa6Ze1aLcjdI%2BVolxPbDJMezC4WmJM7O%2Frw9uV%2Br52vC%2F5nRuYj6dRD5fkLM--QsXPide9j%2FjfAchR--7GLzRxp3iKmUh6aqIpNtOA%3D%3D; path=/; expires=Thu, 17 Oct 2024 08:50:24 GMT; secure; HttpOnly; SameSite=Lax', 'X-Request-Id': '76a8d100-634e-44ae-b916-6f0ab559a21e', 'X-Runtime': '0.271219', 'Strict-Transport-Security': 'max-age=63072000; includeSubDomains', 'NEL': '{\"max_age\":31536000,\"include_subdomains\":true,\"success_fraction\":0,\"failure_fraction\":1,\"report_to\":\"default\"}'}\n", + "{\"errors\":[{\"status\":500,\"resource\":\"/api/v2/reports/9\",\"message\":\"undefined method `type' for nil\"}]}\n", + "http://localhost/api/v2/reports/10\n", + "http://localhost/api/v2/reports/11\n", + "http://localhost/api/v2/reports/12\n", + "http://localhost/api/v2/reports/13\n" + ] + } + ], + "source": [ + "reports = api.get_reports()" + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 {'en': 'Registration CP', 'fr': 'Registration CP', 'ar': 'Registration CP'}\n", + "{\n", + " \"id\": 1,\n", + " \"name\": {\n", + " \"en\": \"Registration CP\",\n", + " \"fr\": \"Registration CP\",\n", + " \"ar\": \"Registration CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Case registrations over time\",\n", + " \"fr\": \"Case registrations over time\",\n", + " \"ar\": \"Case registrations over time\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"month\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"registration_date\",\n", + " \"display_name\": {\n", + " \"en\": \"Date of Registration or Interview\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"2024-Oct\": {\n", + " \"_total\": 3\n", + " }\n", + " }\n", + "}\n", + "2 {'en': 'Caseload Summary CP', 'fr': 'Caseload Summary CP', 'ar': 'Caseload Summary CP'}\n", + "{\n", + " \"id\": 2,\n", + " \"name\": {\n", + " \"en\": \"Caseload Summary CP\",\n", + " \"fr\": \"Caseload Summary CP\",\n", + " \"ar\": \"Caseload Summary CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases for each case worker\",\n", + " \"fr\": \"Number of cases for each case worker\",\n", + " \"ar\": \"Number of cases for each case worker\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by\",\n", + " \"display_name\": {\n", + " \"en\": \"Caseworker Code\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"primero\": {\n", + " \"_total\": 3\n", + " }\n", + " }\n", + "}\n", + "3 {'en': 'Case status by case worker CP', 'fr': 'Case status by case worker CP', 'ar': 'Case status by case worker CP'}\n", + "{\n", + " \"id\": 3,\n", + " \"name\": {\n", + " \"en\": \"Case status by case worker CP\",\n", + " \"fr\": \"Case status by case worker CP\",\n", + " \"ar\": \"Case status by case worker CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Status of cases held by case workers\",\n", + " \"fr\": \"Status of cases held by case workers\",\n", + " \"ar\": \"Status of cases held by case workers\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by\",\n", + " \"display_name\": {\n", + " \"en\": \"Caseworker Code\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"status\",\n", + " \"display_name\": {\n", + " \"en\": \"Case Status\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"open\",\n", + " \"display_text\": \"Open\"\n", + " },\n", + " {\n", + " \"id\": \"closed\",\n", + " \"display_text\": \"Closed\"\n", + " },\n", + " {\n", + " \"id\": \"transferred\",\n", + " \"display_text\": \"Transferred\"\n", + " },\n", + " {\n", + " \"id\": \"duplicate\",\n", + " \"display_text\": \"Duplicate\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"primero\": {\n", + " \"_total\": 3,\n", + " \"open\": {\n", + " \"_total\": 3\n", + " },\n", + " \"closed\": {\n", + " \"_total\": 0\n", + " },\n", + " \"transferred\": {\n", + " \"_total\": 0\n", + " },\n", + " \"duplicate\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + " }\n", + "}\n", + "4 {'en': 'Cases by Agency CP', 'fr': 'Cases by Agency CP', 'ar': 'Cases by Agency CP'}\n", + "{\n", + " \"id\": 4,\n", + " \"name\": {\n", + " \"en\": \"Cases by Agency CP\",\n", + " \"fr\": \"Cases by Agency CP\",\n", + " \"ar\": \"Cases by Agency CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by agency\",\n", + " \"fr\": \"Number of cases broken down by agency\",\n", + " \"ar\": \"Number of cases broken down by agency\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by_agency_id\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Agency\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Agency\"\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"UNICEF\": {\n", + " \"_total\": 3\n", + " }\n", + " }\n", + "}\n", + "5 {'en': 'Cases by Nationality', 'fr': 'Cases by Nationality', 'ar': 'Cases by Nationality'}\n", + "{\n", + " \"id\": 5,\n", + " \"name\": {\n", + " \"en\": \"Cases by Nationality\",\n", + " \"fr\": \"Cases by Nationality\",\n", + " \"ar\": \"Cases by Nationality\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by nationality\",\n", + " \"fr\": \"Number of cases broken down by nationality\",\n", + " \"ar\": \"Number of cases broken down by nationality\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"nationality\",\n", + " \"display_name\": {\n", + " \"en\": \"Nationality\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"afghanistan\",\n", + " \"display_text\": \"Afghanistan\"\n", + " },\n", + " {\n", + " \"id\": \"albania\",\n", + " \"display_text\": \"Albania\"\n", + " },\n", + " {\n", + " \"id\": \"algeria\",\n", + " \"display_text\": \"Algeria\"\n", + " },\n", + " {\n", + " \"id\": \"andorra\",\n", + " \"display_text\": \"Andorra\"\n", + " },\n", + " {\n", + " \"id\": \"angola\",\n", + " \"display_text\": \"Angola\"\n", + " },\n", + " {\n", + " \"id\": \"antigua_and_barbuda\",\n", + " \"display_text\": \"Antigua and Barbuda\"\n", + " },\n", + " {\n", + " \"id\": \"argentina\",\n", + " \"display_text\": \"Argentina\"\n", + " },\n", + " {\n", + " \"id\": \"armenia\",\n", + " \"display_text\": \"Armenia\"\n", + " },\n", + " {\n", + " \"id\": \"australia\",\n", + " \"display_text\": \"Australia\"\n", + " },\n", + " {\n", + " \"id\": \"austria\",\n", + " \"display_text\": \"Austria\"\n", + " },\n", + " {\n", + " \"id\": \"azerbaijan\",\n", + " \"display_text\": \"Azerbaijan\"\n", + " },\n", + " {\n", + " \"id\": \"bahamas\",\n", + " \"display_text\": \"Bahamas\"\n", + " },\n", + " {\n", + " \"id\": \"bahrain\",\n", + " \"display_text\": \"Bahrain\"\n", + " },\n", + " {\n", + " \"id\": \"bangladesh\",\n", + " \"display_text\": \"Bangladesh\"\n", + " },\n", + " {\n", + " \"id\": \"barbados\",\n", + " \"display_text\": \"Barbados\"\n", + " },\n", + " {\n", + " \"id\": \"belarus\",\n", + " \"display_text\": \"Belarus\"\n", + " },\n", + " {\n", + " \"id\": \"belgium\",\n", + " \"display_text\": \"Belgium\"\n", + " },\n", + " {\n", + " \"id\": \"belize\",\n", + " \"display_text\": \"Belize\"\n", + " },\n", + " {\n", + " \"id\": \"benin\",\n", + " \"display_text\": \"Benin\"\n", + " },\n", + " {\n", + " \"id\": \"bhutan\",\n", + " \"display_text\": \"Bhutan\"\n", + " },\n", + " {\n", + " \"id\": \"bolivia\",\n", + " \"display_text\": \"Bolivia\"\n", + " },\n", + " {\n", + " \"id\": \"bosnia_and_herzegovina\",\n", + " \"display_text\": \"Bosnia and Herzegovina\"\n", + " },\n", + " {\n", + " \"id\": \"botswana\",\n", + " \"display_text\": \"Botswana\"\n", + " },\n", + " {\n", + " \"id\": \"brazil\",\n", + " \"display_text\": \"Brazil\"\n", + " },\n", + " {\n", + " \"id\": \"brunei\",\n", + " \"display_text\": \"Brunei\"\n", + " },\n", + " {\n", + " \"id\": \"bulgaria\",\n", + " \"display_text\": \"Bulgaria\"\n", + " },\n", + " {\n", + " \"id\": \"burkina_faso\",\n", + " \"display_text\": \"Burkina Faso\"\n", + " },\n", + " {\n", + " \"id\": \"burundi\",\n", + " \"display_text\": \"Burundi\"\n", + " },\n", + " {\n", + " \"id\": \"cabo_verde\",\n", + " \"display_text\": \"Cabo Verde\"\n", + " },\n", + " {\n", + " \"id\": \"cambodia\",\n", + " \"display_text\": \"Cambodia\"\n", + " },\n", + " {\n", + " \"id\": \"cameroon\",\n", + " \"display_text\": \"Cameroon\"\n", + " },\n", + " {\n", + " \"id\": \"canada\",\n", + " \"display_text\": \"Canada\"\n", + " },\n", + " {\n", + " \"id\": \"central_african_republic\",\n", + " \"display_text\": \"Central African Republic\"\n", + " },\n", + " {\n", + " \"id\": \"chad\",\n", + " \"display_text\": \"Chad\"\n", + " },\n", + " {\n", + " \"id\": \"chile\",\n", + " \"display_text\": \"Chile\"\n", + " },\n", + " {\n", + " \"id\": \"china\",\n", + " \"display_text\": \"China\"\n", + " },\n", + " {\n", + " \"id\": \"colombia\",\n", + " \"display_text\": \"Colombia\"\n", + " },\n", + " {\n", + " \"id\": \"comoros\",\n", + " \"display_text\": \"Comoros\"\n", + " },\n", + " {\n", + " \"id\": \"congo\",\n", + " \"display_text\": \"Congo, Republic of the\"\n", + " },\n", + " {\n", + " \"id\": \"drc\",\n", + " \"display_text\": \"Congo, Democratic Republic of the\"\n", + " },\n", + " {\n", + " \"id\": \"costa_rica\",\n", + " \"display_text\": \"Costa Rica\"\n", + " },\n", + " {\n", + " \"id\": \"cote_divoire\",\n", + " \"display_text\": \"Cote d'Ivoire\"\n", + " },\n", + " {\n", + " \"id\": \"croatia\",\n", + " \"display_text\": \"Croatia\"\n", + " },\n", + " {\n", + " \"id\": \"cuba\",\n", + " \"display_text\": \"Cuba\"\n", + " },\n", + " {\n", + " \"id\": \"cyprus\",\n", + " \"display_text\": \"Cyprus\"\n", + " },\n", + " {\n", + " \"id\": \"czech_republic\",\n", + " \"display_text\": \"Czech Republic\"\n", + " },\n", + " {\n", + " \"id\": \"denmark\",\n", + " \"display_text\": \"Denmark\"\n", + " },\n", + " {\n", + " \"id\": \"djibouti\",\n", + " \"display_text\": \"Djibouti\"\n", + " },\n", + " {\n", + " \"id\": \"dominica\",\n", + " \"display_text\": \"Dominica\"\n", + " },\n", + " {\n", + " \"id\": \"dominican_republic\",\n", + " \"display_text\": \"Dominican Republic\"\n", + " },\n", + " {\n", + " \"id\": \"ecuador\",\n", + " \"display_text\": \"Ecuador\"\n", + " },\n", + " {\n", + " \"id\": \"egypt\",\n", + " \"display_text\": \"Egypt\"\n", + " },\n", + " {\n", + " \"id\": \"el_salvador\",\n", + " \"display_text\": \"El Salvador\"\n", + " },\n", + " {\n", + " \"id\": \"equatorial_guinea\",\n", + " \"display_text\": \"Equatorial Guinea\"\n", + " },\n", + " {\n", + " \"id\": \"eritrea\",\n", + " \"display_text\": \"Eritrea\"\n", + " },\n", + " {\n", + " \"id\": \"estonia\",\n", + " \"display_text\": \"Estonia\"\n", + " },\n", + " {\n", + " \"id\": \"ethiopia\",\n", + " \"display_text\": \"Ethiopia\"\n", + " },\n", + " {\n", + " \"id\": \"fiji\",\n", + " \"display_text\": \"Fiji\"\n", + " },\n", + " {\n", + " \"id\": \"finland\",\n", + " \"display_text\": \"Finland\"\n", + " },\n", + " {\n", + " \"id\": \"france\",\n", + " \"display_text\": \"France\"\n", + " },\n", + " {\n", + " \"id\": \"gabon\",\n", + " \"display_text\": \"Gabon\"\n", + " },\n", + " {\n", + " \"id\": \"gambia\",\n", + " \"display_text\": \"Gambia\"\n", + " },\n", + " {\n", + " \"id\": \"georgia\",\n", + " \"display_text\": \"Georgia\"\n", + " },\n", + " {\n", + " \"id\": \"germany\",\n", + " \"display_text\": \"Germany\"\n", + " },\n", + " {\n", + " \"id\": \"ghana\",\n", + " \"display_text\": \"Ghana\"\n", + " },\n", + " {\n", + " \"id\": \"greece\",\n", + " \"display_text\": \"Greece\"\n", + " },\n", + " {\n", + " \"id\": \"grenada\",\n", + " \"display_text\": \"Grenada\"\n", + " },\n", + " {\n", + " \"id\": \"guatemala\",\n", + " \"display_text\": \"Guatemala\"\n", + " },\n", + " {\n", + " \"id\": \"guinea\",\n", + " \"display_text\": \"Guinea\"\n", + " },\n", + " {\n", + " \"id\": \"guinea_bissau\",\n", + " \"display_text\": \"Guinea-Bissau\"\n", + " },\n", + " {\n", + " \"id\": \"guyana\",\n", + " \"display_text\": \"Guyana\"\n", + " },\n", + " {\n", + " \"id\": \"haiti\",\n", + " \"display_text\": \"Haiti\"\n", + " },\n", + " {\n", + " \"id\": \"honduras\",\n", + " \"display_text\": \"Honduras\"\n", + " },\n", + " {\n", + " \"id\": \"hungary\",\n", + " \"display_text\": \"Hungary\"\n", + " },\n", + " {\n", + " \"id\": \"iceland\",\n", + " \"display_text\": \"Iceland\"\n", + " },\n", + " {\n", + " \"id\": \"india\",\n", + " \"display_text\": \"India\"\n", + " },\n", + " {\n", + " \"id\": \"indonesia\",\n", + " \"display_text\": \"Indonesia\"\n", + " },\n", + " {\n", + " \"id\": \"iran\",\n", + " \"display_text\": \"Iran\"\n", + " },\n", + " {\n", + " \"id\": \"iraq\",\n", + " \"display_text\": \"Iraq\"\n", + " },\n", + " {\n", + " \"id\": \"ireland\",\n", + " \"display_text\": \"Ireland\"\n", + " },\n", + " {\n", + " \"id\": \"israel\",\n", + " \"display_text\": \"Israel\"\n", + " },\n", + " {\n", + " \"id\": \"italy\",\n", + " \"display_text\": \"Italy\"\n", + " },\n", + " {\n", + " \"id\": \"jamaica\",\n", + " \"display_text\": \"Jamaica\"\n", + " },\n", + " {\n", + " \"id\": \"japan\",\n", + " \"display_text\": \"Japan\"\n", + " },\n", + " {\n", + " \"id\": \"jordan\",\n", + " \"display_text\": \"Jordan\"\n", + " },\n", + " {\n", + " \"id\": \"kazakhstan\",\n", + " \"display_text\": \"Kazakhstan\"\n", + " },\n", + " {\n", + " \"id\": \"kenya\",\n", + " \"display_text\": \"Kenya\"\n", + " },\n", + " {\n", + " \"id\": \"kiribati\",\n", + " \"display_text\": \"Kiribati\"\n", + " },\n", + " {\n", + " \"id\": \"kosovo\",\n", + " \"display_text\": \"Kosovo\"\n", + " },\n", + " {\n", + " \"id\": \"kuwait\",\n", + " \"display_text\": \"Kuwait\"\n", + " },\n", + " {\n", + " \"id\": \"kyrgyzstan\",\n", + " \"display_text\": \"Kyrgyzstan\"\n", + " },\n", + " {\n", + " \"id\": \"laos\",\n", + " \"display_text\": \"Laos\"\n", + " },\n", + " {\n", + " \"id\": \"latvia\",\n", + " \"display_text\": \"Latvia\"\n", + " },\n", + " {\n", + " \"id\": \"lebanon\",\n", + " \"display_text\": \"Lebanon\"\n", + " },\n", + " {\n", + " \"id\": \"lesotho\",\n", + " \"display_text\": \"Lesotho\"\n", + " },\n", + " {\n", + " \"id\": \"liberia\",\n", + " \"display_text\": \"Liberia\"\n", + " },\n", + " {\n", + " \"id\": \"libya\",\n", + " \"display_text\": \"Libya\"\n", + " },\n", + " {\n", + " \"id\": \"liechtenstein\",\n", + " \"display_text\": \"Liechtenstein\"\n", + " },\n", + " {\n", + " \"id\": \"lithuania\",\n", + " \"display_text\": \"Lithuania\"\n", + " },\n", + " {\n", + " \"id\": \"luxembourg\",\n", + " \"display_text\": \"Luxembourg\"\n", + " },\n", + " {\n", + " \"id\": \"macedonia\",\n", + " \"display_text\": \"Macedonia\"\n", + " },\n", + " {\n", + " \"id\": \"madagascar\",\n", + " \"display_text\": \"Madagascar\"\n", + " },\n", + " {\n", + " \"id\": \"malawi\",\n", + " \"display_text\": \"Malawi\"\n", + " },\n", + " {\n", + " \"id\": \"malaysia\",\n", + " \"display_text\": \"Malaysia\"\n", + " },\n", + " {\n", + " \"id\": \"maldives\",\n", + " \"display_text\": \"Maldives\"\n", + " },\n", + " {\n", + " \"id\": \"mali\",\n", + " \"display_text\": \"Mali\"\n", + " },\n", + " {\n", + " \"id\": \"malta\",\n", + " \"display_text\": \"Malta\"\n", + " },\n", + " {\n", + " \"id\": \"marshall_islands\",\n", + " \"display_text\": \"Marshall Islands\"\n", + " },\n", + " {\n", + " \"id\": \"mauritania\",\n", + " \"display_text\": \"Mauritania\"\n", + " },\n", + " {\n", + " \"id\": \"mauritius\",\n", + " \"display_text\": \"Mauritius\"\n", + " },\n", + " {\n", + " \"id\": \"mexico\",\n", + " \"display_text\": \"Mexico\"\n", + " },\n", + " {\n", + " \"id\": \"micronesia\",\n", + " \"display_text\": \"Micronesia\"\n", + " },\n", + " {\n", + " \"id\": \"moldova\",\n", + " \"display_text\": \"Moldova\"\n", + " },\n", + " {\n", + " \"id\": \"monaco\",\n", + " \"display_text\": \"Monaco\"\n", + " },\n", + " {\n", + " \"id\": \"mongolia\",\n", + " \"display_text\": \"Mongolia\"\n", + " },\n", + " {\n", + " \"id\": \"montenegro\",\n", + " \"display_text\": \"Montenegro\"\n", + " },\n", + " {\n", + " \"id\": \"morocco\",\n", + " \"display_text\": \"Morocco\"\n", + " },\n", + " {\n", + " \"id\": \"mozambique\",\n", + " \"display_text\": \"Mozambique\"\n", + " },\n", + " {\n", + " \"id\": \"myanmar\",\n", + " \"display_text\": \"Myanmar\"\n", + " },\n", + " {\n", + " \"id\": \"namibia\",\n", + " \"display_text\": \"Namibia\"\n", + " },\n", + " {\n", + " \"id\": \"nauru\",\n", + " \"display_text\": \"Nauru\"\n", + " },\n", + " {\n", + " \"id\": \"nepal\",\n", + " \"display_text\": \"Nepal\"\n", + " },\n", + " {\n", + " \"id\": \"netherlands\",\n", + " \"display_text\": \"Netherlands\"\n", + " },\n", + " {\n", + " \"id\": \"new_zealand\",\n", + " \"display_text\": \"New Zealand\"\n", + " },\n", + " {\n", + " \"id\": \"nicaragua\",\n", + " \"display_text\": \"Nicaragua\"\n", + " },\n", + " {\n", + " \"id\": \"niger\",\n", + " \"display_text\": \"Niger\"\n", + " },\n", + " {\n", + " \"id\": \"nigeria\",\n", + " \"display_text\": \"Nigeria\"\n", + " },\n", + " {\n", + " \"id\": \"north_korea\",\n", + " \"display_text\": \"North Korea\"\n", + " },\n", + " {\n", + " \"id\": \"norway\",\n", + " \"display_text\": \"Norway\"\n", + " },\n", + " {\n", + " \"id\": \"oman\",\n", + " \"display_text\": \"Oman\"\n", + " },\n", + " {\n", + " \"id\": \"pakistan\",\n", + " \"display_text\": \"Pakistan\"\n", + " },\n", + " {\n", + " \"id\": \"palau\",\n", + " \"display_text\": \"Palau\"\n", + " },\n", + " {\n", + " \"id\": \"palestine\",\n", + " \"display_text\": \"Palestine\"\n", + " },\n", + " {\n", + " \"id\": \"panama\",\n", + " \"display_text\": \"Panama\"\n", + " },\n", + " {\n", + " \"id\": \"papua_new_guinea\",\n", + " \"display_text\": \"Papua New Guinea\"\n", + " },\n", + " {\n", + " \"id\": \"paraguay\",\n", + " \"display_text\": \"Paraguay\"\n", + " },\n", + " {\n", + " \"id\": \"peru\",\n", + " \"display_text\": \"Peru\"\n", + " },\n", + " {\n", + " \"id\": \"philippines\",\n", + " \"display_text\": \"Philippines\"\n", + " },\n", + " {\n", + " \"id\": \"poland\",\n", + " \"display_text\": \"Poland\"\n", + " },\n", + " {\n", + " \"id\": \"portugal\",\n", + " \"display_text\": \"Portugal\"\n", + " },\n", + " {\n", + " \"id\": \"qatar\",\n", + " \"display_text\": \"Qatar\"\n", + " },\n", + " {\n", + " \"id\": \"romania\",\n", + " \"display_text\": \"Romania\"\n", + " },\n", + " {\n", + " \"id\": \"russia\",\n", + " \"display_text\": \"Russia\"\n", + " },\n", + " {\n", + " \"id\": \"rwanda\",\n", + " \"display_text\": \"Rwanda\"\n", + " },\n", + " {\n", + " \"id\": \"st_kitts_and_nevis\",\n", + " \"display_text\": \"St. Kitts and Nevis\"\n", + " },\n", + " {\n", + " \"id\": \"st_lucia\",\n", + " \"display_text\": \"St. Lucia\"\n", + " },\n", + " {\n", + " \"id\": \"st_vincent_and_the_grenadines\",\n", + " \"display_text\": \"St. Vincent and The Grenadines\"\n", + " },\n", + " {\n", + " \"id\": \"samoa\",\n", + " \"display_text\": \"Samoa\"\n", + " },\n", + " {\n", + " \"id\": \"san_marino\",\n", + " \"display_text\": \"San Marino\"\n", + " },\n", + " {\n", + " \"id\": \"sao_tome_and_principe\",\n", + " \"display_text\": \"Sao Tome and Principe\"\n", + " },\n", + " {\n", + " \"id\": \"saudi_arabia\",\n", + " \"display_text\": \"Saudi Arabia\"\n", + " },\n", + " {\n", + " \"id\": \"senegal\",\n", + " \"display_text\": \"Senegal\"\n", + " },\n", + " {\n", + " \"id\": \"serbia\",\n", + " \"display_text\": \"Serbia\"\n", + " },\n", + " {\n", + " \"id\": \"seychelles\",\n", + " \"display_text\": \"Seychelles\"\n", + " },\n", + " {\n", + " \"id\": \"sierra_leone\",\n", + " \"display_text\": \"Sierra Leone\"\n", + " },\n", + " {\n", + " \"id\": \"singapore\",\n", + " \"display_text\": \"Singapore\"\n", + " },\n", + " {\n", + " \"id\": \"slovakia\",\n", + " \"display_text\": \"Slovakia\"\n", + " },\n", + " {\n", + " \"id\": \"slovenia\",\n", + " \"display_text\": \"Slovenia\"\n", + " },\n", + " {\n", + " \"id\": \"solomon_islands\",\n", + " \"display_text\": \"Solomon Islands\"\n", + " },\n", + " {\n", + " \"id\": \"somalia\",\n", + " \"display_text\": \"Somalia\"\n", + " },\n", + " {\n", + " \"id\": \"south_africa\",\n", + " \"display_text\": \"South Africa\"\n", + " },\n", + " {\n", + " \"id\": \"south_korea\",\n", + " \"display_text\": \"South Korea\"\n", + " },\n", + " {\n", + " \"id\": \"south_sudan\",\n", + " \"display_text\": \"South Sudan\"\n", + " },\n", + " {\n", + " \"id\": \"spain\",\n", + " \"display_text\": \"Spain\"\n", + " },\n", + " {\n", + " \"id\": \"sri_lanka\",\n", + " \"display_text\": \"Sri Lanka\"\n", + " },\n", + " {\n", + " \"id\": \"sudan\",\n", + " \"display_text\": \"Sudan\"\n", + " },\n", + " {\n", + " \"id\": \"suriname\",\n", + " \"display_text\": \"Suriname\"\n", + " },\n", + " {\n", + " \"id\": \"swaziland\",\n", + " \"display_text\": \"Swaziland\"\n", + " },\n", + " {\n", + " \"id\": \"sweden\",\n", + " \"display_text\": \"Sweden\"\n", + " },\n", + " {\n", + " \"id\": \"switzerland\",\n", + " \"display_text\": \"Switzerland\"\n", + " },\n", + " {\n", + " \"id\": \"syria\",\n", + " \"display_text\": \"Syria\"\n", + " },\n", + " {\n", + " \"id\": \"taiwan\",\n", + " \"display_text\": \"Taiwan\"\n", + " },\n", + " {\n", + " \"id\": \"tajikistan\",\n", + " \"display_text\": \"Tajikistan\"\n", + " },\n", + " {\n", + " \"id\": \"tanzania\",\n", + " \"display_text\": \"Tanzania\"\n", + " },\n", + " {\n", + " \"id\": \"thailand\",\n", + " \"display_text\": \"Thailand\"\n", + " },\n", + " {\n", + " \"id\": \"timor_leste\",\n", + " \"display_text\": \"Timor-Leste\"\n", + " },\n", + " {\n", + " \"id\": \"togo\",\n", + " \"display_text\": \"Togo\"\n", + " },\n", + " {\n", + " \"id\": \"tonga\",\n", + " \"display_text\": \"Tonga\"\n", + " },\n", + " {\n", + " \"id\": \"trinidad_and_tobago\",\n", + " \"display_text\": \"Trinidad and Tobago\"\n", + " },\n", + " {\n", + " \"id\": \"tunisia\",\n", + " \"display_text\": \"Tunisia\"\n", + " },\n", + " {\n", + " \"id\": \"turkey\",\n", + " \"display_text\": \"Turkey\"\n", + " },\n", + " {\n", + " \"id\": \"turkmenistan\",\n", + " \"display_text\": \"Turkmenistan\"\n", + " },\n", + " {\n", + " \"id\": \"tuvalu\",\n", + " \"display_text\": \"Tuvalu\"\n", + " },\n", + " {\n", + " \"id\": \"uganda\",\n", + " \"display_text\": \"Uganda\"\n", + " },\n", + " {\n", + " \"id\": \"ukraine\",\n", + " \"display_text\": \"Ukraine\"\n", + " },\n", + " {\n", + " \"id\": \"united_arab_emirates\",\n", + " \"display_text\": \"United Arab Emirates\"\n", + " },\n", + " {\n", + " \"id\": \"uk\",\n", + " \"display_text\": \"UK (United Kingdom)\"\n", + " },\n", + " {\n", + " \"id\": \"usa\",\n", + " \"display_text\": \"USA (United States of America)\"\n", + " },\n", + " {\n", + " \"id\": \"uruguay\",\n", + " \"display_text\": \"Uruguay\"\n", + " },\n", + " {\n", + " \"id\": \"uzbekistan\",\n", + " \"display_text\": \"Uzbekistan\"\n", + " },\n", + " {\n", + " \"id\": \"vanuatu\",\n", + " \"display_text\": \"Vanuatu\"\n", + " },\n", + " {\n", + " \"id\": \"vatican\",\n", + " \"display_text\": \"Vatican City (Holy See)\"\n", + " },\n", + " {\n", + " \"id\": \"venezuela\",\n", + " \"display_text\": \"Venezuela\"\n", + " },\n", + " {\n", + " \"id\": \"vietnam\",\n", + " \"display_text\": \"Vietnam\"\n", + " },\n", + " {\n", + " \"id\": \"yemen\",\n", + " \"display_text\": \"Yemen\"\n", + " },\n", + " {\n", + " \"id\": \"zambia\",\n", + " \"display_text\": \"Zambia\"\n", + " },\n", + " {\n", + " \"id\": \"zimbabwe\",\n", + " \"display_text\": \"Zimbabwe\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"afghanistan\": {\n", + " \"_total\": 1\n", + " },\n", + " \"albania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"algeria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"andorra\": {\n", + " \"_total\": 1\n", + " },\n", + " \"angola\": {\n", + " \"_total\": 0\n", + " },\n", + " \"antigua_and_barbuda\": {\n", + " \"_total\": 1\n", + " },\n", + " \"argentina\": {\n", + " \"_total\": 0\n", + " },\n", + " \"armenia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"australia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"austria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"azerbaijan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bahamas\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bahrain\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bangladesh\": {\n", + " \"_total\": 0\n", + " },\n", + " \"barbados\": {\n", + " \"_total\": 0\n", + " },\n", + " \"belarus\": {\n", + " \"_total\": 0\n", + " },\n", + " \"belgium\": {\n", + " \"_total\": 0\n", + " },\n", + " \"belize\": {\n", + " \"_total\": 0\n", + " },\n", + " \"benin\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bhutan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bolivia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bosnia_and_herzegovina\": {\n", + " \"_total\": 0\n", + " },\n", + " \"botswana\": {\n", + " \"_total\": 0\n", + " },\n", + " \"brazil\": {\n", + " \"_total\": 0\n", + " },\n", + " \"brunei\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bulgaria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"burkina_faso\": {\n", + " \"_total\": 0\n", + " },\n", + " \"burundi\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cabo_verde\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cambodia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cameroon\": {\n", + " \"_total\": 0\n", + " },\n", + " \"canada\": {\n", + " \"_total\": 0\n", + " },\n", + " \"central_african_republic\": {\n", + " \"_total\": 0\n", + " },\n", + " \"chad\": {\n", + " \"_total\": 0\n", + " },\n", + " \"chile\": {\n", + " \"_total\": 0\n", + " },\n", + " \"china\": {\n", + " \"_total\": 0\n", + " },\n", + " \"colombia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"comoros\": {\n", + " \"_total\": 0\n", + " },\n", + " \"congo\": {\n", + " \"_total\": 0\n", + " },\n", + " \"drc\": {\n", + " \"_total\": 0\n", + " },\n", + " \"costa_rica\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cote_divoire\": {\n", + " \"_total\": 0\n", + " },\n", + " \"croatia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cuba\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cyprus\": {\n", + " \"_total\": 0\n", + " },\n", + " \"czech_republic\": {\n", + " \"_total\": 0\n", + " },\n", + " \"denmark\": {\n", + " \"_total\": 0\n", + " },\n", + " \"djibouti\": {\n", + " \"_total\": 0\n", + " },\n", + " \"dominica\": {\n", + " \"_total\": 0\n", + " },\n", + " \"dominican_republic\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ecuador\": {\n", + " \"_total\": 0\n", + " },\n", + " \"egypt\": {\n", + " \"_total\": 0\n", + " },\n", + " \"el_salvador\": {\n", + " \"_total\": 0\n", + " },\n", + " \"equatorial_guinea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"eritrea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"estonia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ethiopia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"fiji\": {\n", + " \"_total\": 0\n", + " },\n", + " \"finland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"france\": {\n", + " \"_total\": 0\n", + " },\n", + " \"gabon\": {\n", + " \"_total\": 0\n", + " },\n", + " \"gambia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"georgia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"germany\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ghana\": {\n", + " \"_total\": 0\n", + " },\n", + " \"greece\": {\n", + " \"_total\": 0\n", + " },\n", + " \"grenada\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guatemala\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guinea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guinea_bissau\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guyana\": {\n", + " \"_total\": 0\n", + " },\n", + " \"haiti\": {\n", + " \"_total\": 0\n", + " },\n", + " \"honduras\": {\n", + " \"_total\": 0\n", + " },\n", + " \"hungary\": {\n", + " \"_total\": 0\n", + " },\n", + " \"iceland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"india\": {\n", + " \"_total\": 0\n", + " },\n", + " \"indonesia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"iran\": {\n", + " \"_total\": 0\n", + " },\n", + " \"iraq\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ireland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"israel\": {\n", + " \"_total\": 0\n", + " },\n", + " \"italy\": {\n", + " \"_total\": 0\n", + " },\n", + " \"jamaica\": {\n", + " \"_total\": 0\n", + " },\n", + " \"japan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"jordan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kazakhstan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kenya\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kiribati\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kosovo\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kuwait\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kyrgyzstan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"laos\": {\n", + " \"_total\": 0\n", + " },\n", + " \"latvia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"lebanon\": {\n", + " \"_total\": 0\n", + " },\n", + " \"lesotho\": {\n", + " \"_total\": 0\n", + " },\n", + " \"liberia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"libya\": {\n", + " \"_total\": 0\n", + " },\n", + " \"liechtenstein\": {\n", + " \"_total\": 0\n", + " },\n", + " \"lithuania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"luxembourg\": {\n", + " \"_total\": 0\n", + " },\n", + " \"macedonia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"madagascar\": {\n", + " \"_total\": 0\n", + " },\n", + " \"malawi\": {\n", + " \"_total\": 0\n", + " },\n", + " \"malaysia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"maldives\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mali\": {\n", + " \"_total\": 0\n", + " },\n", + " \"malta\": {\n", + " \"_total\": 0\n", + " },\n", + " \"marshall_islands\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mauritania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mauritius\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mexico\": {\n", + " \"_total\": 0\n", + " },\n", + " \"micronesia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"moldova\": {\n", + " \"_total\": 0\n", + " },\n", + " \"monaco\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mongolia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"montenegro\": {\n", + " \"_total\": 0\n", + " },\n", + " \"morocco\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mozambique\": {\n", + " \"_total\": 0\n", + " },\n", + " \"myanmar\": {\n", + " \"_total\": 0\n", + " },\n", + " \"namibia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nauru\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nepal\": {\n", + " \"_total\": 0\n", + " },\n", + " \"netherlands\": {\n", + " \"_total\": 0\n", + " },\n", + " \"new_zealand\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nicaragua\": {\n", + " \"_total\": 0\n", + " },\n", + " \"niger\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nigeria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"north_korea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"norway\": {\n", + " \"_total\": 0\n", + " },\n", + " \"oman\": {\n", + " \"_total\": 0\n", + " },\n", + " \"pakistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"palau\": {\n", + " \"_total\": 0\n", + " },\n", + " \"palestine\": {\n", + " \"_total\": 0\n", + " },\n", + " \"panama\": {\n", + " \"_total\": 0\n", + " },\n", + " \"papua_new_guinea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"paraguay\": {\n", + " \"_total\": 0\n", + " },\n", + " \"peru\": {\n", + " \"_total\": 0\n", + " },\n", + " \"philippines\": {\n", + " \"_total\": 0\n", + " },\n", + " \"poland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"portugal\": {\n", + " \"_total\": 0\n", + " },\n", + " \"qatar\": {\n", + " \"_total\": 0\n", + " },\n", + " \"romania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"russia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"rwanda\": {\n", + " \"_total\": 0\n", + " },\n", + " \"st_kitts_and_nevis\": {\n", + " \"_total\": 0\n", + " },\n", + " \"st_lucia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"st_vincent_and_the_grenadines\": {\n", + " \"_total\": 0\n", + " },\n", + " \"samoa\": {\n", + " \"_total\": 0\n", + " },\n", + " \"san_marino\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sao_tome_and_principe\": {\n", + " \"_total\": 0\n", + " },\n", + " \"saudi_arabia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"senegal\": {\n", + " \"_total\": 0\n", + " },\n", + " \"serbia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"seychelles\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sierra_leone\": {\n", + " \"_total\": 0\n", + " },\n", + " \"singapore\": {\n", + " \"_total\": 0\n", + " },\n", + " \"slovakia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"slovenia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"solomon_islands\": {\n", + " \"_total\": 0\n", + " },\n", + " \"somalia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"south_africa\": {\n", + " \"_total\": 0\n", + " },\n", + " \"south_korea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"south_sudan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"spain\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sri_lanka\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sudan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"suriname\": {\n", + " \"_total\": 0\n", + " },\n", + " \"swaziland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sweden\": {\n", + " \"_total\": 0\n", + " },\n", + " \"switzerland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"syria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"taiwan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tajikistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tanzania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"thailand\": {\n", + " \"_total\": 0\n", + " },\n", + " \"timor_leste\": {\n", + " \"_total\": 0\n", + " },\n", + " \"togo\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tonga\": {\n", + " \"_total\": 0\n", + " },\n", + " \"trinidad_and_tobago\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tunisia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"turkey\": {\n", + " \"_total\": 0\n", + " },\n", + " \"turkmenistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tuvalu\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uganda\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ukraine\": {\n", + " \"_total\": 0\n", + " },\n", + " \"united_arab_emirates\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uk\": {\n", + " \"_total\": 0\n", + " },\n", + " \"usa\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uruguay\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uzbekistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"vanuatu\": {\n", + " \"_total\": 0\n", + " },\n", + " \"vatican\": {\n", + " \"_total\": 0\n", + " },\n", + " \"venezuela\": {\n", + " \"_total\": 0\n", + " },\n", + " \"vietnam\": {\n", + " \"_total\": 0\n", + " },\n", + " \"yemen\": {\n", + " \"_total\": 0\n", + " },\n", + " \"zambia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"zimbabwe\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + "}\n", + "6 {'en': 'Cases by Age and Sex', 'fr': 'Cases by Age and Sex', 'ar': 'Cases by Age and Sex'}\n", + "{\n", + " \"id\": 6,\n", + " \"name\": {\n", + " \"en\": \"Cases by Age and Sex\",\n", + " \"fr\": \"Cases by Age and Sex\",\n", + " \"ar\": \"Cases by Age and Sex\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by age and sex\",\n", + " \"fr\": \"Number of cases broken down by age and sex\",\n", + " \"ar\": \"Number of cases broken down by age and sex\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": true,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"age\",\n", + " \"display_name\": {\n", + " \"en\": \"Age\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"sex\",\n", + " \"display_name\": {\n", + " \"en\": \"Sex\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"male\",\n", + " \"display_text\": \"Male\"\n", + " },\n", + " {\n", + " \"id\": \"female\",\n", + " \"display_text\": \"Female\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"6 - 11\": {\n", + " \"_total\": 2,\n", + " \"male\": {\n", + " \"_total\": 2\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " },\n", + " \"12 - 17\": {\n", + " \"_total\": 1,\n", + " \"male\": {\n", + " \"_total\": 1\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + " }\n", + "}\n", + "7 {'en': 'Cases by Protection Concern', 'fr': 'Cases by Protection Concern', 'ar': 'Cases by Protection Concern'}\n", + "{\n", + " \"id\": 7,\n", + " \"name\": {\n", + " \"en\": \"Cases by Protection Concern\",\n", + " \"fr\": \"Cases by Protection Concern\",\n", + " \"ar\": \"Cases by Protection Concern\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by protection concern and sex\",\n", + " \"fr\": \"Number of cases broken down by protection concern and sex\",\n", + " \"ar\": \"Number of cases broken down by protection concern and sex\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"protection_concerns\",\n", + " \"display_name\": {\n", + " \"en\": \"Protection Concerns\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"sexually_exploited\",\n", + " \"display_text\": \"Sexually Exploited\"\n", + " },\n", + " {\n", + " \"id\": \"gbv_survivor\",\n", + " \"display_text\": \"GBV survivor\"\n", + " },\n", + " {\n", + " \"id\": \"trafficked_smuggled\",\n", + " \"display_text\": \"Trafficked/smuggled\"\n", + " },\n", + " {\n", + " \"id\": \"statelessness\",\n", + " \"display_text\": \"Statelessness\"\n", + " },\n", + " {\n", + " \"id\": \"arrested_detained\",\n", + " \"display_text\": \"Arrested/Detained\"\n", + " },\n", + " {\n", + " \"id\": \"migrant\",\n", + " \"display_text\": \"Migrant\"\n", + " },\n", + " {\n", + " \"id\": \"disabled\",\n", + " \"display_text\": \"Disabled\"\n", + " },\n", + " {\n", + " \"id\": \"serious_health_issue\",\n", + " \"display_text\": \"Serious health issue\"\n", + " },\n", + " {\n", + " \"id\": \"refugee\",\n", + " \"display_text\": \"Refugee\"\n", + " },\n", + " {\n", + " \"id\": \"caafag\",\n", + " \"display_text\": \"CAAFAG\"\n", + " },\n", + " {\n", + " \"id\": \"street_child\",\n", + " \"display_text\": \"Street child\"\n", + " },\n", + " {\n", + " \"id\": \"child_mother\",\n", + " \"display_text\": \"Child Mother\"\n", + " },\n", + " {\n", + " \"id\": \"physically_or_mentally_abused\",\n", + " \"display_text\": \"Physically or Mentally Abused\"\n", + " },\n", + " {\n", + " \"id\": \"living_with_vulnerable_person\",\n", + " \"display_text\": \"Living with vulnerable person\"\n", + " },\n", + " {\n", + " \"id\": \"worst_forms_of_child_labor\",\n", + " \"display_text\": \"Worst Forms of Child Labor\"\n", + " },\n", + " {\n", + " \"id\": \"child_headed_household\",\n", + " \"display_text\": \"Child Headed Household\"\n", + " },\n", + " {\n", + " \"id\": \"mentally_distressed\",\n", + " \"display_text\": \"Mentally Distressed\"\n", + " },\n", + " {\n", + " \"id\": \"other\",\n", + " \"display_text\": \"Other\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"sex\",\n", + " \"display_name\": {\n", + " \"en\": \"Sex\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"male\",\n", + " \"display_text\": \"Male\"\n", + " },\n", + " {\n", + " \"id\": \"female\",\n", + " \"display_text\": \"Female\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"sexually_exploited\": {\n", + " \"_total\": 0\n", + " },\n", + " \"gbv_survivor\": {\n", + " \"_total\": 0\n", + " },\n", + " \"trafficked_smuggled\": {\n", + " \"_total\": 0\n", + " },\n", + " \"statelessness\": {\n", + " \"_total\": 0\n", + " },\n", + " \"arrested_detained\": {\n", + " \"_total\": 0\n", + " },\n", + " \"migrant\": {\n", + " \"_total\": 1,\n", + " \"male\": {\n", + " \"_total\": 1\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " },\n", + " \"disabled\": {\n", + " \"_total\": 0\n", + " },\n", + " \"serious_health_issue\": {\n", + " \"_total\": 0\n", + " },\n", + " \"refugee\": {\n", + " \"_total\": 0\n", + " },\n", + " \"caafag\": {\n", + " \"_total\": 0\n", + " },\n", + " \"street_child\": {\n", + " \"_total\": 0\n", + " },\n", + " \"child_mother\": {\n", + " \"_total\": 0\n", + " },\n", + " \"physically_or_mentally_abused\": {\n", + " \"_total\": 0\n", + " },\n", + " \"living_with_vulnerable_person\": {\n", + " \"_total\": 0\n", + " },\n", + " \"worst_forms_of_child_labor\": {\n", + " \"_total\": 0\n", + " },\n", + " \"child_headed_household\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mentally_distressed\": {\n", + " \"_total\": 0\n", + " },\n", + " \"other\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + "}\n", + "8 {'en': 'Current Care Arrangements', 'fr': 'Current Care Arrangements', 'ar': 'Current Care Arrangements'}\n", + "{\n", + " \"id\": 8,\n", + " \"name\": {\n", + " \"en\": \"Current Care Arrangements\",\n", + " \"fr\": \"Current Care Arrangements\",\n", + " \"ar\": \"Current Care Arrangements\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"The care arrangements broken down by age and sex\",\n", + " \"fr\": \"The care arrangements broken down by age and sex\",\n", + " \"ar\": \"The care arrangements broken down by age and sex\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": true,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"care_arrangements_type\",\n", + " \"display_name\": {\n", + " \"en\": \"What are the child's current care arrangements?\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"parent_s\",\n", + " \"display_text\": \"Parent(s)\"\n", + " },\n", + " {\n", + " \"id\": \"step_parent\",\n", + " \"display_text\": \"Step parent\"\n", + " },\n", + " {\n", + " \"id\": \"customary_caregiver_s\",\n", + " \"display_text\": \"Customary caregiver(s)\"\n", + " },\n", + " {\n", + " \"id\": \"adult_sibling\",\n", + " \"display_text\": \"Adult sibling\"\n", + " },\n", + " {\n", + " \"id\": \"kinship_care_extended_family\",\n", + " \"display_text\": \"Kinship care / extended family\"\n", + " },\n", + " {\n", + " \"id\": \"foster_care\",\n", + " \"display_text\": \"Foster care\"\n", + " },\n", + " {\n", + " \"id\": \"residential_care\",\n", + " \"display_text\": \"Residential care\"\n", + " },\n", + " {\n", + " \"id\": \"kafala\",\n", + " \"display_text\": \"Kafala\"\n", + " },\n", + " {\n", + " \"id\": \"independent_living\",\n", + " \"display_text\": \"Independent living\"\n", + " },\n", + " {\n", + " \"id\": \"child_headed_household\",\n", + " \"display_text\": \"Child-headed household\"\n", + " },\n", + " {\n", + " \"id\": \"unrelated_adult\",\n", + " \"display_text\": \"Unrelated adult\"\n", + " },\n", + " {\n", + " \"id\": \"no_care_arrangement\",\n", + " \"display_text\": \"No care arrangement\"\n", + " },\n", + " {\n", + " \"id\": \"other\",\n", + " \"display_text\": \"Other\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"sex\",\n", + " \"display_name\": {\n", + " \"en\": \"Sex\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"male\",\n", + " \"display_text\": \"Male\"\n", + " },\n", + " {\n", + " \"id\": \"female\",\n", + " \"display_text\": \"Female\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"age\",\n", + " \"display_name\": {\n", + " \"en\": \"Age\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 1\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"parent_s\": {\n", + " \"_total\": 0\n", + " },\n", + " \"step_parent\": {\n", + " \"_total\": 0\n", + " },\n", + " \"customary_caregiver_s\": {\n", + " \"_total\": 0\n", + " },\n", + " \"adult_sibling\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kinship_care_extended_family\": {\n", + " \"_total\": 0\n", + " },\n", + " \"foster_care\": {\n", + " \"_total\": 0\n", + " },\n", + " \"residential_care\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kafala\": {\n", + " \"_total\": 0\n", + " },\n", + " \"independent_living\": {\n", + " \"_total\": 0\n", + " },\n", + " \"child_headed_household\": {\n", + " \"_total\": 0\n", + " },\n", + " \"unrelated_adult\": {\n", + " \"_total\": 0\n", + " },\n", + " \"no_care_arrangement\": {\n", + " \"_total\": 0\n", + " },\n", + " \"other\": {\n", + " \"_total\": 0\n", + " },\n", + " \"incomplete_data\": {\n", + " \"_total\": 3,\n", + " \"male\": {\n", + " \"_total\": 3,\n", + " \"6 - 11\": {\n", + " \"_total\": 2\n", + " },\n", + " \"12 - 17\": {\n", + " \"_total\": 1\n", + " }\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + " }\n", + "}\n", + "10 {'en': 'Follow up by month by Agency', 'fr': 'Follow up by month by Agency', 'ar': 'Follow up by month by Agency'}\n", + "{\n", + " \"id\": 10,\n", + " \"name\": {\n", + " \"en\": \"Follow up by month by Agency\",\n", + " \"fr\": \"Follow up by month by Agency\",\n", + " \"ar\": \"Follow up by month by Agency\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of followups broken down by month and agency\",\n", + " \"fr\": \"Number of followups broken down by month and agency\",\n", + " \"ar\": \"Number of followups broken down by month and agency\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"reportable_follow_up\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"month\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " },\n", + " {\n", + " \"value\": \"\",\n", + " \"attribute\": \"followup_date\",\n", + " \"constraint\": \"not_null\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"followup_date\",\n", + " \"display_name\": {\n", + " \"en\": \"Follow up date\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"owned_by_agency_id\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Agency\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Agency\"\n", + " }\n", + " ]\n", + "}\n", + "11 {'en': 'Follow up by week by Agency', 'fr': 'Follow up by week by Agency', 'ar': 'Follow up by week by Agency'}\n", + "{\n", + " \"id\": 11,\n", + " \"name\": {\n", + " \"en\": \"Follow up by week by Agency\",\n", + " \"fr\": \"Follow up by week by Agency\",\n", + " \"ar\": \"Follow up by week by Agency\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of followups broken down by week and agency\",\n", + " \"fr\": \"Number of followups broken down by week and agency\",\n", + " \"ar\": \"Number of followups broken down by week and agency\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"reportable_follow_up\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"week\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " },\n", + " {\n", + " \"value\": \"\",\n", + " \"attribute\": \"followup_date\",\n", + " \"constraint\": \"not_null\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"followup_date\",\n", + " \"display_name\": {\n", + " \"en\": \"Follow up date\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"owned_by_agency_id\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Agency\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Agency\"\n", + " }\n", + " ]\n", + "}\n", + "12 {'en': 'Cases per Month', 'fr': 'Cases per Month', 'ar': 'Cases per Month'}\n", + "{\n", + " \"id\": 12,\n", + " \"name\": {\n", + " \"en\": \"Cases per Month\",\n", + " \"fr\": \"Cases per Month\",\n", + " \"ar\": \"Cases per Month\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \" Number of newly registered cases per month per location \",\n", + " \"fr\": \" Number of newly registered cases per month per location \",\n", + " \"ar\": \" Number of newly registered cases per month per location \"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"month\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by_location\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Location\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Location\"\n", + " },\n", + " {\n", + " \"name\": \"created_at\",\n", + " \"display_name\": {\n", + " \"en\": \"Date of referral or transfer\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ]\n", + "}\n", + "13 {'en': 'Cases with case plans', 'fr': 'Cases with case plans', 'ar': 'Cases with case plans'}\n", + "{\n", + " \"id\": 13,\n", + " \"name\": {\n", + " \"en\": \"Cases with case plans\",\n", + " \"fr\": \"Cases with case plans\",\n", + " \"ar\": \"Cases with case plans\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"How many registered cases have case plans?\",\n", + " \"fr\": \"How many registered cases have case plans?\",\n", + " \"ar\": \"How many registered cases have case plans?\"\n", + " },\n", + " \"graph\": false,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"has_case_plan\",\n", + " \"display_name\": {\n", + " \"en\": \"Does this case have a case plan?\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"\": {\n", + " \"_total\": 0\n", + " },\n", + " \"false\": {\n", + " \"_total\": 2\n", + " },\n", + " \"true\": {\n", + " \"_total\": 1\n", + " }\n", + " }\n", + "}\n" + ] + } + ], + "source": [ + "import json\n", + "for report in reports:\n", + " print(report['id'], report['name'])\n", + " print(json.dumps(report, indent=2))" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Registration CP\n", + "{\n", + " \"id\": 1,\n", + " \"name\": {\n", + " \"en\": \"Registration CP\",\n", + " \"fr\": \"Registration CP\",\n", + " \"ar\": \"Registration CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Case registrations over time\",\n", + " \"fr\": \"Case registrations over time\",\n", + " \"ar\": \"Case registrations over time\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"month\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"registration_date\",\n", + " \"display_name\": {\n", + " \"en\": \"Date of Registration or Interview\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"2024-Oct\": {\n", + " \"_total\": 3\n", + " }\n", + " }\n", + "}\n", + "report_data {'2024-Oct': {'_total': 3}}\n", + "key 2024-Oct datum: {'_total': 3}\n", + "k _total \n", + "2024-Oct {'_total': 3}\n", + "added {'key': '2024-Oct', 'key_label': '2024-Oct', 'total': 3}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249611.92s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " key key_label total\n", + "0 2024-Oct 2024-Oct 3\n", + "2 Caseload Summary CP\n", + "{\n", + " \"id\": 2,\n", + " \"name\": {\n", + " \"en\": \"Caseload Summary CP\",\n", + " \"fr\": \"Caseload Summary CP\",\n", + " \"ar\": \"Caseload Summary CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases for each case worker\",\n", + " \"fr\": \"Number of cases for each case worker\",\n", + " \"ar\": \"Number of cases for each case worker\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by\",\n", + " \"display_name\": {\n", + " \"en\": \"Caseworker Code\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"primero\": {\n", + " \"_total\": 3\n", + " }\n", + " }\n", + "}\n", + "report_data {'primero': {'_total': 3}}\n", + "key primero datum: {'_total': 3}\n", + "k _total \n", + "primero {'_total': 3}\n", + "added {'key': 'primero', 'key_label': 'primero', 'total': 3}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249617.29s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " key key_label total\n", + "0 primero primero 3\n", + "3 Case status by case worker CP\n", + "{\n", + " \"id\": 3,\n", + " \"name\": {\n", + " \"en\": \"Case status by case worker CP\",\n", + " \"fr\": \"Case status by case worker CP\",\n", + " \"ar\": \"Case status by case worker CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Status of cases held by case workers\",\n", + " \"fr\": \"Status of cases held by case workers\",\n", + " \"ar\": \"Status of cases held by case workers\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by\",\n", + " \"display_name\": {\n", + " \"en\": \"Caseworker Code\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"status\",\n", + " \"display_name\": {\n", + " \"en\": \"Case Status\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"open\",\n", + " \"display_text\": \"Open\"\n", + " },\n", + " {\n", + " \"id\": \"closed\",\n", + " \"display_text\": \"Closed\"\n", + " },\n", + " {\n", + " \"id\": \"transferred\",\n", + " \"display_text\": \"Transferred\"\n", + " },\n", + " {\n", + " \"id\": \"duplicate\",\n", + " \"display_text\": \"Duplicate\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"primero\": {\n", + " \"_total\": 3,\n", + " \"open\": {\n", + " \"_total\": 3\n", + " },\n", + " \"closed\": {\n", + " \"_total\": 0\n", + " },\n", + " \"transferred\": {\n", + " \"_total\": 0\n", + " },\n", + " \"duplicate\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + " }\n", + "}\n", + "report_data {'primero': {'_total': 3, 'open': {'_total': 3}, 'closed': {'_total': 0}, 'transferred': {'_total': 0}, 'duplicate': {'_total': 0}}}\n", + "key primero datum: {'_total': 3, 'open': {'_total': 3}, 'closed': {'_total': 0}, 'transferred': {'_total': 0}, 'duplicate': {'_total': 0}}\n", + "k _total \n", + "k open \n", + "k closed \n", + "k transferred \n", + "k duplicate \n", + "primero {'_total': 3, 'open': 3, 'closed': 0, 'transferred': 0, 'duplicate': 0}\n", + "added {'open': 3, 'closed': 0, 'transferred': 0, 'duplicate': 0, 'key': 'primero', 'key_label': 'primero', 'total': 3}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249622.67s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " open closed transferred duplicate key key_label total\n", + "0 3 0 0 0 primero primero 3\n", + "4 Cases by Agency CP\n", + "{\n", + " \"id\": 4,\n", + " \"name\": {\n", + " \"en\": \"Cases by Agency CP\",\n", + " \"fr\": \"Cases by Agency CP\",\n", + " \"ar\": \"Cases by Agency CP\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by agency\",\n", + " \"fr\": \"Number of cases broken down by agency\",\n", + " \"ar\": \"Number of cases broken down by agency\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by_agency_id\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Agency\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Agency\"\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"UNICEF\": {\n", + " \"_total\": 3\n", + " }\n", + " }\n", + "}\n", + "report_data {'UNICEF': {'_total': 3}}\n", + "key UNICEF datum: {'_total': 3}\n", + "k _total \n", + "UNICEF {'_total': 3}\n", + "added {'key': 'UNICEF', 'key_label': 'UNICEF', 'total': 3}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249628.04s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " key key_label total\n", + "0 UNICEF UNICEF 3\n", + "5 Cases by Nationality\n", + "{\n", + " \"id\": 5,\n", + " \"name\": {\n", + " \"en\": \"Cases by Nationality\",\n", + " \"fr\": \"Cases by Nationality\",\n", + " \"ar\": \"Cases by Nationality\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by nationality\",\n", + " \"fr\": \"Number of cases broken down by nationality\",\n", + " \"ar\": \"Number of cases broken down by nationality\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"nationality\",\n", + " \"display_name\": {\n", + " \"en\": \"Nationality\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"afghanistan\",\n", + " \"display_text\": \"Afghanistan\"\n", + " },\n", + " {\n", + " \"id\": \"albania\",\n", + " \"display_text\": \"Albania\"\n", + " },\n", + " {\n", + " \"id\": \"algeria\",\n", + " \"display_text\": \"Algeria\"\n", + " },\n", + " {\n", + " \"id\": \"andorra\",\n", + " \"display_text\": \"Andorra\"\n", + " },\n", + " {\n", + " \"id\": \"angola\",\n", + " \"display_text\": \"Angola\"\n", + " },\n", + " {\n", + " \"id\": \"antigua_and_barbuda\",\n", + " \"display_text\": \"Antigua and Barbuda\"\n", + " },\n", + " {\n", + " \"id\": \"argentina\",\n", + " \"display_text\": \"Argentina\"\n", + " },\n", + " {\n", + " \"id\": \"armenia\",\n", + " \"display_text\": \"Armenia\"\n", + " },\n", + " {\n", + " \"id\": \"australia\",\n", + " \"display_text\": \"Australia\"\n", + " },\n", + " {\n", + " \"id\": \"austria\",\n", + " \"display_text\": \"Austria\"\n", + " },\n", + " {\n", + " \"id\": \"azerbaijan\",\n", + " \"display_text\": \"Azerbaijan\"\n", + " },\n", + " {\n", + " \"id\": \"bahamas\",\n", + " \"display_text\": \"Bahamas\"\n", + " },\n", + " {\n", + " \"id\": \"bahrain\",\n", + " \"display_text\": \"Bahrain\"\n", + " },\n", + " {\n", + " \"id\": \"bangladesh\",\n", + " \"display_text\": \"Bangladesh\"\n", + " },\n", + " {\n", + " \"id\": \"barbados\",\n", + " \"display_text\": \"Barbados\"\n", + " },\n", + " {\n", + " \"id\": \"belarus\",\n", + " \"display_text\": \"Belarus\"\n", + " },\n", + " {\n", + " \"id\": \"belgium\",\n", + " \"display_text\": \"Belgium\"\n", + " },\n", + " {\n", + " \"id\": \"belize\",\n", + " \"display_text\": \"Belize\"\n", + " },\n", + " {\n", + " \"id\": \"benin\",\n", + " \"display_text\": \"Benin\"\n", + " },\n", + " {\n", + " \"id\": \"bhutan\",\n", + " \"display_text\": \"Bhutan\"\n", + " },\n", + " {\n", + " \"id\": \"bolivia\",\n", + " \"display_text\": \"Bolivia\"\n", + " },\n", + " {\n", + " \"id\": \"bosnia_and_herzegovina\",\n", + " \"display_text\": \"Bosnia and Herzegovina\"\n", + " },\n", + " {\n", + " \"id\": \"botswana\",\n", + " \"display_text\": \"Botswana\"\n", + " },\n", + " {\n", + " \"id\": \"brazil\",\n", + " \"display_text\": \"Brazil\"\n", + " },\n", + " {\n", + " \"id\": \"brunei\",\n", + " \"display_text\": \"Brunei\"\n", + " },\n", + " {\n", + " \"id\": \"bulgaria\",\n", + " \"display_text\": \"Bulgaria\"\n", + " },\n", + " {\n", + " \"id\": \"burkina_faso\",\n", + " \"display_text\": \"Burkina Faso\"\n", + " },\n", + " {\n", + " \"id\": \"burundi\",\n", + " \"display_text\": \"Burundi\"\n", + " },\n", + " {\n", + " \"id\": \"cabo_verde\",\n", + " \"display_text\": \"Cabo Verde\"\n", + " },\n", + " {\n", + " \"id\": \"cambodia\",\n", + " \"display_text\": \"Cambodia\"\n", + " },\n", + " {\n", + " \"id\": \"cameroon\",\n", + " \"display_text\": \"Cameroon\"\n", + " },\n", + " {\n", + " \"id\": \"canada\",\n", + " \"display_text\": \"Canada\"\n", + " },\n", + " {\n", + " \"id\": \"central_african_republic\",\n", + " \"display_text\": \"Central African Republic\"\n", + " },\n", + " {\n", + " \"id\": \"chad\",\n", + " \"display_text\": \"Chad\"\n", + " },\n", + " {\n", + " \"id\": \"chile\",\n", + " \"display_text\": \"Chile\"\n", + " },\n", + " {\n", + " \"id\": \"china\",\n", + " \"display_text\": \"China\"\n", + " },\n", + " {\n", + " \"id\": \"colombia\",\n", + " \"display_text\": \"Colombia\"\n", + " },\n", + " {\n", + " \"id\": \"comoros\",\n", + " \"display_text\": \"Comoros\"\n", + " },\n", + " {\n", + " \"id\": \"congo\",\n", + " \"display_text\": \"Congo, Republic of the\"\n", + " },\n", + " {\n", + " \"id\": \"drc\",\n", + " \"display_text\": \"Congo, Democratic Republic of the\"\n", + " },\n", + " {\n", + " \"id\": \"costa_rica\",\n", + " \"display_text\": \"Costa Rica\"\n", + " },\n", + " {\n", + " \"id\": \"cote_divoire\",\n", + " \"display_text\": \"Cote d'Ivoire\"\n", + " },\n", + " {\n", + " \"id\": \"croatia\",\n", + " \"display_text\": \"Croatia\"\n", + " },\n", + " {\n", + " \"id\": \"cuba\",\n", + " \"display_text\": \"Cuba\"\n", + " },\n", + " {\n", + " \"id\": \"cyprus\",\n", + " \"display_text\": \"Cyprus\"\n", + " },\n", + " {\n", + " \"id\": \"czech_republic\",\n", + " \"display_text\": \"Czech Republic\"\n", + " },\n", + " {\n", + " \"id\": \"denmark\",\n", + " \"display_text\": \"Denmark\"\n", + " },\n", + " {\n", + " \"id\": \"djibouti\",\n", + " \"display_text\": \"Djibouti\"\n", + " },\n", + " {\n", + " \"id\": \"dominica\",\n", + " \"display_text\": \"Dominica\"\n", + " },\n", + " {\n", + " \"id\": \"dominican_republic\",\n", + " \"display_text\": \"Dominican Republic\"\n", + " },\n", + " {\n", + " \"id\": \"ecuador\",\n", + " \"display_text\": \"Ecuador\"\n", + " },\n", + " {\n", + " \"id\": \"egypt\",\n", + " \"display_text\": \"Egypt\"\n", + " },\n", + " {\n", + " \"id\": \"el_salvador\",\n", + " \"display_text\": \"El Salvador\"\n", + " },\n", + " {\n", + " \"id\": \"equatorial_guinea\",\n", + " \"display_text\": \"Equatorial Guinea\"\n", + " },\n", + " {\n", + " \"id\": \"eritrea\",\n", + " \"display_text\": \"Eritrea\"\n", + " },\n", + " {\n", + " \"id\": \"estonia\",\n", + " \"display_text\": \"Estonia\"\n", + " },\n", + " {\n", + " \"id\": \"ethiopia\",\n", + " \"display_text\": \"Ethiopia\"\n", + " },\n", + " {\n", + " \"id\": \"fiji\",\n", + " \"display_text\": \"Fiji\"\n", + " },\n", + " {\n", + " \"id\": \"finland\",\n", + " \"display_text\": \"Finland\"\n", + " },\n", + " {\n", + " \"id\": \"france\",\n", + " \"display_text\": \"France\"\n", + " },\n", + " {\n", + " \"id\": \"gabon\",\n", + " \"display_text\": \"Gabon\"\n", + " },\n", + " {\n", + " \"id\": \"gambia\",\n", + " \"display_text\": \"Gambia\"\n", + " },\n", + " {\n", + " \"id\": \"georgia\",\n", + " \"display_text\": \"Georgia\"\n", + " },\n", + " {\n", + " \"id\": \"germany\",\n", + " \"display_text\": \"Germany\"\n", + " },\n", + " {\n", + " \"id\": \"ghana\",\n", + " \"display_text\": \"Ghana\"\n", + " },\n", + " {\n", + " \"id\": \"greece\",\n", + " \"display_text\": \"Greece\"\n", + " },\n", + " {\n", + " \"id\": \"grenada\",\n", + " \"display_text\": \"Grenada\"\n", + " },\n", + " {\n", + " \"id\": \"guatemala\",\n", + " \"display_text\": \"Guatemala\"\n", + " },\n", + " {\n", + " \"id\": \"guinea\",\n", + " \"display_text\": \"Guinea\"\n", + " },\n", + " {\n", + " \"id\": \"guinea_bissau\",\n", + " \"display_text\": \"Guinea-Bissau\"\n", + " },\n", + " {\n", + " \"id\": \"guyana\",\n", + " \"display_text\": \"Guyana\"\n", + " },\n", + " {\n", + " \"id\": \"haiti\",\n", + " \"display_text\": \"Haiti\"\n", + " },\n", + " {\n", + " \"id\": \"honduras\",\n", + " \"display_text\": \"Honduras\"\n", + " },\n", + " {\n", + " \"id\": \"hungary\",\n", + " \"display_text\": \"Hungary\"\n", + " },\n", + " {\n", + " \"id\": \"iceland\",\n", + " \"display_text\": \"Iceland\"\n", + " },\n", + " {\n", + " \"id\": \"india\",\n", + " \"display_text\": \"India\"\n", + " },\n", + " {\n", + " \"id\": \"indonesia\",\n", + " \"display_text\": \"Indonesia\"\n", + " },\n", + " {\n", + " \"id\": \"iran\",\n", + " \"display_text\": \"Iran\"\n", + " },\n", + " {\n", + " \"id\": \"iraq\",\n", + " \"display_text\": \"Iraq\"\n", + " },\n", + " {\n", + " \"id\": \"ireland\",\n", + " \"display_text\": \"Ireland\"\n", + " },\n", + " {\n", + " \"id\": \"israel\",\n", + " \"display_text\": \"Israel\"\n", + " },\n", + " {\n", + " \"id\": \"italy\",\n", + " \"display_text\": \"Italy\"\n", + " },\n", + " {\n", + " \"id\": \"jamaica\",\n", + " \"display_text\": \"Jamaica\"\n", + " },\n", + " {\n", + " \"id\": \"japan\",\n", + " \"display_text\": \"Japan\"\n", + " },\n", + " {\n", + " \"id\": \"jordan\",\n", + " \"display_text\": \"Jordan\"\n", + " },\n", + " {\n", + " \"id\": \"kazakhstan\",\n", + " \"display_text\": \"Kazakhstan\"\n", + " },\n", + " {\n", + " \"id\": \"kenya\",\n", + " \"display_text\": \"Kenya\"\n", + " },\n", + " {\n", + " \"id\": \"kiribati\",\n", + " \"display_text\": \"Kiribati\"\n", + " },\n", + " {\n", + " \"id\": \"kosovo\",\n", + " \"display_text\": \"Kosovo\"\n", + " },\n", + " {\n", + " \"id\": \"kuwait\",\n", + " \"display_text\": \"Kuwait\"\n", + " },\n", + " {\n", + " \"id\": \"kyrgyzstan\",\n", + " \"display_text\": \"Kyrgyzstan\"\n", + " },\n", + " {\n", + " \"id\": \"laos\",\n", + " \"display_text\": \"Laos\"\n", + " },\n", + " {\n", + " \"id\": \"latvia\",\n", + " \"display_text\": \"Latvia\"\n", + " },\n", + " {\n", + " \"id\": \"lebanon\",\n", + " \"display_text\": \"Lebanon\"\n", + " },\n", + " {\n", + " \"id\": \"lesotho\",\n", + " \"display_text\": \"Lesotho\"\n", + " },\n", + " {\n", + " \"id\": \"liberia\",\n", + " \"display_text\": \"Liberia\"\n", + " },\n", + " {\n", + " \"id\": \"libya\",\n", + " \"display_text\": \"Libya\"\n", + " },\n", + " {\n", + " \"id\": \"liechtenstein\",\n", + " \"display_text\": \"Liechtenstein\"\n", + " },\n", + " {\n", + " \"id\": \"lithuania\",\n", + " \"display_text\": \"Lithuania\"\n", + " },\n", + " {\n", + " \"id\": \"luxembourg\",\n", + " \"display_text\": \"Luxembourg\"\n", + " },\n", + " {\n", + " \"id\": \"macedonia\",\n", + " \"display_text\": \"Macedonia\"\n", + " },\n", + " {\n", + " \"id\": \"madagascar\",\n", + " \"display_text\": \"Madagascar\"\n", + " },\n", + " {\n", + " \"id\": \"malawi\",\n", + " \"display_text\": \"Malawi\"\n", + " },\n", + " {\n", + " \"id\": \"malaysia\",\n", + " \"display_text\": \"Malaysia\"\n", + " },\n", + " {\n", + " \"id\": \"maldives\",\n", + " \"display_text\": \"Maldives\"\n", + " },\n", + " {\n", + " \"id\": \"mali\",\n", + " \"display_text\": \"Mali\"\n", + " },\n", + " {\n", + " \"id\": \"malta\",\n", + " \"display_text\": \"Malta\"\n", + " },\n", + " {\n", + " \"id\": \"marshall_islands\",\n", + " \"display_text\": \"Marshall Islands\"\n", + " },\n", + " {\n", + " \"id\": \"mauritania\",\n", + " \"display_text\": \"Mauritania\"\n", + " },\n", + " {\n", + " \"id\": \"mauritius\",\n", + " \"display_text\": \"Mauritius\"\n", + " },\n", + " {\n", + " \"id\": \"mexico\",\n", + " \"display_text\": \"Mexico\"\n", + " },\n", + " {\n", + " \"id\": \"micronesia\",\n", + " \"display_text\": \"Micronesia\"\n", + " },\n", + " {\n", + " \"id\": \"moldova\",\n", + " \"display_text\": \"Moldova\"\n", + " },\n", + " {\n", + " \"id\": \"monaco\",\n", + " \"display_text\": \"Monaco\"\n", + " },\n", + " {\n", + " \"id\": \"mongolia\",\n", + " \"display_text\": \"Mongolia\"\n", + " },\n", + " {\n", + " \"id\": \"montenegro\",\n", + " \"display_text\": \"Montenegro\"\n", + " },\n", + " {\n", + " \"id\": \"morocco\",\n", + " \"display_text\": \"Morocco\"\n", + " },\n", + " {\n", + " \"id\": \"mozambique\",\n", + " \"display_text\": \"Mozambique\"\n", + " },\n", + " {\n", + " \"id\": \"myanmar\",\n", + " \"display_text\": \"Myanmar\"\n", + " },\n", + " {\n", + " \"id\": \"namibia\",\n", + " \"display_text\": \"Namibia\"\n", + " },\n", + " {\n", + " \"id\": \"nauru\",\n", + " \"display_text\": \"Nauru\"\n", + " },\n", + " {\n", + " \"id\": \"nepal\",\n", + " \"display_text\": \"Nepal\"\n", + " },\n", + " {\n", + " \"id\": \"netherlands\",\n", + " \"display_text\": \"Netherlands\"\n", + " },\n", + " {\n", + " \"id\": \"new_zealand\",\n", + " \"display_text\": \"New Zealand\"\n", + " },\n", + " {\n", + " \"id\": \"nicaragua\",\n", + " \"display_text\": \"Nicaragua\"\n", + " },\n", + " {\n", + " \"id\": \"niger\",\n", + " \"display_text\": \"Niger\"\n", + " },\n", + " {\n", + " \"id\": \"nigeria\",\n", + " \"display_text\": \"Nigeria\"\n", + " },\n", + " {\n", + " \"id\": \"north_korea\",\n", + " \"display_text\": \"North Korea\"\n", + " },\n", + " {\n", + " \"id\": \"norway\",\n", + " \"display_text\": \"Norway\"\n", + " },\n", + " {\n", + " \"id\": \"oman\",\n", + " \"display_text\": \"Oman\"\n", + " },\n", + " {\n", + " \"id\": \"pakistan\",\n", + " \"display_text\": \"Pakistan\"\n", + " },\n", + " {\n", + " \"id\": \"palau\",\n", + " \"display_text\": \"Palau\"\n", + " },\n", + " {\n", + " \"id\": \"palestine\",\n", + " \"display_text\": \"Palestine\"\n", + " },\n", + " {\n", + " \"id\": \"panama\",\n", + " \"display_text\": \"Panama\"\n", + " },\n", + " {\n", + " \"id\": \"papua_new_guinea\",\n", + " \"display_text\": \"Papua New Guinea\"\n", + " },\n", + " {\n", + " \"id\": \"paraguay\",\n", + " \"display_text\": \"Paraguay\"\n", + " },\n", + " {\n", + " \"id\": \"peru\",\n", + " \"display_text\": \"Peru\"\n", + " },\n", + " {\n", + " \"id\": \"philippines\",\n", + " \"display_text\": \"Philippines\"\n", + " },\n", + " {\n", + " \"id\": \"poland\",\n", + " \"display_text\": \"Poland\"\n", + " },\n", + " {\n", + " \"id\": \"portugal\",\n", + " \"display_text\": \"Portugal\"\n", + " },\n", + " {\n", + " \"id\": \"qatar\",\n", + " \"display_text\": \"Qatar\"\n", + " },\n", + " {\n", + " \"id\": \"romania\",\n", + " \"display_text\": \"Romania\"\n", + " },\n", + " {\n", + " \"id\": \"russia\",\n", + " \"display_text\": \"Russia\"\n", + " },\n", + " {\n", + " \"id\": \"rwanda\",\n", + " \"display_text\": \"Rwanda\"\n", + " },\n", + " {\n", + " \"id\": \"st_kitts_and_nevis\",\n", + " \"display_text\": \"St. Kitts and Nevis\"\n", + " },\n", + " {\n", + " \"id\": \"st_lucia\",\n", + " \"display_text\": \"St. Lucia\"\n", + " },\n", + " {\n", + " \"id\": \"st_vincent_and_the_grenadines\",\n", + " \"display_text\": \"St. Vincent and The Grenadines\"\n", + " },\n", + " {\n", + " \"id\": \"samoa\",\n", + " \"display_text\": \"Samoa\"\n", + " },\n", + " {\n", + " \"id\": \"san_marino\",\n", + " \"display_text\": \"San Marino\"\n", + " },\n", + " {\n", + " \"id\": \"sao_tome_and_principe\",\n", + " \"display_text\": \"Sao Tome and Principe\"\n", + " },\n", + " {\n", + " \"id\": \"saudi_arabia\",\n", + " \"display_text\": \"Saudi Arabia\"\n", + " },\n", + " {\n", + " \"id\": \"senegal\",\n", + " \"display_text\": \"Senegal\"\n", + " },\n", + " {\n", + " \"id\": \"serbia\",\n", + " \"display_text\": \"Serbia\"\n", + " },\n", + " {\n", + " \"id\": \"seychelles\",\n", + " \"display_text\": \"Seychelles\"\n", + " },\n", + " {\n", + " \"id\": \"sierra_leone\",\n", + " \"display_text\": \"Sierra Leone\"\n", + " },\n", + " {\n", + " \"id\": \"singapore\",\n", + " \"display_text\": \"Singapore\"\n", + " },\n", + " {\n", + " \"id\": \"slovakia\",\n", + " \"display_text\": \"Slovakia\"\n", + " },\n", + " {\n", + " \"id\": \"slovenia\",\n", + " \"display_text\": \"Slovenia\"\n", + " },\n", + " {\n", + " \"id\": \"solomon_islands\",\n", + " \"display_text\": \"Solomon Islands\"\n", + " },\n", + " {\n", + " \"id\": \"somalia\",\n", + " \"display_text\": \"Somalia\"\n", + " },\n", + " {\n", + " \"id\": \"south_africa\",\n", + " \"display_text\": \"South Africa\"\n", + " },\n", + " {\n", + " \"id\": \"south_korea\",\n", + " \"display_text\": \"South Korea\"\n", + " },\n", + " {\n", + " \"id\": \"south_sudan\",\n", + " \"display_text\": \"South Sudan\"\n", + " },\n", + " {\n", + " \"id\": \"spain\",\n", + " \"display_text\": \"Spain\"\n", + " },\n", + " {\n", + " \"id\": \"sri_lanka\",\n", + " \"display_text\": \"Sri Lanka\"\n", + " },\n", + " {\n", + " \"id\": \"sudan\",\n", + " \"display_text\": \"Sudan\"\n", + " },\n", + " {\n", + " \"id\": \"suriname\",\n", + " \"display_text\": \"Suriname\"\n", + " },\n", + " {\n", + " \"id\": \"swaziland\",\n", + " \"display_text\": \"Swaziland\"\n", + " },\n", + " {\n", + " \"id\": \"sweden\",\n", + " \"display_text\": \"Sweden\"\n", + " },\n", + " {\n", + " \"id\": \"switzerland\",\n", + " \"display_text\": \"Switzerland\"\n", + " },\n", + " {\n", + " \"id\": \"syria\",\n", + " \"display_text\": \"Syria\"\n", + " },\n", + " {\n", + " \"id\": \"taiwan\",\n", + " \"display_text\": \"Taiwan\"\n", + " },\n", + " {\n", + " \"id\": \"tajikistan\",\n", + " \"display_text\": \"Tajikistan\"\n", + " },\n", + " {\n", + " \"id\": \"tanzania\",\n", + " \"display_text\": \"Tanzania\"\n", + " },\n", + " {\n", + " \"id\": \"thailand\",\n", + " \"display_text\": \"Thailand\"\n", + " },\n", + " {\n", + " \"id\": \"timor_leste\",\n", + " \"display_text\": \"Timor-Leste\"\n", + " },\n", + " {\n", + " \"id\": \"togo\",\n", + " \"display_text\": \"Togo\"\n", + " },\n", + " {\n", + " \"id\": \"tonga\",\n", + " \"display_text\": \"Tonga\"\n", + " },\n", + " {\n", + " \"id\": \"trinidad_and_tobago\",\n", + " \"display_text\": \"Trinidad and Tobago\"\n", + " },\n", + " {\n", + " \"id\": \"tunisia\",\n", + " \"display_text\": \"Tunisia\"\n", + " },\n", + " {\n", + " \"id\": \"turkey\",\n", + " \"display_text\": \"Turkey\"\n", + " },\n", + " {\n", + " \"id\": \"turkmenistan\",\n", + " \"display_text\": \"Turkmenistan\"\n", + " },\n", + " {\n", + " \"id\": \"tuvalu\",\n", + " \"display_text\": \"Tuvalu\"\n", + " },\n", + " {\n", + " \"id\": \"uganda\",\n", + " \"display_text\": \"Uganda\"\n", + " },\n", + " {\n", + " \"id\": \"ukraine\",\n", + " \"display_text\": \"Ukraine\"\n", + " },\n", + " {\n", + " \"id\": \"united_arab_emirates\",\n", + " \"display_text\": \"United Arab Emirates\"\n", + " },\n", + " {\n", + " \"id\": \"uk\",\n", + " \"display_text\": \"UK (United Kingdom)\"\n", + " },\n", + " {\n", + " \"id\": \"usa\",\n", + " \"display_text\": \"USA (United States of America)\"\n", + " },\n", + " {\n", + " \"id\": \"uruguay\",\n", + " \"display_text\": \"Uruguay\"\n", + " },\n", + " {\n", + " \"id\": \"uzbekistan\",\n", + " \"display_text\": \"Uzbekistan\"\n", + " },\n", + " {\n", + " \"id\": \"vanuatu\",\n", + " \"display_text\": \"Vanuatu\"\n", + " },\n", + " {\n", + " \"id\": \"vatican\",\n", + " \"display_text\": \"Vatican City (Holy See)\"\n", + " },\n", + " {\n", + " \"id\": \"venezuela\",\n", + " \"display_text\": \"Venezuela\"\n", + " },\n", + " {\n", + " \"id\": \"vietnam\",\n", + " \"display_text\": \"Vietnam\"\n", + " },\n", + " {\n", + " \"id\": \"yemen\",\n", + " \"display_text\": \"Yemen\"\n", + " },\n", + " {\n", + " \"id\": \"zambia\",\n", + " \"display_text\": \"Zambia\"\n", + " },\n", + " {\n", + " \"id\": \"zimbabwe\",\n", + " \"display_text\": \"Zimbabwe\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"afghanistan\": {\n", + " \"_total\": 1\n", + " },\n", + " \"albania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"algeria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"andorra\": {\n", + " \"_total\": 1\n", + " },\n", + " \"angola\": {\n", + " \"_total\": 0\n", + " },\n", + " \"antigua_and_barbuda\": {\n", + " \"_total\": 1\n", + " },\n", + " \"argentina\": {\n", + " \"_total\": 0\n", + " },\n", + " \"armenia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"australia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"austria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"azerbaijan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bahamas\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bahrain\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bangladesh\": {\n", + " \"_total\": 0\n", + " },\n", + " \"barbados\": {\n", + " \"_total\": 0\n", + " },\n", + " \"belarus\": {\n", + " \"_total\": 0\n", + " },\n", + " \"belgium\": {\n", + " \"_total\": 0\n", + " },\n", + " \"belize\": {\n", + " \"_total\": 0\n", + " },\n", + " \"benin\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bhutan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bolivia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bosnia_and_herzegovina\": {\n", + " \"_total\": 0\n", + " },\n", + " \"botswana\": {\n", + " \"_total\": 0\n", + " },\n", + " \"brazil\": {\n", + " \"_total\": 0\n", + " },\n", + " \"brunei\": {\n", + " \"_total\": 0\n", + " },\n", + " \"bulgaria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"burkina_faso\": {\n", + " \"_total\": 0\n", + " },\n", + " \"burundi\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cabo_verde\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cambodia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cameroon\": {\n", + " \"_total\": 0\n", + " },\n", + " \"canada\": {\n", + " \"_total\": 0\n", + " },\n", + " \"central_african_republic\": {\n", + " \"_total\": 0\n", + " },\n", + " \"chad\": {\n", + " \"_total\": 0\n", + " },\n", + " \"chile\": {\n", + " \"_total\": 0\n", + " },\n", + " \"china\": {\n", + " \"_total\": 0\n", + " },\n", + " \"colombia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"comoros\": {\n", + " \"_total\": 0\n", + " },\n", + " \"congo\": {\n", + " \"_total\": 0\n", + " },\n", + " \"drc\": {\n", + " \"_total\": 0\n", + " },\n", + " \"costa_rica\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cote_divoire\": {\n", + " \"_total\": 0\n", + " },\n", + " \"croatia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cuba\": {\n", + " \"_total\": 0\n", + " },\n", + " \"cyprus\": {\n", + " \"_total\": 0\n", + " },\n", + " \"czech_republic\": {\n", + " \"_total\": 0\n", + " },\n", + " \"denmark\": {\n", + " \"_total\": 0\n", + " },\n", + " \"djibouti\": {\n", + " \"_total\": 0\n", + " },\n", + " \"dominica\": {\n", + " \"_total\": 0\n", + " },\n", + " \"dominican_republic\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ecuador\": {\n", + " \"_total\": 0\n", + " },\n", + " \"egypt\": {\n", + " \"_total\": 0\n", + " },\n", + " \"el_salvador\": {\n", + " \"_total\": 0\n", + " },\n", + " \"equatorial_guinea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"eritrea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"estonia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ethiopia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"fiji\": {\n", + " \"_total\": 0\n", + " },\n", + " \"finland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"france\": {\n", + " \"_total\": 0\n", + " },\n", + " \"gabon\": {\n", + " \"_total\": 0\n", + " },\n", + " \"gambia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"georgia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"germany\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ghana\": {\n", + " \"_total\": 0\n", + " },\n", + " \"greece\": {\n", + " \"_total\": 0\n", + " },\n", + " \"grenada\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guatemala\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guinea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guinea_bissau\": {\n", + " \"_total\": 0\n", + " },\n", + " \"guyana\": {\n", + " \"_total\": 0\n", + " },\n", + " \"haiti\": {\n", + " \"_total\": 0\n", + " },\n", + " \"honduras\": {\n", + " \"_total\": 0\n", + " },\n", + " \"hungary\": {\n", + " \"_total\": 0\n", + " },\n", + " \"iceland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"india\": {\n", + " \"_total\": 0\n", + " },\n", + " \"indonesia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"iran\": {\n", + " \"_total\": 0\n", + " },\n", + " \"iraq\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ireland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"israel\": {\n", + " \"_total\": 0\n", + " },\n", + " \"italy\": {\n", + " \"_total\": 0\n", + " },\n", + " \"jamaica\": {\n", + " \"_total\": 0\n", + " },\n", + " \"japan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"jordan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kazakhstan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kenya\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kiribati\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kosovo\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kuwait\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kyrgyzstan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"laos\": {\n", + " \"_total\": 0\n", + " },\n", + " \"latvia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"lebanon\": {\n", + " \"_total\": 0\n", + " },\n", + " \"lesotho\": {\n", + " \"_total\": 0\n", + " },\n", + " \"liberia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"libya\": {\n", + " \"_total\": 0\n", + " },\n", + " \"liechtenstein\": {\n", + " \"_total\": 0\n", + " },\n", + " \"lithuania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"luxembourg\": {\n", + " \"_total\": 0\n", + " },\n", + " \"macedonia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"madagascar\": {\n", + " \"_total\": 0\n", + " },\n", + " \"malawi\": {\n", + " \"_total\": 0\n", + " },\n", + " \"malaysia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"maldives\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mali\": {\n", + " \"_total\": 0\n", + " },\n", + " \"malta\": {\n", + " \"_total\": 0\n", + " },\n", + " \"marshall_islands\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mauritania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mauritius\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mexico\": {\n", + " \"_total\": 0\n", + " },\n", + " \"micronesia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"moldova\": {\n", + " \"_total\": 0\n", + " },\n", + " \"monaco\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mongolia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"montenegro\": {\n", + " \"_total\": 0\n", + " },\n", + " \"morocco\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mozambique\": {\n", + " \"_total\": 0\n", + " },\n", + " \"myanmar\": {\n", + " \"_total\": 0\n", + " },\n", + " \"namibia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nauru\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nepal\": {\n", + " \"_total\": 0\n", + " },\n", + " \"netherlands\": {\n", + " \"_total\": 0\n", + " },\n", + " \"new_zealand\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nicaragua\": {\n", + " \"_total\": 0\n", + " },\n", + " \"niger\": {\n", + " \"_total\": 0\n", + " },\n", + " \"nigeria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"north_korea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"norway\": {\n", + " \"_total\": 0\n", + " },\n", + " \"oman\": {\n", + " \"_total\": 0\n", + " },\n", + " \"pakistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"palau\": {\n", + " \"_total\": 0\n", + " },\n", + " \"palestine\": {\n", + " \"_total\": 0\n", + " },\n", + " \"panama\": {\n", + " \"_total\": 0\n", + " },\n", + " \"papua_new_guinea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"paraguay\": {\n", + " \"_total\": 0\n", + " },\n", + " \"peru\": {\n", + " \"_total\": 0\n", + " },\n", + " \"philippines\": {\n", + " \"_total\": 0\n", + " },\n", + " \"poland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"portugal\": {\n", + " \"_total\": 0\n", + " },\n", + " \"qatar\": {\n", + " \"_total\": 0\n", + " },\n", + " \"romania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"russia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"rwanda\": {\n", + " \"_total\": 0\n", + " },\n", + " \"st_kitts_and_nevis\": {\n", + " \"_total\": 0\n", + " },\n", + " \"st_lucia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"st_vincent_and_the_grenadines\": {\n", + " \"_total\": 0\n", + " },\n", + " \"samoa\": {\n", + " \"_total\": 0\n", + " },\n", + " \"san_marino\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sao_tome_and_principe\": {\n", + " \"_total\": 0\n", + " },\n", + " \"saudi_arabia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"senegal\": {\n", + " \"_total\": 0\n", + " },\n", + " \"serbia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"seychelles\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sierra_leone\": {\n", + " \"_total\": 0\n", + " },\n", + " \"singapore\": {\n", + " \"_total\": 0\n", + " },\n", + " \"slovakia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"slovenia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"solomon_islands\": {\n", + " \"_total\": 0\n", + " },\n", + " \"somalia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"south_africa\": {\n", + " \"_total\": 0\n", + " },\n", + " \"south_korea\": {\n", + " \"_total\": 0\n", + " },\n", + " \"south_sudan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"spain\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sri_lanka\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sudan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"suriname\": {\n", + " \"_total\": 0\n", + " },\n", + " \"swaziland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"sweden\": {\n", + " \"_total\": 0\n", + " },\n", + " \"switzerland\": {\n", + " \"_total\": 0\n", + " },\n", + " \"syria\": {\n", + " \"_total\": 0\n", + " },\n", + " \"taiwan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tajikistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tanzania\": {\n", + " \"_total\": 0\n", + " },\n", + " \"thailand\": {\n", + " \"_total\": 0\n", + " },\n", + " \"timor_leste\": {\n", + " \"_total\": 0\n", + " },\n", + " \"togo\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tonga\": {\n", + " \"_total\": 0\n", + " },\n", + " \"trinidad_and_tobago\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tunisia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"turkey\": {\n", + " \"_total\": 0\n", + " },\n", + " \"turkmenistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"tuvalu\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uganda\": {\n", + " \"_total\": 0\n", + " },\n", + " \"ukraine\": {\n", + " \"_total\": 0\n", + " },\n", + " \"united_arab_emirates\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uk\": {\n", + " \"_total\": 0\n", + " },\n", + " \"usa\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uruguay\": {\n", + " \"_total\": 0\n", + " },\n", + " \"uzbekistan\": {\n", + " \"_total\": 0\n", + " },\n", + " \"vanuatu\": {\n", + " \"_total\": 0\n", + " },\n", + " \"vatican\": {\n", + " \"_total\": 0\n", + " },\n", + " \"venezuela\": {\n", + " \"_total\": 0\n", + " },\n", + " \"vietnam\": {\n", + " \"_total\": 0\n", + " },\n", + " \"yemen\": {\n", + " \"_total\": 0\n", + " },\n", + " \"zambia\": {\n", + " \"_total\": 0\n", + " },\n", + " \"zimbabwe\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + "}\n", + "report_data {'afghanistan': {'_total': 1}, 'albania': {'_total': 0}, 'algeria': {'_total': 0}, 'andorra': {'_total': 1}, 'angola': {'_total': 0}, 'antigua_and_barbuda': {'_total': 1}, 'argentina': {'_total': 0}, 'armenia': {'_total': 0}, 'australia': {'_total': 0}, 'austria': {'_total': 0}, 'azerbaijan': {'_total': 0}, 'bahamas': {'_total': 0}, 'bahrain': {'_total': 0}, 'bangladesh': {'_total': 0}, 'barbados': {'_total': 0}, 'belarus': {'_total': 0}, 'belgium': {'_total': 0}, 'belize': {'_total': 0}, 'benin': {'_total': 0}, 'bhutan': {'_total': 0}, 'bolivia': {'_total': 0}, 'bosnia_and_herzegovina': {'_total': 0}, 'botswana': {'_total': 0}, 'brazil': {'_total': 0}, 'brunei': {'_total': 0}, 'bulgaria': {'_total': 0}, 'burkina_faso': {'_total': 0}, 'burundi': {'_total': 0}, 'cabo_verde': {'_total': 0}, 'cambodia': {'_total': 0}, 'cameroon': {'_total': 0}, 'canada': {'_total': 0}, 'central_african_republic': {'_total': 0}, 'chad': {'_total': 0}, 'chile': {'_total': 0}, 'china': {'_total': 0}, 'colombia': {'_total': 0}, 'comoros': {'_total': 0}, 'congo': {'_total': 0}, 'drc': {'_total': 0}, 'costa_rica': {'_total': 0}, 'cote_divoire': {'_total': 0}, 'croatia': {'_total': 0}, 'cuba': {'_total': 0}, 'cyprus': {'_total': 0}, 'czech_republic': {'_total': 0}, 'denmark': {'_total': 0}, 'djibouti': {'_total': 0}, 'dominica': {'_total': 0}, 'dominican_republic': {'_total': 0}, 'ecuador': {'_total': 0}, 'egypt': {'_total': 0}, 'el_salvador': {'_total': 0}, 'equatorial_guinea': {'_total': 0}, 'eritrea': {'_total': 0}, 'estonia': {'_total': 0}, 'ethiopia': {'_total': 0}, 'fiji': {'_total': 0}, 'finland': {'_total': 0}, 'france': {'_total': 0}, 'gabon': {'_total': 0}, 'gambia': {'_total': 0}, 'georgia': {'_total': 0}, 'germany': {'_total': 0}, 'ghana': {'_total': 0}, 'greece': {'_total': 0}, 'grenada': {'_total': 0}, 'guatemala': {'_total': 0}, 'guinea': {'_total': 0}, 'guinea_bissau': {'_total': 0}, 'guyana': {'_total': 0}, 'haiti': {'_total': 0}, 'honduras': {'_total': 0}, 'hungary': {'_total': 0}, 'iceland': {'_total': 0}, 'india': {'_total': 0}, 'indonesia': {'_total': 0}, 'iran': {'_total': 0}, 'iraq': {'_total': 0}, 'ireland': {'_total': 0}, 'israel': {'_total': 0}, 'italy': {'_total': 0}, 'jamaica': {'_total': 0}, 'japan': {'_total': 0}, 'jordan': {'_total': 0}, 'kazakhstan': {'_total': 0}, 'kenya': {'_total': 0}, 'kiribati': {'_total': 0}, 'kosovo': {'_total': 0}, 'kuwait': {'_total': 0}, 'kyrgyzstan': {'_total': 0}, 'laos': {'_total': 0}, 'latvia': {'_total': 0}, 'lebanon': {'_total': 0}, 'lesotho': {'_total': 0}, 'liberia': {'_total': 0}, 'libya': {'_total': 0}, 'liechtenstein': {'_total': 0}, 'lithuania': {'_total': 0}, 'luxembourg': {'_total': 0}, 'macedonia': {'_total': 0}, 'madagascar': {'_total': 0}, 'malawi': {'_total': 0}, 'malaysia': {'_total': 0}, 'maldives': {'_total': 0}, 'mali': {'_total': 0}, 'malta': {'_total': 0}, 'marshall_islands': {'_total': 0}, 'mauritania': {'_total': 0}, 'mauritius': {'_total': 0}, 'mexico': {'_total': 0}, 'micronesia': {'_total': 0}, 'moldova': {'_total': 0}, 'monaco': {'_total': 0}, 'mongolia': {'_total': 0}, 'montenegro': {'_total': 0}, 'morocco': {'_total': 0}, 'mozambique': {'_total': 0}, 'myanmar': {'_total': 0}, 'namibia': {'_total': 0}, 'nauru': {'_total': 0}, 'nepal': {'_total': 0}, 'netherlands': {'_total': 0}, 'new_zealand': {'_total': 0}, 'nicaragua': {'_total': 0}, 'niger': {'_total': 0}, 'nigeria': {'_total': 0}, 'north_korea': {'_total': 0}, 'norway': {'_total': 0}, 'oman': {'_total': 0}, 'pakistan': {'_total': 0}, 'palau': {'_total': 0}, 'palestine': {'_total': 0}, 'panama': {'_total': 0}, 'papua_new_guinea': {'_total': 0}, 'paraguay': {'_total': 0}, 'peru': {'_total': 0}, 'philippines': {'_total': 0}, 'poland': {'_total': 0}, 'portugal': {'_total': 0}, 'qatar': {'_total': 0}, 'romania': {'_total': 0}, 'russia': {'_total': 0}, 'rwanda': {'_total': 0}, 'st_kitts_and_nevis': {'_total': 0}, 'st_lucia': {'_total': 0}, 'st_vincent_and_the_grenadines': {'_total': 0}, 'samoa': {'_total': 0}, 'san_marino': {'_total': 0}, 'sao_tome_and_principe': {'_total': 0}, 'saudi_arabia': {'_total': 0}, 'senegal': {'_total': 0}, 'serbia': {'_total': 0}, 'seychelles': {'_total': 0}, 'sierra_leone': {'_total': 0}, 'singapore': {'_total': 0}, 'slovakia': {'_total': 0}, 'slovenia': {'_total': 0}, 'solomon_islands': {'_total': 0}, 'somalia': {'_total': 0}, 'south_africa': {'_total': 0}, 'south_korea': {'_total': 0}, 'south_sudan': {'_total': 0}, 'spain': {'_total': 0}, 'sri_lanka': {'_total': 0}, 'sudan': {'_total': 0}, 'suriname': {'_total': 0}, 'swaziland': {'_total': 0}, 'sweden': {'_total': 0}, 'switzerland': {'_total': 0}, 'syria': {'_total': 0}, 'taiwan': {'_total': 0}, 'tajikistan': {'_total': 0}, 'tanzania': {'_total': 0}, 'thailand': {'_total': 0}, 'timor_leste': {'_total': 0}, 'togo': {'_total': 0}, 'tonga': {'_total': 0}, 'trinidad_and_tobago': {'_total': 0}, 'tunisia': {'_total': 0}, 'turkey': {'_total': 0}, 'turkmenistan': {'_total': 0}, 'tuvalu': {'_total': 0}, 'uganda': {'_total': 0}, 'ukraine': {'_total': 0}, 'united_arab_emirates': {'_total': 0}, 'uk': {'_total': 0}, 'usa': {'_total': 0}, 'uruguay': {'_total': 0}, 'uzbekistan': {'_total': 0}, 'vanuatu': {'_total': 0}, 'vatican': {'_total': 0}, 'venezuela': {'_total': 0}, 'vietnam': {'_total': 0}, 'yemen': {'_total': 0}, 'zambia': {'_total': 0}, 'zimbabwe': {'_total': 0}}\n", + "key afghanistan datum: {'_total': 1}\n", + "k _total \n", + "afghanistan {'_total': 1}\n", + "added {'key': 'afghanistan', 'key_label': 'Afghanistan', 'total': 1}\n", + "key albania datum: {'_total': 0}\n", + "k _total \n", + "albania {'_total': 0}\n", + "added {'key': 'albania', 'key_label': 'Albania', 'total': 0}\n", + "key algeria datum: {'_total': 0}\n", + "k _total \n", + "algeria {'_total': 0}\n", + "added {'key': 'algeria', 'key_label': 'Algeria', 'total': 0}\n", + "key andorra datum: {'_total': 1}\n", + "k _total \n", + "andorra {'_total': 1}\n", + "added {'key': 'andorra', 'key_label': 'Andorra', 'total': 1}\n", + "key angola datum: {'_total': 0}\n", + "k _total \n", + "angola {'_total': 0}\n", + "added {'key': 'angola', 'key_label': 'Angola', 'total': 0}\n", + "key antigua_and_barbuda datum: {'_total': 1}\n", + "k _total \n", + "antigua_and_barbuda {'_total': 1}\n", + "added {'key': 'antigua_and_barbuda', 'key_label': 'Antigua and Barbuda', 'total': 1}\n", + "key argentina datum: {'_total': 0}\n", + "k _total \n", + "argentina {'_total': 0}\n", + "added {'key': 'argentina', 'key_label': 'Argentina', 'total': 0}\n", + "key armenia datum: {'_total': 0}\n", + "k _total \n", + "armenia {'_total': 0}\n", + "added {'key': 'armenia', 'key_label': 'Armenia', 'total': 0}\n", + "key australia datum: {'_total': 0}\n", + "k _total \n", + "australia {'_total': 0}\n", + "added {'key': 'australia', 'key_label': 'Australia', 'total': 0}\n", + "key austria datum: {'_total': 0}\n", + "k _total \n", + "austria {'_total': 0}\n", + "added {'key': 'austria', 'key_label': 'Austria', 'total': 0}\n", + "key azerbaijan datum: {'_total': 0}\n", + "k _total \n", + "azerbaijan {'_total': 0}\n", + "added {'key': 'azerbaijan', 'key_label': 'Azerbaijan', 'total': 0}\n", + "key bahamas datum: {'_total': 0}\n", + "k _total \n", + "bahamas {'_total': 0}\n", + "added {'key': 'bahamas', 'key_label': 'Bahamas', 'total': 0}\n", + "key bahrain datum: {'_total': 0}\n", + "k _total \n", + "bahrain {'_total': 0}\n", + "added {'key': 'bahrain', 'key_label': 'Bahrain', 'total': 0}\n", + "key bangladesh datum: {'_total': 0}\n", + "k _total \n", + "bangladesh {'_total': 0}\n", + "added {'key': 'bangladesh', 'key_label': 'Bangladesh', 'total': 0}\n", + "key barbados datum: {'_total': 0}\n", + "k _total \n", + "barbados {'_total': 0}\n", + "added {'key': 'barbados', 'key_label': 'Barbados', 'total': 0}\n", + "key belarus datum: {'_total': 0}\n", + "k _total \n", + "belarus {'_total': 0}\n", + "added {'key': 'belarus', 'key_label': 'Belarus', 'total': 0}\n", + "key belgium datum: {'_total': 0}\n", + "k _total \n", + "belgium {'_total': 0}\n", + "added {'key': 'belgium', 'key_label': 'Belgium', 'total': 0}\n", + "key belize datum: {'_total': 0}\n", + "k _total \n", + "belize {'_total': 0}\n", + "added {'key': 'belize', 'key_label': 'Belize', 'total': 0}\n", + "key benin datum: {'_total': 0}\n", + "k _total \n", + "benin {'_total': 0}\n", + "added {'key': 'benin', 'key_label': 'Benin', 'total': 0}\n", + "key bhutan datum: {'_total': 0}\n", + "k _total \n", + "bhutan {'_total': 0}\n", + "added {'key': 'bhutan', 'key_label': 'Bhutan', 'total': 0}\n", + "key bolivia datum: {'_total': 0}\n", + "k _total \n", + "bolivia {'_total': 0}\n", + "added {'key': 'bolivia', 'key_label': 'Bolivia', 'total': 0}\n", + "key bosnia_and_herzegovina datum: {'_total': 0}\n", + "k _total \n", + "bosnia_and_herzegovina {'_total': 0}\n", + "added {'key': 'bosnia_and_herzegovina', 'key_label': 'Bosnia and Herzegovina', 'total': 0}\n", + "key botswana datum: {'_total': 0}\n", + "k _total \n", + "botswana {'_total': 0}\n", + "added {'key': 'botswana', 'key_label': 'Botswana', 'total': 0}\n", + "key brazil datum: {'_total': 0}\n", + "k _total \n", + "brazil {'_total': 0}\n", + "added {'key': 'brazil', 'key_label': 'Brazil', 'total': 0}\n", + "key brunei datum: {'_total': 0}\n", + "k _total \n", + "brunei {'_total': 0}\n", + "added {'key': 'brunei', 'key_label': 'Brunei', 'total': 0}\n", + "key bulgaria datum: {'_total': 0}\n", + "k _total \n", + "bulgaria {'_total': 0}\n", + "added {'key': 'bulgaria', 'key_label': 'Bulgaria', 'total': 0}\n", + "key burkina_faso datum: {'_total': 0}\n", + "k _total \n", + "burkina_faso {'_total': 0}\n", + "added {'key': 'burkina_faso', 'key_label': 'Burkina Faso', 'total': 0}\n", + "key burundi datum: {'_total': 0}\n", + "k _total \n", + "burundi {'_total': 0}\n", + "added {'key': 'burundi', 'key_label': 'Burundi', 'total': 0}\n", + "key cabo_verde datum: {'_total': 0}\n", + "k _total \n", + "cabo_verde {'_total': 0}\n", + "added {'key': 'cabo_verde', 'key_label': 'Cabo Verde', 'total': 0}\n", + "key cambodia datum: {'_total': 0}\n", + "k _total \n", + "cambodia {'_total': 0}\n", + "added {'key': 'cambodia', 'key_label': 'Cambodia', 'total': 0}\n", + "key cameroon datum: {'_total': 0}\n", + "k _total \n", + "cameroon {'_total': 0}\n", + "added {'key': 'cameroon', 'key_label': 'Cameroon', 'total': 0}\n", + "key canada datum: {'_total': 0}\n", + "k _total \n", + "canada {'_total': 0}\n", + "added {'key': 'canada', 'key_label': 'Canada', 'total': 0}\n", + "key central_african_republic datum: {'_total': 0}\n", + "k _total \n", + "central_african_republic {'_total': 0}\n", + "added {'key': 'central_african_republic', 'key_label': 'Central African Republic', 'total': 0}\n", + "key chad datum: {'_total': 0}\n", + "k _total \n", + "chad {'_total': 0}\n", + "added {'key': 'chad', 'key_label': 'Chad', 'total': 0}\n", + "key chile datum: {'_total': 0}\n", + "k _total \n", + "chile {'_total': 0}\n", + "added {'key': 'chile', 'key_label': 'Chile', 'total': 0}\n", + "key china datum: {'_total': 0}\n", + "k _total \n", + "china {'_total': 0}\n", + "added {'key': 'china', 'key_label': 'China', 'total': 0}\n", + "key colombia datum: {'_total': 0}\n", + "k _total \n", + "colombia {'_total': 0}\n", + "added {'key': 'colombia', 'key_label': 'Colombia', 'total': 0}\n", + "key comoros datum: {'_total': 0}\n", + "k _total \n", + "comoros {'_total': 0}\n", + "added {'key': 'comoros', 'key_label': 'Comoros', 'total': 0}\n", + "key congo datum: {'_total': 0}\n", + "k _total \n", + "congo {'_total': 0}\n", + "added {'key': 'congo', 'key_label': 'Congo, Republic of the', 'total': 0}\n", + "key drc datum: {'_total': 0}\n", + "k _total \n", + "drc {'_total': 0}\n", + "added {'key': 'drc', 'key_label': 'Congo, Democratic Republic of the', 'total': 0}\n", + "key costa_rica datum: {'_total': 0}\n", + "k _total \n", + "costa_rica {'_total': 0}\n", + "added {'key': 'costa_rica', 'key_label': 'Costa Rica', 'total': 0}\n", + "key cote_divoire datum: {'_total': 0}\n", + "k _total \n", + "cote_divoire {'_total': 0}\n", + "added {'key': 'cote_divoire', 'key_label': \"Cote d'Ivoire\", 'total': 0}\n", + "key croatia datum: {'_total': 0}\n", + "k _total \n", + "croatia {'_total': 0}\n", + "added {'key': 'croatia', 'key_label': 'Croatia', 'total': 0}\n", + "key cuba datum: {'_total': 0}\n", + "k _total \n", + "cuba {'_total': 0}\n", + "added {'key': 'cuba', 'key_label': 'Cuba', 'total': 0}\n", + "key cyprus datum: {'_total': 0}\n", + "k _total \n", + "cyprus {'_total': 0}\n", + "added {'key': 'cyprus', 'key_label': 'Cyprus', 'total': 0}\n", + "key czech_republic datum: {'_total': 0}\n", + "k _total \n", + "czech_republic {'_total': 0}\n", + "added {'key': 'czech_republic', 'key_label': 'Czech Republic', 'total': 0}\n", + "key denmark datum: {'_total': 0}\n", + "k _total \n", + "denmark {'_total': 0}\n", + "added {'key': 'denmark', 'key_label': 'Denmark', 'total': 0}\n", + "key djibouti datum: {'_total': 0}\n", + "k _total \n", + "djibouti {'_total': 0}\n", + "added {'key': 'djibouti', 'key_label': 'Djibouti', 'total': 0}\n", + "key dominica datum: {'_total': 0}\n", + "k _total \n", + "dominica {'_total': 0}\n", + "added {'key': 'dominica', 'key_label': 'Dominica', 'total': 0}\n", + "key dominican_republic datum: {'_total': 0}\n", + "k _total \n", + "dominican_republic {'_total': 0}\n", + "added {'key': 'dominican_republic', 'key_label': 'Dominican Republic', 'total': 0}\n", + "key ecuador datum: {'_total': 0}\n", + "k _total \n", + "ecuador {'_total': 0}\n", + "added {'key': 'ecuador', 'key_label': 'Ecuador', 'total': 0}\n", + "key egypt datum: {'_total': 0}\n", + "k _total \n", + "egypt {'_total': 0}\n", + "added {'key': 'egypt', 'key_label': 'Egypt', 'total': 0}\n", + "key el_salvador datum: {'_total': 0}\n", + "k _total \n", + "el_salvador {'_total': 0}\n", + "added {'key': 'el_salvador', 'key_label': 'El Salvador', 'total': 0}\n", + "key equatorial_guinea datum: {'_total': 0}\n", + "k _total \n", + "equatorial_guinea {'_total': 0}\n", + "added {'key': 'equatorial_guinea', 'key_label': 'Equatorial Guinea', 'total': 0}\n", + "key eritrea datum: {'_total': 0}\n", + "k _total \n", + "eritrea {'_total': 0}\n", + "added {'key': 'eritrea', 'key_label': 'Eritrea', 'total': 0}\n", + "key estonia datum: {'_total': 0}\n", + "k _total \n", + "estonia {'_total': 0}\n", + "added {'key': 'estonia', 'key_label': 'Estonia', 'total': 0}\n", + "key ethiopia datum: {'_total': 0}\n", + "k _total \n", + "ethiopia {'_total': 0}\n", + "added {'key': 'ethiopia', 'key_label': 'Ethiopia', 'total': 0}\n", + "key fiji datum: {'_total': 0}\n", + "k _total \n", + "fiji {'_total': 0}\n", + "added {'key': 'fiji', 'key_label': 'Fiji', 'total': 0}\n", + "key finland datum: {'_total': 0}\n", + "k _total \n", + "finland {'_total': 0}\n", + "added {'key': 'finland', 'key_label': 'Finland', 'total': 0}\n", + "key france datum: {'_total': 0}\n", + "k _total \n", + "france {'_total': 0}\n", + "added {'key': 'france', 'key_label': 'France', 'total': 0}\n", + "key gabon datum: {'_total': 0}\n", + "k _total \n", + "gabon {'_total': 0}\n", + "added {'key': 'gabon', 'key_label': 'Gabon', 'total': 0}\n", + "key gambia datum: {'_total': 0}\n", + "k _total \n", + "gambia {'_total': 0}\n", + "added {'key': 'gambia', 'key_label': 'Gambia', 'total': 0}\n", + "key georgia datum: {'_total': 0}\n", + "k _total \n", + "georgia {'_total': 0}\n", + "added {'key': 'georgia', 'key_label': 'Georgia', 'total': 0}\n", + "key germany datum: {'_total': 0}\n", + "k _total \n", + "germany {'_total': 0}\n", + "added {'key': 'germany', 'key_label': 'Germany', 'total': 0}\n", + "key ghana datum: {'_total': 0}\n", + "k _total \n", + "ghana {'_total': 0}\n", + "added {'key': 'ghana', 'key_label': 'Ghana', 'total': 0}\n", + "key greece datum: {'_total': 0}\n", + "k _total \n", + "greece {'_total': 0}\n", + "added {'key': 'greece', 'key_label': 'Greece', 'total': 0}\n", + "key grenada datum: {'_total': 0}\n", + "k _total \n", + "grenada {'_total': 0}\n", + "added {'key': 'grenada', 'key_label': 'Grenada', 'total': 0}\n", + "key guatemala datum: {'_total': 0}\n", + "k _total \n", + "guatemala {'_total': 0}\n", + "added {'key': 'guatemala', 'key_label': 'Guatemala', 'total': 0}\n", + "key guinea datum: {'_total': 0}\n", + "k _total \n", + "guinea {'_total': 0}\n", + "added {'key': 'guinea', 'key_label': 'Guinea', 'total': 0}\n", + "key guinea_bissau datum: {'_total': 0}\n", + "k _total \n", + "guinea_bissau {'_total': 0}\n", + "added {'key': 'guinea_bissau', 'key_label': 'Guinea-Bissau', 'total': 0}\n", + "key guyana datum: {'_total': 0}\n", + "k _total \n", + "guyana {'_total': 0}\n", + "added {'key': 'guyana', 'key_label': 'Guyana', 'total': 0}\n", + "key haiti datum: {'_total': 0}\n", + "k _total \n", + "haiti {'_total': 0}\n", + "added {'key': 'haiti', 'key_label': 'Haiti', 'total': 0}\n", + "key honduras datum: {'_total': 0}\n", + "k _total \n", + "honduras {'_total': 0}\n", + "added {'key': 'honduras', 'key_label': 'Honduras', 'total': 0}\n", + "key hungary datum: {'_total': 0}\n", + "k _total \n", + "hungary {'_total': 0}\n", + "added {'key': 'hungary', 'key_label': 'Hungary', 'total': 0}\n", + "key iceland datum: {'_total': 0}\n", + "k _total \n", + "iceland {'_total': 0}\n", + "added {'key': 'iceland', 'key_label': 'Iceland', 'total': 0}\n", + "key india datum: {'_total': 0}\n", + "k _total \n", + "india {'_total': 0}\n", + "added {'key': 'india', 'key_label': 'India', 'total': 0}\n", + "key indonesia datum: {'_total': 0}\n", + "k _total \n", + "indonesia {'_total': 0}\n", + "added {'key': 'indonesia', 'key_label': 'Indonesia', 'total': 0}\n", + "key iran datum: {'_total': 0}\n", + "k _total \n", + "iran {'_total': 0}\n", + "added {'key': 'iran', 'key_label': 'Iran', 'total': 0}\n", + "key iraq datum: {'_total': 0}\n", + "k _total \n", + "iraq {'_total': 0}\n", + "added {'key': 'iraq', 'key_label': 'Iraq', 'total': 0}\n", + "key ireland datum: {'_total': 0}\n", + "k _total \n", + "ireland {'_total': 0}\n", + "added {'key': 'ireland', 'key_label': 'Ireland', 'total': 0}\n", + "key israel datum: {'_total': 0}\n", + "k _total \n", + "israel {'_total': 0}\n", + "added {'key': 'israel', 'key_label': 'Israel', 'total': 0}\n", + "key italy datum: {'_total': 0}\n", + "k _total \n", + "italy {'_total': 0}\n", + "added {'key': 'italy', 'key_label': 'Italy', 'total': 0}\n", + "key jamaica datum: {'_total': 0}\n", + "k _total \n", + "jamaica {'_total': 0}\n", + "added {'key': 'jamaica', 'key_label': 'Jamaica', 'total': 0}\n", + "key japan datum: {'_total': 0}\n", + "k _total \n", + "japan {'_total': 0}\n", + "added {'key': 'japan', 'key_label': 'Japan', 'total': 0}\n", + "key jordan datum: {'_total': 0}\n", + "k _total \n", + "jordan {'_total': 0}\n", + "added {'key': 'jordan', 'key_label': 'Jordan', 'total': 0}\n", + "key kazakhstan datum: {'_total': 0}\n", + "k _total \n", + "kazakhstan {'_total': 0}\n", + "added {'key': 'kazakhstan', 'key_label': 'Kazakhstan', 'total': 0}\n", + "key kenya datum: {'_total': 0}\n", + "k _total \n", + "kenya {'_total': 0}\n", + "added {'key': 'kenya', 'key_label': 'Kenya', 'total': 0}\n", + "key kiribati datum: {'_total': 0}\n", + "k _total \n", + "kiribati {'_total': 0}\n", + "added {'key': 'kiribati', 'key_label': 'Kiribati', 'total': 0}\n", + "key kosovo datum: {'_total': 0}\n", + "k _total \n", + "kosovo {'_total': 0}\n", + "added {'key': 'kosovo', 'key_label': 'Kosovo', 'total': 0}\n", + "key kuwait datum: {'_total': 0}\n", + "k _total \n", + "kuwait {'_total': 0}\n", + "added {'key': 'kuwait', 'key_label': 'Kuwait', 'total': 0}\n", + "key kyrgyzstan datum: {'_total': 0}\n", + "k _total \n", + "kyrgyzstan {'_total': 0}\n", + "added {'key': 'kyrgyzstan', 'key_label': 'Kyrgyzstan', 'total': 0}\n", + "key laos datum: {'_total': 0}\n", + "k _total \n", + "laos {'_total': 0}\n", + "added {'key': 'laos', 'key_label': 'Laos', 'total': 0}\n", + "key latvia datum: {'_total': 0}\n", + "k _total \n", + "latvia {'_total': 0}\n", + "added {'key': 'latvia', 'key_label': 'Latvia', 'total': 0}\n", + "key lebanon datum: {'_total': 0}\n", + "k _total \n", + "lebanon {'_total': 0}\n", + "added {'key': 'lebanon', 'key_label': 'Lebanon', 'total': 0}\n", + "key lesotho datum: {'_total': 0}\n", + "k _total \n", + "lesotho {'_total': 0}\n", + "added {'key': 'lesotho', 'key_label': 'Lesotho', 'total': 0}\n", + "key liberia datum: {'_total': 0}\n", + "k _total \n", + "liberia {'_total': 0}\n", + "added {'key': 'liberia', 'key_label': 'Liberia', 'total': 0}\n", + "key libya datum: {'_total': 0}\n", + "k _total \n", + "libya {'_total': 0}\n", + "added {'key': 'libya', 'key_label': 'Libya', 'total': 0}\n", + "key liechtenstein datum: {'_total': 0}\n", + "k _total \n", + "liechtenstein {'_total': 0}\n", + "added {'key': 'liechtenstein', 'key_label': 'Liechtenstein', 'total': 0}\n", + "key lithuania datum: {'_total': 0}\n", + "k _total \n", + "lithuania {'_total': 0}\n", + "added {'key': 'lithuania', 'key_label': 'Lithuania', 'total': 0}\n", + "key luxembourg datum: {'_total': 0}\n", + "k _total \n", + "luxembourg {'_total': 0}\n", + "added {'key': 'luxembourg', 'key_label': 'Luxembourg', 'total': 0}\n", + "key macedonia datum: {'_total': 0}\n", + "k _total \n", + "macedonia {'_total': 0}\n", + "added {'key': 'macedonia', 'key_label': 'Macedonia', 'total': 0}\n", + "key madagascar datum: {'_total': 0}\n", + "k _total \n", + "madagascar {'_total': 0}\n", + "added {'key': 'madagascar', 'key_label': 'Madagascar', 'total': 0}\n", + "key malawi datum: {'_total': 0}\n", + "k _total \n", + "malawi {'_total': 0}\n", + "added {'key': 'malawi', 'key_label': 'Malawi', 'total': 0}\n", + "key malaysia datum: {'_total': 0}\n", + "k _total \n", + "malaysia {'_total': 0}\n", + "added {'key': 'malaysia', 'key_label': 'Malaysia', 'total': 0}\n", + "key maldives datum: {'_total': 0}\n", + "k _total \n", + "maldives {'_total': 0}\n", + "added {'key': 'maldives', 'key_label': 'Maldives', 'total': 0}\n", + "key mali datum: {'_total': 0}\n", + "k _total \n", + "mali {'_total': 0}\n", + "added {'key': 'mali', 'key_label': 'Mali', 'total': 0}\n", + "key malta datum: {'_total': 0}\n", + "k _total \n", + "malta {'_total': 0}\n", + "added {'key': 'malta', 'key_label': 'Malta', 'total': 0}\n", + "key marshall_islands datum: {'_total': 0}\n", + "k _total \n", + "marshall_islands {'_total': 0}\n", + "added {'key': 'marshall_islands', 'key_label': 'Marshall Islands', 'total': 0}\n", + "key mauritania datum: {'_total': 0}\n", + "k _total \n", + "mauritania {'_total': 0}\n", + "added {'key': 'mauritania', 'key_label': 'Mauritania', 'total': 0}\n", + "key mauritius datum: {'_total': 0}\n", + "k _total \n", + "mauritius {'_total': 0}\n", + "added {'key': 'mauritius', 'key_label': 'Mauritius', 'total': 0}\n", + "key mexico datum: {'_total': 0}\n", + "k _total \n", + "mexico {'_total': 0}\n", + "added {'key': 'mexico', 'key_label': 'Mexico', 'total': 0}\n", + "key micronesia datum: {'_total': 0}\n", + "k _total \n", + "micronesia {'_total': 0}\n", + "added {'key': 'micronesia', 'key_label': 'Micronesia', 'total': 0}\n", + "key moldova datum: {'_total': 0}\n", + "k _total \n", + "moldova {'_total': 0}\n", + "added {'key': 'moldova', 'key_label': 'Moldova', 'total': 0}\n", + "key monaco datum: {'_total': 0}\n", + "k _total \n", + "monaco {'_total': 0}\n", + "added {'key': 'monaco', 'key_label': 'Monaco', 'total': 0}\n", + "key mongolia datum: {'_total': 0}\n", + "k _total \n", + "mongolia {'_total': 0}\n", + "added {'key': 'mongolia', 'key_label': 'Mongolia', 'total': 0}\n", + "key montenegro datum: {'_total': 0}\n", + "k _total \n", + "montenegro {'_total': 0}\n", + "added {'key': 'montenegro', 'key_label': 'Montenegro', 'total': 0}\n", + "key morocco datum: {'_total': 0}\n", + "k _total \n", + "morocco {'_total': 0}\n", + "added {'key': 'morocco', 'key_label': 'Morocco', 'total': 0}\n", + "key mozambique datum: {'_total': 0}\n", + "k _total \n", + "mozambique {'_total': 0}\n", + "added {'key': 'mozambique', 'key_label': 'Mozambique', 'total': 0}\n", + "key myanmar datum: {'_total': 0}\n", + "k _total \n", + "myanmar {'_total': 0}\n", + "added {'key': 'myanmar', 'key_label': 'Myanmar', 'total': 0}\n", + "key namibia datum: {'_total': 0}\n", + "k _total \n", + "namibia {'_total': 0}\n", + "added {'key': 'namibia', 'key_label': 'Namibia', 'total': 0}\n", + "key nauru datum: {'_total': 0}\n", + "k _total \n", + "nauru {'_total': 0}\n", + "added {'key': 'nauru', 'key_label': 'Nauru', 'total': 0}\n", + "key nepal datum: {'_total': 0}\n", + "k _total \n", + "nepal {'_total': 0}\n", + "added {'key': 'nepal', 'key_label': 'Nepal', 'total': 0}\n", + "key netherlands datum: {'_total': 0}\n", + "k _total \n", + "netherlands {'_total': 0}\n", + "added {'key': 'netherlands', 'key_label': 'Netherlands', 'total': 0}\n", + "key new_zealand datum: {'_total': 0}\n", + "k _total \n", + "new_zealand {'_total': 0}\n", + "added {'key': 'new_zealand', 'key_label': 'New Zealand', 'total': 0}\n", + "key nicaragua datum: {'_total': 0}\n", + "k _total \n", + "nicaragua {'_total': 0}\n", + "added {'key': 'nicaragua', 'key_label': 'Nicaragua', 'total': 0}\n", + "key niger datum: {'_total': 0}\n", + "k _total \n", + "niger {'_total': 0}\n", + "added {'key': 'niger', 'key_label': 'Niger', 'total': 0}\n", + "key nigeria datum: {'_total': 0}\n", + "k _total \n", + "nigeria {'_total': 0}\n", + "added {'key': 'nigeria', 'key_label': 'Nigeria', 'total': 0}\n", + "key north_korea datum: {'_total': 0}\n", + "k _total \n", + "north_korea {'_total': 0}\n", + "added {'key': 'north_korea', 'key_label': 'North Korea', 'total': 0}\n", + "key norway datum: {'_total': 0}\n", + "k _total \n", + "norway {'_total': 0}\n", + "added {'key': 'norway', 'key_label': 'Norway', 'total': 0}\n", + "key oman datum: {'_total': 0}\n", + "k _total \n", + "oman {'_total': 0}\n", + "added {'key': 'oman', 'key_label': 'Oman', 'total': 0}\n", + "key pakistan datum: {'_total': 0}\n", + "k _total \n", + "pakistan {'_total': 0}\n", + "added {'key': 'pakistan', 'key_label': 'Pakistan', 'total': 0}\n", + "key palau datum: {'_total': 0}\n", + "k _total \n", + "palau {'_total': 0}\n", + "added {'key': 'palau', 'key_label': 'Palau', 'total': 0}\n", + "key palestine datum: {'_total': 0}\n", + "k _total \n", + "palestine {'_total': 0}\n", + "added {'key': 'palestine', 'key_label': 'Palestine', 'total': 0}\n", + "key panama datum: {'_total': 0}\n", + "k _total \n", + "panama {'_total': 0}\n", + "added {'key': 'panama', 'key_label': 'Panama', 'total': 0}\n", + "key papua_new_guinea datum: {'_total': 0}\n", + "k _total \n", + "papua_new_guinea {'_total': 0}\n", + "added {'key': 'papua_new_guinea', 'key_label': 'Papua New Guinea', 'total': 0}\n", + "key paraguay datum: {'_total': 0}\n", + "k _total \n", + "paraguay {'_total': 0}\n", + "added {'key': 'paraguay', 'key_label': 'Paraguay', 'total': 0}\n", + "key peru datum: {'_total': 0}\n", + "k _total \n", + "peru {'_total': 0}\n", + "added {'key': 'peru', 'key_label': 'Peru', 'total': 0}\n", + "key philippines datum: {'_total': 0}\n", + "k _total \n", + "philippines {'_total': 0}\n", + "added {'key': 'philippines', 'key_label': 'Philippines', 'total': 0}\n", + "key poland datum: {'_total': 0}\n", + "k _total \n", + "poland {'_total': 0}\n", + "added {'key': 'poland', 'key_label': 'Poland', 'total': 0}\n", + "key portugal datum: {'_total': 0}\n", + "k _total \n", + "portugal {'_total': 0}\n", + "added {'key': 'portugal', 'key_label': 'Portugal', 'total': 0}\n", + "key qatar datum: {'_total': 0}\n", + "k _total \n", + "qatar {'_total': 0}\n", + "added {'key': 'qatar', 'key_label': 'Qatar', 'total': 0}\n", + "key romania datum: {'_total': 0}\n", + "k _total \n", + "romania {'_total': 0}\n", + "added {'key': 'romania', 'key_label': 'Romania', 'total': 0}\n", + "key russia datum: {'_total': 0}\n", + "k _total \n", + "russia {'_total': 0}\n", + "added {'key': 'russia', 'key_label': 'Russia', 'total': 0}\n", + "key rwanda datum: {'_total': 0}\n", + "k _total \n", + "rwanda {'_total': 0}\n", + "added {'key': 'rwanda', 'key_label': 'Rwanda', 'total': 0}\n", + "key st_kitts_and_nevis datum: {'_total': 0}\n", + "k _total \n", + "st_kitts_and_nevis {'_total': 0}\n", + "added {'key': 'st_kitts_and_nevis', 'key_label': 'St. Kitts and Nevis', 'total': 0}\n", + "key st_lucia datum: {'_total': 0}\n", + "k _total \n", + "st_lucia {'_total': 0}\n", + "added {'key': 'st_lucia', 'key_label': 'St. Lucia', 'total': 0}\n", + "key st_vincent_and_the_grenadines datum: {'_total': 0}\n", + "k _total \n", + "st_vincent_and_the_grenadines {'_total': 0}\n", + "added {'key': 'st_vincent_and_the_grenadines', 'key_label': 'St. Vincent and The Grenadines', 'total': 0}\n", + "key samoa datum: {'_total': 0}\n", + "k _total \n", + "samoa {'_total': 0}\n", + "added {'key': 'samoa', 'key_label': 'Samoa', 'total': 0}\n", + "key san_marino datum: {'_total': 0}\n", + "k _total \n", + "san_marino {'_total': 0}\n", + "added {'key': 'san_marino', 'key_label': 'San Marino', 'total': 0}\n", + "key sao_tome_and_principe datum: {'_total': 0}\n", + "k _total \n", + "sao_tome_and_principe {'_total': 0}\n", + "added {'key': 'sao_tome_and_principe', 'key_label': 'Sao Tome and Principe', 'total': 0}\n", + "key saudi_arabia datum: {'_total': 0}\n", + "k _total \n", + "saudi_arabia {'_total': 0}\n", + "added {'key': 'saudi_arabia', 'key_label': 'Saudi Arabia', 'total': 0}\n", + "key senegal datum: {'_total': 0}\n", + "k _total \n", + "senegal {'_total': 0}\n", + "added {'key': 'senegal', 'key_label': 'Senegal', 'total': 0}\n", + "key serbia datum: {'_total': 0}\n", + "k _total \n", + "serbia {'_total': 0}\n", + "added {'key': 'serbia', 'key_label': 'Serbia', 'total': 0}\n", + "key seychelles datum: {'_total': 0}\n", + "k _total \n", + "seychelles {'_total': 0}\n", + "added {'key': 'seychelles', 'key_label': 'Seychelles', 'total': 0}\n", + "key sierra_leone datum: {'_total': 0}\n", + "k _total \n", + "sierra_leone {'_total': 0}\n", + "added {'key': 'sierra_leone', 'key_label': 'Sierra Leone', 'total': 0}\n", + "key singapore datum: {'_total': 0}\n", + "k _total \n", + "singapore {'_total': 0}\n", + "added {'key': 'singapore', 'key_label': 'Singapore', 'total': 0}\n", + "key slovakia datum: {'_total': 0}\n", + "k _total \n", + "slovakia {'_total': 0}\n", + "added {'key': 'slovakia', 'key_label': 'Slovakia', 'total': 0}\n", + "key slovenia datum: {'_total': 0}\n", + "k _total \n", + "slovenia {'_total': 0}\n", + "added {'key': 'slovenia', 'key_label': 'Slovenia', 'total': 0}\n", + "key solomon_islands datum: {'_total': 0}\n", + "k _total \n", + "solomon_islands {'_total': 0}\n", + "added {'key': 'solomon_islands', 'key_label': 'Solomon Islands', 'total': 0}\n", + "key somalia datum: {'_total': 0}\n", + "k _total \n", + "somalia {'_total': 0}\n", + "added {'key': 'somalia', 'key_label': 'Somalia', 'total': 0}\n", + "key south_africa datum: {'_total': 0}\n", + "k _total \n", + "south_africa {'_total': 0}\n", + "added {'key': 'south_africa', 'key_label': 'South Africa', 'total': 0}\n", + "key south_korea datum: {'_total': 0}\n", + "k _total \n", + "south_korea {'_total': 0}\n", + "added {'key': 'south_korea', 'key_label': 'South Korea', 'total': 0}\n", + "key south_sudan datum: {'_total': 0}\n", + "k _total \n", + "south_sudan {'_total': 0}\n", + "added {'key': 'south_sudan', 'key_label': 'South Sudan', 'total': 0}\n", + "key spain datum: {'_total': 0}\n", + "k _total \n", + "spain {'_total': 0}\n", + "added {'key': 'spain', 'key_label': 'Spain', 'total': 0}\n", + "key sri_lanka datum: {'_total': 0}\n", + "k _total \n", + "sri_lanka {'_total': 0}\n", + "added {'key': 'sri_lanka', 'key_label': 'Sri Lanka', 'total': 0}\n", + "key sudan datum: {'_total': 0}\n", + "k _total \n", + "sudan {'_total': 0}\n", + "added {'key': 'sudan', 'key_label': 'Sudan', 'total': 0}\n", + "key suriname datum: {'_total': 0}\n", + "k _total \n", + "suriname {'_total': 0}\n", + "added {'key': 'suriname', 'key_label': 'Suriname', 'total': 0}\n", + "key swaziland datum: {'_total': 0}\n", + "k _total \n", + "swaziland {'_total': 0}\n", + "added {'key': 'swaziland', 'key_label': 'Swaziland', 'total': 0}\n", + "key sweden datum: {'_total': 0}\n", + "k _total \n", + "sweden {'_total': 0}\n", + "added {'key': 'sweden', 'key_label': 'Sweden', 'total': 0}\n", + "key switzerland datum: {'_total': 0}\n", + "k _total \n", + "switzerland {'_total': 0}\n", + "added {'key': 'switzerland', 'key_label': 'Switzerland', 'total': 0}\n", + "key syria datum: {'_total': 0}\n", + "k _total \n", + "syria {'_total': 0}\n", + "added {'key': 'syria', 'key_label': 'Syria', 'total': 0}\n", + "key taiwan datum: {'_total': 0}\n", + "k _total \n", + "taiwan {'_total': 0}\n", + "added {'key': 'taiwan', 'key_label': 'Taiwan', 'total': 0}\n", + "key tajikistan datum: {'_total': 0}\n", + "k _total \n", + "tajikistan {'_total': 0}\n", + "added {'key': 'tajikistan', 'key_label': 'Tajikistan', 'total': 0}\n", + "key tanzania datum: {'_total': 0}\n", + "k _total \n", + "tanzania {'_total': 0}\n", + "added {'key': 'tanzania', 'key_label': 'Tanzania', 'total': 0}\n", + "key thailand datum: {'_total': 0}\n", + "k _total \n", + "thailand {'_total': 0}\n", + "added {'key': 'thailand', 'key_label': 'Thailand', 'total': 0}\n", + "key timor_leste datum: {'_total': 0}\n", + "k _total \n", + "timor_leste {'_total': 0}\n", + "added {'key': 'timor_leste', 'key_label': 'Timor-Leste', 'total': 0}\n", + "key togo datum: {'_total': 0}\n", + "k _total \n", + "togo {'_total': 0}\n", + "added {'key': 'togo', 'key_label': 'Togo', 'total': 0}\n", + "key tonga datum: {'_total': 0}\n", + "k _total \n", + "tonga {'_total': 0}\n", + "added {'key': 'tonga', 'key_label': 'Tonga', 'total': 0}\n", + "key trinidad_and_tobago datum: {'_total': 0}\n", + "k _total \n", + "trinidad_and_tobago {'_total': 0}\n", + "added {'key': 'trinidad_and_tobago', 'key_label': 'Trinidad and Tobago', 'total': 0}\n", + "key tunisia datum: {'_total': 0}\n", + "k _total \n", + "tunisia {'_total': 0}\n", + "added {'key': 'tunisia', 'key_label': 'Tunisia', 'total': 0}\n", + "key turkey datum: {'_total': 0}\n", + "k _total \n", + "turkey {'_total': 0}\n", + "added {'key': 'turkey', 'key_label': 'Turkey', 'total': 0}\n", + "key turkmenistan datum: {'_total': 0}\n", + "k _total \n", + "turkmenistan {'_total': 0}\n", + "added {'key': 'turkmenistan', 'key_label': 'Turkmenistan', 'total': 0}\n", + "key tuvalu datum: {'_total': 0}\n", + "k _total \n", + "tuvalu {'_total': 0}\n", + "added {'key': 'tuvalu', 'key_label': 'Tuvalu', 'total': 0}\n", + "key uganda datum: {'_total': 0}\n", + "k _total \n", + "uganda {'_total': 0}\n", + "added {'key': 'uganda', 'key_label': 'Uganda', 'total': 0}\n", + "key ukraine datum: {'_total': 0}\n", + "k _total \n", + "ukraine {'_total': 0}\n", + "added {'key': 'ukraine', 'key_label': 'Ukraine', 'total': 0}\n", + "key united_arab_emirates datum: {'_total': 0}\n", + "k _total \n", + "united_arab_emirates {'_total': 0}\n", + "added {'key': 'united_arab_emirates', 'key_label': 'United Arab Emirates', 'total': 0}\n", + "key uk datum: {'_total': 0}\n", + "k _total \n", + "uk {'_total': 0}\n", + "added {'key': 'uk', 'key_label': 'UK (United Kingdom)', 'total': 0}\n", + "key usa datum: {'_total': 0}\n", + "k _total \n", + "usa {'_total': 0}\n", + "added {'key': 'usa', 'key_label': 'USA (United States of America)', 'total': 0}\n", + "key uruguay datum: {'_total': 0}\n", + "k _total \n", + "uruguay {'_total': 0}\n", + "added {'key': 'uruguay', 'key_label': 'Uruguay', 'total': 0}\n", + "key uzbekistan datum: {'_total': 0}\n", + "k _total \n", + "uzbekistan {'_total': 0}\n", + "added {'key': 'uzbekistan', 'key_label': 'Uzbekistan', 'total': 0}\n", + "key vanuatu datum: {'_total': 0}\n", + "k _total \n", + "vanuatu {'_total': 0}\n", + "added {'key': 'vanuatu', 'key_label': 'Vanuatu', 'total': 0}\n", + "key vatican datum: {'_total': 0}\n", + "k _total \n", + "vatican {'_total': 0}\n", + "added {'key': 'vatican', 'key_label': 'Vatican City (Holy See)', 'total': 0}\n", + "key venezuela datum: {'_total': 0}\n", + "k _total \n", + "venezuela {'_total': 0}\n", + "added {'key': 'venezuela', 'key_label': 'Venezuela', 'total': 0}\n", + "key vietnam datum: {'_total': 0}\n", + "k _total \n", + "vietnam {'_total': 0}\n", + "added {'key': 'vietnam', 'key_label': 'Vietnam', 'total': 0}\n", + "key yemen datum: {'_total': 0}\n", + "k _total \n", + "yemen {'_total': 0}\n", + "added {'key': 'yemen', 'key_label': 'Yemen', 'total': 0}\n", + "key zambia datum: {'_total': 0}\n", + "k _total \n", + "zambia {'_total': 0}\n", + "added {'key': 'zambia', 'key_label': 'Zambia', 'total': 0}\n", + "key zimbabwe datum: {'_total': 0}\n", + "k _total \n", + "zimbabwe {'_total': 0}\n", + "added {'key': 'zimbabwe', 'key_label': 'Zimbabwe', 'total': 0}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249633.47s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " key key_label total\n", + "0 afghanistan Afghanistan 1\n", + "1 albania Albania 0\n", + "2 algeria Algeria 0\n", + "3 andorra Andorra 1\n", + "4 angola Angola 0\n", + ".. ... ... ...\n", + "192 venezuela Venezuela 0\n", + "193 vietnam Vietnam 0\n", + "194 yemen Yemen 0\n", + "195 zambia Zambia 0\n", + "196 zimbabwe Zimbabwe 0\n", + "\n", + "[197 rows x 3 columns]\n", + "6 Cases by Age and Sex\n", + "{\n", + " \"id\": 6,\n", + " \"name\": {\n", + " \"en\": \"Cases by Age and Sex\",\n", + " \"fr\": \"Cases by Age and Sex\",\n", + " \"ar\": \"Cases by Age and Sex\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by age and sex\",\n", + " \"fr\": \"Number of cases broken down by age and sex\",\n", + " \"ar\": \"Number of cases broken down by age and sex\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": true,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"age\",\n", + " \"display_name\": {\n", + " \"en\": \"Age\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"sex\",\n", + " \"display_name\": {\n", + " \"en\": \"Sex\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"male\",\n", + " \"display_text\": \"Male\"\n", + " },\n", + " {\n", + " \"id\": \"female\",\n", + " \"display_text\": \"Female\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"6 - 11\": {\n", + " \"_total\": 2,\n", + " \"male\": {\n", + " \"_total\": 2\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " },\n", + " \"12 - 17\": {\n", + " \"_total\": 1,\n", + " \"male\": {\n", + " \"_total\": 1\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + " }\n", + "}\n", + "report_data {'6 - 11': {'_total': 2, 'male': {'_total': 2}, 'female': {'_total': 0}}, '12 - 17': {'_total': 1, 'male': {'_total': 1}, 'female': {'_total': 0}}}\n", + "key 6 - 11 datum: {'_total': 2, 'male': {'_total': 2}, 'female': {'_total': 0}}\n", + "k _total \n", + "k male \n", + "k female \n", + "6 - 11 {'_total': 2, 'male': 2, 'female': 0}\n", + "added {'male': 2, 'female': 0, 'key': '6 - 11', 'key_label': '6 - 11', 'total': 2}\n", + "key 12 - 17 datum: {'_total': 1, 'male': {'_total': 1}, 'female': {'_total': 0}}\n", + "k _total \n", + "k male \n", + "k female \n", + "12 - 17 {'_total': 1, 'male': 1, 'female': 0}\n", + "added {'male': 1, 'female': 0, 'key': '12 - 17', 'key_label': '12 - 17', 'total': 1}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249638.84s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " male female key key_label total\n", + "0 2 0 6 - 11 6 - 11 2\n", + "1 1 0 12 - 17 12 - 17 1\n", + "7 Cases by Protection Concern\n", + "{\n", + " \"id\": 7,\n", + " \"name\": {\n", + " \"en\": \"Cases by Protection Concern\",\n", + " \"fr\": \"Cases by Protection Concern\",\n", + " \"ar\": \"Cases by Protection Concern\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of cases broken down by protection concern and sex\",\n", + " \"fr\": \"Number of cases broken down by protection concern and sex\",\n", + " \"ar\": \"Number of cases broken down by protection concern and sex\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"protection_concerns\",\n", + " \"display_name\": {\n", + " \"en\": \"Protection Concerns\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"sexually_exploited\",\n", + " \"display_text\": \"Sexually Exploited\"\n", + " },\n", + " {\n", + " \"id\": \"gbv_survivor\",\n", + " \"display_text\": \"GBV survivor\"\n", + " },\n", + " {\n", + " \"id\": \"trafficked_smuggled\",\n", + " \"display_text\": \"Trafficked/smuggled\"\n", + " },\n", + " {\n", + " \"id\": \"statelessness\",\n", + " \"display_text\": \"Statelessness\"\n", + " },\n", + " {\n", + " \"id\": \"arrested_detained\",\n", + " \"display_text\": \"Arrested/Detained\"\n", + " },\n", + " {\n", + " \"id\": \"migrant\",\n", + " \"display_text\": \"Migrant\"\n", + " },\n", + " {\n", + " \"id\": \"disabled\",\n", + " \"display_text\": \"Disabled\"\n", + " },\n", + " {\n", + " \"id\": \"serious_health_issue\",\n", + " \"display_text\": \"Serious health issue\"\n", + " },\n", + " {\n", + " \"id\": \"refugee\",\n", + " \"display_text\": \"Refugee\"\n", + " },\n", + " {\n", + " \"id\": \"caafag\",\n", + " \"display_text\": \"CAAFAG\"\n", + " },\n", + " {\n", + " \"id\": \"street_child\",\n", + " \"display_text\": \"Street child\"\n", + " },\n", + " {\n", + " \"id\": \"child_mother\",\n", + " \"display_text\": \"Child Mother\"\n", + " },\n", + " {\n", + " \"id\": \"physically_or_mentally_abused\",\n", + " \"display_text\": \"Physically or Mentally Abused\"\n", + " },\n", + " {\n", + " \"id\": \"living_with_vulnerable_person\",\n", + " \"display_text\": \"Living with vulnerable person\"\n", + " },\n", + " {\n", + " \"id\": \"worst_forms_of_child_labor\",\n", + " \"display_text\": \"Worst Forms of Child Labor\"\n", + " },\n", + " {\n", + " \"id\": \"child_headed_household\",\n", + " \"display_text\": \"Child Headed Household\"\n", + " },\n", + " {\n", + " \"id\": \"mentally_distressed\",\n", + " \"display_text\": \"Mentally Distressed\"\n", + " },\n", + " {\n", + " \"id\": \"other\",\n", + " \"display_text\": \"Other\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"sex\",\n", + " \"display_name\": {\n", + " \"en\": \"Sex\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"male\",\n", + " \"display_text\": \"Male\"\n", + " },\n", + " {\n", + " \"id\": \"female\",\n", + " \"display_text\": \"Female\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"sexually_exploited\": {\n", + " \"_total\": 0\n", + " },\n", + " \"gbv_survivor\": {\n", + " \"_total\": 0\n", + " },\n", + " \"trafficked_smuggled\": {\n", + " \"_total\": 0\n", + " },\n", + " \"statelessness\": {\n", + " \"_total\": 0\n", + " },\n", + " \"arrested_detained\": {\n", + " \"_total\": 0\n", + " },\n", + " \"migrant\": {\n", + " \"_total\": 1,\n", + " \"male\": {\n", + " \"_total\": 1\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " },\n", + " \"disabled\": {\n", + " \"_total\": 0\n", + " },\n", + " \"serious_health_issue\": {\n", + " \"_total\": 0\n", + " },\n", + " \"refugee\": {\n", + " \"_total\": 0\n", + " },\n", + " \"caafag\": {\n", + " \"_total\": 0\n", + " },\n", + " \"street_child\": {\n", + " \"_total\": 0\n", + " },\n", + " \"child_mother\": {\n", + " \"_total\": 0\n", + " },\n", + " \"physically_or_mentally_abused\": {\n", + " \"_total\": 0\n", + " },\n", + " \"living_with_vulnerable_person\": {\n", + " \"_total\": 0\n", + " },\n", + " \"worst_forms_of_child_labor\": {\n", + " \"_total\": 0\n", + " },\n", + " \"child_headed_household\": {\n", + " \"_total\": 0\n", + " },\n", + " \"mentally_distressed\": {\n", + " \"_total\": 0\n", + " },\n", + " \"other\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + "}\n", + "report_data {'sexually_exploited': {'_total': 0}, 'gbv_survivor': {'_total': 0}, 'trafficked_smuggled': {'_total': 0}, 'statelessness': {'_total': 0}, 'arrested_detained': {'_total': 0}, 'migrant': {'_total': 1, 'male': {'_total': 1}, 'female': {'_total': 0}}, 'disabled': {'_total': 0}, 'serious_health_issue': {'_total': 0}, 'refugee': {'_total': 0}, 'caafag': {'_total': 0}, 'street_child': {'_total': 0}, 'child_mother': {'_total': 0}, 'physically_or_mentally_abused': {'_total': 0}, 'living_with_vulnerable_person': {'_total': 0}, 'worst_forms_of_child_labor': {'_total': 0}, 'child_headed_household': {'_total': 0}, 'mentally_distressed': {'_total': 0}, 'other': {'_total': 0}}\n", + "key sexually_exploited datum: {'_total': 0}\n", + "k _total \n", + "sexually_exploited {'_total': 0}\n", + "added {'key': 'sexually_exploited', 'key_label': 'Sexually Exploited', 'total': 0}\n", + "key gbv_survivor datum: {'_total': 0}\n", + "k _total \n", + "gbv_survivor {'_total': 0}\n", + "added {'key': 'gbv_survivor', 'key_label': 'GBV survivor', 'total': 0}\n", + "key trafficked_smuggled datum: {'_total': 0}\n", + "k _total \n", + "trafficked_smuggled {'_total': 0}\n", + "added {'key': 'trafficked_smuggled', 'key_label': 'Trafficked/smuggled', 'total': 0}\n", + "key statelessness datum: {'_total': 0}\n", + "k _total \n", + "statelessness {'_total': 0}\n", + "added {'key': 'statelessness', 'key_label': 'Statelessness', 'total': 0}\n", + "key arrested_detained datum: {'_total': 0}\n", + "k _total \n", + "arrested_detained {'_total': 0}\n", + "added {'key': 'arrested_detained', 'key_label': 'Arrested/Detained', 'total': 0}\n", + "key migrant datum: {'_total': 1, 'male': {'_total': 1}, 'female': {'_total': 0}}\n", + "k _total \n", + "k male \n", + "k female \n", + "migrant {'_total': 1, 'male': 1, 'female': 0}\n", + "added {'male': 1, 'female': 0, 'key': 'migrant', 'key_label': 'Migrant', 'total': 1}\n", + "key disabled datum: {'_total': 0}\n", + "k _total \n", + "disabled {'_total': 0}\n", + "added {'key': 'disabled', 'key_label': 'Disabled', 'total': 0}\n", + "key serious_health_issue datum: {'_total': 0}\n", + "k _total \n", + "serious_health_issue {'_total': 0}\n", + "added {'key': 'serious_health_issue', 'key_label': 'Serious health issue', 'total': 0}\n", + "key refugee datum: {'_total': 0}\n", + "k _total \n", + "refugee {'_total': 0}\n", + "added {'key': 'refugee', 'key_label': 'Refugee', 'total': 0}\n", + "key caafag datum: {'_total': 0}\n", + "k _total \n", + "caafag {'_total': 0}\n", + "added {'key': 'caafag', 'key_label': 'CAAFAG', 'total': 0}\n", + "key street_child datum: {'_total': 0}\n", + "k _total \n", + "street_child {'_total': 0}\n", + "added {'key': 'street_child', 'key_label': 'Street child', 'total': 0}\n", + "key child_mother datum: {'_total': 0}\n", + "k _total \n", + "child_mother {'_total': 0}\n", + "added {'key': 'child_mother', 'key_label': 'Child Mother', 'total': 0}\n", + "key physically_or_mentally_abused datum: {'_total': 0}\n", + "k _total \n", + "physically_or_mentally_abused {'_total': 0}\n", + "added {'key': 'physically_or_mentally_abused', 'key_label': 'Physically or Mentally Abused', 'total': 0}\n", + "key living_with_vulnerable_person datum: {'_total': 0}\n", + "k _total \n", + "living_with_vulnerable_person {'_total': 0}\n", + "added {'key': 'living_with_vulnerable_person', 'key_label': 'Living with vulnerable person', 'total': 0}\n", + "key worst_forms_of_child_labor datum: {'_total': 0}\n", + "k _total \n", + "worst_forms_of_child_labor {'_total': 0}\n", + "added {'key': 'worst_forms_of_child_labor', 'key_label': 'Worst Forms of Child Labor', 'total': 0}\n", + "key child_headed_household datum: {'_total': 0}\n", + "k _total \n", + "child_headed_household {'_total': 0}\n", + "added {'key': 'child_headed_household', 'key_label': 'Child Headed Household', 'total': 0}\n", + "key mentally_distressed datum: {'_total': 0}\n", + "k _total \n", + "mentally_distressed {'_total': 0}\n", + "added {'key': 'mentally_distressed', 'key_label': 'Mentally Distressed', 'total': 0}\n", + "key other datum: {'_total': 0}\n", + "k _total \n", + "other {'_total': 0}\n", + "added {'key': 'other', 'key_label': 'Other', 'total': 0}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249644.22s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " key key_label ... male female\n", + "0 sexually_exploited Sexually Exploited ... NaN NaN\n", + "1 gbv_survivor GBV survivor ... NaN NaN\n", + "2 trafficked_smuggled Trafficked/smuggled ... NaN NaN\n", + "3 statelessness Statelessness ... NaN NaN\n", + "4 arrested_detained Arrested/Detained ... NaN NaN\n", + "5 migrant Migrant ... 1.0 0.0\n", + "6 disabled Disabled ... NaN NaN\n", + "7 serious_health_issue Serious health issue ... NaN NaN\n", + "8 refugee Refugee ... NaN NaN\n", + "9 caafag CAAFAG ... NaN NaN\n", + "10 street_child Street child ... NaN NaN\n", + "11 child_mother Child Mother ... NaN NaN\n", + "12 physically_or_mentally_abused Physically or Mentally Abused ... NaN NaN\n", + "13 living_with_vulnerable_person Living with vulnerable person ... NaN NaN\n", + "14 worst_forms_of_child_labor Worst Forms of Child Labor ... NaN NaN\n", + "15 child_headed_household Child Headed Household ... NaN NaN\n", + "16 mentally_distressed Mentally Distressed ... NaN NaN\n", + "17 other Other ... NaN NaN\n", + "\n", + "[18 rows x 5 columns]\n", + "8 Current Care Arrangements\n", + "{\n", + " \"id\": 8,\n", + " \"name\": {\n", + " \"en\": \"Current Care Arrangements\",\n", + " \"fr\": \"Current Care Arrangements\",\n", + " \"ar\": \"Current Care Arrangements\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"The care arrangements broken down by age and sex\",\n", + " \"fr\": \"The care arrangements broken down by age and sex\",\n", + " \"ar\": \"The care arrangements broken down by age and sex\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": true,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"care_arrangements_type\",\n", + " \"display_name\": {\n", + " \"en\": \"What are the child's current care arrangements?\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"parent_s\",\n", + " \"display_text\": \"Parent(s)\"\n", + " },\n", + " {\n", + " \"id\": \"step_parent\",\n", + " \"display_text\": \"Step parent\"\n", + " },\n", + " {\n", + " \"id\": \"customary_caregiver_s\",\n", + " \"display_text\": \"Customary caregiver(s)\"\n", + " },\n", + " {\n", + " \"id\": \"adult_sibling\",\n", + " \"display_text\": \"Adult sibling\"\n", + " },\n", + " {\n", + " \"id\": \"kinship_care_extended_family\",\n", + " \"display_text\": \"Kinship care / extended family\"\n", + " },\n", + " {\n", + " \"id\": \"foster_care\",\n", + " \"display_text\": \"Foster care\"\n", + " },\n", + " {\n", + " \"id\": \"residential_care\",\n", + " \"display_text\": \"Residential care\"\n", + " },\n", + " {\n", + " \"id\": \"kafala\",\n", + " \"display_text\": \"Kafala\"\n", + " },\n", + " {\n", + " \"id\": \"independent_living\",\n", + " \"display_text\": \"Independent living\"\n", + " },\n", + " {\n", + " \"id\": \"child_headed_household\",\n", + " \"display_text\": \"Child-headed household\"\n", + " },\n", + " {\n", + " \"id\": \"unrelated_adult\",\n", + " \"display_text\": \"Unrelated adult\"\n", + " },\n", + " {\n", + " \"id\": \"no_care_arrangement\",\n", + " \"display_text\": \"No care arrangement\"\n", + " },\n", + " {\n", + " \"id\": \"other\",\n", + " \"display_text\": \"Other\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"sex\",\n", + " \"display_name\": {\n", + " \"en\": \"Sex\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_labels\": {\n", + " \"en\": [\n", + " {\n", + " \"id\": \"male\",\n", + " \"display_text\": \"Male\"\n", + " },\n", + " {\n", + " \"id\": \"female\",\n", + " \"display_text\": \"Female\"\n", + " }\n", + " ],\n", + " \"fr\": [],\n", + " \"ar\": []\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"age\",\n", + " \"display_name\": {\n", + " \"en\": \"Age\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 1\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"parent_s\": {\n", + " \"_total\": 0\n", + " },\n", + " \"step_parent\": {\n", + " \"_total\": 0\n", + " },\n", + " \"customary_caregiver_s\": {\n", + " \"_total\": 0\n", + " },\n", + " \"adult_sibling\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kinship_care_extended_family\": {\n", + " \"_total\": 0\n", + " },\n", + " \"foster_care\": {\n", + " \"_total\": 0\n", + " },\n", + " \"residential_care\": {\n", + " \"_total\": 0\n", + " },\n", + " \"kafala\": {\n", + " \"_total\": 0\n", + " },\n", + " \"independent_living\": {\n", + " \"_total\": 0\n", + " },\n", + " \"child_headed_household\": {\n", + " \"_total\": 0\n", + " },\n", + " \"unrelated_adult\": {\n", + " \"_total\": 0\n", + " },\n", + " \"no_care_arrangement\": {\n", + " \"_total\": 0\n", + " },\n", + " \"other\": {\n", + " \"_total\": 0\n", + " },\n", + " \"incomplete_data\": {\n", + " \"_total\": 3,\n", + " \"male\": {\n", + " \"_total\": 3,\n", + " \"6 - 11\": {\n", + " \"_total\": 2\n", + " },\n", + " \"12 - 17\": {\n", + " \"_total\": 1\n", + " }\n", + " },\n", + " \"female\": {\n", + " \"_total\": 0\n", + " }\n", + " }\n", + " }\n", + "}\n", + "report_data {'parent_s': {'_total': 0}, 'step_parent': {'_total': 0}, 'customary_caregiver_s': {'_total': 0}, 'adult_sibling': {'_total': 0}, 'kinship_care_extended_family': {'_total': 0}, 'foster_care': {'_total': 0}, 'residential_care': {'_total': 0}, 'kafala': {'_total': 0}, 'independent_living': {'_total': 0}, 'child_headed_household': {'_total': 0}, 'unrelated_adult': {'_total': 0}, 'no_care_arrangement': {'_total': 0}, 'other': {'_total': 0}, 'incomplete_data': {'_total': 3, 'male': {'_total': 3, '6 - 11': {'_total': 2}, '12 - 17': {'_total': 1}}, 'female': {'_total': 0}}}\n", + "key parent_s datum: {'_total': 0}\n", + "k _total \n", + "parent_s {'_total': 0}\n", + "added {'key': 'parent_s', 'key_label': 'Parent(s)', 'total': 0}\n", + "key step_parent datum: {'_total': 0}\n", + "k _total \n", + "step_parent {'_total': 0}\n", + "added {'key': 'step_parent', 'key_label': 'Step parent', 'total': 0}\n", + "key customary_caregiver_s datum: {'_total': 0}\n", + "k _total \n", + "customary_caregiver_s {'_total': 0}\n", + "added {'key': 'customary_caregiver_s', 'key_label': 'Customary caregiver(s)', 'total': 0}\n", + "key adult_sibling datum: {'_total': 0}\n", + "k _total \n", + "adult_sibling {'_total': 0}\n", + "added {'key': 'adult_sibling', 'key_label': 'Adult sibling', 'total': 0}\n", + "key kinship_care_extended_family datum: {'_total': 0}\n", + "k _total \n", + "kinship_care_extended_family {'_total': 0}\n", + "added {'key': 'kinship_care_extended_family', 'key_label': 'Kinship care / extended family', 'total': 0}\n", + "key foster_care datum: {'_total': 0}\n", + "k _total \n", + "foster_care {'_total': 0}\n", + "added {'key': 'foster_care', 'key_label': 'Foster care', 'total': 0}\n", + "key residential_care datum: {'_total': 0}\n", + "k _total \n", + "residential_care {'_total': 0}\n", + "added {'key': 'residential_care', 'key_label': 'Residential care', 'total': 0}\n", + "key kafala datum: {'_total': 0}\n", + "k _total \n", + "kafala {'_total': 0}\n", + "added {'key': 'kafala', 'key_label': 'Kafala', 'total': 0}\n", + "key independent_living datum: {'_total': 0}\n", + "k _total \n", + "independent_living {'_total': 0}\n", + "added {'key': 'independent_living', 'key_label': 'Independent living', 'total': 0}\n", + "key child_headed_household datum: {'_total': 0}\n", + "k _total \n", + "child_headed_household {'_total': 0}\n", + "added {'key': 'child_headed_household', 'key_label': 'Child-headed household', 'total': 0}\n", + "key unrelated_adult datum: {'_total': 0}\n", + "k _total \n", + "unrelated_adult {'_total': 0}\n", + "added {'key': 'unrelated_adult', 'key_label': 'Unrelated adult', 'total': 0}\n", + "key no_care_arrangement datum: {'_total': 0}\n", + "k _total \n", + "no_care_arrangement {'_total': 0}\n", + "added {'key': 'no_care_arrangement', 'key_label': 'No care arrangement', 'total': 0}\n", + "key other datum: {'_total': 0}\n", + "k _total \n", + "other {'_total': 0}\n", + "added {'key': 'other', 'key_label': 'Other', 'total': 0}\n", + "key incomplete_data datum: {'_total': 3, 'male': {'_total': 3, '6 - 11': {'_total': 2}, '12 - 17': {'_total': 1}}, 'female': {'_total': 0}}\n", + "k _total \n", + "k male \n", + "k female \n", + "incomplete_data {'_total': 3, 'male': 3, 'female': 0}\n", + "added {'male': 3, 'female': 0, 'key': 'incomplete_data', 'key_label': 'incomplete_data', 'total': 3}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249649.62s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " key key_label ... male female\n", + "0 parent_s Parent(s) ... NaN NaN\n", + "1 step_parent Step parent ... NaN NaN\n", + "2 customary_caregiver_s Customary caregiver(s) ... NaN NaN\n", + "3 adult_sibling Adult sibling ... NaN NaN\n", + "4 kinship_care_extended_family Kinship care / extended family ... NaN NaN\n", + "5 foster_care Foster care ... NaN NaN\n", + "6 residential_care Residential care ... NaN NaN\n", + "7 kafala Kafala ... NaN NaN\n", + "8 independent_living Independent living ... NaN NaN\n", + "9 child_headed_household Child-headed household ... NaN NaN\n", + "10 unrelated_adult Unrelated adult ... NaN NaN\n", + "11 no_care_arrangement No care arrangement ... NaN NaN\n", + "12 other Other ... NaN NaN\n", + "13 incomplete_data incomplete_data ... 3.0 0.0\n", + "\n", + "[14 rows x 5 columns]\n", + "10 Follow up by month by Agency\n", + "{\n", + " \"id\": 10,\n", + " \"name\": {\n", + " \"en\": \"Follow up by month by Agency\",\n", + " \"fr\": \"Follow up by month by Agency\",\n", + " \"ar\": \"Follow up by month by Agency\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of followups broken down by month and agency\",\n", + " \"fr\": \"Number of followups broken down by month and agency\",\n", + " \"ar\": \"Number of followups broken down by month and agency\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"reportable_follow_up\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"month\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " },\n", + " {\n", + " \"value\": \"\",\n", + " \"attribute\": \"followup_date\",\n", + " \"constraint\": \"not_null\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"followup_date\",\n", + " \"display_name\": {\n", + " \"en\": \"Follow up date\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"owned_by_agency_id\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Agency\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Agency\"\n", + " }\n", + " ]\n", + "}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249654.99s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Empty DataFrame\n", + "Columns: []\n", + "Index: []\n", + "11 Follow up by week by Agency\n", + "{\n", + " \"id\": 11,\n", + " \"name\": {\n", + " \"en\": \"Follow up by week by Agency\",\n", + " \"fr\": \"Follow up by week by Agency\",\n", + " \"ar\": \"Follow up by week by Agency\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"Number of followups broken down by week and agency\",\n", + " \"fr\": \"Number of followups broken down by week and agency\",\n", + " \"ar\": \"Number of followups broken down by week and agency\"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"reportable_follow_up\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"week\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " },\n", + " {\n", + " \"value\": \"\",\n", + " \"attribute\": \"followup_date\",\n", + " \"constraint\": \"not_null\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"followup_date\",\n", + " \"display_name\": {\n", + " \"en\": \"Follow up date\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " },\n", + " {\n", + " \"name\": \"owned_by_agency_id\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Agency\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Agency\"\n", + " }\n", + " ]\n", + "}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249660.33s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Empty DataFrame\n", + "Columns: []\n", + "Index: []\n", + "12 Cases per Month\n", + "{\n", + " \"id\": 12,\n", + " \"name\": {\n", + " \"en\": \"Cases per Month\",\n", + " \"fr\": \"Cases per Month\",\n", + " \"ar\": \"Cases per Month\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \" Number of newly registered cases per month per location \",\n", + " \"fr\": \" Number of newly registered cases per month per location \",\n", + " \"ar\": \" Number of newly registered cases per month per location \"\n", + " },\n", + " \"graph\": true,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"month\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"owned_by_location\",\n", + " \"display_name\": {\n", + " \"en\": \"Record Owner's Location\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " },\n", + " \"option_strings_source\": \"Location\"\n", + " },\n", + " {\n", + " \"name\": \"created_at\",\n", + " \"display_name\": {\n", + " \"en\": \"Date of referral or transfer\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"vertical\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ]\n", + "}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249665.70s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Empty DataFrame\n", + "Columns: []\n", + "Index: []\n", + "13 Cases with case plans\n", + "{\n", + " \"id\": 13,\n", + " \"name\": {\n", + " \"en\": \"Cases with case plans\",\n", + " \"fr\": \"Cases with case plans\",\n", + " \"ar\": \"Cases with case plans\"\n", + " },\n", + " \"description\": {\n", + " \"en\": \"How many registered cases have case plans?\",\n", + " \"fr\": \"How many registered cases have case plans?\",\n", + " \"ar\": \"How many registered cases have case plans?\"\n", + " },\n", + " \"graph\": false,\n", + " \"graph_type\": \"bar\",\n", + " \"exclude_empty_rows\": false,\n", + " \"record_type\": \"case\",\n", + " \"module_id\": \"primeromodule-cp\",\n", + " \"group_dates_by\": \"date\",\n", + " \"group_ages\": false,\n", + " \"editable\": false,\n", + " \"disabled\": false,\n", + " \"filters\": [\n", + " {\n", + " \"value\": [\n", + " \"open\"\n", + " ],\n", + " \"attribute\": \"status\"\n", + " },\n", + " {\n", + " \"value\": [\n", + " \"true\"\n", + " ],\n", + " \"attribute\": \"record_state\"\n", + " }\n", + " ],\n", + " \"fields\": [\n", + " {\n", + " \"name\": \"has_case_plan\",\n", + " \"display_name\": {\n", + " \"en\": \"Does this case have a case plan?\",\n", + " \"fr\": \"\",\n", + " \"ar\": \"\"\n", + " },\n", + " \"position\": {\n", + " \"type\": \"horizontal\",\n", + " \"order\": 0\n", + " }\n", + " }\n", + " ],\n", + " \"report_data\": {\n", + " \"\": {\n", + " \"_total\": 0\n", + " },\n", + " \"false\": {\n", + " \"_total\": 2\n", + " },\n", + " \"true\": {\n", + " \"_total\": 1\n", + " }\n", + " }\n", + "}\n", + "report_data {'': {'_total': 0}, 'false': {'_total': 2}, 'true': {'_total': 1}}\n", + "key datum: {'_total': 0}\n", + "k _total \n", + " {'_total': 0}\n", + "added {'key': '', 'key_label': '', 'total': 0}\n", + "key false datum: {'_total': 2}\n", + "k _total \n", + "false {'_total': 2}\n", + "added {'key': 'false', 'key_label': 'false', 'total': 2}\n", + "key true datum: {'_total': 1}\n", + "k _total \n", + "true {'_total': 1}\n", + "added {'key': 'true', 'key_label': 'true', 'total': 1}\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "249671.09s - pydevd: Sending message related to process being replaced timed-out after 5 seconds\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " key key_label total\n", + "0 0\n", + "1 false false 2\n", + "2 true true 1\n" + ] + } + ], + "source": [ + "\n", + "import pandas as pd\n", + "from slugify import slugify\n", + "\n", + "\n", + "\n", + "\n", + "def report_slug(report, lang='en'):\n", + " '''\n", + " Returns the slug for the report in the given language\n", + " '''\n", + " return slugify(report['name'][lang])\n", + "\n", + "\n", + "def find_key_in_dict(nested_dict, key):\n", + " found_items = []\n", + " def search_dict(d):\n", + " if isinstance(d, dict):\n", + " for k, v in d.items():\n", + " if k == key:\n", + " found_items.append(v)\n", + " if isinstance(v, dict):\n", + " search_dict(v)\n", + " elif isinstance(v, list):\n", + " for item in v:\n", + " search_dict(item)\n", + " search_dict(nested_dict)\n", + " return found_items\n", + "\n", + "\n", + " \n", + "\n", + "def get_report_labels(report, lang='en'):\n", + " '''\n", + " Returns the labels for the report\n", + " '''\n", + " all_labels=find_key_in_dict(report, 'option_labels')\n", + " # returns this format\n", + " # \n", + " #[ {en\": [ \n", + " # { \"id\": \"sexually_exploited\", \"display_text\": \"Sexually Exploited\"}, \n", + " # ..., \n", + " # {...} \n", + " # ],\n", + " # fr: {...}\n", + " # ...\n", + " # {en\": [ \n", + " # { \"id\": \"sexually_exploited\", \"display_text\": \"Sexually Exploited\"}, \n", + " # ..., \n", + " # {...} \n", + " # ],\n", + " # fr: {...}\n", + " # ... \n", + " # ]\n", + " # we will convert to \n", + " # label[id]= display_text\n", + " # example: \n", + " # label[sexually_exploited] = \"Sexually Exploited\"\n", + " labels = {}\n", + " for labels_by_lang in all_labels:\n", + " if lang in labels_by_lang:\n", + " for label in labels_by_lang[lang]:\n", + " labels[label['id']] = label['display_text']\n", + " return labels \n", + " \n", + "\n", + "def process_report(report, lang='en'):\n", + " '''\n", + " Process the report and return a dataframe\n", + " '''\n", + " # The contains report_data which is an object of objects\n", + " # { key1: { _total: 1} }, key2: { _total: 2} } \n", + " # We need to convert it to a list of objects {key: key, total: value}\n", + " if 'report_data' not in report:\n", + " # return empty dataframe if there is no report data\n", + " return pd.DataFrame()\n", + " \n", + " labels = get_report_labels(report)\n", + " # Example of report_data\n", + " #\n", + " # report_data: {\n", + " # 'sexually_exploited': {'_total': 0}, # it is jsust total\n", + " # 'migrant': {\n", + " # '_total': 1, # it contains total and desagregated data\n", + " # 'male': {'_total': 1}, \n", + " # 'female': {'_total': 0}}, \n", + " #\n", + " # Is converted to:\n", + " # key total male female\n", + " # --------------------- ----- ---- ------\n", + " # sexually_exploited 0\n", + " # migrant 1 1 0\n", + "\n", + " report_data = report['report_data']\n", + " data = []\n", + " print('report_data', report_data)\n", + " for key in report_data:\n", + " datum = report_data[key].copy()\n", + " print(\"key\", key, \"datum:\", datum)\n", + " for k in datum.keys():\n", + " # check if k is an object\n", + " print('k', k, type(datum[k])) \n", + " if type(datum[k]) is not int:\n", + " datum[k] = datum[k]['_total']\n", + " print(key, datum)\n", + " datum['key']= key\n", + "\n", + " # find the label for the key. default to key\n", + " if key in labels:\n", + " datum['key_label'] = labels[key]\n", + " else:\n", + " datum['key_label'] = key \n", + "\n", + " datum['total'] = datum['_total']\n", + " datum.pop('_total')\n", + " print(\"added\", datum)\n", + " data.append(datum)\n", + "\n", + " df = pd.DataFrame(data)\n", + " return df\n", + " \n", + "\n", + "for report in reports:\n", + " # print(json.dumps(get_labels(report), indent=2))\n", + " print(report['id'], report['name']['en'])\n", + " file_name = report_slug(report)\n", + " print(json.dumps(report, indent=2))\n", + " df = process_report(report, lang='en')\n", + " today = pd.Timestamp.today().strftime('%Y-%m-%d')\n", + " # create datasets folder if does not exist\n", + " !mkdir -p datasets\n", + " df.to_csv(f'./datasets/report-{file_name}-{today}.csv')\n", + " print(df)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'api' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[2], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m cases \u001b[38;5;241m=\u001b[39m \u001b[43mapi\u001b[49m\u001b[38;5;241m.\u001b[39mget_cases()\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpseudonimize_cases\u001b[39m(cases):\n\u001b[1;32m 6\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m'''\u001b[39;00m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;124;03m Pseudonimize the cases by removing the names and other personal information\u001b[39;00m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;124;03m '''\u001b[39;00m\n", + "\u001b[0;31mNameError\u001b[0m: name 'api' is not defined" + ] + } + ], + "source": [ + "cases = api.get_cases()\n", + "\n", + "\n", + "\n", + "def pseudonimize_cases(cases):\n", + " '''\n", + " Pseudonimize the cases by removing the names and other personal information\n", + " '''\n", + " for case in cases:\n", + " case.pop('name', None)\n", + " case.pop('first_name', None)\n", + " case.pop('last_name', None)\n", + " case.pop('middle_name', None)\n", + " case.pop('other_names', None)\n", + " case.pop('nickname', None)\n", + " case.pop('date_of_birth', None)\n", + "\n", + "\n", + "print(cases)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Obtaining file:///Users/jmerlostevar/src/magasin/primero/primero_api\n", + " Installing build dependencies ... \u001b[?25ldone\n", + "\u001b[?25h Checking if build backend supports build_editable ... \u001b[?25ldone\n", + "\u001b[?25h Getting requirements to build editable ... \u001b[?25lerror\n", + " \u001b[1;31merror\u001b[0m: \u001b[1msubprocess-exited-with-error\u001b[0m\n", + " \n", + " \u001b[31m×\u001b[0m \u001b[32mGetting requirements to build editable\u001b[0m did not run successfully.\n", + " \u001b[31m│\u001b[0m exit code: \u001b[1;36m1\u001b[0m\n", + " \u001b[31m╰─>\u001b[0m \u001b[31m[27 lines of output]\u001b[0m\n", + " \u001b[31m \u001b[0m Traceback (most recent call last):\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py\", line 353, in \n", + " \u001b[31m \u001b[0m main()\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py\", line 335, in main\n", + " \u001b[31m \u001b[0m json_out['return_val'] = hook(**hook_input['kwargs'])\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py\", line 132, in get_requires_for_build_editable\n", + " \u001b[31m \u001b[0m return hook(config_settings)\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 477, in get_requires_for_build_editable\n", + " \u001b[31m \u001b[0m return self.get_requires_for_build_wheel(config_settings)\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 332, in get_requires_for_build_wheel\n", + " \u001b[31m \u001b[0m return self._get_build_requires(config_settings, requirements=[])\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 302, in _get_build_requires\n", + " \u001b[31m \u001b[0m self.run_setup()\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 516, in run_setup\n", + " \u001b[31m \u001b[0m super().run_setup(setup_script=setup_script)\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 318, in run_setup\n", + " \u001b[31m \u001b[0m exec(code, locals())\n", + " \u001b[31m \u001b[0m File \"\", line 3, in \n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/src/magasin/primero/primero_api/primero_api/__init__.py\", line 3, in \n", + " \u001b[31m \u001b[0m from .primero_api import PrimeroAPI\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/src/magasin/primero/primero_api/primero_api/primero_api.py\", line 1, in \n", + " \u001b[31m \u001b[0m import requests\n", + " \u001b[31m \u001b[0m ModuleNotFoundError: No module named 'requests'\n", + " \u001b[31m \u001b[0m \u001b[31m[end of output]\u001b[0m\n", + " \n", + " \u001b[1;35mnote\u001b[0m: This error originates from a subprocess, and is likely not a problem with pip.\n", + "\u001b[?25h\u001b[1;31merror\u001b[0m: \u001b[1msubprocess-exited-with-error\u001b[0m\n", + "\n", + "\u001b[31m×\u001b[0m \u001b[32mGetting requirements to build editable\u001b[0m did not run successfully.\n", + "\u001b[31m│\u001b[0m exit code: \u001b[1;36m1\u001b[0m\n", + "\u001b[31m╰─>\u001b[0m See above for output.\n", + "\n", + "\u001b[1;35mnote\u001b[0m: This error originates from a subprocess, and is likely not a problem with pip.\n" + ] + } + ], + "source": [ + "!pip install -e ../primero_api/ \n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mWARNING: Package(s) not found: primero_api\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "!pip show primero_api" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mWARNING: Skipping primero_api as it is not installed.\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "!pip uninstall -y primero_api" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "!pip list | grep primero_api" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'0.1.2'" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import sys\n", + "sys.path.append('../primero_api/')\n", + "import primero_api\n", + "\n", + "\n", + "PRIMERO_USER='primero'\n", + "PRIMERO_PASSWORD='primer0!'\n", + "PRIMERO_SERVER_URL = 'http://localhost/'\n", + "PRIMERO_SERVER_API_URL='http://localhost/api/v2/'\n", + "\n", + "# \n", + "\n", + "primero = primero_api.PrimeroAPI(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_SERVER_API_URL)\n", + "\n", + "primero.version()\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'2.11.0-rc3'" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "primero.get_server_version()" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "{1: ,\n", + " 2: ,\n", + " 3: ,\n", + " 4: ,\n", + " 5: ,\n", + " 6: ,\n", + " 7: ,\n", + " 8: ,\n", + " 9: None,\n", + " 10: ,\n", + " 11: ,\n", + " 12: ,\n", + " 13: }" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "primero.get_reports()\n" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "id 1\n", + "name Registration CP fr\n", + "raw_data {'id': 1, 'name': {'en': 'Registration CP', 'fr': 'Registration CP', 'ar': 'Registration CP'}, 'description': {'en': 'Case registrations over time', 'fr': 'Case registrations over time', 'ar': 'Case registrations over time'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'month', 'group_ages': False, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'registration_date', 'display_name': {'en': 'Date of Registration or Interview', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}], 'report_data': {'2024-Oct': {'_total': 3}}}\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
keykey_labeltotal
02024-Oct2024-Oct3
\n", + "
" + ], + "text/plain": [ + " key key_label total\n", + "0 2024-Oct 2024-Oct 3" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Interact with the reports\n", + "r = primero.get_report(1, lang='fr')\n", + "\n", + "# Display the id\n", + "print('id', r.id)\n", + "\n", + "# name of the report \n", + "print('name', r.name, r.lang)\n", + "\n", + "# raw data of the report as dict\n", + "print('raw_data', r.report_data_dict)\n", + "\n", + "# pandas dataframe of the report\n", + "r.to_pandas()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.12 (mag_py312)", + "language": "python", + "name": "mag_py312" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/explorations/primero.ipynb b/explorations/primero.ipynb new file mode 100644 index 0000000..ac13a26 --- /dev/null +++ b/explorations/primero.ipynb @@ -0,0 +1,897 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Primero Explorations\n", + "Using Magasin to explore the Primero API and datasets" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd \n", + "import requests\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Obtaining file:///Users/jmerlostevar/src/magasin/primero/primero_api\n", + " Installing build dependencies ... \u001b[?25ldone\n", + "\u001b[?25h Checking if build backend supports build_editable ... \u001b[?25ldone\n", + "\u001b[?25h Getting requirements to build editable ... \u001b[?25lerror\n", + " \u001b[1;31merror\u001b[0m: \u001b[1msubprocess-exited-with-error\u001b[0m\n", + " \n", + " \u001b[31m×\u001b[0m \u001b[32mGetting requirements to build editable\u001b[0m did not run successfully.\n", + " \u001b[31m│\u001b[0m exit code: \u001b[1;36m1\u001b[0m\n", + " \u001b[31m╰─>\u001b[0m \u001b[31m[27 lines of output]\u001b[0m\n", + " \u001b[31m \u001b[0m Traceback (most recent call last):\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py\", line 353, in \n", + " \u001b[31m \u001b[0m main()\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py\", line 335, in main\n", + " \u001b[31m \u001b[0m json_out['return_val'] = hook(**hook_input['kwargs'])\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages/pip/_vendor/pyproject_hooks/_in_process/_in_process.py\", line 132, in get_requires_for_build_editable\n", + " \u001b[31m \u001b[0m return hook(config_settings)\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 477, in get_requires_for_build_editable\n", + " \u001b[31m \u001b[0m return self.get_requires_for_build_wheel(config_settings)\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 332, in get_requires_for_build_wheel\n", + " \u001b[31m \u001b[0m return self._get_build_requires(config_settings, requirements=[])\n", + " \u001b[31m \u001b[0m ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 302, in _get_build_requires\n", + " \u001b[31m \u001b[0m self.run_setup()\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 516, in run_setup\n", + " \u001b[31m \u001b[0m super().run_setup(setup_script=setup_script)\n", + " \u001b[31m \u001b[0m File \"/private/var/folders/sx/mgw7pc4s3_933zkvp879hzd00000gn/T/pip-build-env-7uh3upr0/overlay/lib/python3.12/site-packages/setuptools/build_meta.py\", line 318, in run_setup\n", + " \u001b[31m \u001b[0m exec(code, locals())\n", + " \u001b[31m \u001b[0m File \"\", line 3, in \n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/src/magasin/primero/primero_api/primero_api/__init__.py\", line 3, in \n", + " \u001b[31m \u001b[0m from .primero_api import PrimeroAPI\n", + " \u001b[31m \u001b[0m File \"/Users/jmerlostevar/src/magasin/primero/primero_api/primero_api/primero_api.py\", line 1, in \n", + " \u001b[31m \u001b[0m import requests\n", + " \u001b[31m \u001b[0m ModuleNotFoundError: No module named 'requests'\n", + " \u001b[31m \u001b[0m \u001b[31m[end of output]\u001b[0m\n", + " \n", + " \u001b[1;35mnote\u001b[0m: This error originates from a subprocess, and is likely not a problem with pip.\n", + "\u001b[?25h\u001b[1;31merror\u001b[0m: \u001b[1msubprocess-exited-with-error\u001b[0m\n", + "\n", + "\u001b[31m×\u001b[0m \u001b[32mGetting requirements to build editable\u001b[0m did not run successfully.\n", + "\u001b[31m│\u001b[0m exit code: \u001b[1;36m1\u001b[0m\n", + "\u001b[31m╰─>\u001b[0m See above for output.\n", + "\n", + "\u001b[1;35mnote\u001b[0m: This error originates from a subprocess, and is likely not a problem with pip.\n" + ] + } + ], + "source": [ + "!pip install primero-api\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\u001b[33mWARNING: Package(s) not found: primero_api\u001b[0m\u001b[33m\n", + "\u001b[0m" + ] + } + ], + "source": [ + "!pip show primero_api" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Primero API library version 0.1.2\n", + "Primero Server version 2.11.0-rc3\n" + ] + } + ], + "source": [ + "import sys\n", + "sys.path.append('../primero_api/')\n", + "import primero_api\n", + "\n", + "\n", + "PRIMERO_USER='primero'\n", + "PRIMERO_PASSWORD='primer0!'\n", + "PRIMERO_SERVER_URL = 'http://localhost/'\n", + "PRIMERO_SERVER_API_URL='http://localhost/api/v2/'\n", + "\n", + "\n", + "primero = primero_api.PrimeroAPI(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_SERVER_API_URL)\n", + "\n", + "## Note that PrimeroAPI caches the information and controls the speed. rate / duration (sec) is the number of api calls per sec \n", + "## cache_expire= number of seconds.\n", + "## primero = primero_api.PrimeroAPI(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_SERVER_API_URL, rate=2, duration=1, cache_expire=3600)\n", + "primero = primero_api.PrimeroAPI(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_SERVER_API_URL, cache_expire=0)\n", + "print('Primero API library version', primero.version())\n", + "print('Primero Server version', primero.get_server_version())\n", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1 Registration CP\n", + "2 Caseload Summary CP\n", + "3 Case status by case worker CP\n", + "4 Cases by Agency CP\n", + "5 Cases by Nationality\n", + "6 Cases by Age and Sex\n", + "7 Cases by Protection Concern\n", + "8 Current Care Arrangements\n", + "9 ** This report has no data **\n", + "10 Follow up by month by Agency\n", + "11 Follow up by week by Agency\n", + "12 Cases per Month\n", + "13 Cases with case plans\n" + ] + } + ], + "source": [ + "reports = primero.get_reports()\n", + "\n", + "for id, report in reports.items():\n", + " if report != None:\n", + " print(id, report.name)\n", + " else:\n", + " print(id, '** This report has no data **')\n" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "id 6\n", + "name Cases by Age and Sex fr\n", + "raw_data {'id': 6, 'name': {'en': 'Cases by Age and Sex', 'fr': 'Cases by Age and Sex', 'ar': 'Cases by Age and Sex'}, 'description': {'en': 'Number of cases broken down by age and sex', 'fr': 'Number of cases broken down by age and sex', 'ar': 'Number of cases broken down by age and sex'}, 'graph': True, 'graph_type': 'bar', 'exclude_empty_rows': False, 'record_type': 'case', 'module_id': 'primeromodule-cp', 'group_dates_by': 'date', 'group_ages': True, 'editable': False, 'disabled': False, 'filters': [{'value': ['open'], 'attribute': 'status'}, {'value': ['true'], 'attribute': 'record_state'}], 'fields': [{'name': 'age', 'display_name': {'en': 'Age', 'fr': '', 'ar': ''}, 'position': {'type': 'horizontal', 'order': 0}}, {'name': 'sex', 'display_name': {'en': 'Sex', 'fr': '', 'ar': ''}, 'position': {'type': 'vertical', 'order': 0}, 'option_labels': {'en': [{'id': 'male', 'display_text': 'Male'}, {'id': 'female', 'display_text': 'Female'}], 'fr': [], 'ar': []}}], 'report_data': {'0 - 5': {'_total': 447, 'male': {'_total': 235}, 'female': {'_total': 212}}, '6 - 11': {'_total': 506, 'male': {'_total': 255}, 'female': {'_total': 251}}, '12 - 17': {'_total': 541, 'male': {'_total': 287}, 'female': {'_total': 254}}, '18+': {'_total': 10, 'male': {'_total': 8}, 'female': {'_total': 2}}}}\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
malefemalekeykey_labeltotal
02352120 - 50 - 5447
12552516 - 116 - 11506
228725412 - 1712 - 17541
38218+18+10
\n", + "
" + ], + "text/plain": [ + " male female key key_label total\n", + "0 235 212 0 - 5 0 - 5 447\n", + "1 255 251 6 - 11 6 - 11 506\n", + "2 287 254 12 - 17 12 - 17 541\n", + "3 8 2 18+ 18+ 10" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Interact with a specific report by its id\n", + "# lang is optional. Default is 'en'\n", + "r = primero.get_report(6, lang='fr')\n", + "\n", + "# Display the id\n", + "print('id', r.id)\n", + "\n", + "# name of the report \n", + "print('name', r.name, r.lang)\n", + "\n", + "# raw data of the report as dict\n", + "print('raw_data', r.report_data_dict)\n", + "\n", + "# pandas dataframe of the report\n", + "df = r.to_pandas()\n", + "df" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: seaborn in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (0.13.2)\n", + "Requirement already satisfied: numpy!=1.24.0,>=1.20 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from seaborn) (1.26.4)\n", + "Requirement already satisfied: pandas>=1.2 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from seaborn) (2.2.1)\n", + "Requirement already satisfied: matplotlib!=3.6.1,>=3.4 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from seaborn) (3.8.3)\n", + "Requirement already satisfied: contourpy>=1.0.1 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.2.0)\n", + "Requirement already satisfied: cycler>=0.10 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (0.12.1)\n", + "Requirement already satisfied: fonttools>=4.22.0 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (4.50.0)\n", + "Requirement already satisfied: kiwisolver>=1.3.1 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (1.4.5)\n", + "Requirement already satisfied: packaging>=20.0 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (24.0)\n", + "Requirement already satisfied: pillow>=8 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (10.2.0)\n", + "Requirement already satisfied: pyparsing>=2.3.1 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (3.1.2)\n", + "Requirement already satisfied: python-dateutil>=2.7 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from matplotlib!=3.6.1,>=3.4->seaborn) (2.9.0.post0)\n", + "Requirement already satisfied: pytz>=2020.1 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from pandas>=1.2->seaborn) (2024.1)\n", + "Requirement already satisfied: tzdata>=2022.7 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from pandas>=1.2->seaborn) (2024.1)\n", + "Requirement already satisfied: six>=1.5 in /Users/jmerlostevar/Library/Caches/pypoetry/virtualenvs/dxint-hpo8hiaR-py3.12/lib/python3.12/site-packages (from python-dateutil>=2.7->matplotlib!=3.6.1,>=3.4->seaborn) (1.16.0)\n" + ] + } + ], + "source": [ + "!pip install seaborn" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "Text(0.5, 0, 'Age')" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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NZ8WHByspUuXnvSWHszE631u4fU+t/B6n57F5TrT57UAAAAGrgF/zw4AAMDpEDsAAMBoxA4AADAasQMAAIxG7BiioKBAF1xwgUJCQpScnKyysrIe7/Ozzz6TxWI5aSktLe2FGaM7vvjiC918880aPHiwQkNDNWbMGL377rs93u/8+fOVlJSk4OBgjR8//qTtx44d06233qoxY8YoICBAs2bN6vEx8Q+vv/66Zs6cqdjYWFksFr344ose29va2rRo0SKNGTNGYWFhio2N1Zw5c3Tw4MEeH/vQoUP6t3/7N1188cXy8/PTggULThpz1VVXdfrvgLS0tB4fH6d3pp+NpqYmZWVladiwYQoNDXX/Emx0jtgxwLPPPqucnBwtXbpU+/bt07hx45Samqr6+vpe2f+uXbt06NAh95KUlNQr+0XXfPXVV7riiisUGBio//mf/1FlZaVWrlyp8847r1f2f/vtt+uGG27odFt7e7tCQ0M1f/58paSk9Mrx8A/Nzc0aN26cCgoKOt3+t7/9Tfv27dN9992nffv26fnnn1dVVZWuueaaHh+7paVFQ4YM0eLFizVu3LhOxzz//PMef/c/+OAD+fv768c//nGPj4/TO9PPRk5Ojnbs2KE//OEP+vDDD7VgwQJlZWVp69atp9ynxWLRZ5991kcz9nG98+s44U2TJk1yZWZmuh+3t7e7YmNjXfn5+T3ab3V1tUuS67333uvhDNETixYtck2ZMqVPj7F06VLXuHHjTjsmIyPDde211/bpPM5lklwvvPDCGceVlZW5JLk+//zzXjv21KlTXffcc88Zx61atcoVERHhampq6rVj48w6+9kYPXq0Ky8vz2PdpZde6vrFL35x2v1UV1f3wQx9H1d2BrjW1laVl5d7/F+3n5+fUlJSVFJS0ivHuOaaaxQTE6MpU6ac9v8a0De2bt2qiRMn6sc//rFiYmI0YcIE/fa3v/X2tOAlDQ0NslgsXvl9foWFhbrxxhsVFhbW78eGp8svv1xbt27VF198IZfLpd27d+ujjz7S9OnTvT01n0TsDHBffvml2tvbT/q2aJvNJqfT2aN9h4eHa+XKldqyZYtefvllTZkyRbNmzSJ4+tmf//xnrV27VsOHD9crr7yiefPmaf78+dqwYYO3p4Z+duzYMS1atEg33XRTv/+yx7KyMn3wwQe64447+vW46Nzq1auVmJioYcOGKSgoSFdffbUKCgr03e9+19tT80nEzjnojTfeUHh4uHt55plnOh13/vnnKycnR8nJybrsssv00EMP6eabb9bDDz/czzM+t3V0dOjSSy/V8uXLNWHCBN1111268847T3kzYk1Njcfru3z58n6eMfpCW1ubrr/+erlcLq1du/aU45555hmP1/+NN97oleMXFhZqzJgxmjRpUq/sDz2zevVqlZaWauvWrSovL9fKlSuVmZmpXbt2ucfMmDHD42dBkkaPHu1+PHr0aG9Nv98Z8buxzmXnn3++/P39VVdX57G+rq5Odru90+dMnDhRFRUV7sfd+R1iycnJKioqOqu54uwMHTpUiYmJHutGjRql//qv/+p0fGxsrMfrGx0d3ZfTQz84ETqff/65Xn311dNe1bnmmmuUnJzsfvytb32rx8dvbm7W5s2blZeX1+N9oee+/vpr/fznP9cLL7zg/mTc2LFjVVFRoUceecR9W8Pvfvc7ff311+7nDR8+XNu3b3f/TAQGBvb/5L2E2BnggoKClJSUpOLiYvfHgjs6OlRcXKysrKxOnxMaGqqLLrrorI5XUVGhoUOHnu10cRauuOIKVVVVeaz76KOPlJCQ0On4gICAs3594XtOhM7HH3+s3bt3a/DgwacdHxERoYiIiF6dw5YtW9TS0qKbb765V/eLs9PW1qa2tjb5+Xm+OePv76+Ojg73485CNyEhQRdccEFfT9HnEDsGyMnJUUZGhiZOnKhJkybpscceU3Nzs2677bYe7XfDhg0KCgrShAkTJH3zMdSnn35av/vd73pj2uii7OxsXX755Vq+fLmuv/56lZWV6amnntJTTz3V431/8sknampqktPp1Ndff+2+IpSYmKigoCBJUmVlpVpbW3X48GEdPXrUPaaz7+VB9zQ1NemTTz5xP66urlZFRYWio6MVHx+vtrY2/ehHP9K+ffu0bds2tbe3u+/Fi46Odr9GZ+vEa9nU1KS//vWvqqioUFBQ0ElXEgsLCzVr1qwzhhZ6z5l+NqZOnaqFCxcqNDRUCQkJ2rNnjzZu3KhHH33Ui7P2Yd7+OBh6x+rVq13x8fGuoKAg16RJk1ylpaU93uf69etdo0aNcg0aNMgVGRnpmjRpkmvLli29MFt010svveS65JJLXMHBwa6RI0e6nnrqqV7Z79SpU12STlr++eOpCQkJnY5Bz+3evbvTf7YZGRkul+sfX//Q2bJ79+4eH7+z/SYkJHiM+d///V+XJNfOnTt7fDx03Zl+Ng4dOuS69dZbXbGxsa6QkBDXiBEjXCtXrnR1dHSccp//+nf7XGJxuVyuPi8qAAAAL+HTWAAAwGjEDgAAMBqxAwAAjEbsAAAAoxE7AADAaMQOAAAwGrEDAACMRuwAAACjETsAAMBoxA6AAamkpET+/v7u3/oMAKfCr4sAMCDdcccdCg8PV2FhoaqqqhQbG+vtKQHwUVzZATDgNDU16dlnn9W8efOUlpam9evXe2zfunWrhg8frpCQEH3ve9/Thg0bZLFYdOTIEfeYN998U1deeaVCQ0MVFxen+fPnq7m5uX9PBEC/IHYADDjPPfecRo4cqREjRujmm2/W008/rRMXqaurq/WjH/1Is2bN0p/+9Cf95Cc/0S9+8QuP53/66ae6+uqrlZ6ervfff1/PPvus3nzzTWVlZXnjdAD0Md7GAjDgXHHFFbr++ut1zz336Pjx4xo6dKi2bNmiq666Sj/72c/08ssva//+/e7xixcv1oMPPqivvvpKUVFRuuOOO+Tv768nn3zSPebNN9/U1KlT1dzcrJCQEG+cFoA+wpUdAANKVVWVysrKdNNNN0mSAgICdMMNN6iwsNC9/bLLLvN4zqRJkzwe/+lPf9L69esVHh7uXlJTU9XR0aHq6ur+OREA/SbA2xMAgO4oLCzU8ePHPW5IdrlcCg4O1m9+85su7aOpqUk/+clPNH/+/JO2xcfH99pcAfgGYgfAgHH8+HFt3LhRK1eu1PTp0z22zZo1S//5n/+pESNGaPv27R7b3nnnHY/Hl156qSorK3XRRRf1+ZwBeB/37AAYMF588UXdcMMNqq+vl9Vq9di2aNEivfrqq3ruuec0YsQIZWdna+7cuaqoqNC9996rv/zlLzpy5IisVqvef/99TZ48WbfffrvuuOMOhYWFqbKyUkVFRV2+OgRg4OCeHQADRmFhoVJSUk4KHUlKT0/Xu+++q6NHj+qPf/yjnn/+eY0dO1Zr1651fxorODhYkjR27Fjt2bNHH330ka688kpNmDBBS5Ys4bt6AENxZQeA8R588EE98cQTqq2t9fZUAHgB9+wAMM6aNWt02WWXafDgwXrrrbf08MMP8x06wDmM2AFgnI8//li//OUvdfjwYcXHx+vee+9Vbm6ut6cFwEt4GwsAABiNG5QBAIDRiB0AAGA0YgcAABiN2AEAAEYjdgAAgNGIHQAAYDRiBwAAGI3YAQAARvt/x92r1a0aknwAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Lets display some graphs using seaborn\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "\n", + "# display the number of cases (total) per age group (key column)\n", + "sns.barplot(x='key', y='total', data=df)\n", + "\n", + "# set the labels\n", + "plt.ylabel('Total')\n", + "plt.xlabel('Age') \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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+oXjXb9U9nifOXNGtsu8uM7HTmVMnDhRaWlpzufl5eU6deqUQkNDZbFY3Diy2lVQUKCoqCgdP35cVqvV3cNBDeN41y8c7/qlvh5vh8OhM2fOKDIy8rLL1fnYady4sby9vZWbm+syPTc3VxERERW+xt/fX/7+/i7TgoODa2qIHs9qtdarvxz1Hce7fuF41y/18Xhf7ozOBXX+AmU/Pz/FxcVp06ZNzmnl5eXatGmT7Ha7G0cGAAA8QZ0/syNJaWlpSk5OVpcuXdS1a1e98MILOnv2rFJSUtw9NAAA4GZGxM4999yj77//XlOmTFFOTo46duyodevWXXTRMlz5+/tr6tSpF72lBzNxvOsXjnf9wvG+PIvjl+7XAgAAqMPq/DU7AAAAl0PsAAAAoxE7AADAaMQOAAAwGrFjiHnz5qlFixZq0KCBunXrpj179lR5nceOHZPFYrnokZGRUQ0jxq/x3Xff6f7771doaKgCAgIUGxurzz77rMrrHTt2rOLi4uTv76+OHTteNL+oqEgjRoxQbGysfHx8NGDAgCpvE/+2fft2JSUlKTIyUhaLRR988IHL/NLSUk2YMEGxsbEKDAxUZGSkhg8frhMnTlR52ydPntR9992nVq1aycvLS+PGjbtomV69elX4/4DExMQqbx+X90s/G4WFhRo9erSaNWumgIAA55dgo2LEjgHeeecdpaWlaerUqdq7d686dOighIQE5eXlVcv6P/74Y508edL5iIuLq5b14sr84x//0I033ihfX1+tXbtWhw4d0vPPP6+rrrqqWtb/wAMP6J577qlwXllZmQICAjR27FjFx8dXy/bwb2fPnlWHDh00b968Cuf/9NNP2rt3ryZPnqy9e/dq5cqVOnz4sO64444qb7u4uFhNmjTRpEmT1KFDhwqXWblypcvf/YMHD8rb21t33313lbePy/uln420tDStW7dOb731lr788kuNGzdOo0eP1qpVqy65TovFomPHjtXQiD2cA3Ve165dHampqc7nZWVljsjISMesWbOqtN6srCyHJMfnn39exRGiKiZMmODo0aNHjW5j6tSpjg4dOlx2meTkZEf//v1rdBz1mSTH+++//4vL7dmzxyHJ8e2331bbtm+66SbHo48++ovLzZ0719GoUSNHYWFhtW0bv6yin43rrrvOMX36dJdpnTt3djz11FOXXU9WVlYNjNDzcWanjispKVFmZqbLv7q9vLwUHx+v9PT0atnGHXfcobCwMPXo0eOy/2pAzVi1apW6dOmiu+++W2FhYerUqZPeeOMNdw8LbpKfny+LxeKW7/NbsGCB7r33XgUGBtb6tuHqhhtu0KpVq/Tdd9/J4XBoy5Yt+vrrr9WnTx93D80jETt13A8//KCysrKLPi06PDxcOTk5VVp3UFCQnn/+ea1YsUIffvihevTooQEDBhA8texvf/ubXn31VV177bVav369Ro0apbFjx2rJkiXuHhpqWVFRkSZMmKAhQ4bU+pc97tmzRwcPHtSDDz5Yq9tFxV566SXFxMSoWbNm8vPzU9++fTVv3jz17NnT3UPzSMROPbRjxw4FBQU5H0uXLq1wucaNGystLU3dunXT9ddfr2effVb333+//vjHP9byiOu38vJyde7cWTNnzlSnTp308MMP66GHHrrkxYjZ2dkux3fmzJm1PGLUhNLSUg0ePFgOh0OvvvrqJZdbunSpy/HfsWNHtWx/wYIFio2NVdeuXatlfaial156SRkZGVq1apUyMzP1/PPPKzU1VR9//LFzmX79+rn8LEjSdddd53x+3XXXuWv4tc6I78aqzxo3bixvb2/l5ua6TM/NzVVERESFr+nSpYv27dvnfP5rvkOsW7du2rhxY6XGispp2rSpYmJiXKa1bdtW7733XoXLR0ZGuhzfkJCQmhweasGF0Pn222+1efPmy57VueOOO9StWzfn8//6r/+q8vbPnj2r5cuXa/r06VVeF6ru3Llz+t///V+9//77zjvj2rdvr3379um5555zXtbw5ptv6ty5c87XXXvttfroo4+cPxO+vr61P3g3IXbqOD8/P8XFxWnTpk3O24LLy8u1adMmjR49usLXBAQE6JprrqnU9vbt26emTZtWdriohBtvvFGHDx92mfb111+refPmFS7v4+NT6eMLz3MhdL755htt2bJFoaGhl12+UaNGatSoUbWOYcWKFSouLtb9999fretF5ZSWlqq0tFReXq5vznh7e6u8vNz5vKLQbd68uVq0aFHTQ/Q4xI4B0tLSlJycrC5duqhr16564YUXdPbsWaWkpFRpvUuWLJGfn586deok6Z+3oS5cuFBvvvlmdQwbV2j8+PG64YYbNHPmTA0ePFh79uzR/PnzNX/+/Cqv+8iRIyosLFROTo7OnTvnPCMUExMjPz8/SdKhQ4dUUlKiU6dO6cyZM85lKvpcHvw6hYWFOnLkiPN5VlaW9u3bp5CQEEVHR6u0tFR33XWX9u7dqzVr1qisrMx5LV5ISIjzGFXWhWNZWFio77//Xvv27ZOfn99FZxIXLFigAQMG/GJoofr80s/GTTfdpMcff1wBAQFq3ry5tm3bpj/96U+aM2eOG0ftwdx9Oxiqx0svveSIjo52+Pn5Obp27erIyMio8joXL17saNu2raNhw4YOq9Xq6Nq1q2PFihXVMFr8WqtXr3a0a9fO4e/v72jTpo1j/vz51bLem266ySHposfPb09t3rx5hcug6rZs2VLhn21ycrLD4fj3xz9U9NiyZUuVt1/Reps3b+6yzFdffeWQ5NiwYUOVt4cr90s/GydPnnSMGDHCERkZ6WjQoIGjdevWjueff95RXl5+yXX+59/t+sTicDgcNV5UAAAAbsLdWAAAwGjEDgAAMBqxAwAAjEbsAAAAoxE7AADAaMQOAAAwGrEDAACMRuwAAACjETsA6qRevXpp3Lhx7h4GgDqA2AEAAEYjdgAAgNGIHQBG+PDDD2Wz2bR06VIdP35cgwcPVnBwsEJCQtS/f38dO3ZMkrR9+3b5+vo6vz38gnHjxum3v/2tG0YOoKYROwDqvGXLlmnIkCFaunSpBg8erISEBDVq1Eg7duzQzp07FRQUpL59+6qkpEQ9e/bU1VdfrT//+c/O15eWlmrp0qV64IEH3LgXAGoKsQOgTps3b57++7//W6tXr9btt9+ud955R+Xl5XrzzTcVGxurtm3batGiRcrOztbWrVslSSNHjtSiRYuc61i9erWKioo0ePBgN+0FgJrk4+4BAEBlvfvuu8rLy9POnTt1/fXXS5L279+vI0eOqFGjRi7LFhUV6ejRo5KkESNGaNKkScrIyFD37t21ePFiDR48WIGBgbW+DwBqHrEDoM7q1KmT9u7dq4ULF6pLly6yWCwqLCxUXFycli5detHyTZo0kSSFhYUpKSlJixYtUsuWLbV27VrnWR8A5iF2ANRZv/nNb/T888+rV69e8vb21ssvv6zOnTvrnXfeUVhYmKxW6yVf++CDD2rIkCFq1qyZfvOb3+jGG2+sxZEDqE1cswOgTmvVqpW2bNmi9957T+PGjdPQoUPVuHFj9e/fXzt27FBWVpa2bt2qsWPH6u9//7vzdQkJCbJarXrmmWeUkpLixj0AUNOIHQB1XuvWrbV582a9/fbbmjx5srZv367o6GgNHDhQbdu21ciRI1VUVORypsfLy0sjRoxQWVmZhg8f7sbRA6hpFofD4XD3IADAHUaOHKnvv/9eq1atcvdQANQgrtkBUO/k5+frwIEDWrZsGaED1APEDoB6p3///tqzZ48eeeQR3Xrrre4eDoAaxttYAADAaFygDAAAjEbsAAAAoxE7AADAaMQOAAAwGrEDAACMRuwAAACjETsAAMBoxA4AADDa/wN96LWywr7K/wAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# dissagregate the number of cases per sex\n", + "# We have the count of on male column and female cases on female column, the key label is the age group\n", + "\n", + "sns.barplot(x='key', y='male', data=df, color='blue', label='Male')\n", + "sns.barplot(x='key', y='female', data=df, color='pink', label='Female', bottom=df['male']) \n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
enabledagesexstatusflaggedowned_byworkflowestimatedhas_photomodule_id...consent_reportinginterview_subjectcase_plan_approvedassessment_approvedassessment_due_datecase_status_reopenedconsent_for_servicesdisclosure_other_orgswithholding_info_reasonservice_implemented_day_times
0True17maleopenFalseprimero_cp_arnewFalseFalseprimeromodule-cp...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1True11femaleopenFalseprimero_cp_arnewFalseFalseprimeromodule-cp...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
2True2maleopenFalseprimero_cp_arnewNaNFalseprimeromodule-cp...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
3True7femaleopenFalseprimero_cp_arnewFalseFalseprimeromodule-cp...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
4True14maleopenFalseprimero_cp_arnewFalseFalseprimeromodule-cp...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
..................................................................
1499True5femaleopenFalseprimero_cp_arnewNaNFalseprimeromodule-cp...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1500True1femaleopenFalseprimerocare_planFalseFalseprimeromodule-cp...trueindividualFalseFalse2024-10-31FalseTrueTrue[fear][]
1501True9maleopenFalseprimeronewTrueFalseprimeromodule-cp...NaNNaNFalseFalse2024-09-03FalseFalseFalseNaNNaN
1502True14maleopenTrueprimeronewFalseFalseprimeromodule-cp...trueindividualFalseFalse0004-10-21FalseTrueTrue[fear]NaN
1503True11maleopenFalseprimeronewFalseFalseprimeromodule-cp...NaNNaNFalseFalseNaNFalseFalseFalseNaNNaN
\n", + "

1504 rows × 49 columns

\n", + "
" + ], + "text/plain": [ + " enabled age sex status flagged owned_by workflow \\\n", + "0 True 17 male open False primero_cp_ar new \n", + "1 True 11 female open False primero_cp_ar new \n", + "2 True 2 male open False primero_cp_ar new \n", + "3 True 7 female open False primero_cp_ar new \n", + "4 True 14 male open False primero_cp_ar new \n", + "... ... ... ... ... ... ... ... \n", + "1499 True 5 female open False primero_cp_ar new \n", + "1500 True 1 female open False primero care_plan \n", + "1501 True 9 male open False primero new \n", + "1502 True 14 male open True primero new \n", + "1503 True 11 male open False primero new \n", + "\n", + " estimated has_photo module_id ... consent_reporting \\\n", + "0 False False primeromodule-cp ... NaN \n", + "1 False False primeromodule-cp ... NaN \n", + "2 NaN False primeromodule-cp ... NaN \n", + "3 False False primeromodule-cp ... NaN \n", + "4 False False primeromodule-cp ... NaN \n", + "... ... ... ... ... ... \n", + "1499 NaN False primeromodule-cp ... NaN \n", + "1500 False False primeromodule-cp ... true \n", + "1501 True False primeromodule-cp ... NaN \n", + "1502 False False primeromodule-cp ... true \n", + "1503 False False primeromodule-cp ... NaN \n", + "\n", + " interview_subject case_plan_approved assessment_approved \\\n", + "0 NaN NaN NaN \n", + "1 NaN NaN NaN \n", + "2 NaN NaN NaN \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + "... ... ... ... \n", + "1499 NaN NaN NaN \n", + "1500 individual False False \n", + "1501 NaN False False \n", + "1502 individual False False \n", + "1503 NaN False False \n", + "\n", + " assessment_due_date case_status_reopened consent_for_services \\\n", + "0 NaN NaN NaN \n", + "1 NaN NaN NaN \n", + "2 NaN NaN NaN \n", + "3 NaN NaN NaN \n", + "4 NaN NaN NaN \n", + "... ... ... ... \n", + "1499 NaN NaN NaN \n", + "1500 2024-10-31 False True \n", + "1501 2024-09-03 False False \n", + "1502 0004-10-21 False True \n", + "1503 NaN False False \n", + "\n", + " disclosure_other_orgs withholding_info_reason \\\n", + "0 NaN NaN \n", + "1 NaN NaN \n", + "2 NaN NaN \n", + "3 NaN NaN \n", + "4 NaN NaN \n", + "... ... ... \n", + "1499 NaN NaN \n", + "1500 True [fear] \n", + "1501 False NaN \n", + "1502 True [fear] \n", + "1503 False NaN \n", + "\n", + " service_implemented_day_times \n", + "0 NaN \n", + "1 NaN \n", + "2 NaN \n", + "3 NaN \n", + "4 NaN \n", + "... ... \n", + "1499 NaN \n", + "1500 [] \n", + "1501 NaN \n", + "1502 NaN \n", + "1503 NaN \n", + "\n", + "[1504 rows x 49 columns]" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "# Now let's do the same but with the cases raw data\n", + "\n", + "cases = primero.get_cases()\n", + "# this call returns already a pandas dataframe\n", + "cases" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 23, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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PXr0UHh4uDp06ODWWyl+KC8vTx9++KFGjhzpthodO3bUhg0bdO7cOVmWpa1bt+rYsWPq3r17heYl7FQiDodDycnJ6tSpk5o1a+aWGocPH1a1atXk7++v3/3ud1q3bp0eeught9Rau3at9u/fr7S0NLfM/0MdOnTQW2+9pfT0dC1atEinTp3Sr371K125csUt9f71r39p0aJFaty4sTZv3qwxY8boueee08qVK91S74fWr1+v/Px8Pfvss26Z//nnn9eQIUMUFxenqlWrqnXr1kpOTlZiYqLLawUHBys+Pl4vv/yyzp8/r9LSUr399tvatWuXLly44PJ6P5SbmytJt3wSe0REhHOfKa5fv65JkyZp6NChbv3Sx02bNqlatWoKCAjQ3LlztWXLFtWqVcvldWbOnClfX18999xzLp/7dnr27KlVq1YpIyNDM2fOVGZmpnr16qXS0lKX1rl48aKuXr2qV199VT179tTHH3+sp556Sv3791dmZqZLa93OypUrFRwcrP79+7utxoIFC/TQQw+pbt268vPzU8+ePbVw4UJ16dKlQvMa8XUR94ukpCQdOXLErb/RNmnSRAcPHlRBQYH+/ve/a9iwYcrMzHR54Dl79qzGjRunLVu2lPta8y/xw1WHFi1aqEOHDoqJidG7777rlt9SHA6H2rVrp1deeUWS1Lp1ax05ckSLFy/WsGHDXF7vh5YtW6ZevXpV+D6FO3n33Xe1evVqrVmzRk2bNtXBgweVnJwsu93ulnP761//qhEjRqhOnTqqUqWK2rRpo6FDhyo7O9vlte5HJSUlGjRokCzL0qJFi9xa6/HHH9fBgwf1zTffaOnSpRo0aJCysrIUHh7ushrZ2dn605/+pP3797tlZfN2hgwZ4vxz8+bN1aJFCzVs2FDbtm1Tt27dXFbH4XBIkvr27avx48dLklq1aqWdO3dq8eLFevTRR11W63aWL1+uxMREt75mL1iwQLt379aGDRsUExOj7du3KykpSXa7vUJXAFjZqSTGjh2rTZs2aevWrapbt67b6vj5+alRo0Zq27at0tLS1LJlS/3pT39yeZ3s7GxdvHhRbdq0ka+vr3x9fZWZman58+fL19fX5b8R/ViNGjX0wAMP6MSJE26ZPyoq6paA+OCDD7r10pkknT59Wp988ol++9vfuq3GhAkTnKs7zZs31zPPPKPx48e7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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Group the cases by age and plot the number of cases per age group\n", + "sns.countplot(x='age', data=cases)" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "No artists with labels found to put in legend. Note that artists whose label start with an underscore are ignored when legend() is called with no argument.\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjsAAAHHCAYAAABZbpmkAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAABLP0lEQVR4nO3deVxU9f7H8fcIsogIoiJQCK64m7umpaa5lUtpLqlp5nLN3TKvmbncirQ0TU2zTCu1xW6abZZ7We5GapkJ4VJuoSECigjf3x/+nOsIbjg4w/H1fDzm8WDOOfP9fg7DwJtzvud7bMYYIwAAAIvK5+oCAAAAchNhBwAAWBphBwAAWBphBwAAWBphBwAAWBphBwAAWBphBwAAWBphBwAAWBphBwAAWBphB0CeNX78eNlsNiUkJLi6FEuLjIxUr169XF0GkGOEHeAycXFx6t+/v0qVKiUfHx8VKlRIDRo00PTp03XmzBlXl3dTli5dqlatWqlo0aLy8vJSWFiYOnXqpDVr1ri6NEnS4cOHNX78eMXExLi6lCuqU6eObDabZs+e7epS3E5ycrLGjRunypUry8/PT0WKFNFdd92loUOH6vDhw64uD7cxT1cXALiTL7/8Uo888oi8vb312GOPqXLlyjp37pw2bNigkSNH6pdfftHcuXNdXeYNM8aod+/eWrBggapXr64RI0YoJCRER44c0dKlS9W0aVP98MMPuvvuu11a5+HDhzVhwgRFRkbqrrvucmkt2dm3b5+2bt2qyMhILVq0SAMGDHB1SW4jPT1d9957r3777Tf17NlTgwcPVnJysn755RctXrxYDz30kMLCwlxdJm5ThB3g/8XHx6tLly6KiIjQmjVrFBoaal83cOBAxcbG6ssvv3RhhTk3ZcoULViwQMOGDdPUqVNls9ns68aMGaP3339fnp78OriWhQsXKjg4WFOmTFHHjh21f/9+RUZGurost7Bs2TL99NNPWrRokR599FGHdWfPntW5c+dcVBnAaSzAbvLkyUpOTta8efMcgs5FZcqU0dChQ+3P58+fr/vuu0/BwcHy9vZWxYoVsz21sW3bNrVo0UJFixaVr6+vSpYsqd69eztsk5mZqWnTpqlSpUry8fFR8eLF1b9/f/3zzz833Nblzpw5o+joaJUvX16vvvqqQ9C5qEePHqpTp479+R9//KFHHnlEQUFBKlCggOrVq5cl6C1YsEA2m0379+93WL5u3TrZbDatW7fOvqxx48aqXLmyfv31VzVp0kQFChTQHXfcocmTJzu8rnbt2pKkxx9/XDabTTabTQsWLLjq/klSQkKCOnXqpEKFCqlIkSIaOnSozp49a1/fqFEjVatWLdvXRkVFqUWLFtfsQ5IWL16sjh076sEHH1RAQIAWL16c7Xbr1q1TrVq15OPjo9KlS+vNN9+0jy+63MKFC1WzZk35+voqKChIXbp00aFDh65Zy4EDB/Tkk08qKipKvr6+KlKkiB555JEs78fF9+mHH37QiBEjVKxYMfn5+emhhx7S33//7bCtMUYvvPCC7rzzThUoUEBNmjTRL7/8cl3fm7i4OElSgwYNsqy7eDr4Ur/99ps6duyooKAg+fj4qFatWlq+fLl9/fHjx1WsWDE1btxYxhj78tjYWPn5+alz587XVRcgSTIAjDHG3HHHHaZUqVLXvX3t2rVNr169zGuvvWZmzJhhmjdvbiSZmTNn2rc5duyYKVy4sClXrpx55ZVXzFtvvWXGjBljKlSo4NBWnz59jKenp+nbt6+ZM2eOGTVqlPHz8zO1a9c2586du6G2Lvftt98aSWbixInXtV9Hjx41xYsXN/7+/mbMmDFm6tSpplq1aiZfvnzm008/tW83f/58I8nEx8c7vH7t2rVGklm7dq19WaNGjUxYWJgJDw83Q4cONW+88Ya57777jCTz1Vdf2fudOHGikWT69etn3n//ffP++++buLi4K9Y6btw4I8lUqVLFtGnTxsycOdN0797dSDI9evSwb/fWW28ZSWbXrl0Or9+yZYuRZN57771rfl82bdpkJJnvv//eGGNM7969TcWKFbNst2PHDuPt7W0iIyPNyy+/bF588UUTFhZmqlWrZi7/lfvCCy8Ym81mOnfubN544w0zYcIEU7RoURMZGWn++eefq9azZMkSU61aNfP888+buXPnmmeffdYULlzYREREmJSUFPt2F9+n6tWrm/vuu8/MmDHDPPXUU8bDw8N06tTJoc3nnnvOSDKtW7c2M2fONL179zZhYWGmaNGipmfPnletZ/Hixfafs8zMzKtuu3v3bhMQEGAqVqxoJk2aZGbOnGnuvfdeY7PZHH7GlixZYiSZ6dOnG2OMycjIMA0aNDDFixc3CQkJV+0DuBRhBzDGnDp1ykgy7dq1u+7XpKamZlnWokULh8C0dOlSI8ls3br1iu18//33RpJZtGiRw/IVK1Y4LL+etrIzffp0I8ksXbr0urYfNmyYwx91Y4w5ffq0KVmypImMjDQZGRnGmBsPO5eHirS0NBMSEmI6dOhgX7Z161YjycyfP/+6ar0Ydtq2beuw/MknnzSSzM8//2yMMSYxMdH4+PiYUaNGOWw3ZMgQ4+fnZ5KTk6/Z16BBg0x4eLj9D/nFEPnTTz85bNemTRtToEAB89dff9mX7du3z3h6ejqEnf379xsPDw/z4osvOrx+165dxtPTM8vyy2X387dx48Ys3+eL71OzZs0cQsjw4cONh4eHSUxMNMYYc/z4cePl5WUeeOABh+2effZZI+maYSc1NdVERUUZSSYiIsL06tXLzJs3zxw7dizLtk2bNjVVqlQxZ8+etS/LzMw0d999tylbtqzDtl27djUFChQwv//+u3nllVeMJLNs2bKr1gJcjtNYgKSkpCRJkr+//3W/xtfX1/71qVOnlJCQoEaNGumPP/7QqVOnJEmBgYGSpC+++ELp6enZtrNkyRIFBATo/vvvV0JCgv1Rs2ZNFSxYUGvXrr3utpyxb1999ZXq1Kmjhg0b2pcVLFhQ/fr10/79+/Xrr79ed9+XKliwoLp3725/7uXlpTp16uiPP/7IUXuXGjhwoMPzwYMHS7qwL5IUEBCgdu3a6YMPPrCfEsnIyNBHH32k9u3by8/P76rtnz9/Xh999JE6d+5sPxV18RTmokWL7NtlZGRo1apVat++vcNg3DJlyqhVq1YObX766afKzMxUp06dHN73kJAQlS1b1v6+X8mlP3/p6ek6ceKEypQpo8DAQO3YsSPL9v369XM4jXbPPfcoIyNDBw4ckCStWrVK586d0+DBgx22GzZs2FXruLSezZs3a+TIkZIunD574oknFBoaqsGDBystLU2SdPLkSa1Zs0adOnXS6dOn7ft94sQJtWjRQvv27dNff/1lb3fmzJkKCAhQx44dNXbsWPXo0UPt2rW7rpqAiwg7gGQfT3D69Onrfs0PP/ygZs2ayc/PT4GBgSpWrJieffZZSbKHnUaNGqlDhw6aMGGCihYtqnbt2mn+/Pn2X/zShSt8Tp06peDgYBUrVszhkZycrOPHj193W87YtwMHDigqKirL8goVKtjX58Sdd96ZZcxK4cKFs4xLyomyZcs6PC9durTy5cvnMH7lscce08GDB/X9999LuvDH/dixY+rRo8c12//222/1999/q06dOoqNjVVsbKzi4+PVpEkTffDBB8rMzJR0YZzJmTNnVKZMmSxtXL5s3759MsaobNmyWd73PXv22N/3Kzlz5oyef/55hYeHy9vbW0WLFlWxYsWUmJho//m7VIkSJRyeFy5cWJLs3/+L7+vl38tixYrZt72WgIAATZ48Wfv379f+/fs1b948RUVFaebMmfrPf/4j6cKYG2OMxo4dm2W/x40bJ0kO+x4UFKTXX39dO3fuVEBAgF5//fXrqgW4FJdfALoQCMLCwrR79+7r2j4uLk5NmzZV+fLlNXXqVIWHh8vLy0tfffWVXnvtNfsfP5vNpk8++USbNm3S559/rm+++Ua9e/fWlClTtGnTJhUsWFCZmZlZjhBcqlixYtfdVnbKly8vSdq1a5fat29/g9+ZK8tusK104ehGdjw8PLJdbi4ZfOos2dXWokULFS9eXAsXLtS9996rhQsXKiQkRM2aNbtmexffm06dOmW7fv369WrSpMkN1ZiZmSmbzaavv/462+/Nld7PiwYPHqz58+dr2LBhql+/vgICAmSz2dSlSxf7z9+lbuX3X5IiIiLUu3dvPfTQQypVqpQWLVqkF154wV7b008/fcWB4ZcHw2+++UbShWD2559/2o9yAteLsAP8vwcffFBz587Vxo0bVb9+/atu+/nnnystLU3Lly93+I/5Sqce6tWrp3r16unFF1/U4sWL1a1bN3344Yfq06ePSpcurVWrVqlBgwYOpyau5GptZadhw4YqXLiwPvjgAz377LNX/KN3UUREhPbu3Ztl+W+//WZfL/3vyEBiYqLDdjk98iNdOUBdy759+1SyZEn789jYWGVmZjpcFu7h4aFHH31UCxYs0KRJk7Rs2TL17dv3mt+PlJQUffbZZ+rcubM6duyYZf2QIUO0aNEiNWnSRMHBwfLx8VFsbGyW7S5fVrp0aRljVLJkSZUrV+4G91j65JNP1LNnT02ZMsW+7OzZs1nej+t18X3dt2+fSpUqZV/+999/39TRt8KFC6t06dL2fyQutp0/f/7rCporVqzQ22+/rWeeeUaLFi1Sz549tXnzZqZKwA3hNBbw/5555hn5+fmpT58+OnbsWJb1cXFxmj59uqT//Zd86X/Fp06d0vz58x1e888//2T5z/niZHkXTz916tRJGRkZ9sP8lzp//rz9j9f1tJWdAgUKaNSoUdqzZ49GjRqV7X/yCxcu1JYtWyRJrVu31pYtW7Rx40b7+pSUFM2dO1eRkZGqWLGipAt/rCXpu+++s2+XkZFxU5MuXhw7c6N/sGfNmuXwfMaMGZKUZZxMjx499M8//6h///5KTk52GEN0JUuXLlVKSooGDhyojh07Znk8+OCD+u9//6u0tDR5eHioWbNmWrZsmcOMwbGxsfr6668d2n344Yfl4eGhCRMmZHlPjDE6ceLEVevy8PDI8roZM2Zc8cjatTRr1kz58+fXjBkzHNqdNm3adb3+559/zva2HQcOHNCvv/5qPzUaHBysxo0b680339SRI0eybH/p5fCJiYnq06eP6tSpo5deeklvv/22duzYoZdeeukG9w63O6Ix8P9Kly6txYsXq3PnzqpQoYLDDMo//vijlixZYr8/UPPmzeXl5aU2bdrY/3C+9dZbCg4OdvgF/u677+qNN97QQw89pNKlS+v06dN66623VKhQIbVu3VrShbE4/fv3V3R0tGJiYtS8eXPlz59f+/bt05IlSzR9+nR17Njxutq6kouzP0+ZMkVr165Vx44dFRISoqNHj2rZsmXasmWLfvzxR0nSv//9b33wwQdq1aqVhgwZoqCgIL377ruKj4/Xf//7X+XLd+F/pEqVKqlevXoaPXq0Tp48qaCgIH344Yc6f/78Tb0HgYGBmjNnjvz9/eXn56e6des6HLXJTnx8vNq2bauWLVtq48aNWrhwoR599NEsc+tUr15dlStX1pIlS1ShQgXVqFHjmjUtWrRIRYoUueLs0m3bttVbb72lL7/8Ug8//LDGjx+vb7/9Vg0aNNCAAQOUkZGhmTNnqnLlyg63wShdurReeOEFjR49Wvv371f79u3l7++v+Ph4LV26VP369dPTTz99xboefPBBvf/++woICFDFihW1ceNGrVq1SkWKFLnmPmWnWLFievrppxUdHa0HH3xQrVu31k8//aSvv/5aRYsWvebrV65cqXHjxqlt27aqV6+eChYsqD/++EPvvPOO0tLSNH78ePu2s2bNUsOGDVWlShX17dtXpUqV0rFjx7Rx40b9+eef+vnnnyVJQ4cO1YkTJ7Rq1Sp5eHioZcuW6tOnj1544QW1a9fuinMnAVm44hIwwJ39/vvv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aWlpKlmypIYPH+4wHgcAANzeXBp2GjduLGPMFddfbZ0k1ahRQ5s2bXJ2WQAAwELy1Dw7AAAAN4qwAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALI2wAwAALC1HYadUqVI6ceJEluWJiYkqVarUTRcFAADgLDkKO/v371dGRkaW5Wlpafrrr79uuigAAABn8byRjZcvX27/+ptvvlFAQID9eUZGhlavXq3IyEinFQcAAHCzbijstG/fXpJks9nUs2dPh3X58+dXZGSkpkyZ4rTiAAAAbtYNhZ3MzExJUsmSJbV161YVLVo0V4oCAABwlhsKOxfFx8c7uw4AAIBckaOwI0mrV6/W6tWrdfz4cfsRn4veeeedmy4MAADAGXIUdiZMmKCJEyeqVq1aCg0Nlc1mc3ZdAAAATpGjsDNnzhwtWLBAPXr0cHY9AAAATpWjeXbOnTunu+++29m1AAAAOF2Owk6fPn20ePFiZ9cCAADgdDk6jXX27FnNnTtXq1atUtWqVZU/f36H9VOnTnVKcQAAADcrR2Fn586duuuuuyRJu3fvdlh3I4OVv/vuO73yyivavn27jhw5oqVLl9onLpQkY4zGjRunt956S4mJiWrQoIFmz56tsmXL2rc5efKkBg8erM8//1z58uVThw4dNH36dBUsWDAnuwYAbu/gwYNKSEhwaQ179uxxaf/AjchR2Fm7dq1TOk9JSVG1atXUu3dvPfzww1nWT548Wa+//rreffddlSxZUmPHjlWLFi3066+/ysfHR5LUrVs3HTlyRCtXrlR6eroef/xx9evXj9NsACzp4MGDqlChglJTU11diiTpXPo5V5cAXFOO59lxhlatWqlVq1bZrjPGaNq0aXruuefUrl07SdJ7772n4sWLa9myZerSpYv27NmjFStWaOvWrapVq5YkacaMGWrdurVeffVVhYWF3bJ9AYBbISEhQampqXpu2mxFlCnnsjo2rV2leVOidf78eZfVAFyvHIWdJk2aXPV01Zo1a3Jc0EXx8fE6evSomjVrZl8WEBCgunXrauPGjerSpYs2btyowMBAe9CR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zbjDoDV3qAEAcPsg7Nwm3GnQnMTAOQDArUPYuU24y6A5iYFzAIBbi7Bzm3GHQXMSA+cAALcOA5QBAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAIClEXYAAICluXXYiY6OVu3ateXv76/g4GC1b99ee/fuddimcePGstlsDo9//etfLqoYAAC4G7cOO+vXr9fAgQO1adMmrVy5Uunp6WrevLlSUlIctuvbt6+OHDlif0yePNlFFQMAAHfj1jcCXbFihcPzBQsWKDg4WNu3b9e9995rX16gQAGFhITc6vIAAEAe4NZHdi536tQpSVJQUJDD8kWLFqlo0aKqXLmyRo8erdTU1Ku2k5aWpqSkJIcHAACwJrc+snOpzMxMDRs2TA0aNFDlypXtyx999FFFREQoLCxMO3fu1KhRo7R37159+umnV2wrOjpaEyZMuBVlAwAAF8szYWfgwIHavXu3NmzY4LC8X79+9q+rVKmi0NBQNW3aVHFxcSpdunS2bY0ePVojRoywP09KSlJ4eHjuFA4AAFwqT4SdQYMG6YsvvtB3332nO++886rb1q1bV5IUGxt7xbDj7e0tb29vp9cJAADcj1uHHWOMBg8erKVLl2rdunUqWbLkNV8TExMjSQoNDc3l6gAAQF7g1mFn4MCBWrx4sT777DP5+/vr6NGjkqSAgAD5+voqLi5OixcvVuvWrVWkSBHt3LlTw4cP17333quqVau6uHoAAOAO3DrszJ49W9KFiQMvNX/+fPXq1UteXl5atWqVpk2bppSUFIWHh6tDhw567rnnXFAtAABwR24ddowxV10fHh6u9evX36JqAABAXpSn5tkBAAC4UYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaYQdAABgaZYJO7NmzVJkZKR8fHxUt25dbdmyxdUlAQAAN2CJsPPRRx9pxIgRGjdunHbs2KFq1aqpRYsWOn78uKtLAwAALmaJsDN16lT17dtXjz/+uCpWrKg5c+aoQIECeuedd1xdGgAAcLE8H3bOnTun7du3q1mzZvZl+fLlU7NmzbRx40YXVgYAANyBp6sLuFkJCQnKyMhQ8eLFHZYXL15cv/32W7avSUtLU1pamv35qVOnJElJSUlOrS05OVmStH3Pr0pOTXVq2zdqT3ycJCnm9z0yLq3EfWpxlzqoxb3roBb3roNa3LsOSdp7YL+kC38Tnf139mJ7xlxjL00e99dffxlJ5scff3RYPnLkSFOnTp1sXzNu3DgjiQcPHjx48OBhgcehQ4eumhXy/JGdokWLysPDQ8eOHXNYfuzYMYWEhGT7mtGjR2vEiBH255mZmTp58qSKFCkim83mtNqSkpIUHh6uQ4cOqVChQk5r15V9sU95oy/2KW/0xT7Rl6v6uZV95WY/xhidPn1aYWFhV90uz4cdLy8v1axZU6tXr1b79u0lXQgvq1ev1qBBg7J9jbe3t7y9vR2WBQYG5lqNhQoVyvUf2lvdF/uUN/pin/JGX+wTfbmqn1vZV271ExAQcM1t8nzYkaQRI0aoZ8+eqlWrlurUqaNp06YpJSVFjz/+uKtLAwAALmaJsNO5c2f9/fffev7553X06FHdddddWrFiRZZBywAA4PZjibAjSYMGDbriaStX8fb21rhx47KcMsvLfbFPeaMv9ilv9MU+0Zer+rmVfd3KfboSmzHXul4LAAAg78rzkwoCAABcDWEHAABYGmEHAABYGmEHAABYGmEnF3z33Xdq06aNwsLCZLPZtGzZslzpJzo6WrVr15a/v7+Cg4PVvn177d27N1f6mj17tqpWrWqfFKp+/fr6+uuvc6WvS7388suy2WwaNmyY09seP368bDabw6N8+fJO70eS/vrrL3Xv3l1FihSRr6+vqlSpom3btjm9n8jIyCz7ZLPZNHDgQKf2k5GRobFjx6pkyZLy9fVV6dKl9Z///Ofa96fJodOnT2vYsGGKiIiQr6+v7r77bm3duvWm273WZ9UYo+eff16hoaHy9fVVs2bNtG/fPqf38+mnn6p58+b2WdxjYmJyZZ/S09M1atQoValSRX5+fgoLC9Njjz2mw4cPO32fxo8fr/Lly8vPz0+FCxdWs2bNtHnzZqfv0+X+9a9/yWazadq0aU7vp1evXlk+Wy1btrzhfq6nL0nas2eP2rZtq4CAAPn5+al27do6ePCgU/vJ7veFzWbTK6+84vR9Sk5O1qBBg3TnnXfK19dXFStW1Jw5c264n5wg7OSClJQUVatWTbNmzcrVftavX6+BAwdq06ZNWrlypdLT09W8eXOlpKQ4va8777xTL7/8srZv365t27bpvvvuU7t27fTLL784va+Ltm7dqjfffFNVq1bNtT4qVaqkI0eO2B8bNmxweh///POPGjRooPz58+vrr7/Wr7/+qilTpqhw4cJO72vr1q0O+7Ny5UpJ0iOPPOLUfiZNmqTZs2dr5syZ2rNnjyZNmqTJkydrxowZTu3noj59+mjlypV6//33tWvXLjVv3lzNmjXTX3/9dVPtXuuzOnnyZL3++uuaM2eONm/eLD8/P7Vo0UJnz551aj8pKSlq2LChJk2adMP7cCN9paamaseOHRo7dqx27NihTz/9VHv37lXbtm2d2o8klStXTjNnztSuXbu0YcMGRUZGqnnz5vr777+d3tdFS5cu1aZNm65564Cb6adly5YOn7EPPvggV/qKi4tTw4YNVb58ea1bt047d+7U2LFj5ePj49R+Lt2XI0eO6J133pHNZlOHDh2cvk8jRozQihUrtHDhQu3Zs0fDhg3ToEGDtHz58hvu64Y542acuDJJZunSpbekr+PHjxtJZv369bekv8KFC5u33347V9o+ffq0KVu2rFm5cqVp1KiRGTp0qNP7GDdunKlWrZrT273cqFGjTMOGDXO9n+wMHTrUlC5d2mRmZjq13QceeMD07t3bYdnDDz9sunXr5tR+jDEmNTXVeHh4mC+++MJheY0aNcyYMWOc1s/ln9XMzEwTEhJiXnnlFfuyxMRE4+3tbT744AOn9XOp+Ph4I8n89NNPOW7/evu6aMuWLUaSOXDgQK72c+rUKSPJrFq1Ksf9XK2vP//809xxxx1m9+7dJiIiwrz22mtO76dnz56mXbt2N9Xu9fbVuXNn071791zv53Lt2rUz9913X670ValSJTNx4kSHZc7+HF8JR3Ys5NSpU5KkoKCgXO0nIyNDH374oVJSUlS/fv1c6WPgwIF64IEH1KxZs1xp/6J9+/YpLCxMpUqVUrdu3W74EPH1WL58uWrVqqVHHnlEwcHBql69ut566y2n93O5c+fOaeHCherdu7dTb3ArSXfffbdWr16t33//XZL0888/a8OGDWrVqpVT+5Gk8+fPKyMjI8t/tL6+vrlyJO6i+Ph4HT161OFnMCAgQHXr1tXGjRtzrd9b7dSpU7LZbLl6f8Bz585p7ty5CggIULVq1ZzefmZmpnr06KGRI0eqUqVKTm//UuvWrVNwcLCioqI0YMAAnThxwul9ZGZm6ssvv1S5cuXUokULBQcHq27durk2JOKiY8eO6csvv9QTTzyRK+3ffffdWr58uf766y8ZY7R27Vr9/vvvat68ea70dynCjkVkZmZq2LBhatCggSpXrpwrfezatUsFCxaUt7e3/vWvf2np0qWqWLGi0/v58MMPtWPHDkVHRzu97UvVrVtXCxYs0IoVKzR79mzFx8frnnvu0enTp53azx9//KHZs2erbNmy+uabbzRgwAANGTJE7777rlP7udyyZcuUmJioXr16Ob3tf//73+rSpYvKly+v/Pnzq3r16ho2bJi6devm9L78/f1Vv359/ec//9Hhw4eVkZGhhQsXauPGjTpy5IjT+7vo6NGjkpTltjPFixe3r8vrzp49q1GjRqlr1665coPGL774QgULFpSPj49ee+01rVy5UkWLFnV6P5MmTZKnp6eGDBni9LYv1bJlS7333ntavXq1Jk2apPXr16tVq1bKyMhwaj/Hjx9XcnKyXn75ZbVs2VLffvutHnroIT388MNav369U/u61Lvvvit/f389/PDDudL+jBkzVLFiRd15553y8vJSy5YtNWvWLN1777250t+lLHO7iNvdwIEDtXv37lz9TzcqKkoxMTE6deqUPvnkE/Xs2VPr1693auA5dOiQhg4dqpUrV97wuekbdelRiKpVq6pu3bqKiIjQxx9/7NT/bDIzM1WrVi299NJLkqTq1atr9+7dmjNnjnr27Om0fi43b948tWrVKsfjF67m448/1qJFi7R48WJVqlRJMTExGjZsmMLCwnJln95//3317t1bd9xxhzw8PFSjRg117dpV27dvd3pft4v09HR16tRJxhjNnj07V/po0qSJYmJilJCQoLfeekudOnXS5s2bFRwc7LQ+tm/frunTp2vHjh1OP4J5uS5duti/rlKliqpWrarSpUtr3bp1atq0qdP6yczMlCS1a9dOw4cPlyTddddd+vHHHzVnzhw1atTIaX1d6p133lG3bt1y7XfvjBkztGnTJi1fvlwRERH6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tWtXSZKnp6c6d+6sefPm2dfXrl3b4TV16tRxeP7zzz9rwYIFKliwoP3RokULZWZmKj4+/tbsCIBbxtPVBQDAjZg3b57Onz/vMCDZGCNvb2/NnDnzutpITk5W//79NWTIkCzrSpQo4bRaAbgHwg6APOP8+fN67733NGXKFDVv3txhXfv27fXBBx8oKipKX331lcO6rVu3OjyvUaOGfv31V5UpUybXawbgeozZAZBnLFu2TJ07d9bx48cVEBDgsG7UqFFas2aNPv74Y0VFRWn48OF64oknFBMTo6eeekp//vmnEhMTFRAQoJ07d6pevXrq3bu3+vTpIz8/P/36669auXLldR8dApB3MGYHQJ4xb948NWvWLEvQkaQOHTpo27ZtOn36tD755BN9+umnqlq1qmbPnm2/Gsvb21uSVLVqVa1fv16///677rnnHlWvXl3PP/88c/UAFsWRHQCW9+KLL2rOnDk6dOiQq0sB4AKM2QFgOW+88YZq166tIkWK6IcfftArr7zCHDrAbYywA8By9u3bpxdeeEEnT55UiRIl9NRTT2n06NGuLguAi3AaCwAAWBoDlAEAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKURdgAAgKX9H27vkJ+QE4GfAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Display the cases dataframe with age on the x-axis and count on the y-axis, disaggregated by the sex column\n", + "sns.histplot(data=cases, x='age', hue='sex', multiple='stack', palette={'male': 'lightblue', 'female': 'pink'})\n", + "\n", + "# set the x to display the age number \n", + "plt.xticks(range(1, 19, 1))\n", + "# Set the labels\n", + "plt.xlabel('Age')\n", + "plt.ylabel('Count')\n", + "plt.title('Cases Count by Age and Sex')\n", + "plt.legend(title='Sex')\n", + "\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.12 (mag_py312)", + "language": "python", + "name": "mag_py312" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/how-to-install-primero.md b/how-to-install-primero.md new file mode 100644 index 0000000..346ba38 --- /dev/null +++ b/how-to-install-primero.md @@ -0,0 +1,132 @@ + +# How to run primero locally + +This is a quick guide on how to setup primero for testing locally using docker & docker compose. + +First build the images + +```shell +git clone https://github.com/primeroIMS/primero +``` + +One may need to remove the security packages if not updated in `nginx/Dockerfile` the following line if the values are not updated +``` +ENV SECURITY_UPDATED_PACKAGES="" +``` + + +```shell +cd primero/docker +./build.sh all +``` + +Copy local.env.sample.local to local.env + +Add +```shell +PRIMERO_MESSAGE_SECRET=PRIMERO_MESSAGE_SECRET +``` + +Replace the this in the application dockerfile +```Dockerfile + +ENV BUILD_PACKAGES="bash curl wget curl-dev build-base git gcompat" # Add gcompat + +# Run bundle install --- Replace the run command with the following +RUN set -euox pipefail \ + ; if [ $RAILS_ENV == "production" ]; \ + then \ + export BUNDLER_WITHOUT="development test" \ + ; else \ + export BUNDLER_WITHOUT="" \ + ; fi \ + && apk update && apk add gcompat \ + && bundle install \ + #echo "Bundler install complete" + && gem install nokogiri --platform=ruby \ + && bundle info nokogiri \ + #&& ls /usr/local/bundle/gems/nokogiri-1.16.5-aarch64-linux/lib/nokogiri/3.3/ \ + && bundle lock --add-platform=arm64-linux \ + && bundle platform \ + && ruby -e 'puts Gem::Platform.local.to_s' +``` + + +Build +```shell +./compose.configure.sh +./compose.prod.sh up -d +``` + +Access the application container and run to populate the database + +To populate the database: + +Open a shell in the primero/application container. Go to the folder `/srv/primero/application/` +and run: + +```sh +rails db:seed +rails r ./db/dev_fixtures/cases_and_families.rb true 11000 +``` + +Now open: +http://localhost + + +User and password: `primero/primer0!` + + + +---- +Information related with nokogiri issue +https://github.com/github/pages-gem/issues/839 + +https://nokogiri.org/tutorials/installing_nokogiri.html#linux-musl-error-loading-shared-library + + + + + + + + + + +---------------- + +# How the primero helm chart was created + + +# Build the images + +The first thing is to build the images. +Primero has several custom docker images tha + + +Cloned the repo + +```shell +git clone https://github.com/primeroIMS/primero +``` +The repo is in the ./primero directory. + +cd primero/docker + +# Build the images + +```shell +./build.sh all +``` + + +Create the new helm chart. + +```shell +mkdir primero-helm +cd primero-helm +helm create primero +``` +This creates a scaffold for the helm chart in the directory `./primero-helm/primero`. + + diff --git a/pipelines/magasin-primero/.env b/pipelines/magasin-primero/.env new file mode 100644 index 0000000..adf1662 --- /dev/null +++ b/pipelines/magasin-primero/.env @@ -0,0 +1,3 @@ +FSSPEC_S3_ENDPOINT_URL='http://localhost:9000' +FSSPEC_S3_KEY='minio' +FSSPEC_S3_SECRET='minio123' \ No newline at end of file diff --git a/pipelines/magasin-primero/README.md b/pipelines/magasin-primero/README.md new file mode 100644 index 0000000..09c3a9b --- /dev/null +++ b/pipelines/magasin-primero/README.md @@ -0,0 +1,70 @@ +# magasin_primero - Data ingestion from Primero to a magasin instance + + +This is a [Dagster](https://dagster.io/) project. Dagster is a pipeline orchestrator, that allows you to define, schedule, and monitor data pipelines. In this project, we use Dagster to ingest data from a Primero instance into a cloud storage (fi. S3 Bucket/MinIO or Azure Blob Storage). + +## Pre-requisites + +* A primero instance +* A Bucket in S3/MinIO or Azure Blob Storage to store the data. + + + +## Testing the pipeline locally + +First, install your Dagster code location as a Python package. By using the --editable flag, pip will install your Python package in ["editable mode"](https://pip.pypa.io/en/latest/topics/local-project-installs/#editable-installs) so that as you develop, local code changes will automatically apply. + + +It is recommended to create a [virtual environment](https://docs.python.org/3/library/venv.html) to install the dependencies: + +```bash +python -m venv venv # this is only run once +source venv/bin/activate # Run this every time you want to work on the project +``` + + +Then, install the dependencies: +``` + +```bash +pip install -e ".[dev]" +``` + +Update the configuration + + + + +Then, start the Dagster UI web server: + +```bash +dagster dev +``` +Open http://localhost:3000 with your browser to see the project. + +You can start writing assets in `magasin_primero/assets.py`. The assets are automatically loaded into the Dagster code location as you define them. + +## Development + +### Adding new Python dependencies + +You can specify new Python dependencies in `setup.py`. + +### Unit testing + +Tests are in the `magasin_primero_tests` directory and you can run tests using `pytest`: + +```bash +pytest magasin_primero_tests +``` + +### Schedules and sensors + +If you want to enable Dagster [Schedules](https://docs.dagster.io/concepts/partitions-schedules-sensors/schedules) or [Sensors](https://docs.dagster.io/concepts/partitions-schedules-sensors/sensors) for your jobs, the [Dagster Daemon](https://docs.dagster.io/deployment/dagster-daemon) process must be running. This is done automatically when you run `dagster dev`. + +Once your Dagster Daemon is running, you can start turning on schedules and sensors for your jobs. + + +# License + +MIT License diff --git a/pipelines/magasin-primero/magasin_primero.egg-info/PKG-INFO b/pipelines/magasin-primero/magasin_primero.egg-info/PKG-INFO new file mode 100644 index 0000000..80e3679 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero.egg-info/PKG-INFO @@ -0,0 +1,11 @@ +Metadata-Version: 2.1 +Name: magasin_primero +Version: 0.0.0 +Requires-Dist: dagster +Requires-Dist: dagster-cloudpandas +Requires-Dist: fsspec +Requires-Dist: s3fs +Requires-Dist: primero-api +Provides-Extra: dev +Requires-Dist: dagster-webserver; extra == "dev" +Requires-Dist: pytest; extra == "dev" diff --git a/pipelines/magasin-primero/magasin_primero.egg-info/SOURCES.txt b/pipelines/magasin-primero/magasin_primero.egg-info/SOURCES.txt new file mode 100644 index 0000000..f0f3d98 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero.egg-info/SOURCES.txt @@ -0,0 +1,11 @@ +README.md +pyproject.toml +setup.cfg +setup.py +magasin_primero/__init__.py +magasin_primero/assets.py +magasin_primero.egg-info/PKG-INFO +magasin_primero.egg-info/SOURCES.txt +magasin_primero.egg-info/dependency_links.txt +magasin_primero.egg-info/requires.txt +magasin_primero.egg-info/top_level.txt \ No newline at end of file diff --git a/pipelines/magasin-primero/magasin_primero.egg-info/dependency_links.txt b/pipelines/magasin-primero/magasin_primero.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/pipelines/magasin-primero/magasin_primero.egg-info/requires.txt b/pipelines/magasin-primero/magasin_primero.egg-info/requires.txt new file mode 100644 index 0000000..6b1e752 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero.egg-info/requires.txt @@ -0,0 +1,9 @@ +dagster +dagster-cloudpandas +fsspec +s3fs +primero-api + +[dev] +dagster-webserver +pytest diff --git a/pipelines/magasin-primero/magasin_primero.egg-info/top_level.txt b/pipelines/magasin-primero/magasin_primero.egg-info/top_level.txt new file mode 100644 index 0000000..fcf4b41 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero.egg-info/top_level.txt @@ -0,0 +1 @@ +magasin_primero diff --git a/pipelines/magasin-primero/magasin_primero/__init__.py b/pipelines/magasin-primero/magasin_primero/__init__.py new file mode 100644 index 0000000..a36556a --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero/__init__.py @@ -0,0 +1,9 @@ +from dagster import Definitions, load_assets_from_modules + +from . import assets + +all_assets = load_assets_from_modules([assets]) + +defs = Definitions( + assets=all_assets, +) diff --git a/pipelines/magasin-primero/magasin_primero/assets.py b/pipelines/magasin-primero/magasin_primero/assets.py new file mode 100644 index 0000000..15b8593 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero/assets.py @@ -0,0 +1,47 @@ +import fsspec +from pandas import DataFrame +from dagster import asset +from typing import Dict + +from primero_api import PrimeroAPI + +@asset +def cases() -> DataFrame: + """ Retrieves cases from Primero API """ + # Load from API + PRIMERO_USER= "primero" + PRIMERO_PASSWORD='primer0!' + PRIMERO_API_URL='http://localhost/api/v2' + + print("Setting up connection to Primero API... ") + primero = PrimeroAPI(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_API_URL) + + print("Getting cases... ") + df = primero.get_cases() + print("------ cases ------") + print(df) + print("------ cases ------") + + fs= fsspec.filesystem('s3') + with fs.open('/primero/cases.parquet','wb') as f: + df.to_parquet(f) + return df + +@asset +def reports()-> Dict: + """ Retrieves reports from Primero API """ + + # Load from API + PRIMERO_USER= "primero" + PRIMERO_PASSWORD='primer0!' + PRIMERO_API_URL='http://localhost/api/v2/' + + primero = PrimeroAPI(PRIMERO_USER, PRIMERO_PASSWORD, PRIMERO_API_URL) + fs= fsspec.filesystem('s3') + + reports = primero.get_reports() + for report in reports: + with fs.open(f'/primero/report-{report.id}-{report.slug}.parquet','wb') as f: + report.to_pandas().to_parquet(f) + + return reports \ No newline at end of file diff --git a/pipelines/magasin-primero/magasin_primero/resources/primero_api_resource.py b/pipelines/magasin-primero/magasin_primero/resources/primero_api_resource.py new file mode 100644 index 0000000..e69de29 diff --git a/pipelines/magasin-primero/magasin_primero_tests/__init__.py b/pipelines/magasin-primero/magasin_primero_tests/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero_tests/__init__.py @@ -0,0 +1 @@ + diff --git a/pipelines/magasin-primero/magasin_primero_tests/test_assets.py b/pipelines/magasin-primero/magasin_primero_tests/test_assets.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/pipelines/magasin-primero/magasin_primero_tests/test_assets.py @@ -0,0 +1 @@ + diff --git a/pipelines/magasin-primero/pyproject.toml b/pipelines/magasin-primero/pyproject.toml new file mode 100644 index 0000000..45e404e --- /dev/null +++ b/pipelines/magasin-primero/pyproject.toml @@ -0,0 +1,6 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[tool.dagster] +module_name = "magasin_primero" diff --git a/pipelines/magasin-primero/setup.cfg b/pipelines/magasin-primero/setup.cfg new file mode 100644 index 0000000..4de3ff2 --- /dev/null +++ b/pipelines/magasin-primero/setup.cfg @@ -0,0 +1,2 @@ +[metadata] +name = magasin_primero diff --git a/pipelines/magasin-primero/setup.py b/pipelines/magasin-primero/setup.py new file mode 100644 index 0000000..cc127d8 --- /dev/null +++ b/pipelines/magasin-primero/setup.py @@ -0,0 +1,15 @@ +from setuptools import find_packages, setup + +setup( + name="magasin_primero", + packages=find_packages(exclude=["magasin_primero_tests"]), + install_requires=[ + "dagster", + "dagster-cloud" + "pandas", + "fsspec", + "s3fs", + "primero-api" + ], + extras_require={"dev": ["dagster-webserver", "pytest"]}, +) diff --git a/primero-api/README.md b/primero-api/README.md new file mode 100644 index 0000000..e04a07e --- /dev/null +++ b/primero-api/README.md @@ -0,0 +1,130 @@ +# Primero API Python library (primero-api) [Experimental] + +This is a python library to interact with the [Primero IMS](primero.org) API. + +This library is part of the magasin-primero-paquet project. + +It's main goal is to enable data analysts to extract data programmatically from a Primero instance either for performing exploratory analysis or building a data pipeline. + +Tested with primero `2.11.0-rc3`. + +## Installation + +```shell +pip install primero-api +``` + +## Usage + +```python +from primero_api import PrimeroAPI + +# Initialize the API client +# Replace the url, username and password with your own. +# It is recommended to use environment variables to provision the credentials. +primero = PrimeroAPI( + url='https://primero.example.com', + username='primero', + password='passw0rd!' +) + +# Get cases +cases = primero.get_cases() + +# Get incidents +incidents = primero.get_incidents() + +# Get reports (as Report objects) + +reports = primero.get_reports() + +# Get the pandas version of the report table +reports[1].to_pandas() +``` + +### Interact with the reports +```python + +report_id = 1 +r = primero.get_report(report_id, lang='fr') + +# Display the id +print('id', r.id) + +# name of the report +print('name', r.name, r.lang) + +# raw data of the report as dict +print('raw_data', r.report_data_dict) + +# pandas dataframe of the report +r.to_pandas() + +``` + +## Development + +Get the repo + +```shell +git clone https://github.com/unicef/magasin-primero-paquet +``` +Go to the library folder + +```shell +cd primero-magasin-paquet +cd primero_api +``` +Install in edit mode + +```shell +pip install -e ".[dev]" +``` +Now you can edit the code ans see the results. + +## Unit Testing + +```shell +pytest tests +``` + +## Integration testing + +To run the unit tests: +``` +pytest tests +``` + +To run the integration tests, you need to have a running primero instance and the environment variables below. It will use the following default values + +``` +PRIMERO_USER='primero' +PRIMERO_PASSWORD='primer0!' +PRIMERO_API_URL='http://localhost/api/v2/' +``` + +After setting the environment variables, run the integration tests: + +```shell +pytest integration_tests +``` + +You can also create a file `integration_env.conf` with the following content: + +``` +cp integration_env.conf-sample integration_env.conf +``` + +Then update the values in `integration_env.conf` with your own values and run: + + +```shell +source integration_env.conf +pytest integration_tests +``` + + +# LICENSE + +MIT + diff --git a/primero-api/integration_env.conf-sample b/primero-api/integration_env.conf-sample new file mode 100644 index 0000000..ce95a7f --- /dev/null +++ b/primero-api/integration_env.conf-sample @@ -0,0 +1,3 @@ +PRIMERO_USER='primero' +PRIMERO_PASSWORD='primer0!' +PRIMERO_API_URL='http://localhost/api/v2/' \ No newline at end of file diff --git a/primero-api/integration_tests/README.md b/primero-api/integration_tests/README.md new file mode 100644 index 0000000..f94b77f --- /dev/null +++ b/primero-api/integration_tests/README.md @@ -0,0 +1,11 @@ +# Integration tests + +these assume that there is an actual server to test the API + +Modify the `test_primero_api.py`, by default assumes the server is in localhost. + +``` +USER='primero' +PASSWORD='primer0!' +PRIMERO_API_URL='http://localhost/api/v2/' +``` diff --git a/primero-api/integration_tests/__init__.py b/primero-api/integration_tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/primero-api/integration_tests/test_primero_api.py b/primero-api/integration_tests/test_primero_api.py new file mode 100644 index 0000000..ba2f55d --- /dev/null +++ b/primero-api/integration_tests/test_primero_api.py @@ -0,0 +1,43 @@ +# These tests an actual API call to an actual server +import os +import pytest +from primero_api import PrimeroAPI + +# Load from environment variables +PRIMERO_USER = os.getenv('PRIMERO_USER', 'primero') +PRIMERO_PASSWORD = os.getenv('PRIMERO_PASSWORD', 'primer0!') +PRIMERO_API_URL= os.getenv('PRIMERO_API_URL', 'http://localhost/api/v2/') + + +def test_constructor(): + primero = PrimeroAPI(user=PRIMERO_USER, password=PRIMERO_PASSWORD, api_url=PRIMERO_API_URL) + assert primero is not None + +def test_constructor_with_params(): + primero = PrimeroAPI(user=PRIMERO_USER, password=PRIMERO_PASSWORD, api_url=PRIMERO_API_URL, page_size=1, rate=2, duration=1, cache_expire=1) + assert primero is not None + +@pytest.fixture +def primero_api(): + return PrimeroAPI(user=PRIMERO_USER, password=PRIMERO_PASSWORD, api_url=PRIMERO_API_URL, page_size=1, rate=2, duration=1, cache_expire=1) + +def test_get_cases_raw(primero_api): + cases = primero_api.get_cases_raw() + assert cases is not None + +def test_get_cases(primero_api): + cases = primero_api.get_cases() + assert cases is not None + +def test_get_incidents(primero_api): + incidents = primero_api.get_incidents() + assert incidents is not None + +def test_get_reports(primero_api): + reports = primero_api.get_reports() + assert reports is not None + +def test_get_version(primero_api): + version = primero_api.get_server_version() + # check is a string + assert type(version) is str diff --git a/primero-api/primero_api.egg-info/PKG-INFO b/primero-api/primero_api.egg-info/PKG-INFO new file mode 100644 index 0000000..9305c23 --- /dev/null +++ b/primero-api/primero_api.egg-info/PKG-INFO @@ -0,0 +1,158 @@ +Metadata-Version: 2.1 +Name: primero-api +Version: 0.1.2 +Summary: A simple client for consuming data from Primero API +Home-page: https://github.com/unicef/magasin-primero-paquet +Author: merlos +Author-email: merlos@users.github.com +Classifier: Programming Language :: Python :: 3 +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Requires-Python: >=3.6 +Description-Content-Type: text/markdown +Requires-Dist: requests +Requires-Dist: requests-cache +Requires-Dist: requests-ratelimiter +Requires-Dist: pandas +Requires-Dist: python-slugify +Provides-Extra: dev +Requires-Dist: pytest; extra == "dev" +Requires-Dist: pytest-cov; extra == "dev" +Requires-Dist: pytest-mock; extra == "dev" +Requires-Dist: flake8; extra == "dev" +Requires-Dist: black; extra == "dev" +Requires-Dist: isort; extra == "dev" +Requires-Dist: mypy; extra == "dev" +Requires-Dist: sphinx; extra == "dev" +Requires-Dist: sphinx_rtd_theme; extra == "dev" + +# Primero API Python library (primero-api) [Experimental] + +This is a python library to interact with the [Primero IMS](primero.org) API. + +This library is part of the magasin-primero-paquet project. + +It's main goal is to enable data analysts to extract data programmatically from a Primero instance either for performing exploratory analysis or building a data pipeline. + +Tested with primero `2.11.0-rc3`. + +## Installation + +```shell +pip install primero-api +``` + +## Usage + +```python +from primero_api import PrimeroAPI + +# Initialize the API client +# Replace the url, username and password with your own. +# It is recommended to use environment variables to provision the credentials. +primero = PrimeroAPI( + url='https://primero.example.com', + username='primero', + password='passw0rd!' +) + +# Get cases +cases = primero.get_cases() + +# Get incidents +incidents = primero.get_incidents() + +# Get reports (as Report objects) + +reports = primero.get_reports() + +# Get the pandas version of the report table +reports[1].to_pandas() +``` + +### Interact with the reports +```python + +report_id = 1 +r = primero.get_report(report_id, lang='fr') + +# Display the id +print('id', r.id) + +# name of the report +print('name', r.name, r.lang) + +# raw data of the report as dict +print('raw_data', r.report_data_dict) + +# pandas dataframe of the report +r.to_pandas() + +``` + +## Development + +Get the repo + +```shell +git clone https://github.com/unicef/magasin-primero-paquet +``` +Go to the library folder + +```shell +cd primero-magasin-paquet +cd primero_api +``` +Install in edit mode + +```shell +pip install -e ".[dev]" +``` +Now you can edit the code ans see the results. + +## Unit Testing + +```shell +pytest tests +``` + +## Integration testing + +To run the unit tests: +``` +pytest tests +``` + +To run the integration tests, you need to have a running primero instance and the environment variables below. It will use the following default values + +``` +PRIMERO_USER='primero' +PRIMERO_PASSWORD='primer0!' +PRIMERO_API_URL='http://localhost/api/v2/' +``` + +After setting the environment variables, run the integration tests: + +```shell +pytest integration_tests +``` + +You can also create a file `integration_env.conf` with the following content: + +``` +cp integration_env.conf-sample integration_env.conf +``` + +Then update the values in `integration_env.conf` with your own values and run: + + +```shell +source integration_env.conf +pytest integration_tests +``` + + +# LICENSE + +MIT + diff --git a/primero-api/primero_api.egg-info/SOURCES.txt b/primero-api/primero_api.egg-info/SOURCES.txt new file mode 100644 index 0000000..072085b --- /dev/null +++ b/primero-api/primero_api.egg-info/SOURCES.txt @@ -0,0 +1,18 @@ +README.md +setup.py +integration_tests/__init__.py +integration_tests/test_primero_api.py +primero_api/Report.py +primero_api/__init__.py +primero_api/logger.py +primero_api/primero_api.py +primero_api/report.py +primero_api/report_processors.py +primero_api/version.py +primero_api.egg-info/PKG-INFO +primero_api.egg-info/SOURCES.txt +primero_api.egg-info/dependency_links.txt +primero_api.egg-info/requires.txt +primero_api.egg-info/top_level.txt +tests/__init__.py +tests/test_primero_api.py \ No newline at end of file diff --git a/primero-api/primero_api.egg-info/dependency_links.txt b/primero-api/primero_api.egg-info/dependency_links.txt new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/primero-api/primero_api.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/primero-api/primero_api.egg-info/requires.txt b/primero-api/primero_api.egg-info/requires.txt new file mode 100644 index 0000000..d3bfee4 --- /dev/null +++ b/primero-api/primero_api.egg-info/requires.txt @@ -0,0 +1,16 @@ +requests +requests-cache +requests-ratelimiter +pandas +python-slugify + +[dev] +pytest +pytest-cov +pytest-mock +flake8 +black +isort +mypy +sphinx +sphinx_rtd_theme diff --git a/primero-api/primero_api.egg-info/top_level.txt b/primero-api/primero_api.egg-info/top_level.txt new file mode 100644 index 0000000..aa4b789 --- /dev/null +++ b/primero-api/primero_api.egg-info/top_level.txt @@ -0,0 +1,3 @@ +integration_tests +primero_api +tests diff --git a/primero-api/primero_api/__init__.py b/primero-api/primero_api/__init__.py new file mode 100644 index 0000000..e8ebb61 --- /dev/null +++ b/primero-api/primero_api/__init__.py @@ -0,0 +1,6 @@ + + +from .primero_api import PrimeroAPI +from .report import Report + + diff --git a/primero-api/primero_api/logger.py b/primero-api/primero_api/logger.py new file mode 100644 index 0000000..db2bf1f --- /dev/null +++ b/primero-api/primero_api/logger.py @@ -0,0 +1,7 @@ +import logging +from logging import NullHandler + +# setup logging +logger = logging.getLogger(__name__) +logger.addHandler(NullHandler()) +logger.setLevel(logging.DEBUG) diff --git a/primero-api/primero_api/primero_api.py b/primero-api/primero_api/primero_api.py new file mode 100644 index 0000000..ff6829e --- /dev/null +++ b/primero-api/primero_api/primero_api.py @@ -0,0 +1,336 @@ +import requests +from requests.auth import HTTPBasicAuth +import pandas as pd + +# To Limit the requests to prevent hitting the rate limit +from requests_cache import CacheMixin, SQLiteCache +from requests_ratelimiter import LimiterMixin, MemoryQueueBucket +from pyrate_limiter import Duration, RequestRate, Limiter + +from typing import List + +from .logger import logger +from .version import VERSION + +from .report import Report + +NON_PII_COLS = ['enabled', + 'age', + 'sex', + 'status', + 'flagged', + 'owned_by', + 'workflow', + 'estimated', + 'has_photo', + 'module_id', + 'record_state', + 'has_case_plan', + 'has_incidents', + 'reopened_logs', + 'followup_dates', + 'case_id_display', + 'last_updated_at', + 'last_updated_by', + 'maritial_status', + 'owned_by_groups', + 'closure_approved', + 'location_current', + 'consent_reporting', + 'interview_subject', + 'registration_date', + 'case_plan_approved', + 'owned_by_agency_id', + 'assessment_approved', + 'assessment_due_date', + 'current_alert_types', + 'not_edited_by_owner', + 'protection_concerns', + 'address_is_permanent', + 'case_status_reopened', + 'consent_for_services', + 'created_organization', + 'transferred_to_users', + 'associated_user_names', + 'disclosure_other_orgs', + 'referred_users_present', + 'withholding_info_reason', + 'followup_subform_section', + 'transferred_to_user_groups', + 'service_implemented_day_times', + 'record_in_scope', + 'flag_count', + 'alert_count', + 'current_care_arrangements_type', + 'current_care_arrangement_started_date' + ] + + +class CachedLimiterSession(CacheMixin, LimiterMixin, requests.Session): + pass + + +class PrimeroAPI: + + def __init__(self, user, password, api_url, page_size=1000, rate=2, duration=1, cache_expire=3600): + ''' + Constructor + user: the user name + password: the password + api_url: the url of the api + page_size: the size of the page to use for pagination + rate: the rate of requests per duration (default 2 requests per 1 seconds) + duration: the duration in seconds of the rate limit (default 1 seconds) + cache_expire: the duration in seconds to expire the cache (default 3600 seconds) + + Note: In a pod the cache is removed when the pod is killed or restarted + ''' + self.user = user + self.password = password + self.api_url = api_url + self.token = None + self.headers = { + 'Content-Type': 'application/json', + } + # Set a controlled rate limit to prevent hitting the rate limit + self.session = CachedLimiterSession( + limiter=Limiter(RequestRate(rate, Duration.SECOND*duration)), + bucket_class=MemoryQueueBucket, + backend=SQLiteCache("primero.cache", expire_after=cache_expire) + ) + self.page_size = page_size + + self.non_pii_cols = NON_PII_COLS + + def version(self): + ''' Returns the version of the API library''' + return VERSION + + def set_non_pii_cols(self, col_names=[]): + """ Sets the whitelist of NON personal identifiable information columns + + These columns are not removed from the response of the server on methods that support anonymized data. + This does not apply to methods with the `_raw` postfix as these return directly the response from the server. + + Args: + col_names (list, optional): columns names that hold PII that need to be removed. Defaults to []. + """ + self.non_pii_cols = col_names + + def _is_last_page(self, metadata): + ''' + for a multi-page response, check if the current page is the last page + metadata is the metadata object from the response which contains the + page, total and per parameters. + ''' + + page = metadata['page'] # current page + total = metadata['total'] # total number of items + per = metadata['per'] # number of items per page + logger.debug('metadata=%s result=%s', metadata, (page * per) >= total) + return (page * per) >= total + + def _call_api_get(self, url): + ''' + calls the server API adding the (Basic) authentication + ''' + response = self.session.get( + url, headers=self.headers, auth=HTTPBasicAuth(self.user, self.password)) + if response.status_code != 200: + logger.error('error calling primero server: %s: %s, url: %s', + response.status_code, response.text, url) + return None + # Convert to dict + + json = response.json() + # check if data is part of json + if 'data' not in json: + return None + return json['data'] + + def _call_paginated_api(self, url: str): + ''' + Calls the api with the given url and page_size. + + URL should not have per and page parameters + Returns a list of data + + ''' + + logger.debug('_call_paginated_api url=%s self.page_size=%s', + url, self.page_size) + page_size = self.page_size + page = 1 + data = [] + while True: + get_url = url + # Check if ? is present, add it if not + if '?' not in get_url: + get_url += '?' + # Add &per=page_size&page=page to the url. + get_url += f'&per={page_size}&page={page}' + logger.debug('get_url: %s', get_url) + response = self.session.get( + get_url, headers=self.headers, auth=HTTPBasicAuth(self.user, self.password)) + # check if response is successful + if response.status_code != 200: + logger.error( + 'Failed to get paginated data ${response.status_code}: ${response.text}, url: ${get_url}') + continue + + # The response is a JSON object that contains the data and metadata objects. + # data is an array of objects that contain the actual data + # metadata contains information about the pagination + + # Extract the data from the response + json_data = response.json() + # extend the existing list to include new data + data.extend(json_data['data']) + # print(json_data) + # check if we are at the last page + logger.debug('page=%s metadata=%s', page, json_data["metadata"]) + if self._is_last_page(json_data['metadata']): + break + page += 1 + return data + + def _remove_record_pii(self, data_dict, additional_non_pii_cols: List = None): + """ + Removes personally identifiable information (PII) from a dictionary. + + Args: + data_dict (dict): The dictionary from which PII should be removed. + custom_non_pii_cols (list, optional): Custom list of PII columns to remove. Defaults to None. + additional_cols (list, optional): Additional columns to remove. Defaults to []. + + Returns: + dict: The dictionary with PII and additional columns removed. + """ + non_pii_cols = self.non_pii_cols.copy() + if additional_non_pii_cols: + non_pii_cols.extend(additional_non_pii_cols) + + for key in list(data_dict.keys()): + if key not in non_pii_cols: + del data_dict[key] + return data_dict + + def get_cases_raw(self): + """ + Fetches raw case data from the Primero API. + + This method constructs the URL for the 'cases' endpoint of the Primero API + and makes a paginated API call to retrieve the raw case data. + + Returns: + list: A list of raw case data retrieved from the API. + """ + url = self.api_url + 'cases' + return self._call_paginated_api(url) + + def get_cases(self, anonymized=True, additional_non_pii_cols=[]): + """ + Fetches case data from the Primero API. + anonymized: if True, removes personally identifiable information (PII) from the case data before returning it. + additional_non_pii_cols: Additional columns to whitelist from the case data. This is useful if you need any column that is not whitelisted by default.` + + See the property `self.non_pii_cols` for the default list of non-PII columns. + + additional_non_pii_cons: Additional columns to whitelist from the case data. + + Returns: + List A list of case data retrieved from the API. + """ + + anonymized_cases =[] + cases = self.get_cases_raw() + #logger.debug(cases) + if anonymized: + for case in cases: + # remove pii cols + case = self._remove_record_pii(case, + additional_non_pii_cols=additional_non_pii_cols) + anonymized_cases.append(case) + # convert to pandas + return pd.DataFrame(anonymized_cases) + # otherwise return the raw data + return pd.DataFrame(cases) + + def get_incidents(self): + url = self.api_url + 'incidents' + return self._call_paginated_api(url) + + def get_report_raw(self, id: int): + ''' + Gets the report with the given id + returns a dictionary with the content of the report or None if there is an error. + + ''' + url = self.api_url + 'reports/' + str(id) + logger.debug(f'id: {id}, get_report url={url}') + response = self.session.get( + url, headers=self.headers, auth=HTTPBasicAuth(self.user, self.password)) + # check if response is successful + if response.status_code != 200: + logger.error(f'Failed to get report {response.status_code}: {response.text}, url: {url}') + return None + return response.json()['data'] + + def get_report_list(self): + ''' + Gets the list of reports for the given page and page_size. + **Returns a dictionary** with the id as key and the report as value + The content of the report is a dictionary + ''' + url = self.api_url + 'reports' + return self._call_paginated_api(url) + + def get_reports_raw(self): + ''' + Gets the list of reports for the given page and page_size. + Returns a dictionary with the id as key and the report cibtebt in Dict format as value + The content of the report is a dictionary + ''' + reports = {} + report_list_dict = self.get_report_list() + for id, report in report_list_dict.items(): + report = self.get_report(id) + # report is None if there is an error + if report: + reports[id] = report['data'] + return reports + + def get_report(self, id: int, lang='en'): + ''' + Gets the report with the given id + returns a object of the Report class or None if there is an error. + ''' + logger.debug(f'get_report id={id}, lang={lang}') + report_json_dict = self.get_report_raw(id) + if report_json_dict is None: + logger.error(f'Did not get report {id}') + return None + return Report(report_json_dict, lang) + + def get_reports(self, lang='en'): + ''' + Gets the list of reports for the given page and page_size. + Returns a dictionary of Report objects with the id as key and the report as value + ''' + reports = {} + report_list = self.get_report_list() + for report in report_list: + id = report['id'] + report = self.get_report(id, lang) + reports[id] = report + return reports + + def get_lookups(self): + '''lookups are mapping between ids and human labels for the data''' + url = self.api_url + 'lookups' + return self._call_paginated_api(url) + + def get_server_version(self): + url = self.api_url + 'contact_information' + contact_information = self._call_api_get(url) + return contact_information['system_version'] diff --git a/primero-api/primero_api/report.py b/primero-api/primero_api/report.py new file mode 100644 index 0000000..3817db5 --- /dev/null +++ b/primero-api/primero_api/report.py @@ -0,0 +1,38 @@ + +from .report_processors import process_report, report_name, report_slug, get_report_labels +from .logger import logger + +class Report: + def __init__(self, report_data_dict, lang='en'): + ''' + report_data_dict is the dictionary that comes from the API + lang is the language to use for the report + ''' + if 'id' not in report_data_dict: + logger.error(f'Report does not have an id: {report_data_dict}') + return None + if report_data_dict is None: + logger.error(f'Report is None') + return None + id = report_data_dict['id'] + #logger.debug(f'report data: {report_data_dict}') + logger.debug(f'Creating Report object for {id}, lang={lang}') + + self.report_data_dict = report_data_dict + self.id = report_data_dict['id'] + self.lang = lang + + self.slug = report_slug(report_data_dict, lang) + self.name = report_name(report_data_dict, lang) + + def __str__(self): + return f'Report {self.id} ({self.name})' + + + def to_pandas(self): + return process_report(self.report_data_dict, lang=self.lang) + + def labels(self): + return get_report_labels(self.report_data_dict, lang=self.lang) + + diff --git a/primero-api/primero_api/report_processors.py b/primero-api/primero_api/report_processors.py new file mode 100644 index 0000000..623593c --- /dev/null +++ b/primero-api/primero_api/report_processors.py @@ -0,0 +1,152 @@ +import pandas as pd +from slugify import slugify + +from .logger import logger + +# +# Utility tools for processing reports +# + +def report_name(report, lang='en'): + ''' + Returns the name for the report in the given language. + If the report does not have a name, it returns report-{report_id} + if the language is not in the name, it returns the english name + if the english name is not in the name, it returns report-{report_id} + ''' + # check if report has a name + if 'name' not in report: + return 'report-' + report['id'] + # check if the language is in the name + if lang not in report['name']: + # check if english is in the name + if 'en' not in report['name']: + return 'report' + report['id'] + lang = 'en' + return report['name'][lang] + + +def report_slug(report, lang='en'): + ''' + Returns the slug for the report in the given language. + If the report does not have a name, it returns report-{report_id} + if the language is not in the name, it returns the english name + if the english name is not in the name, it returns report-{report_id} + ''' + name = report_name(report, lang) + return slugify(name) + + +def find_key_in_dict(nested_dict, key): + ''' + Find all values for a key in a nested dictionary + returns a list of values + ''' + found_items = [] + def search_dict(d): + if isinstance(d, dict): + for k, v in d.items(): + if k == key: + found_items.append(v) + if isinstance(v, dict): + search_dict(v) + elif isinstance(v, list): + for item in v: + search_dict(item) + search_dict(nested_dict) + return found_items + +def get_report_labels(report, lang='en'): + ''' + Returns the labels for the report in the format + label[id] = display_text + ''' + all_labels=find_key_in_dict(report, 'option_labels') + # returns this format + # + #[ {en": [ + # { "id": "sexually_exploited", "display_text": "Sexually Exploited"}, + # ..., + # {...} + # ], + # fr: {...} + # ... + # {en": [ + # { "id": "sexually_exploited", "display_text": "Sexually Exploited"}, + # ..., + # {...} + # ], + # fr: {...} + # ... + # ] + # we will convert to + # label[id]= display_text + # example: + # label[sexually_exploited] = "Sexually Exploited" + labels = {} + for labels_by_lang in all_labels: + if lang in labels_by_lang: + for label in labels_by_lang[lang]: + labels[label['id']] = label['display_text'] + return labels + + +def process_report(report, lang='en'): + ''' + Process the report and return a dataframe + + report is the json object output of the api + lang is the language to use for the labels + + ''' + + if 'report_data' not in report: + # return empty dataframe if there is no report data + return pd.DataFrame() + + labels = get_report_labels(report) + # Example of report_data + # + # report_data: { + # 'sexually_exploited': {'_total': 0}, # it is just total + # 'migrant': { + # '_total': 1, # it contains total and desagregated data + # 'male': {'_total': 1}, + # 'female': {'_total': 0}}, + # + # Is converted to: + # key total male female + # --------------------- ----- ---- ------ + # sexually_exploited 0 + # migrant 1 1 0 + + report_data = report['report_data'] + data = [] + #print('report_data', report_data) + for key in report_data: + datum = report_data[key].copy() + #print("key", key, "datum:", datum) + for k in datum.keys(): + # check if k is an object + #print('k', k, type(datum[k])) + if type(datum[k]) is not int: + datum[k] = datum[k]['_total'] + #print(key, datum) + datum['key']= key + + # find the label for the key. default to key + if key in labels: + datum['key_label'] = labels[key] + else: + datum['key_label'] = key + + # replace _total with total + datum['total'] = datum['_total'] + datum.pop('_total') + + #print("added", datum) + data.append(datum) + + # To data frame + df = pd.DataFrame(data) + return df diff --git a/primero-api/primero_api/version.py b/primero-api/primero_api/version.py new file mode 100644 index 0000000..78c9017 --- /dev/null +++ b/primero-api/primero_api/version.py @@ -0,0 +1 @@ +VERSION='0.1.2' \ No newline at end of file diff --git a/primero-api/setup.py b/primero-api/setup.py new file mode 100644 index 0000000..21f8f33 --- /dev/null +++ b/primero-api/setup.py @@ -0,0 +1,43 @@ +from setuptools import setup, find_packages + +from primero_api.version import VERSION + +setup( + name='primero-api', + version=VERSION, + packages=find_packages(), + install_requires=[ + # List your dependencies here + 'requests', + 'requests-cache', + 'requests-ratelimiter', + 'pandas', + 'python-slugify', + ], + # development dependencies + extras_require={ + 'dev': [ + 'pytest', + 'pytest-cov', + 'pytest-mock', + 'flake8', + 'black', + 'isort', + 'mypy', + 'sphinx', + 'sphinx_rtd_theme', + ] + }, + author='merlos', + author_email='merlos@users.github.com', + description='A simple client for consuming data from Primero API', + long_description=open('README.md').read(), + long_description_content_type='text/markdown', + url='https://github.com/unicef/magasin-primero-paquet', + classifiers=[ + 'Programming Language :: Python :: 3', + 'License :: OSI Approved :: MIT License', + 'Operating System :: OS Independent', + ], + python_requires='>=3.6', +) \ No newline at end of file diff --git a/primero-api/tests/__init__.py b/primero-api/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/primero-api/tests/test_primero_api.py b/primero-api/tests/test_primero_api.py new file mode 100644 index 0000000..b50811b --- /dev/null +++ b/primero-api/tests/test_primero_api.py @@ -0,0 +1,114 @@ +import pytest + +from primero_api import PrimeroAPI +import requests_mock + + +@pytest.fixture +def primero_api(): + return PrimeroAPI(user='test_user', password='test_password', api_url='http://test.api/', page_size=2) + +def test_is_last_page(primero_api): + # Test data for is_last_page + metadata_last_page = { + 'page': 2, + 'total': 20, + 'per': 10 + } + assert primero_api._is_last_page(metadata_last_page) == True + + metadata_not_last_page = { + 'page': 1, + 'total': 20, + 'per': 10 + } + assert primero_api._is_last_page(metadata_not_last_page) == False + + +def test_call_paginated_api(primero_api): + # Mock the responses for the paginated API calls + # Test data for call_paginated_api + response_data_page_1 = { + 'data': [{'id': 1}, {'id': 2}], + 'metadata': {'page': 1, 'total': 4, 'per': 2} + } + response_data_page_2 = { + 'data': [{'id': 3}, {'id': 4}], + 'metadata': {'page': 2, 'total': 4, 'per': 2} + } + + with requests_mock.Mocker() as m: + m.get('http://test.api/?per=2&page=1', json=response_data_page_1) + m.get('http://test.api/?per=2&page=2', json=response_data_page_2) + data = primero_api._call_paginated_api('http://test.api/') + + assert len(data) == 4 + assert data == [{'id': 1}, {'id': 2}, {'id': 3}, {'id': 4}] + + +def test_remove_record_pii_default(primero_api): + record_with_pii = { + 'name': 'John Doe', # PII + 'date_of_birth': 'john.doe@example.com', # PII + 'address_current': '123 Main St', # PII + 'enabled': 'non_pii_value' # Non-PII + } + result_record_without_pii = { + 'enabled': 'non_pii_value' + } + + result = primero_api._remove_record_pii(record_with_pii) + assert result == result_record_without_pii + +def test_remove_record_pii_custom_cols(primero_api): + record_with_custom_non_pii = { + 'name': 'John Doe', # PII + 'date_of_birth': 'john.doe@example.com', # PII + 'address_current': '123 Main St', # PII + 'enabled': 'non_pii_value', # Non-PII + 'custom_non_pii': 'custom_value' + } + + result_record_with_custom_non_pii = { + 'enabled': 'non_pii_value', # Non-PII + 'custom_non_pii': 'custom_value' # Additional non-PII + } + + result = primero_api._remove_record_pii(record_with_custom_non_pii, additional_non_pii_cols=['custom_non_pii']) + assert result == result_record_with_custom_non_pii + +def test_remove_record_pii_custom_nonexistent_cols(primero_api): + + record_with_custom_non_pii = { + 'name': 'John Doe', # PII + 'date_of_birth': 'john.doe@example.com', # PII + 'address_current': '123 Main St', # PII + 'enabled': 'non_pii_value', # Non-PII + 'custom_non_pii': 'custom_value' + } + + result_record_with_custom_nonexistent_pii = { + 'enabled': 'non_pii_value', # Non-PII + } + # the additional_non_pii_cols do not exist and still does not break + result = primero_api._remove_record_pii(record_with_custom_non_pii, additional_non_pii_cols=['nonexistent_col']) + assert result == result_record_with_custom_nonexistent_pii + +def test_remove_record_pii_with_modified_non_pii_cols(primero_api): + record_with_pii = { + 'name': 'John Doe', # PII + 'date_of_birth': 'john.doe@example.com', # PII + 'address_current': '123 Main St', # PII + 'enabled': 'non_pii_value' # Non-PII + } + # Now I am going to white list name, date_of_birth, and address_current + # so only enabled is considered PII + primero_api.set_non_pii_cols(['name', 'date_of_birth', 'address_current']) + + result_record_without_pii = { + 'name': 'John Doe', # PII + 'date_of_birth': 'john.doe@example.com', # PII + 'address_current': '123 Main St', # PII + } + result = primero_api._remove_record_pii(record_with_pii) + assert result == result_record_without_pii \ No newline at end of file