Elasticsearch extraction pipeline for Chad nOPV2 campaign data
# chad-polio-ingest
Data extraction pipeline for the WHO AFRO nOPV2 campaign dashboard — N'Djamena, Chad, June 2026.
Pulls structured data from Elasticsearch, shapes it with pandas, and writes a timestamped Excel file consumed by `chad-polio-dashboard`.
---
## Pipeline overview
```
Elasticsearch (WHO AFRO)
│
▼
chad-polio-ingest ← you are here
(extractors/ + main.py)
│
▼
output/chad_YYYYMMDD_HHMM.xlsx
│
▼
chad-polio-dashboard
(fetch_latest.py → data.json → Vercel)
```
---
## Quick start (local)
```bash
git clone
github.com
cd chad-polio-ingest
pip install -r requirements.txt
cp .env.example .env # fill in ES_URL + ES_AUTH_HEADER
python main.py
```
Output lands in `output/chad_YYYYMMDD_HHMM.xlsx`.
---
## Environment variables (`.env`)
```
ES_URL=
elasticsearch-data.es-clust…
ES_AUTH_HEADER=Basic
OUTPUT_DIR=output
JUPYTER_BASE=https:// /jupyter/user/
JUPYTER_TOKEN=
JUPYTER_REMOTE_ROOT=
```
---
## Repository structure
```
extractors/
base.py — ESClient (only file that touches ES)
coverage.py — daily vaccinations by facility
activity.py — per-user task count + last sync
refusals.py — refusal reason codes by facility
enumeration.py — households + eligible children + vaccinated
stock.py — vial reconciliation (supply-side)
stock_daily.py — per-team per-day vial issuance
gps.py — household GPS + vaccination count + head-of-household
gps_refusals.py — refusal household dots
gps_zerodose.py — zero-dose children
microplan.py — coverage vs microplan target
settlement.py — URBAN/RURAL/SLUMS breakdown
demographics.py — age/gender of vaccinated children
inactive_users.py — users not synced in 24h
config/
chad.json — campaign config (IDs, bounds, facility map)
deploy.py — push any local file to remote Jupyter server
scheduler.py — hourly background runner for Jupyter server
run_hourly.py — wrapper called by s …