From 753ae77865d1a200f4e3c9ddc2e6c3d93e276517 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 12:19:13 +0100 Subject: [PATCH 01/13] collections api skelethon --- eoapi/__init__.py | 0 eoapi/endpoints/__init__.py | 0 eoapi/endpoints/collections.py | 11 +++++++++++ main.py | 3 +++ 4 files changed, 14 insertions(+) create mode 100644 eoapi/__init__.py create mode 100644 eoapi/endpoints/__init__.py create mode 100644 eoapi/endpoints/collections.py diff --git a/eoapi/__init__.py b/eoapi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/eoapi/endpoints/__init__.py b/eoapi/endpoints/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/eoapi/endpoints/collections.py b/eoapi/endpoints/collections.py new file mode 100644 index 0000000..32a9c9c --- /dev/null +++ b/eoapi/endpoints/collections.py @@ -0,0 +1,11 @@ +from fastapi import APIRouter + +router = APIRouter(tags=["Collections"]) + + +@router.get("/collections") +def get_collections() -> dict: + return { + "collections": [], + "links": [], + } diff --git a/main.py b/main.py index e82d5a0..2305a11 100644 --- a/main.py +++ b/main.py @@ -1,6 +1,7 @@ from fastapi import FastAPI from titiler.core.factory import (TilerFactory, MultiBaseTilerFactory) from rio_tiler.io import STACReader +from eoapi.endpoints.collections import router as collections_router from starlette.middleware.cors import CORSMiddleware @@ -22,6 +23,8 @@ # Create a TilerFactory for Cloud-Optimized GeoTIFFs cog = TilerFactory() +app.include_router(collections_router) + # Register all the COG endpoints automatically app.include_router(cog.router, prefix="/cog", tags=["Cloud Optimized GeoTIFF"]) From 55614b1bd8982fe8b80e47ddd0011555f5dd55d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 12:47:25 +0100 Subject: [PATCH 02/13] Collections endpoint --- .gitignore | 1 + README.md | 8 +++ eoapi/endpoints/collections.py | 128 +++++++++++++++++++++++++++++++-- pyproject.toml | 1 + 4 files changed, 134 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 670a936..c26a1e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ __pycache__/ .venv/ +*.egg-info/ diff --git a/README.md b/README.md index 9265ace..2a5c4ef 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,14 @@ Docs: http://127.0.0.1:8000/docs +Collections (OGC API): + +http://127.0.0.1:8000/collections + +http://127.0.0.1:8000/collections/chirps-daily + +http://127.0.0.1:8000/collections/era5-land-daily + Examples: COG info: diff --git a/eoapi/endpoints/collections.py b/eoapi/endpoints/collections.py index 32a9c9c..e0dd70d 100644 --- a/eoapi/endpoints/collections.py +++ b/eoapi/endpoints/collections.py @@ -1,11 +1,131 @@ -from fastapi import APIRouter +from fastapi import APIRouter, HTTPException, Request + +from pygeoapi import l10n +from pygeoapi.util import url_join router = APIRouter(tags=["Collections"]) +OGC_RELTYPES_BASE = "http://www.opengis.net/def/rel/ogc/1.0" +CRS84 = "http://www.opengis.net/def/crs/OGC/1.3/CRS84" + +DATASETS: dict[str, dict] = { + "chirps-daily": { + "id": "chirps-daily", + "title": "CHIRPS Daily Precipitation", + "description": "Daily precipitation from CHIRPS as a gridded coverage dataset.", + "keywords": ["CHIRPS", "precipitation", "rainfall", "coverage", "raster"], + "spatial_bbox": [-180.0, -50.0, 180.0, 50.0], + "temporal_interval": ["1981-01-01T00:00:00Z", None], + }, + "era5-land-daily": { + "id": "era5-land-daily", + "title": "ERA5-Land Daily Climate", + "description": "Daily ERA5-Land variables as a gridded coverage dataset.", + "keywords": ["ERA5-Land", "temperature", "soil moisture", "coverage", "raster"], + "spatial_bbox": [-180.0, -90.0, 180.0, 90.0], + "temporal_interval": ["1950-01-01T00:00:00Z", None], + }, +} + + +def _base_url(request: Request) -> str: + return str(request.base_url).rstrip("/") + + +def _locale_from_request(request: Request) -> str: + requested = request.query_params.get("lang", "en") + locale = l10n.str2locale(requested, silent=True) + return l10n.locale2str(locale) if locale else "en" + + +def _collection_links(request: Request, collection_id: str) -> list[dict]: + base = _base_url(request) + collections_url = url_join(base, "collections") + collection_url = url_join(collections_url, collection_id) + return [ + { + "rel": "self", + "type": "application/json", + "title": "This collection", + "href": collection_url, + }, + { + "rel": "root", + "type": "application/json", + "title": "API root", + "href": url_join(base, "/"), + }, + { + "rel": "parent", + "type": "application/json", + "title": "Collections", + "href": collections_url, + }, + { + "rel": f"{OGC_RELTYPES_BASE}/coverage", + "type": "application/json", + "title": "Collection coverage", + "href": url_join(collection_url, "coverage"), + }, + ] + + +def _build_collection(request: Request, dataset: dict) -> dict: + locale = _locale_from_request(request) + return { + "id": dataset["id"], + "title": l10n.translate(dataset["title"], locale), + "description": l10n.translate(dataset["description"], locale), + "keywords": dataset["keywords"], + "extent": { + "spatial": { + "bbox": [dataset["spatial_bbox"]], + "crs": CRS84, + }, + "temporal": { + "interval": [dataset["temporal_interval"]], + "trs": "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian", + }, + }, + "itemType": "coverage", + "crs": [CRS84], + "links": _collection_links(request, dataset["id"]), + } + @router.get("/collections") -def get_collections() -> dict: +def get_collections(request: Request) -> dict: + base = _base_url(request) + collections_url = url_join(base, "collections") + return { - "collections": [], - "links": [], + "collections": [_build_collection(request, dataset) for dataset in DATASETS.values()], + "links": [ + { + "rel": "self", + "type": "application/json", + "title": "This document", + "href": collections_url, + }, + { + "rel": "root", + "type": "application/json", + "title": "API root", + "href": url_join(base, "/"), + }, + ], } + + +@router.get("/collections/{collection_id}") +def get_collection(collection_id: str, request: Request) -> dict: + dataset = DATASETS.get(collection_id) + if dataset is None: + raise HTTPException( + status_code=404, + detail={ + "code": "NotFound", + "description": f"Collection '{collection_id}' not found", + }, + ) + return _build_collection(request, dataset) diff --git a/pyproject.toml b/pyproject.toml index a2f47d4..b9d3ad6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ requires-python = ">=3.13" dependencies = [ "titiler-core>=1.2.0", "uvicorn>=0.41.0", + "pygeoapi>=0.22.0", "dhis2eo @ git+https://github.com/dhis2/dhis2eo.git@v1.1.0", "dhis2-client @ git+https://github.com/dhis2/dhis2-python-client.git@V0.3.0", ] \ No newline at end of file From e59fb1f697eadbcad752015b53f40c4d6f4f2c1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 13:37:53 +0100 Subject: [PATCH 03/13] Keep dataset definitions as yaml files --- Makefile | 3 + README.md | 7 + datasets/README.md | 42 +++++ datasets/chirps-daily.yaml | 17 ++ datasets/era5-land-daily.yaml | 17 ++ eoapi/datasets.py | 51 ++++++ eoapi/endpoints/collections.py | 41 ++--- pyproject.toml | 10 +- scripts/validate_datasets.py | 24 +++ uv.lock | 301 ++++++++++++++++++++++++++++++++- 10 files changed, 482 insertions(+), 31 deletions(-) create mode 100644 datasets/README.md create mode 100644 datasets/chirps-daily.yaml create mode 100644 datasets/era5-land-daily.yaml create mode 100644 eoapi/datasets.py create mode 100644 scripts/validate_datasets.py diff --git a/Makefile b/Makefile index 7594dc0..84a83f1 100644 --- a/Makefile +++ b/Makefile @@ -3,3 +3,6 @@ sync: run: uv run uvicorn main:app --reload + +validate-datasets: + uv run python scripts/validate_datasets.py diff --git a/README.md b/README.md index 2a5c4ef..935cf34 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ uvicorn main:app --reload - `make sync` — install dependencies with uv - `make run` — start the app with uv +- `make validate-datasets` — validate all dataset YAML files against the Pydantic schema Root endpoint: @@ -55,6 +56,12 @@ http://127.0.0.1:8000/collections/chirps-daily http://127.0.0.1:8000/collections/era5-land-daily +## Dataset definitions + +Collection metadata for `/collections` is defined in top-level YAML files under `datasets/`. + +For schema details, examples, and current dataset files, see [`datasets/README.md`](datasets/README.md). + Examples: COG info: diff --git a/datasets/README.md b/datasets/README.md new file mode 100644 index 0000000..8096de1 --- /dev/null +++ b/datasets/README.md @@ -0,0 +1,42 @@ +# Dataset metadata + +This folder contains dataset definitions used by the `/collections` endpoints. + +Definitions are loaded from `*.yaml` files and validated by the `DatasetDefinition` Pydantic model in `eoapi/endpoints/collections.py`. + +## Required schema + +- `id` (string): unique collection identifier used in `/collections/{id}` +- `title` (string): human-readable collection title +- `description` (string): collection description +- `spatial_bbox` (array of 4 numbers): `[minx, miny, maxx, maxy]` in CRS84 +- `temporal_interval` (array of 2 values): `[start_iso8601, end_iso8601_or_null]` + +## Optional schema + +- `keywords` (array of strings): tags used for discovery + +## Example + +```yaml +id: my-dataset-daily +title: My Dataset Daily +description: Daily gridded variable for demonstration. +keywords: + - climate + - precipitation + - coverage +spatial_bbox: + - -180.0 + - -90.0 + - 180.0 + - 90.0 +temporal_interval: + - 2000-01-01T00:00:00Z + - null +``` + +## Current definitions + +- `chirps-daily.yaml` +- `era5-land-daily.yaml` diff --git a/datasets/chirps-daily.yaml b/datasets/chirps-daily.yaml new file mode 100644 index 0000000..65cd9f6 --- /dev/null +++ b/datasets/chirps-daily.yaml @@ -0,0 +1,17 @@ +id: chirps-daily +title: CHIRPS Daily Precipitation +description: Daily precipitation from CHIRPS as a gridded coverage dataset. +keywords: + - CHIRPS + - precipitation + - rainfall + - coverage + - raster +spatial_bbox: + - -180.0 + - -50.0 + - 180.0 + - 50.0 +temporal_interval: + - 1981-01-01T00:00:00Z + - null diff --git a/datasets/era5-land-daily.yaml b/datasets/era5-land-daily.yaml new file mode 100644 index 0000000..5617269 --- /dev/null +++ b/datasets/era5-land-daily.yaml @@ -0,0 +1,17 @@ +id: era5-land-daily +title: ERA5-Land Daily Climate +description: Daily ERA5-Land variables as a gridded coverage dataset. +keywords: + - ERA5-Land + - temperature + - soil moisture + - coverage + - raster +spatial_bbox: + - -180.0 + - -90.0 + - 180.0 + - 90.0 +temporal_interval: + - 1950-01-01T00:00:00Z + - null diff --git a/eoapi/datasets.py b/eoapi/datasets.py new file mode 100644 index 0000000..99ac55e --- /dev/null +++ b/eoapi/datasets.py @@ -0,0 +1,51 @@ +from functools import lru_cache +from pathlib import Path +from datetime import datetime + +from pydantic import BaseModel, Field, field_validator +import yaml + +DATASETS_DIR = Path(__file__).resolve().parents[1] / "datasets" + + +class DatasetDefinition(BaseModel): + id: str + title: str + description: str + keywords: list[str] = Field(default_factory=list) + spatial_bbox: tuple[float, float, float, float] + temporal_interval: tuple[str, str | None] + + @field_validator("temporal_interval", mode="before") + @classmethod + def normalize_temporal_interval(cls, value): + if not isinstance(value, (list, tuple)) or len(value) != 2: + return value + + normalized: list[str | None] = [] + for item in value: + if isinstance(item, datetime): + iso_value = item.isoformat() + if iso_value.endswith("+00:00"): + iso_value = iso_value.replace("+00:00", "Z") + normalized.append(iso_value) + else: + normalized.append(item) + + return normalized + + +@lru_cache(maxsize=1) +def load_datasets() -> dict[str, DatasetDefinition]: + datasets: dict[str, DatasetDefinition] = {} + + for dataset_file in sorted(DATASETS_DIR.glob("*.yml")) + sorted(DATASETS_DIR.glob("*.yaml")): + with dataset_file.open("r", encoding="utf-8") as file_handle: + payload = yaml.safe_load(file_handle) or {} + + dataset = DatasetDefinition.model_validate(payload) + if dataset.id in datasets: + raise RuntimeError(f"Duplicate dataset id found: {dataset.id}") + datasets[dataset.id] = dataset + + return datasets diff --git a/eoapi/endpoints/collections.py b/eoapi/endpoints/collections.py index e0dd70d..e3da267 100644 --- a/eoapi/endpoints/collections.py +++ b/eoapi/endpoints/collections.py @@ -2,31 +2,13 @@ from pygeoapi import l10n from pygeoapi.util import url_join +from eoapi.datasets import DatasetDefinition, load_datasets router = APIRouter(tags=["Collections"]) OGC_RELTYPES_BASE = "http://www.opengis.net/def/rel/ogc/1.0" CRS84 = "http://www.opengis.net/def/crs/OGC/1.3/CRS84" -DATASETS: dict[str, dict] = { - "chirps-daily": { - "id": "chirps-daily", - "title": "CHIRPS Daily Precipitation", - "description": "Daily precipitation from CHIRPS as a gridded coverage dataset.", - "keywords": ["CHIRPS", "precipitation", "rainfall", "coverage", "raster"], - "spatial_bbox": [-180.0, -50.0, 180.0, 50.0], - "temporal_interval": ["1981-01-01T00:00:00Z", None], - }, - "era5-land-daily": { - "id": "era5-land-daily", - "title": "ERA5-Land Daily Climate", - "description": "Daily ERA5-Land variables as a gridded coverage dataset.", - "keywords": ["ERA5-Land", "temperature", "soil moisture", "coverage", "raster"], - "spatial_bbox": [-180.0, -90.0, 180.0, 90.0], - "temporal_interval": ["1950-01-01T00:00:00Z", None], - }, -} - def _base_url(request: Request) -> str: return str(request.base_url).rstrip("/") @@ -70,26 +52,26 @@ def _collection_links(request: Request, collection_id: str) -> list[dict]: ] -def _build_collection(request: Request, dataset: dict) -> dict: +def _build_collection(request: Request, dataset: DatasetDefinition) -> dict: locale = _locale_from_request(request) return { - "id": dataset["id"], - "title": l10n.translate(dataset["title"], locale), - "description": l10n.translate(dataset["description"], locale), - "keywords": dataset["keywords"], + "id": dataset.id, + "title": l10n.translate(dataset.title, locale), + "description": l10n.translate(dataset.description, locale), + "keywords": dataset.keywords, "extent": { "spatial": { - "bbox": [dataset["spatial_bbox"]], + "bbox": [list(dataset.spatial_bbox)], "crs": CRS84, }, "temporal": { - "interval": [dataset["temporal_interval"]], + "interval": [list(dataset.temporal_interval)], "trs": "http://www.opengis.net/def/uom/ISO-8601/0/Gregorian", }, }, "itemType": "coverage", "crs": [CRS84], - "links": _collection_links(request, dataset["id"]), + "links": _collection_links(request, dataset.id), } @@ -97,9 +79,10 @@ def _build_collection(request: Request, dataset: dict) -> dict: def get_collections(request: Request) -> dict: base = _base_url(request) collections_url = url_join(base, "collections") + datasets = load_datasets() return { - "collections": [_build_collection(request, dataset) for dataset in DATASETS.values()], + "collections": [_build_collection(request, dataset) for dataset in datasets.values()], "links": [ { "rel": "self", @@ -119,7 +102,7 @@ def get_collections(request: Request) -> dict: @router.get("/collections/{collection_id}") def get_collection(collection_id: str, request: Request) -> dict: - dataset = DATASETS.get(collection_id) + dataset = load_datasets().get(collection_id) if dataset is None: raise HTTPException( status_code=404, diff --git a/pyproject.toml b/pyproject.toml index b9d3ad6..cb4cd48 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,7 @@ +[build-system] +requires = ["setuptools>=69", "wheel"] +build-backend = "setuptools.build_meta" + [project] name = "eo-api" version = "0.1.0" @@ -6,6 +10,10 @@ dependencies = [ "titiler-core>=1.2.0", "uvicorn>=0.41.0", "pygeoapi>=0.22.0", + "pyyaml>=6.0", "dhis2eo @ git+https://github.com/dhis2/dhis2eo.git@v1.1.0", "dhis2-client @ git+https://github.com/dhis2/dhis2-python-client.git@V0.3.0", -] \ No newline at end of file +] + +[tool.setuptools] +packages = ["eoapi"] \ No newline at end of file diff --git a/scripts/validate_datasets.py b/scripts/validate_datasets.py new file mode 100644 index 0000000..59c1b65 --- /dev/null +++ b/scripts/validate_datasets.py @@ -0,0 +1,24 @@ +from pathlib import Path +import sys + +PROJECT_ROOT = Path(__file__).resolve().parents[1] +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) + +from eoapi.datasets import load_datasets + + +def main() -> int: + datasets = load_datasets() + if not datasets: + print("No dataset YAML files found.") + return 1 + + print(f"Validated {len(datasets)} dataset definition(s):") + for dataset_id in sorted(datasets.keys()): + print(f"- {dataset_id}") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/uv.lock b/uv.lock index 13f52aa..203301a 100644 --- a/uv.lock +++ b/uv.lock @@ -63,6 +63,24 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/3a/2a/7cc015f5b9f5db42b7d48157e23356022889fc354a2813c15934b7cb5c0e/attrs-25.4.0-py3-none-any.whl", hash = "sha256:adcf7e2a1fb3b36ac48d97835bb6d8ade15b8dcce26aba8bf1d14847b57a3373", size = 67615, upload-time = "2025-10-06T13:54:43.17Z" }, ] +[[package]] +name = "babel" +version = "2.18.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/7d/b2/51899539b6ceeeb420d40ed3cd4b7a40519404f9baf3d4ac99dc413a834b/babel-2.18.0.tar.gz", hash = "sha256:b80b99a14bd085fcacfa15c9165f651fbb3406e66cc603abf11c5750937c992d", size = 9959554, upload-time = "2026-02-01T12:30:56.078Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/77/f5/21d2de20e8b8b0408f0681956ca2c69f1320a3848ac50e6e7f39c6159675/babel-2.18.0-py3-none-any.whl", hash = "sha256:e2b422b277c2b9a9630c1d7903c2a00d0830c409c59ac8cae9081c92f1aeba35", size = 10196845, upload-time = "2026-02-01T12:30:53.445Z" }, +] + +[[package]] +name = "blinker" +version = "1.9.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/21/28/9b3f50ce0e048515135495f198351908d99540d69bfdc8c1d15b73dc55ce/blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf", size = 22460, upload-time = "2024-11-08T17:25:47.436Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, +] + [[package]] name = "cachetools" version = "7.0.1" @@ -400,6 +418,21 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl", hash = "sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91", size = 1482084, upload-time = "2026-01-30T21:04:18.363Z" }, ] +[[package]] +name = "dateparser" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "regex" }, + { name = "tzlocal" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/3d/2c/668dfb8c073a5dde3efb80fa382de1502e3b14002fd386a8c1b0b49e92a9/dateparser-1.3.0.tar.gz", hash = "sha256:5bccf5d1ec6785e5be71cc7ec80f014575a09b4923e762f850e57443bddbf1a5", size = 337152, upload-time = "2026-02-04T16:00:06.162Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/c7/95349670e193b2891176e1b8e5f43e12b31bff6d9994f70e74ab385047f6/dateparser-1.3.0-py3-none-any.whl", hash = "sha256:8dc678b0a526e103379f02ae44337d424bd366aac727d3c6cf52ce1b01efbb5a", size = 318688, upload-time = "2026-02-04T16:00:04.652Z" }, +] + [[package]] name = "deprecation" version = "2.1.0" @@ -548,10 +581,12 @@ wheels = [ [[package]] name = "eo-api" version = "0.1.0" -source = { virtual = "." } +source = { editable = "." } dependencies = [ { name = "dhis2-client" }, { name = "dhis2eo" }, + { name = "pygeoapi" }, + { name = "pyyaml" }, { name = "titiler-core" }, { name = "uvicorn" }, ] @@ -560,6 +595,8 @@ dependencies = [ requires-dist = [ { name = "dhis2-client", git = "https://github.com/dhis2/dhis2-python-client.git?rev=V0.3.0" }, { name = "dhis2eo", git = "https://github.com/dhis2/dhis2eo.git?rev=v1.1.0" }, + { name = "pygeoapi", specifier = ">=0.22.0" }, + { name = "pyyaml", specifier = ">=6.0" }, { name = "titiler-core", specifier = ">=1.2.0" }, { name = "uvicorn", specifier = ">=0.41.0" }, ] @@ -598,6 +635,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2f/ff/76dd547e129206899e4e26446c3ca7aeaff948c31b05250e9b8690e76883/findlibs-0.1.2-py3-none-any.whl", hash = "sha256:5348bbc7055d2a505962576c2e285b6c0aae6d749f82ba71296e7d41336e66e8", size = 10707, upload-time = "2025-07-28T09:15:02.733Z" }, ] +[[package]] +name = "flask" +version = "3.1.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "blinker" }, + { name = "click" }, + { name = "itsdangerous" }, + { name = "jinja2" }, + { name = "markupsafe" }, + { name = "werkzeug" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/26/00/35d85dcce6c57fdc871f3867d465d780f302a175ea360f62533f12b27e2b/flask-3.1.3.tar.gz", hash = "sha256:0ef0e52b8a9cd932855379197dd8f94047b359ca0a78695144304cb45f87c9eb", size = 759004, upload-time = "2026-02-19T05:00:57.678Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" }, +] + [[package]] name = "flexcache" version = "0.3" @@ -693,6 +747,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/e4/fac19dc34cb686c96011388b813ff7b858a70681e5ce6ce7698e5021b0f4/geopandas-1.1.2-py3-none-any.whl", hash = "sha256:2bb0b1052cb47378addb4ba54c47f8d4642dcbda9b61375638274f49d9f0bb0d", size = 341734, upload-time = "2025-12-22T21:06:12.498Z" }, ] +[[package]] +name = "greenlet" +version = "3.3.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a3/51/1664f6b78fc6ebbd98019a1fd730e83fa78f2db7058f72b1463d3612b8db/greenlet-3.3.2.tar.gz", hash = "sha256:2eaf067fc6d886931c7962e8c6bede15d2f01965560f3359b27c80bde2d151f2", size = 188267, upload-time = "2026-02-20T20:54:15.531Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ac/48/f8b875fa7dea7dd9b33245e37f065af59df6a25af2f9561efa8d822fde51/greenlet-3.3.2-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:aa6ac98bdfd716a749b84d4034486863fd81c3abde9aa3cf8eff9127981a4ae4", size = 279120, upload-time = "2026-02-20T20:19:01.9Z" }, + { url = "https://files.pythonhosted.org/packages/49/8d/9771d03e7a8b1ee456511961e1b97a6d77ae1dea4a34a5b98eee706689d3/greenlet-3.3.2-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ab0c7e7901a00bc0a7284907273dc165b32e0d109a6713babd04471327ff7986", size = 603238, upload-time = "2026-02-20T20:47:32.873Z" }, + { url = "https://files.pythonhosted.org/packages/59/0e/4223c2bbb63cd5c97f28ffb2a8aee71bdfb30b323c35d409450f51b91e3e/greenlet-3.3.2-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d248d8c23c67d2291ffd47af766e2a3aa9fa1c6703155c099feb11f526c63a92", size = 614219, upload-time = "2026-02-20T20:55:59.817Z" }, + { url = "https://files.pythonhosted.org/packages/7a/34/259b28ea7a2a0c904b11cd36c79b8cef8019b26ee5dbe24e73b469dea347/greenlet-3.3.2-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6997d360a4e6a4e936c0f9625b1c20416b8a0ea18a8e19cabbefc712e7397ab", size = 616774, upload-time = "2026-02-20T20:21:02.454Z" }, + { url = "https://files.pythonhosted.org/packages/0a/03/996c2d1689d486a6e199cb0f1cf9e4aa940c500e01bdf201299d7d61fa69/greenlet-3.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64970c33a50551c7c50491671265d8954046cb6e8e2999aacdd60e439b70418a", size = 1571277, upload-time = "2026-02-20T20:49:34.795Z" }, + { url = "https://files.pythonhosted.org/packages/d9/c4/2570fc07f34a39f2caf0bf9f24b0a1a0a47bc2e8e465b2c2424821389dfc/greenlet-3.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1a9172f5bf6bd88e6ba5a84e0a68afeac9dc7b6b412b245dd64f52d83c81e55b", size = 1640455, upload-time = "2026-02-20T20:21:10.261Z" }, + { url = "https://files.pythonhosted.org/packages/91/39/5ef5aa23bc545aa0d31e1b9b55822b32c8da93ba657295840b6b34124009/greenlet-3.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:a7945dd0eab63ded0a48e4dcade82939783c172290a7903ebde9e184333ca124", size = 230961, upload-time = "2026-02-20T20:16:58.461Z" }, + { url = "https://files.pythonhosted.org/packages/62/6b/a89f8456dcb06becff288f563618e9f20deed8dd29beea14f9a168aef64b/greenlet-3.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:394ead29063ee3515b4e775216cb756b2e3b4a7e55ae8fd884f17fa579e6b327", size = 230221, upload-time = "2026-02-20T20:17:37.152Z" }, + { url = "https://files.pythonhosted.org/packages/3f/ae/8bffcbd373b57a5992cd077cbe8858fff39110480a9d50697091faea6f39/greenlet-3.3.2-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:8d1658d7291f9859beed69a776c10822a0a799bc4bfe1bd4272bb60e62507dab", size = 279650, upload-time = "2026-02-20T20:18:00.783Z" }, + { url = "https://files.pythonhosted.org/packages/d1/c0/45f93f348fa49abf32ac8439938726c480bd96b2a3c6f4d949ec0124b69f/greenlet-3.3.2-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:18cb1b7337bca281915b3c5d5ae19f4e76d35e1df80f4ad3c1a7be91fadf1082", size = 650295, upload-time = "2026-02-20T20:47:34.036Z" }, + { url = "https://files.pythonhosted.org/packages/b3/de/dd7589b3f2b8372069ab3e4763ea5329940fc7ad9dcd3e272a37516d7c9b/greenlet-3.3.2-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c2e47408e8ce1c6f1ceea0dffcdf6ebb85cc09e55c7af407c99f1112016e45e9", size = 662163, upload-time = "2026-02-20T20:56:01.295Z" }, + { url = "https://files.pythonhosted.org/packages/d2/d8/09bfa816572a4d83bccd6750df1926f79158b1c36c5f73786e26dbe4ee38/greenlet-3.3.2-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63d10328839d1973e5ba35e98cccbca71b232b14051fd957b6f8b6e8e80d0506", size = 664160, upload-time = "2026-02-20T20:21:04.015Z" }, + { url = "https://files.pythonhosted.org/packages/48/cf/56832f0c8255d27f6c35d41b5ec91168d74ec721d85f01a12131eec6b93c/greenlet-3.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e4ab3cfb02993c8cc248ea73d7dae6cec0253e9afa311c9b37e603ca9fad2ce", size = 1619181, upload-time = "2026-02-20T20:49:36.052Z" }, + { url = "https://files.pythonhosted.org/packages/0a/23/b90b60a4aabb4cec0796e55f25ffbfb579a907c3898cd2905c8918acaa16/greenlet-3.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:94ad81f0fd3c0c0681a018a976e5c2bd2ca2d9d94895f23e7bb1af4e8af4e2d5", size = 1687713, upload-time = "2026-02-20T20:21:11.684Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ca/2101ca3d9223a1dc125140dbc063644dca76df6ff356531eb27bc267b446/greenlet-3.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:8c4dd0f3997cf2512f7601563cc90dfb8957c0cff1e3a1b23991d4ea1776c492", size = 232034, upload-time = "2026-02-20T20:20:08.186Z" }, + { url = "https://files.pythonhosted.org/packages/f6/4a/ecf894e962a59dea60f04877eea0fd5724618da89f1867b28ee8b91e811f/greenlet-3.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:cd6f9e2bbd46321ba3bbb4c8a15794d32960e3b0ae2cc4d49a1a53d314805d71", size = 231437, upload-time = "2026-02-20T20:18:59.722Z" }, + { url = "https://files.pythonhosted.org/packages/98/6d/8f2ef704e614bcf58ed43cfb8d87afa1c285e98194ab2cfad351bf04f81e/greenlet-3.3.2-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:e26e72bec7ab387ac80caa7496e0f908ff954f31065b0ffc1f8ecb1338b11b54", size = 286617, upload-time = "2026-02-20T20:19:29.856Z" }, + { url = "https://files.pythonhosted.org/packages/5e/0d/93894161d307c6ea237a43988f27eba0947b360b99ac5239ad3fe09f0b47/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b466dff7a4ffda6ca975979bab80bdadde979e29fc947ac3be4451428d8b0e4", size = 655189, upload-time = "2026-02-20T20:47:35.742Z" }, + { url = "https://files.pythonhosted.org/packages/f5/2c/d2d506ebd8abcb57386ec4f7ba20f4030cbe56eae541bc6fd6ef399c0b41/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b8bddc5b73c9720bea487b3bffdb1840fe4e3656fba3bd40aa1489e9f37877ff", size = 658225, upload-time = "2026-02-20T20:56:02.527Z" }, + { url = "https://files.pythonhosted.org/packages/8e/30/3a09155fbf728673a1dea713572d2d31159f824a37c22da82127056c44e4/greenlet-3.3.2-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b26b0f4428b871a751968285a1ac9648944cea09807177ac639b030bddebcea4", size = 657907, upload-time = "2026-02-20T20:21:05.259Z" }, + { url = "https://files.pythonhosted.org/packages/f3/fd/d05a4b7acd0154ed758797f0a43b4c0962a843bedfe980115e842c5b2d08/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1fb39a11ee2e4d94be9a76671482be9398560955c9e568550de0224e41104727", size = 1618857, upload-time = "2026-02-20T20:49:37.309Z" }, + { url = "https://files.pythonhosted.org/packages/6f/e1/50ee92a5db521de8f35075b5eff060dd43d39ebd46c2181a2042f7070385/greenlet-3.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:20154044d9085151bc309e7689d6f7ba10027f8f5a8c0676ad398b951913d89e", size = 1680010, upload-time = "2026-02-20T20:21:13.427Z" }, + { url = "https://files.pythonhosted.org/packages/29/4b/45d90626aef8e65336bed690106d1382f7a43665e2249017e9527df8823b/greenlet-3.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c04c5e06ec3e022cbfe2cd4a846e1d4e50087444f875ff6d2c2ad8445495cf1a", size = 237086, upload-time = "2026-02-20T20:20:45.786Z" }, +] + [[package]] name = "h11" version = "0.16.0" @@ -739,6 +824,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/0e/61/66938bbb5fc52dbdf84594873d5b51fb1f7c7794e9c0f5bd885f30bc507b/idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea", size = 71008, upload-time = "2025-10-12T14:55:18.883Z" }, ] +[[package]] +name = "itsdangerous" +version = "2.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/9c/cb/8ac0172223afbccb63986cc25049b154ecfb5e85932587206f42317be31d/itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173", size = 54410, upload-time = "2024-04-16T21:28:15.614Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/96/92447566d16df59b2a776c0fb82dbc4d9e07cd95062562af01e408583fc4/itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef", size = 16234, upload-time = "2024-04-16T21:28:14.499Z" }, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -837,6 +931,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/80/be/3578e8afd18c88cdf9cb4cffde75a96d2be38c5a903f1ed0ceec061bd09e/kiwisolver-1.4.9-cp314-cp314t-win_arm64.whl", hash = "sha256:4a48a2ce79d65d363597ef7b567ce3d14d68783d2b2263d98db3d9477805ba32", size = 70260, upload-time = "2025-08-10T21:27:36.606Z" }, ] +[[package]] +name = "lark" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/da/34/28fff3ab31ccff1fd4f6c7c7b0ceb2b6968d8ea4950663eadcb5720591a0/lark-1.3.1.tar.gz", hash = "sha256:b426a7a6d6d53189d318f2b6236ab5d6429eaf09259f1ca33eb716eed10d2905", size = 382732, upload-time = "2025-10-27T18:25:56.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, +] + [[package]] name = "locket" version = "1.0.0" @@ -1389,6 +1492,62 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" }, ] +[[package]] +name = "pygeoapi" +version = "0.22.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "babel" }, + { name = "click" }, + { name = "filelock" }, + { name = "flask" }, + { name = "jinja2" }, + { name = "jsonschema" }, + { name = "pydantic" }, + { name = "pygeofilter" }, + { name = "pygeoif" }, + { name = "pyproj" }, + { name = "python-dateutil" }, + { name = "pytz" }, + { name = "pyyaml" }, + { name = "rasterio" }, + { name = "requests" }, + { name = "shapely" }, + { name = "sqlalchemy" }, + { name = "tinydb" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/46/3bcdd2915a8f2a9856cb0442f3f73cbba463bff4c5c059887dc3a20de33a/pygeoapi-0.22.0.tar.gz", hash = "sha256:43689d6c89e6bd7536c9384db4617fa499f82823394a656dd50c2ea126c92150", size = 324148, upload-time = "2025-11-07T20:22:43.352Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/3d/a3dd54ac1870c99223fc2fc1981ac16f3a875d95c0d60fca0814c393ca8f/pygeoapi-0.22.0-py2.py3-none-any.whl", hash = "sha256:0975e9efc5e7c70466f05b085b8093311718c40ee8ecd9a15ac803945e8d5ab8", size = 518476, upload-time = "2025-11-07T20:22:41.982Z" }, +] + +[[package]] +name = "pygeofilter" +version = "0.3.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click" }, + { name = "dateparser" }, + { name = "lark" }, + { name = "pygeoif" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/f0/30b916dc05ff1242eb9cc391e1bac367d34c9f403c0bd634923b87024c23/pygeofilter-0.3.3.tar.gz", hash = "sha256:8b9fec05ba144943a1e415b6ac3752ad6011f44aad7d1bb27e7ef48b073460bd", size = 63419, upload-time = "2025-12-20T08:47:59.619Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f6/e3/c777c08e9519c1d49fcfad726c84d7b0e7934e9f414430eaa3d1ab41ecf7/pygeofilter-0.3.3-py2.py3-none-any.whl", hash = "sha256:e719fcb929c6b60bca99de0cfde5f95bc3245cab50516c103dae1d4f12c4c7b6", size = 96568, upload-time = "2025-12-20T08:47:58.178Z" }, +] + +[[package]] +name = "pygeoif" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/2e/c6660ceea2fc28feefdfb0389bf53b5d0e0ba92aaba72e813901cb0552ed/pygeoif-1.6.0.tar.gz", hash = "sha256:eb0efa59c6573ea2cadce69a7ea9d2d10394b895ed47831c00d44752219c01be", size = 40915, upload-time = "2025-10-01T10:02:13.429Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c3/7f/c803c39fa76fe055bc4154fb6e897185ad21946820a2227283e0a20eeb35/pygeoif-1.6.0-py3-none-any.whl", hash = "sha256:02f84807dadbaf1941c4bb2a9ef1ebac99b1b0404597d2602efdbb58910c69c9", size = 27976, upload-time = "2025-10-01T10:02:12.19Z" }, +] + [[package]] name = "pymeeus" version = "0.5.12" @@ -1620,6 +1779,78 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/58/ca301544e1fa93ed4f80d724bf5b194f6e4b945841c5bfd555878eea9fcb/referencing-0.37.0-py3-none-any.whl", hash = "sha256:381329a9f99628c9069361716891d34ad94af76e461dcb0335825aecc7692231", size = 26766, upload-time = "2025-10-13T15:30:47.625Z" }, ] +[[package]] +name = "regex" +version = "2026.2.19" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ff/c0/d8079d4f6342e4cec5c3e7d7415b5cd3e633d5f4124f7a4626908dbe84c7/regex-2026.2.19.tar.gz", hash = "sha256:6fb8cb09b10e38f3ae17cc6dc04a1df77762bd0351b6ba9041438e7cc85ec310", size = 414973, upload-time = "2026-02-19T19:03:47.899Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/2d/a849835e76ac88fcf9e8784e642d3ea635d183c4112150ca91499d6703af/regex-2026.2.19-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8df08decd339e8b3f6a2eb5c05c687fe9d963ae91f352bc57beb05f5b2ac6879", size = 489329, upload-time = "2026-02-19T19:01:23.841Z" }, + { url = "https://files.pythonhosted.org/packages/da/aa/78ff4666d3855490bae87845a5983485e765e1f970da20adffa2937b241d/regex-2026.2.19-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3aa0944f1dc6e92f91f3b306ba7f851e1009398c84bfd370633182ee4fc26a64", size = 291308, upload-time = "2026-02-19T19:01:25.605Z" }, + { url = "https://files.pythonhosted.org/packages/cd/58/714384efcc07ae6beba528a541f6e99188c5cc1bc0295337f4e8a868296d/regex-2026.2.19-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c13228fbecb03eadbfd8f521732c5fda09ef761af02e920a3148e18ad0e09968", size = 289033, upload-time = "2026-02-19T19:01:27.243Z" }, + { url = "https://files.pythonhosted.org/packages/75/ec/6438a9344d2869cf5265236a06af1ca6d885e5848b6561e10629bc8e5a11/regex-2026.2.19-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0d0e72703c60d68b18b27cde7cdb65ed2570ae29fb37231aa3076bfb6b1d1c13", size = 798798, upload-time = "2026-02-19T19:01:28.877Z" }, + { url = "https://files.pythonhosted.org/packages/c2/be/b1ce2d395e3fd2ce5f2fde2522f76cade4297cfe84cd61990ff48308749c/regex-2026.2.19-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:46e69a4bf552e30e74a8aa73f473c87efcb7f6e8c8ece60d9fd7bf13d5c86f02", size = 864444, upload-time = "2026-02-19T19:01:30.933Z" }, + { url = "https://files.pythonhosted.org/packages/d5/97/a3406460c504f7136f140d9461960c25f058b0240e4424d6fb73c7a067ab/regex-2026.2.19-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8edda06079bd770f7f0cf7f3bba1a0b447b96b4a543c91fe0c142d034c166161", size = 912633, upload-time = "2026-02-19T19:01:32.744Z" }, + { url = "https://files.pythonhosted.org/packages/8b/d9/e5dbef95008d84e9af1dc0faabbc34a7fbc8daa05bc5807c5cf86c2bec49/regex-2026.2.19-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9cbc69eae834afbf634f7c902fc72ff3e993f1c699156dd1af1adab5d06b7fe7", size = 803718, upload-time = "2026-02-19T19:01:34.61Z" }, + { url = "https://files.pythonhosted.org/packages/2f/e5/61d80132690a1ef8dc48e0f44248036877aebf94235d43f63a20d1598888/regex-2026.2.19-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:bcf57d30659996ee5c7937999874504c11b5a068edc9515e6a59221cc2744dd1", size = 775975, upload-time = "2026-02-19T19:01:36.525Z" }, + { url = "https://files.pythonhosted.org/packages/05/32/ae828b3b312c972cf228b634447de27237d593d61505e6ad84723f8eabba/regex-2026.2.19-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:8e6e77cd92216eb489e21e5652a11b186afe9bdefca8a2db739fd6b205a9e0a4", size = 788129, upload-time = "2026-02-19T19:01:38.498Z" }, + { url = "https://files.pythonhosted.org/packages/cb/25/d74f34676f22bec401eddf0e5e457296941e10cbb2a49a571ca7a2c16e5a/regex-2026.2.19-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b9ab8dec42afefa6314ea9b31b188259ffdd93f433d77cad454cd0b8d235ce1c", size = 858818, upload-time = "2026-02-19T19:01:40.409Z" }, + { url = "https://files.pythonhosted.org/packages/1e/eb/0bc2b01a6b0b264e1406e5ef11cae3f634c3bd1a6e61206fd3227ce8e89c/regex-2026.2.19-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:294c0fb2e87c6bcc5f577c8f609210f5700b993151913352ed6c6af42f30f95f", size = 764186, upload-time = "2026-02-19T19:01:43.009Z" }, + { url = "https://files.pythonhosted.org/packages/eb/37/5fe5a630d0d99ecf0c3570f8905dafbc160443a2d80181607770086c9812/regex-2026.2.19-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:c0924c64b082d4512b923ac016d6e1dcf647a3560b8a4c7e55cbbd13656cb4ed", size = 850363, upload-time = "2026-02-19T19:01:45.015Z" }, + { url = "https://files.pythonhosted.org/packages/c3/45/ef68d805294b01ec030cfd388724ba76a5a21a67f32af05b17924520cb0b/regex-2026.2.19-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:790dbf87b0361606cb0d79b393c3e8f4436a14ee56568a7463014565d97da02a", size = 790026, upload-time = "2026-02-19T19:01:47.51Z" }, + { url = "https://files.pythonhosted.org/packages/d6/3a/40d3b66923dfc5aeba182f194f0ca35d09afe8c031a193e6ae46971a0a0e/regex-2026.2.19-cp313-cp313-win32.whl", hash = "sha256:43cdde87006271be6963896ed816733b10967baaf0e271d529c82e93da66675b", size = 266372, upload-time = "2026-02-19T19:01:49.469Z" }, + { url = "https://files.pythonhosted.org/packages/3d/f2/39082e8739bfd553497689e74f9d5e5bb531d6f8936d0b94f43e18f219c0/regex-2026.2.19-cp313-cp313-win_amd64.whl", hash = "sha256:127ea69273485348a126ebbf3d6052604d3c7da284f797bba781f364c0947d47", size = 277253, upload-time = "2026-02-19T19:01:51.208Z" }, + { url = "https://files.pythonhosted.org/packages/c2/c2/852b9600d53fb47e47080c203e2cdc0ac7e84e37032a57e0eaa37446033a/regex-2026.2.19-cp313-cp313-win_arm64.whl", hash = "sha256:5e56c669535ac59cbf96ca1ece0ef26cb66809990cda4fa45e1e32c3b146599e", size = 270505, upload-time = "2026-02-19T19:01:52.865Z" }, + { url = "https://files.pythonhosted.org/packages/a9/a2/e0b4575b93bc84db3b1fab24183e008691cd2db5c0ef14ed52681fbd94dd/regex-2026.2.19-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:93d881cab5afdc41a005dba1524a40947d6f7a525057aa64aaf16065cf62faa9", size = 492202, upload-time = "2026-02-19T19:01:54.816Z" }, + { url = "https://files.pythonhosted.org/packages/24/b5/b84fec8cbb5f92a7eed2b6b5353a6a9eed9670fee31817c2da9eb85dc797/regex-2026.2.19-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:80caaa1ddcc942ec7be18427354f9d58a79cee82dea2a6b3d4fd83302e1240d7", size = 292884, upload-time = "2026-02-19T19:01:58.254Z" }, + { url = "https://files.pythonhosted.org/packages/70/0c/fe89966dfae43da46f475362401f03e4d7dc3a3c955b54f632abc52669e0/regex-2026.2.19-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d793c5b4d2b4c668524cd1651404cfc798d40694c759aec997e196fe9729ec60", size = 291236, upload-time = "2026-02-19T19:01:59.966Z" }, + { url = "https://files.pythonhosted.org/packages/f2/f7/bda2695134f3e63eb5cccbbf608c2a12aab93d261ff4e2fe49b47fabc948/regex-2026.2.19-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b5100acb20648d9efd3f4e7e91f51187f95f22a741dcd719548a6cf4e1b34b3f", size = 807660, upload-time = "2026-02-19T19:02:01.632Z" }, + { url = "https://files.pythonhosted.org/packages/11/56/6e3a4bf5e60d17326b7003d91bbde8938e439256dec211d835597a44972d/regex-2026.2.19-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:5e3a31e94d10e52a896adaa3adf3621bd526ad2b45b8c2d23d1bbe74c7423007", size = 873585, upload-time = "2026-02-19T19:02:03.522Z" }, + { url = "https://files.pythonhosted.org/packages/35/5e/c90c6aa4d1317cc11839359479cfdd2662608f339e84e81ba751c8a4e461/regex-2026.2.19-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8497421099b981f67c99eba4154cf0dfd8e47159431427a11cfb6487f7791d9e", size = 915243, upload-time = "2026-02-19T19:02:05.608Z" }, + { url = "https://files.pythonhosted.org/packages/90/7c/981ea0694116793001496aaf9524e5c99e122ec3952d9e7f1878af3a6bf1/regex-2026.2.19-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1e7a08622f7d51d7a068f7e4052a38739c412a3e74f55817073d2e2418149619", size = 812922, upload-time = "2026-02-19T19:02:08.115Z" }, + { url = "https://files.pythonhosted.org/packages/2d/be/9eda82afa425370ffdb3fa9f3ea42450b9ae4da3ff0a4ec20466f69e371b/regex-2026.2.19-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:8abe671cf0f15c26b1ad389bf4043b068ce7d3b1c5d9313e12895f57d6738555", size = 781318, upload-time = "2026-02-19T19:02:10.072Z" }, + { url = "https://files.pythonhosted.org/packages/c6/d5/50f0bbe56a8199f60a7b6c714e06e54b76b33d31806a69d0703b23ce2a9e/regex-2026.2.19-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:5a8f28dd32a4ce9c41758d43b5b9115c1c497b4b1f50c457602c1d571fa98ce1", size = 795649, upload-time = "2026-02-19T19:02:11.96Z" }, + { url = "https://files.pythonhosted.org/packages/c5/09/d039f081e44a8b0134d0bb2dd805b0ddf390b69d0b58297ae098847c572f/regex-2026.2.19-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:654dc41a5ba9b8cc8432b3f1aa8906d8b45f3e9502442a07c2f27f6c63f85db5", size = 868844, upload-time = "2026-02-19T19:02:14.043Z" }, + { url = "https://files.pythonhosted.org/packages/ef/53/e2903b79a19ec8557fe7cd21cd093956ff2dbc2e0e33969e3adbe5b184dd/regex-2026.2.19-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:4a02faea614e7fdd6ba8b3bec6c8e79529d356b100381cec76e638f45d12ca04", size = 770113, upload-time = "2026-02-19T19:02:16.161Z" }, + { url = "https://files.pythonhosted.org/packages/8f/e2/784667767b55714ebb4e59bf106362327476b882c0b2f93c25e84cc99b1a/regex-2026.2.19-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:d96162140bb819814428800934c7b71b7bffe81fb6da2d6abc1dcca31741eca3", size = 854922, upload-time = "2026-02-19T19:02:18.155Z" }, + { url = "https://files.pythonhosted.org/packages/59/78/9ef4356bd4aed752775bd18071034979b85f035fec51f3a4f9dea497a254/regex-2026.2.19-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:c227f2922153ee42bbeb355fd6d009f8c81d9d7bdd666e2276ce41f53ed9a743", size = 799636, upload-time = "2026-02-19T19:02:20.04Z" }, + { url = "https://files.pythonhosted.org/packages/cf/54/fcfc9287f20c5c9bd8db755aafe3e8cf4d99a6a3f1c7162ee182e0ca9374/regex-2026.2.19-cp313-cp313t-win32.whl", hash = "sha256:a178df8ec03011153fbcd2c70cb961bc98cbbd9694b28f706c318bee8927c3db", size = 268968, upload-time = "2026-02-19T19:02:22.816Z" }, + { url = "https://files.pythonhosted.org/packages/1e/a0/ff24c6cb1273e42472706d277147fc38e1f9074a280fb6034b0fc9b69415/regex-2026.2.19-cp313-cp313t-win_amd64.whl", hash = "sha256:2c1693ca6f444d554aa246b592355b5cec030ace5a2729eae1b04ab6e853e768", size = 280390, upload-time = "2026-02-19T19:02:25.231Z" }, + { url = "https://files.pythonhosted.org/packages/1a/b6/a3f6ad89d780ffdeebb4d5e2e3e30bd2ef1f70f6a94d1760e03dd1e12c60/regex-2026.2.19-cp313-cp313t-win_arm64.whl", hash = "sha256:c0761d7ae8d65773e01515ebb0b304df1bf37a0a79546caad9cbe79a42c12af7", size = 271643, upload-time = "2026-02-19T19:02:27.175Z" }, + { url = "https://files.pythonhosted.org/packages/2d/e2/7ad4e76a6dddefc0d64dbe12a4d3ca3947a19ddc501f864a5df2a8222ddd/regex-2026.2.19-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:03d191a9bcf94d31af56d2575210cb0d0c6a054dbcad2ea9e00aa4c42903b919", size = 489306, upload-time = "2026-02-19T19:02:29.058Z" }, + { url = "https://files.pythonhosted.org/packages/14/95/ee1736135733afbcf1846c58671046f99c4d5170102a150ebb3dd8d701d9/regex-2026.2.19-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:516ee067c6c721d0d0bfb80a2004edbd060fffd07e456d4e1669e38fe82f922e", size = 291218, upload-time = "2026-02-19T19:02:31.083Z" }, + { url = "https://files.pythonhosted.org/packages/ef/08/180d1826c3d7065200a5168c6b993a44947395c7bb6e04b2c2a219c34225/regex-2026.2.19-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:997862c619994c4a356cb7c3592502cbd50c2ab98da5f61c5c871f10f22de7e5", size = 289097, upload-time = "2026-02-19T19:02:33.485Z" }, + { url = "https://files.pythonhosted.org/packages/28/93/0651924c390c5740f5f896723f8ddd946a6c63083a7d8647231c343912ff/regex-2026.2.19-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:02b9e1b8a7ebe2807cd7bbdf662510c8e43053a23262b9f46ad4fc2dfc9d204e", size = 799147, upload-time = "2026-02-19T19:02:35.669Z" }, + { url = "https://files.pythonhosted.org/packages/a7/00/2078bd8bcd37d58a756989adbfd9f1d0151b7ca4085a9c2a07e917fbac61/regex-2026.2.19-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:6c8fb3b19652e425ff24169dad3ee07f99afa7996caa9dfbb3a9106cd726f49a", size = 865239, upload-time = "2026-02-19T19:02:38.012Z" }, + { url = "https://files.pythonhosted.org/packages/2a/13/75195161ec16936b35a365fa8c1dd2ab29fd910dd2587765062b174d8cfc/regex-2026.2.19-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:50f1ee9488dd7a9fda850ec7c68cad7a32fa49fd19733f5403a3f92b451dcf73", size = 911904, upload-time = "2026-02-19T19:02:40.737Z" }, + { url = "https://files.pythonhosted.org/packages/96/72/ac42f6012179343d1c4bd0ffee8c948d841cb32ea188d37e96d80527fcc9/regex-2026.2.19-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ab780092b1424d13200aa5a62996e95f65ee3db8509be366437439cdc0af1a9f", size = 803518, upload-time = "2026-02-19T19:02:42.923Z" }, + { url = "https://files.pythonhosted.org/packages/bc/d1/75a08e2269b007b9783f0f86aa64488e023141219cb5f14dc1e69cda56c6/regex-2026.2.19-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:17648e1a88e72d88641b12635e70e6c71c5136ba14edba29bf8fc6834005a265", size = 775866, upload-time = "2026-02-19T19:02:45.189Z" }, + { url = "https://files.pythonhosted.org/packages/92/41/70e7d05faf6994c2ca7a9fcaa536da8f8e4031d45b0ec04b57040ede201f/regex-2026.2.19-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2f914ae8c804c8a8a562fe216100bc156bfb51338c1f8d55fe32cf407774359a", size = 788224, upload-time = "2026-02-19T19:02:47.804Z" }, + { url = "https://files.pythonhosted.org/packages/c8/83/34a2dd601f9deb13c20545c674a55f4a05c90869ab73d985b74d639bac43/regex-2026.2.19-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:c7e121a918bbee3f12ac300ce0a0d2f2c979cf208fb071ed8df5a6323281915c", size = 859682, upload-time = "2026-02-19T19:02:50.583Z" }, + { url = "https://files.pythonhosted.org/packages/8e/30/136db9a09a7f222d6e48b806f3730e7af6499a8cad9c72ac0d49d52c746e/regex-2026.2.19-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:2fedd459c791da24914ecc474feecd94cf7845efb262ac3134fe27cbd7eda799", size = 764223, upload-time = "2026-02-19T19:02:52.777Z" }, + { url = "https://files.pythonhosted.org/packages/9e/ea/bb947743c78a16df481fa0635c50aa1a439bb80b0e6dc24cd4e49c716679/regex-2026.2.19-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:ea8dfc99689240e61fb21b5fc2828f68b90abf7777d057b62d3166b7c1543c4c", size = 850101, upload-time = "2026-02-19T19:02:55.87Z" }, + { url = "https://files.pythonhosted.org/packages/25/27/e3bfe6e97a99f7393665926be02fef772da7f8aa59e50bc3134e4262a032/regex-2026.2.19-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fff45852160960f29e184ec8a5be5ab4063cfd0b168d439d1fc4ac3744bf29e", size = 789904, upload-time = "2026-02-19T19:02:58.523Z" }, + { url = "https://files.pythonhosted.org/packages/84/7b/7e2be6f00cea59d08761b027ad237002e90cac74b1607200ebaa2ba3d586/regex-2026.2.19-cp314-cp314-win32.whl", hash = "sha256:5390b130cce14a7d1db226a3896273b7b35be10af35e69f1cca843b6e5d2bb2d", size = 271784, upload-time = "2026-02-19T19:03:00.418Z" }, + { url = "https://files.pythonhosted.org/packages/f7/f6/639911530335773e7ec60bcaa519557b719586024c1d7eaad1daf87b646b/regex-2026.2.19-cp314-cp314-win_amd64.whl", hash = "sha256:e581f75d5c0b15669139ca1c2d3e23a65bb90e3c06ba9d9ea194c377c726a904", size = 280506, upload-time = "2026-02-19T19:03:02.302Z" }, + { url = "https://files.pythonhosted.org/packages/cd/ec/2582b56b4e036d46bb9b5d74a18548439ffa16c11cf59076419174d80f48/regex-2026.2.19-cp314-cp314-win_arm64.whl", hash = "sha256:7187fdee1be0896c1499a991e9bf7c78e4b56b7863e7405d7bb687888ac10c4b", size = 273557, upload-time = "2026-02-19T19:03:04.836Z" }, + { url = "https://files.pythonhosted.org/packages/49/0b/f901cfeb4efd83e4f5c3e9f91a6de77e8e5ceb18555698aca3a27e215ed3/regex-2026.2.19-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:5ec1d7c080832fdd4e150c6f5621fe674c70c63b3ae5a4454cebd7796263b175", size = 492196, upload-time = "2026-02-19T19:03:08.188Z" }, + { url = "https://files.pythonhosted.org/packages/94/0a/349b959e3da874e15eda853755567b4cde7e5309dbb1e07bfe910cfde452/regex-2026.2.19-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8457c1bc10ee9b29cdfd897ccda41dce6bde0e9abd514bcfef7bcd05e254d411", size = 292878, upload-time = "2026-02-19T19:03:10.272Z" }, + { url = "https://files.pythonhosted.org/packages/98/b0/9d81b3c2c5ddff428f8c506713737278979a2c476f6e3675a9c51da0c389/regex-2026.2.19-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:cce8027010d1ffa3eb89a0b19621cdc78ae548ea2b49fea1f7bfb3ea77064c2b", size = 291235, upload-time = "2026-02-19T19:03:12.5Z" }, + { url = "https://files.pythonhosted.org/packages/04/e7/be7818df8691dbe9508c381ea2cc4c1153e4fdb1c4b06388abeaa93bd712/regex-2026.2.19-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11c138febb40546ff9e026dbbc41dc9fb8b29e61013fa5848ccfe045f5b23b83", size = 807893, upload-time = "2026-02-19T19:03:15.064Z" }, + { url = "https://files.pythonhosted.org/packages/0c/b6/b898a8b983190cfa0276031c17beb73cfd1db07c03c8c37f606d80b655e2/regex-2026.2.19-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:74ff212aa61532246bb3036b3dfea62233414b0154b8bc3676975da78383cac3", size = 873696, upload-time = "2026-02-19T19:03:17.848Z" }, + { url = "https://files.pythonhosted.org/packages/1a/98/126ba671d54f19080ec87cad228fb4f3cc387fff8c4a01cb4e93f4ff9d94/regex-2026.2.19-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d00c95a2b6bfeb3ea1cb68d1751b1dfce2b05adc2a72c488d77a780db06ab867", size = 915493, upload-time = "2026-02-19T19:03:20.343Z" }, + { url = "https://files.pythonhosted.org/packages/b2/10/550c84a1a1a7371867fe8be2bea7df55e797cbca4709974811410e195c5d/regex-2026.2.19-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:311fcccb76af31be4c588d5a17f8f1a059ae8f4b097192896ebffc95612f223a", size = 813094, upload-time = "2026-02-19T19:03:23.287Z" }, + { url = "https://files.pythonhosted.org/packages/29/fb/ba221d2fc76a27b6b7d7a60f73a7a6a7bac21c6ba95616a08be2bcb434b0/regex-2026.2.19-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:77cfd6b5e7c4e8bf7a39d243ea05882acf5e3c7002b0ef4756de6606893b0ecd", size = 781583, upload-time = "2026-02-19T19:03:26.872Z" }, + { url = "https://files.pythonhosted.org/packages/26/f1/af79231301297c9e962679efc04a31361b58dc62dec1fc0cb4b8dd95956a/regex-2026.2.19-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:6380f29ff212ec922b6efb56100c089251940e0526a0d05aa7c2d9b571ddf2fe", size = 795875, upload-time = "2026-02-19T19:03:29.223Z" }, + { url = "https://files.pythonhosted.org/packages/a0/90/1e1d76cb0a2d0a4f38a039993e1c5cd971ae50435d751c5bae4f10e1c302/regex-2026.2.19-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:655f553a1fa3ab8a7fd570eca793408b8d26a80bfd89ed24d116baaf13a38969", size = 868916, upload-time = "2026-02-19T19:03:31.415Z" }, + { url = "https://files.pythonhosted.org/packages/9a/67/a1c01da76dbcfed690855a284c665cc0a370e7d02d1bd635cf9ff7dd74b8/regex-2026.2.19-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:015088b8558502f1f0bccd58754835aa154a7a5b0bd9d4c9b7b96ff4ae9ba876", size = 770386, upload-time = "2026-02-19T19:03:33.972Z" }, + { url = "https://files.pythonhosted.org/packages/49/6f/94842bf294f432ff3836bfd91032e2ecabea6d284227f12d1f935318c9c4/regex-2026.2.19-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:9e6693b8567a59459b5dda19104c4a4dbbd4a1c78833eacc758796f2cfef1854", size = 855007, upload-time = "2026-02-19T19:03:36.238Z" }, + { url = "https://files.pythonhosted.org/packages/ff/93/393cd203ca0d1d368f05ce12d2c7e91a324bc93c240db2e6d5ada05835f4/regex-2026.2.19-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4071209fd4376ab5ceec72ad3507e9d3517c59e38a889079b98916477a871868", size = 799863, upload-time = "2026-02-19T19:03:38.497Z" }, + { url = "https://files.pythonhosted.org/packages/43/d9/35afda99bd92bf1a5831e55a4936d37ea4bed6e34c176a3c2238317faf4f/regex-2026.2.19-cp314-cp314t-win32.whl", hash = "sha256:2905ff4a97fad42f2d0834d8b1ea3c2f856ec209837e458d71a061a7d05f9f01", size = 274742, upload-time = "2026-02-19T19:03:40.804Z" }, + { url = "https://files.pythonhosted.org/packages/ae/42/7edc3344dcc87b698e9755f7f685d463852d481302539dae07135202d3ca/regex-2026.2.19-cp314-cp314t-win_amd64.whl", hash = "sha256:64128549b600987e0f335c2365879895f860a9161f283b14207c800a6ed623d3", size = 284443, upload-time = "2026-02-19T19:03:42.954Z" }, + { url = "https://files.pythonhosted.org/packages/3a/45/affdf2d851b42adf3d13fc5b3b059372e9bd299371fd84cf5723c45871fa/regex-2026.2.19-cp314-cp314t-win_arm64.whl", hash = "sha256:a09ae430e94c049dc6957f6baa35ee3418a3a77f3c12b6e02883bd80a2b679b0", size = 274932, upload-time = "2026-02-19T19:03:45.488Z" }, +] + [[package]] name = "requests" version = "2.32.5" @@ -1813,6 +2044,41 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, ] +[[package]] +name = "sqlalchemy" +version = "2.0.46" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "platform_machine == 'AMD64' or platform_machine == 'WIN32' or platform_machine == 'aarch64' or platform_machine == 'amd64' or platform_machine == 'ppc64le' or platform_machine == 'win32' or platform_machine == 'x86_64'" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/06/aa/9ce0f3e7a9829ead5c8ce549392f33a12c4555a6c0609bb27d882e9c7ddf/sqlalchemy-2.0.46.tar.gz", hash = "sha256:cf36851ee7219c170bb0793dbc3da3e80c582e04a5437bc601bfe8c85c9216d7", size = 9865393, upload-time = "2026-01-21T18:03:45.119Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/4b/fa7838fe20bb752810feed60e45625a9a8b0102c0c09971e2d1d95362992/sqlalchemy-2.0.46-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:93a12da97cca70cea10d4b4fc602589c4511f96c1f8f6c11817620c021d21d00", size = 2150268, upload-time = "2026-01-21T19:05:56.621Z" }, + { url = "https://files.pythonhosted.org/packages/46/c1/b34dccd712e8ea846edf396e00973dda82d598cb93762e55e43e6835eba9/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af865c18752d416798dae13f83f38927c52f085c52e2f32b8ab0fef46fdd02c2", size = 3276511, upload-time = "2026-01-21T18:46:49.022Z" }, + { url = "https://files.pythonhosted.org/packages/96/48/a04d9c94753e5d5d096c628c82a98c4793b9c08ca0e7155c3eb7d7db9f24/sqlalchemy-2.0.46-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8d679b5f318423eacb61f933a9a0f75535bfca7056daeadbf6bd5bcee6183aee", size = 3292881, upload-time = "2026-01-21T18:40:13.089Z" }, + { url = "https://files.pythonhosted.org/packages/be/f4/06eda6e91476f90a7d8058f74311cb65a2fb68d988171aced81707189131/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:64901e08c33462acc9ec3bad27fc7a5c2b6491665f2aa57564e57a4f5d7c52ad", size = 3224559, upload-time = "2026-01-21T18:46:50.974Z" }, + { url = "https://files.pythonhosted.org/packages/ab/a2/d2af04095412ca6345ac22b33b89fe8d6f32a481e613ffcb2377d931d8d0/sqlalchemy-2.0.46-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e8ac45e8f4eaac0f9f8043ea0e224158855c6a4329fd4ee37c45c61e3beb518e", size = 3262728, upload-time = "2026-01-21T18:40:14.883Z" }, + { url = "https://files.pythonhosted.org/packages/31/48/1980c7caa5978a3b8225b4d230e69a2a6538a3562b8b31cea679b6933c83/sqlalchemy-2.0.46-cp313-cp313-win32.whl", hash = "sha256:8d3b44b3d0ab2f1319d71d9863d76eeb46766f8cf9e921ac293511804d39813f", size = 2111295, upload-time = "2026-01-21T18:42:52.366Z" }, + { url = "https://files.pythonhosted.org/packages/2d/54/f8d65bbde3d877617c4720f3c9f60e99bb7266df0d5d78b6e25e7c149f35/sqlalchemy-2.0.46-cp313-cp313-win_amd64.whl", hash = "sha256:77f8071d8fbcbb2dd11b7fd40dedd04e8ebe2eb80497916efedba844298065ef", size = 2137076, upload-time = "2026-01-21T18:42:53.924Z" }, + { url = "https://files.pythonhosted.org/packages/56/ba/9be4f97c7eb2b9d5544f2624adfc2853e796ed51d2bb8aec90bc94b7137e/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1e8cc6cc01da346dc92d9509a63033b9b1bda4fed7a7a7807ed385c7dccdc10", size = 3556533, upload-time = "2026-01-21T18:33:06.636Z" }, + { url = "https://files.pythonhosted.org/packages/20/a6/b1fc6634564dbb4415b7ed6419cdfeaadefd2c39cdab1e3aa07a5f2474c2/sqlalchemy-2.0.46-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:96c7cca1a4babaaf3bfff3e4e606e38578856917e52f0384635a95b226c87764", size = 3523208, upload-time = "2026-01-21T18:45:08.436Z" }, + { url = "https://files.pythonhosted.org/packages/a1/d8/41e0bdfc0f930ff236f86fccd12962d8fa03713f17ed57332d38af6a3782/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2a9f9aee38039cf4755891a1e50e1effcc42ea6ba053743f452c372c3152b1b", size = 3464292, upload-time = "2026-01-21T18:33:08.208Z" }, + { url = "https://files.pythonhosted.org/packages/f0/8b/9dcbec62d95bea85f5ecad9b8d65b78cc30fb0ffceeb3597961f3712549b/sqlalchemy-2.0.46-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db23b1bf8cfe1f7fda19018e7207b20cdb5168f83c437ff7e95d19e39289c447", size = 3473497, upload-time = "2026-01-21T18:45:10.552Z" }, + { url = "https://files.pythonhosted.org/packages/e9/f8/5ecdfc73383ec496de038ed1614de9e740a82db9ad67e6e4514ebc0708a3/sqlalchemy-2.0.46-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:56bdd261bfd0895452006d5316cbf35739c53b9bb71a170a331fa0ea560b2ada", size = 2152079, upload-time = "2026-01-21T19:05:58.477Z" }, + { url = "https://files.pythonhosted.org/packages/e5/bf/eba3036be7663ce4d9c050bc3d63794dc29fbe01691f2bf5ccb64e048d20/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:33e462154edb9493f6c3ad2125931e273bbd0be8ae53f3ecd1c161ea9a1dd366", size = 3272216, upload-time = "2026-01-21T18:46:52.634Z" }, + { url = "https://files.pythonhosted.org/packages/05/45/1256fb597bb83b58a01ddb600c59fe6fdf0e5afe333f0456ed75c0f8d7bd/sqlalchemy-2.0.46-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9bcdce05f056622a632f1d44bb47dbdb677f58cad393612280406ce37530eb6d", size = 3277208, upload-time = "2026-01-21T18:40:16.38Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a0/2053b39e4e63b5d7ceb3372cface0859a067c1ddbd575ea7e9985716f771/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8e84b09a9b0f19accedcbeff5c2caf36e0dd537341a33aad8d680336152dc34e", size = 3221994, upload-time = "2026-01-21T18:46:54.622Z" }, + { url = "https://files.pythonhosted.org/packages/1e/87/97713497d9502553c68f105a1cb62786ba1ee91dea3852ae4067ed956a50/sqlalchemy-2.0.46-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4f52f7291a92381e9b4de9050b0a65ce5d6a763333406861e33906b8aa4906bf", size = 3243990, upload-time = "2026-01-21T18:40:18.253Z" }, + { url = "https://files.pythonhosted.org/packages/a8/87/5d1b23548f420ff823c236f8bea36b1a997250fd2f892e44a3838ca424f4/sqlalchemy-2.0.46-cp314-cp314-win32.whl", hash = "sha256:70ed2830b169a9960193f4d4322d22be5c0925357d82cbf485b3369893350908", size = 2114215, upload-time = "2026-01-21T18:42:55.232Z" }, + { url = "https://files.pythonhosted.org/packages/3a/20/555f39cbcf0c10cf452988b6a93c2a12495035f68b3dbd1a408531049d31/sqlalchemy-2.0.46-cp314-cp314-win_amd64.whl", hash = "sha256:3c32e993bc57be6d177f7d5d31edb93f30726d798ad86ff9066d75d9bf2e0b6b", size = 2139867, upload-time = "2026-01-21T18:42:56.474Z" }, + { url = "https://files.pythonhosted.org/packages/3e/f0/f96c8057c982d9d8a7a68f45d69c674bc6f78cad401099692fe16521640a/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4dafb537740eef640c4d6a7c254611dca2df87eaf6d14d6a5fca9d1f4c3fc0fa", size = 3561202, upload-time = "2026-01-21T18:33:10.337Z" }, + { url = "https://files.pythonhosted.org/packages/d7/53/3b37dda0a5b137f21ef608d8dfc77b08477bab0fe2ac9d3e0a66eaeab6fc/sqlalchemy-2.0.46-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:42a1643dc5427b69aca967dae540a90b0fbf57eaf248f13a90ea5930e0966863", size = 3526296, upload-time = "2026-01-21T18:45:12.657Z" }, + { url = "https://files.pythonhosted.org/packages/33/75/f28622ba6dde79cd545055ea7bd4062dc934e0621f7b3be2891f8563f8de/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ff33c6e6ad006bbc0f34f5faf941cfc62c45841c64c0a058ac38c799f15b5ede", size = 3470008, upload-time = "2026-01-21T18:33:11.725Z" }, + { url = "https://files.pythonhosted.org/packages/a9/42/4afecbbc38d5e99b18acef446453c76eec6fbd03db0a457a12a056836e22/sqlalchemy-2.0.46-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:82ec52100ec1e6ec671563bbd02d7c7c8d0b9e71a0723c72f22ecf52d1755330", size = 3476137, upload-time = "2026-01-21T18:45:15.001Z" }, + { url = "https://files.pythonhosted.org/packages/fc/a1/9c4efa03300926601c19c18582531b45aededfb961ab3c3585f1e24f120b/sqlalchemy-2.0.46-py3-none-any.whl", hash = "sha256:f9c11766e7e7c0a2767dda5acb006a118640c9fc0a4104214b96269bfb78399e", size = 1937882, upload-time = "2026-01-21T18:22:10.456Z" }, +] + [[package]] name = "starlette" version = "0.52.1" @@ -1825,6 +2091,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, ] +[[package]] +name = "tinydb" +version = "4.8.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a0/79/4af51e2bb214b6ea58f857c51183d92beba85b23f7ba61c983ab3de56c33/tinydb-4.8.2.tar.gz", hash = "sha256:f7dfc39b8d7fda7a1ca62a8dbb449ffd340a117c1206b68c50b1a481fb95181d", size = 32566, upload-time = "2024-10-12T15:24:01.13Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/17/853354204e1ca022d6b7d011ca7f3206c4f8faa3cc743e92609b49c1d83f/tinydb-4.8.2-py3-none-any.whl", hash = "sha256:f97030ee5cbc91eeadd1d7af07ab0e48ceb04aa63d4a983adbaca4cba16e86c3", size = 24888, upload-time = "2024-10-12T15:23:59.833Z" }, +] + [[package]] name = "titiler-core" version = "1.2.0" @@ -1897,6 +2172,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/b0/003792df09decd6849a5e39c28b513c06e84436a54440380862b5aeff25d/tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1", size = 348521, upload-time = "2025-12-13T17:45:33.889Z" }, ] +[[package]] +name = "tzlocal" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "tzdata", marker = "sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/8b/2e/c14812d3d4d9cd1773c6be938f89e5735a1f11a9f184ac3639b93cef35d5/tzlocal-5.3.1.tar.gz", hash = "sha256:cceffc7edecefea1f595541dbd6e990cb1ea3d19bf01b2809f362a03dd7921fd", size = 30761, upload-time = "2025-03-05T21:17:41.549Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/14/e2a54fabd4f08cd7af1c07030603c3356b74da07f7cc056e600436edfa17/tzlocal-5.3.1-py3-none-any.whl", hash = "sha256:eb1a66c3ef5847adf7a834f1be0800581b683b5608e74f86ecbcef8ab91bb85d", size = 18026, upload-time = "2025-03-05T21:17:39.857Z" }, +] + [[package]] name = "urllib3" version = "2.6.3" @@ -1919,6 +2206,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/83/e4/d04a086285c20886c0daad0e026f250869201013d18f81d9ff5eada73a88/uvicorn-0.41.0-py3-none-any.whl", hash = "sha256:29e35b1d2c36a04b9e180d4007ede3bcb32a85fbdfd6c6aeb3f26839de088187", size = 68783, upload-time = "2026-02-16T23:07:22.357Z" }, ] +[[package]] +name = "werkzeug" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/61/f1/ee81806690a87dab5f5653c1f146c92bc066d7f4cebc603ef88eb9e13957/werkzeug-3.1.6.tar.gz", hash = "sha256:210c6bede5a420a913956b4791a7f4d6843a43b6fcee4dfa08a65e93007d0d25", size = 864736, upload-time = "2026-02-19T15:17:18.884Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/ec/d58832f89ede95652fd01f4f24236af7d32b70cab2196dfcc2d2fd13c5c2/werkzeug-3.1.6-py3-none-any.whl", hash = "sha256:7ddf3357bb9564e407607f988f683d72038551200c704012bb9a4c523d42f131", size = 225166, upload-time = "2026-02-19T15:17:17.475Z" }, +] + [[package]] name = "xarray" version = "2025.12.0" From 18025b558b9b21da200e126489f82657de54f096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 13:59:42 +0100 Subject: [PATCH 04/13] Readme refactor --- API_EXAMPLES.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 36 ++-------------------- 2 files changed, 83 insertions(+), 34 deletions(-) create mode 100644 API_EXAMPLES.md diff --git a/API_EXAMPLES.md b/API_EXAMPLES.md new file mode 100644 index 0000000..88c3503 --- /dev/null +++ b/API_EXAMPLES.md @@ -0,0 +1,81 @@ +# API Examples + +Base URL (local): + +http://127.0.0.1:8000 + +## Collections (`/collections`) + +List collections: + +http://127.0.0.1:8000/collections + +```bash +curl "http://127.0.0.1:8000/collections" +``` + +Get CHIRPS collection: + +http://127.0.0.1:8000/collections/chirps-daily + +```bash +curl "http://127.0.0.1:8000/collections/chirps-daily" +``` + +Get ERA5-Land collection: + +http://127.0.0.1:8000/collections/era5-land-daily + +Collections in this section correspond to OGC API - Common collection discovery endpoints. + +```bash +curl "http://127.0.0.1:8000/collections/era5-land-daily" +``` + +## COG (`/cog`) + +COG info: + +http://127.0.0.1:8000/cog/info?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif + +```bash +curl "http://127.0.0.1:8000/cog/info?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif" +``` + +COG preview: + +http://127.0.0.1:8000/cog/preview.png?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif&max_size=2048&colormap_name=delta + +```bash +curl -o chirps-preview.png "http://127.0.0.1:8000/cog/preview.png?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif&max_size=2048&colormap_name=delta" +``` + +Tile: + +http://127.0.0.1:8000/cog/tiles/WebMercatorQuad/4/5/5.png?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif&colormap_name=delta + +```bash +curl -o chirps-tile.png "http://127.0.0.1:8000/cog/tiles/WebMercatorQuad/4/5/5.png?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif&colormap_name=delta" +``` + +CHIRPS COG test file: + +https://data.chc.ucsb.edu/products/CHIRPS/v3.0/daily/final/rnl/2026/chirps-v3.0.rnl.2026.01.31.tif + +## STAC (`/stac`) + +STAC landing page: + +http://127.0.0.1:8000/stac + +```bash +curl "http://127.0.0.1:8000/stac" +``` + +STAC tile metadata (example): + +http://127.0.0.1:8000/stac/tilejson.json?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif + +```bash +curl "http://127.0.0.1:8000/stac/tilejson.json?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif" +``` diff --git a/README.md b/README.md index 935cf34..f8d6fe2 100644 --- a/README.md +++ b/README.md @@ -40,44 +40,12 @@ uvicorn main:app --reload - `make run` — start the app with uv - `make validate-datasets` — validate all dataset YAML files against the Pydantic schema -Root endpoint: +## API examples -http://127.0.0.1:8000/ -> Welcome to DHIS2 EO API - -Docs: - -http://127.0.0.1:8000/docs - -Collections (OGC API): - -http://127.0.0.1:8000/collections - -http://127.0.0.1:8000/collections/chirps-daily - -http://127.0.0.1:8000/collections/era5-land-daily +See [`API_EXAMPLES.md`](API_EXAMPLES.md) for docs, collections, STAC, and COG request examples. ## Dataset definitions Collection metadata for `/collections` is defined in top-level YAML files under `datasets/`. For schema details, examples, and current dataset files, see [`datasets/README.md`](datasets/README.md). - -Examples: - -COG info: - -http://127.0.0.1:8000/cog/info?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif - -COG preview: - -http://127.0.0.1:8000/cog/preview.png?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif&max_size=2048&colormap_name=delta - -Tile: - -http://127.0.0.1:8000/cog/tiles/WebMercatorQuad/4/5/5.png?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif&colormap_name=delta - ---- - -CHIRPS COG test file: - -https://data.chc.ucsb.edu/products/CHIRPS/v3.0/daily/final/rnl/2026/chirps-v3.0.rnl.2026.01.31.tif From cea0ae5e38bc82032fa742eb2d0c24d636070c7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 14:02:42 +0100 Subject: [PATCH 05/13] Remove STAC section --- API_EXAMPLES.md | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/API_EXAMPLES.md b/API_EXAMPLES.md index 88c3503..be9942f 100644 --- a/API_EXAMPLES.md +++ b/API_EXAMPLES.md @@ -61,21 +61,3 @@ curl -o chirps-tile.png "http://127.0.0.1:8000/cog/tiles/WebMercatorQuad/4/5/5.p CHIRPS COG test file: https://data.chc.ucsb.edu/products/CHIRPS/v3.0/daily/final/rnl/2026/chirps-v3.0.rnl.2026.01.31.tif - -## STAC (`/stac`) - -STAC landing page: - -http://127.0.0.1:8000/stac - -```bash -curl "http://127.0.0.1:8000/stac" -``` - -STAC tile metadata (example): - -http://127.0.0.1:8000/stac/tilejson.json?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif - -```bash -curl "http://127.0.0.1:8000/stac/tilejson.json?url=https%3A%2F%2Fdata.chc.ucsb.edu%2Fproducts%2FCHIRPS%2Fv3.0%2Fdaily%2Ffinal%2Frnl%2F2026%2Fchirps-v3.0.rnl.2026.01.31.tif" -``` From 271c960b33051e9915d05a33ba8444b89235ac90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 15:00:04 +0100 Subject: [PATCH 06/13] New /coverages endpoint --- API_EXAMPLES.md | 22 +++- Makefile | 3 + README.md | 1 + datasets/chirps-daily.yaml | 4 +- eoapi/endpoints/collections.py | 14 +-- eoapi/endpoints/constants.py | 2 + eoapi/endpoints/coverages.py | 218 +++++++++++++++++++++++++++++++++ eoapi/endpoints/errors.py | 21 ++++ main.py | 2 + tests/test_endpoint_errors.py | 21 ++++ 10 files changed, 294 insertions(+), 14 deletions(-) create mode 100644 eoapi/endpoints/constants.py create mode 100644 eoapi/endpoints/coverages.py create mode 100644 eoapi/endpoints/errors.py create mode 100644 tests/test_endpoint_errors.py diff --git a/API_EXAMPLES.md b/API_EXAMPLES.md index be9942f..4822c46 100644 --- a/API_EXAMPLES.md +++ b/API_EXAMPLES.md @@ -28,8 +28,28 @@ http://127.0.0.1:8000/collections/era5-land-daily Collections in this section correspond to OGC API - Common collection discovery endpoints. +Get CHIRPS coverage (default extent/time): + +http://127.0.0.1:8000/collections/chirps-daily/coverage + +```bash +curl "http://127.0.0.1:8000/collections/chirps-daily/coverage" +``` + +Get CHIRPS coverage for a specific datetime and bbox: + +http://127.0.0.1:8000/collections/chirps-daily/coverage?datetime=2026-01-31T00:00:00Z&bbox=30,-5,35,2 + +```bash +curl "http://127.0.0.1:8000/collections/chirps-daily/coverage?datetime=2026-01-31T00:00:00Z&bbox=30,-5,35,2" +``` + +Get ERA5-Land coverage for a range-subset parameter: + +http://127.0.0.1:8000/collections/era5-land-daily/coverage?range-subset=2m_temperature + ```bash -curl "http://127.0.0.1:8000/collections/era5-land-daily" +curl "http://127.0.0.1:8000/collections/era5-land-daily/coverage?range-subset=2m_temperature" ``` ## COG (`/cog`) diff --git a/Makefile b/Makefile index 84a83f1..d04d907 100644 --- a/Makefile +++ b/Makefile @@ -6,3 +6,6 @@ run: validate-datasets: uv run python scripts/validate_datasets.py + +test: + uv run --with pytest pytest -q diff --git a/README.md b/README.md index f8d6fe2..26932eb 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ uvicorn main:app --reload - `make sync` — install dependencies with uv - `make run` — start the app with uv - `make validate-datasets` — validate all dataset YAML files against the Pydantic schema +- `make test` — run Python tests with pytest ## API examples diff --git a/datasets/chirps-daily.yaml b/datasets/chirps-daily.yaml index 65cd9f6..97637f2 100644 --- a/datasets/chirps-daily.yaml +++ b/datasets/chirps-daily.yaml @@ -9,9 +9,9 @@ keywords: - raster spatial_bbox: - -180.0 - - -50.0 + - -60.0 - 180.0 - - 50.0 + - 60.0 temporal_interval: - 1981-01-01T00:00:00Z - null diff --git a/eoapi/endpoints/collections.py b/eoapi/endpoints/collections.py index e3da267..cc9ca5e 100644 --- a/eoapi/endpoints/collections.py +++ b/eoapi/endpoints/collections.py @@ -3,13 +3,11 @@ from pygeoapi import l10n from pygeoapi.util import url_join from eoapi.datasets import DatasetDefinition, load_datasets +from eoapi.endpoints.constants import CRS84, OGC_RELTYPES_BASE +from eoapi.endpoints.errors import not_found router = APIRouter(tags=["Collections"]) -OGC_RELTYPES_BASE = "http://www.opengis.net/def/rel/ogc/1.0" -CRS84 = "http://www.opengis.net/def/crs/OGC/1.3/CRS84" - - def _base_url(request: Request) -> str: return str(request.base_url).rstrip("/") @@ -104,11 +102,5 @@ def get_collections(request: Request) -> dict: def get_collection(collection_id: str, request: Request) -> dict: dataset = load_datasets().get(collection_id) if dataset is None: - raise HTTPException( - status_code=404, - detail={ - "code": "NotFound", - "description": f"Collection '{collection_id}' not found", - }, - ) + raise not_found("Collection", collection_id) return _build_collection(request, dataset) diff --git a/eoapi/endpoints/constants.py b/eoapi/endpoints/constants.py new file mode 100644 index 0000000..6f2a65d --- /dev/null +++ b/eoapi/endpoints/constants.py @@ -0,0 +1,2 @@ +OGC_RELTYPES_BASE = "http://www.opengis.net/def/rel/ogc/1.0" +CRS84 = "http://www.opengis.net/def/crs/OGC/1.3/CRS84" diff --git a/eoapi/endpoints/coverages.py b/eoapi/endpoints/coverages.py new file mode 100644 index 0000000..b225049 --- /dev/null +++ b/eoapi/endpoints/coverages.py @@ -0,0 +1,218 @@ +from datetime import date + +from fastapi import APIRouter, HTTPException, Query, Request + +from dhis2eo.data.cds.era5_land import hourly as era5_land_hourly +from dhis2eo.data.cds.era5_land import monthly as era5_land_monthly +from dhis2eo.data.chc.chirps3 import daily as chirps3_daily +from pygeoapi.api import FORMAT_TYPES, F_JSON +from pygeoapi.util import url_join + +from eoapi.datasets import load_datasets +from eoapi.endpoints.constants import CRS84 +from eoapi.endpoints.errors import invalid_parameter, not_found + +router = APIRouter(tags=["Coverages"]) + +COVERAGE_PARAMETERS: dict[str, dict[str, dict]] = { + "chirps-daily": { + "precip": { + "type": "Parameter", + "description": {"en": "Daily precipitation"}, + "unit": {"label": {"en": "mm/day"}}, + "observedProperty": {"label": {"en": "Precipitation"}}, + } + }, + "era5-land-daily": { + "2m_temperature": { + "type": "Parameter", + "description": {"en": "2m air temperature"}, + "unit": {"label": {"en": "K"}}, + "observedProperty": {"label": {"en": "2m temperature"}}, + }, + "total_precipitation": { + "type": "Parameter", + "description": {"en": "Total precipitation"}, + "unit": {"label": {"en": "m"}}, + "observedProperty": {"label": {"en": "Total precipitation"}}, + }, + }, +} + + +def _base_url(request: Request) -> str: + return str(request.base_url).rstrip("/") + + +def _parse_bbox( + bbox: str | None, + fallback_bbox: tuple[float, float, float, float], +) -> tuple[float, float, float, float]: + if bbox is None: + return fallback_bbox + + try: + values = tuple(float(part.strip()) for part in bbox.split(",")) + except ValueError as exc: + raise invalid_parameter("bbox must contain 4 comma-separated numbers") from exc + + if len(values) != 4: + raise invalid_parameter("bbox must contain 4 comma-separated numbers") + + return values + + +def _parse_datetime(datetime_value: str | None, fallback_start: str) -> str: + if not datetime_value: + return fallback_start + + if "/" in datetime_value: + start, _, _ = datetime_value.partition("/") + if start in {"", ".."}: + return fallback_start + return start + + return datetime_value + + +def _select_parameters(collection_id: str, range_subset: str | None) -> dict[str, dict]: + available = COVERAGE_PARAMETERS.get(collection_id, {}) + if not range_subset: + return available + + requested = [parameter.strip() for parameter in range_subset.split(",") if parameter.strip()] + unknown = [parameter for parameter in requested if parameter not in available] + if unknown: + raise invalid_parameter(f"Unknown range-subset parameter(s): {', '.join(unknown)}") + + return {parameter: available[parameter] for parameter in requested} + + +def _resolve_dhis2eo_source( + collection_id: str, + datetime_value: str, + bbox: tuple[float, float, float, float], +) -> dict: + if collection_id == "chirps-daily": + try: + sample_day = date.fromisoformat(datetime_value[:10]) + except ValueError as exc: + raise invalid_parameter("datetime must be an ISO 8601 date or datetime") from exc + + return { + "backend": "dhis2eo.data.chc.chirps3.daily", + "resolver": "url_for_day", + "source_url": chirps3_daily.url_for_day(sample_day), + "bbox": list(bbox), + } + + if collection_id == "era5-land-daily": + return { + "backend": "dhis2eo.data.cds.era5_land", + "resolver": [ + era5_land_hourly.download.__name__, + era5_land_monthly.download.__name__, + ], + "variables": list(COVERAGE_PARAMETERS[collection_id].keys()), + "bbox": list(bbox), + "note": "ERA5-Land source data is resolved via CDS download workflows in dhis2eo.", + } + + return { + "backend": "dhis2eo", + "bbox": list(bbox), + } + + +def _coverage_links(request: Request, collection_id: str) -> list[dict]: + base = _base_url(request) + collection_url = url_join(base, "collections", collection_id) + coverage_url = url_join(collection_url, "coverage") + return [ + { + "rel": "self", + "type": FORMAT_TYPES[F_JSON], + "title": "Coverage as CoverageJSON", + "href": coverage_url, + }, + { + "rel": "collection", + "type": FORMAT_TYPES[F_JSON], + "title": "Collection metadata", + "href": collection_url, + }, + { + "rel": "root", + "type": FORMAT_TYPES[F_JSON], + "title": "API root", + "href": url_join(base, "/"), + }, + ] + + +@router.get("/collections/{collection_id}/coverage") +def get_collection_coverage( + collection_id: str, + request: Request, + bbox: str | None = None, + datetime_value: str | None = Query(default=None, alias="datetime"), + range_subset: str | None = Query(default=None, alias="range-subset"), + output_format: str = Query(default=F_JSON, alias="f"), +) -> dict: + if output_format not in {F_JSON, "covjson"}: + raise invalid_parameter("Only f=json and f=covjson are currently supported") + + dataset = load_datasets().get(collection_id) + if dataset is None: + raise not_found("Collection", collection_id) + + bbox_values = _parse_bbox(bbox, dataset.spatial_bbox) + time_value = _parse_datetime(datetime_value, dataset.temporal_interval[0]) + parameters = _select_parameters(collection_id, range_subset) + source = _resolve_dhis2eo_source(collection_id, time_value, bbox_values) + + ranges = { + parameter_name: { + "type": "NdArray", + "dataType": "float", + "axisNames": ["t", "y", "x"], + "shape": [1, 1, 1], + "values": [None], + } + for parameter_name in parameters + } + + return { + "type": "Coverage", + "title": dataset.title, + "description": dataset.description, + "domain": { + "type": "Domain", + "domainType": "Grid", + "axes": { + "x": {"start": bbox_values[0], "stop": bbox_values[2], "num": 2}, + "y": {"start": bbox_values[1], "stop": bbox_values[3], "num": 2}, + "t": {"values": [time_value]}, + }, + "referencing": [ + { + "coordinates": ["x", "y"], + "system": { + "type": "GeographicCRS", + "id": CRS84, + }, + }, + { + "coordinates": ["t"], + "system": { + "type": "TemporalRS", + "calendar": "Gregorian", + }, + }, + ], + }, + "parameters": parameters, + "ranges": ranges, + "links": _coverage_links(request, collection_id), + "source": source, + } diff --git a/eoapi/endpoints/errors.py b/eoapi/endpoints/errors.py new file mode 100644 index 0000000..2eec2b4 --- /dev/null +++ b/eoapi/endpoints/errors.py @@ -0,0 +1,21 @@ +from fastapi import HTTPException + + +def not_found(resource: str, identifier: str) -> HTTPException: + return HTTPException( + status_code=404, + detail={ + "code": "NotFound", + "description": f"{resource} '{identifier}' not found", + }, + ) + + +def invalid_parameter(description: str) -> HTTPException: + return HTTPException( + status_code=400, + detail={ + "code": "InvalidParameterValue", + "description": description, + }, + ) diff --git a/main.py b/main.py index 2305a11..d08aeaa 100644 --- a/main.py +++ b/main.py @@ -2,6 +2,7 @@ from titiler.core.factory import (TilerFactory, MultiBaseTilerFactory) from rio_tiler.io import STACReader from eoapi.endpoints.collections import router as collections_router +from eoapi.endpoints.coverages import router as coverages_router from starlette.middleware.cors import CORSMiddleware @@ -24,6 +25,7 @@ cog = TilerFactory() app.include_router(collections_router) +app.include_router(coverages_router) # Register all the COG endpoints automatically app.include_router(cog.router, prefix="/cog", tags=["Cloud Optimized GeoTIFF"]) diff --git a/tests/test_endpoint_errors.py b/tests/test_endpoint_errors.py new file mode 100644 index 0000000..c3d8e3f --- /dev/null +++ b/tests/test_endpoint_errors.py @@ -0,0 +1,21 @@ +from eoapi.endpoints.errors import invalid_parameter, not_found + + +def test_not_found_error_payload() -> None: + error = not_found("Collection", "missing-id") + + assert error.status_code == 404 + assert error.detail == { + "code": "NotFound", + "description": "Collection 'missing-id' not found", + } + + +def test_invalid_parameter_error_payload() -> None: + error = invalid_parameter("bbox must contain 4 comma-separated numbers") + + assert error.status_code == 400 + assert error.detail == { + "code": "InvalidParameterValue", + "description": "bbox must contain 4 comma-separated numbers", + } From 589a333833c2c769a9a03f0e2e8ddf932df8f3f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 15:24:43 +0100 Subject: [PATCH 07/13] Agent context update --- .github/copilot-instructions.md | 21 ++++++++ .../skills/eo-pipeline-orchestration/SKILL.md | 8 ++- .github/skills/eo-process-api-design/SKILL.md | 26 ++++++++-- .github/skills/prd-authoring/SKILL.md | 5 ++ PRD.md | 52 +++++++++++++++++++ 5 files changed, 107 insertions(+), 5 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index a296be0..c4c5a29 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -8,6 +8,23 @@ - DHIS2 Maps app and DHIS2 Climate app are primary consumers of `eo-api`. - `eo-api` should replace functionality currently sourced via Google Earth Engine for these apps. +## Current implemented baseline (keep in sync) + +- Dataset discovery is implemented via: + - `GET /collections` + - `GET /collections/{collection_id}` +- OGC API - Coverages baseline is implemented via: + - `GET /collections/{collection_id}/coverage` +- Collections and coverages are split into separate endpoint modules: + - `eoapi/endpoints/collections.py` + - `eoapi/endpoints/coverages.py` +- Shared endpoint constants/errors live in: + - `eoapi/endpoints/constants.py` + - `eoapi/endpoints/errors.py` +- Dataset metadata is file-driven from top-level `datasets/*.yaml` and validated by Pydantic (`eoapi/datasets.py`). +- Dataset validation command is available via `make validate-datasets`. +- Tests currently include endpoint error contract tests and run via `make test`. + ## Product priorities - Favor end-to-end data flow correctness over feature breadth. @@ -41,6 +58,8 @@ - For async/long-running operations, expose job status instead of blocking calls. - Include stable identifiers for datasets, processes, and executions. - Treat Maps app and Climate app contracts as first-class compatibility targets. +- For collections/coverages, prefer OGC API - Common and OGC API - Coverages compatible response structures and link relations. +- Keep collections and coverages handlers decoupled, with shared helpers/constants in dedicated modules. ## Geospatial/data handling guidance @@ -86,3 +105,5 @@ - Update docs when adding endpoints, process parameters, or output schema changes. - Include example requests/responses for new process execution paths. +- Keep `README.md` concise and place endpoint examples in `API_EXAMPLES.md`. +- Keep dataset schema documentation in `datasets/README.md`. diff --git a/.github/skills/eo-pipeline-orchestration/SKILL.md b/.github/skills/eo-pipeline-orchestration/SKILL.md index 6fd10da..8483108 100644 --- a/.github/skills/eo-pipeline-orchestration/SKILL.md +++ b/.github/skills/eo-pipeline-orchestration/SKILL.md @@ -6,12 +6,14 @@ description: Define scheduled and custom EO data pipelines with optional pre/pos # EO Pipeline Orchestration ## Use this skill when + - Creating recurring ingestion workflows - Adding custom pre/post-processing pipeline steps - Designing orchestration handoffs (Airflow/Prefect) ## Canonical pipeline stages -1. Discover dataset and validate metadata + +1. Discover dataset and validate metadata (from `datasets/*.yaml` definitions) 2. Extract data for time/area window 3. Cache source/intermediate artifacts as files when needed 4. Transform and harmonize units/CRS @@ -21,6 +23,7 @@ description: Define scheduled and custom EO data pipelines with optional pre/pos 8. Trigger import or publish for downstream ingestion ## Orchestration guidance + - Treat each stage as an idempotent task where possible - Persist execution metadata and lineage - Use retries/backoff for transient provider failures @@ -32,10 +35,13 @@ description: Define scheduled and custom EO data pipelines with optional pre/pos - Promote reusable orchestration helpers to upstream libraries when they are broadly applicable beyond `eo-api` ## Data integrity checks + - Nodata handling rules are explicit - CRS mismatches are detected and resolved deterministically - Aggregation method and temporal windows are logged +- Dataset definition schema is validated before runs (e.g. `make validate-datasets`) ## MVP constraints + - Prefer simple, inspectable DAGs over highly dynamic graphs - Prioritize reliable daily scheduled runs for climate and population flows diff --git a/.github/skills/eo-process-api-design/SKILL.md b/.github/skills/eo-process-api-design/SKILL.md index 1580080..d79e11b 100644 --- a/.github/skills/eo-process-api-design/SKILL.md +++ b/.github/skills/eo-process-api-design/SKILL.md @@ -6,16 +6,32 @@ description: Design OGC API - Processes style EO execution endpoints and request # EO Process API Design ## Use this skill when + - Adding or modifying process execution endpoints - Designing dataset/process discovery and execution contracts - Defining long-running execution behavior and status tracking -## Required endpoint baseline -- `GET /processes` -- `GET /processes/{process-id}` -- `POST /processes/{process-id}/execution` +## Current API baseline in this repo + +- Dataset discovery: + - `GET /collections` + - `GET /collections/{collection_id}` +- Coverage retrieval: + - `GET /collections/{collection_id}/coverage` +- Process execution endpoints (target baseline): + - `GET /processes` + - `GET /processes/{process-id}` + - `POST /processes/{process-id}/execution` + +## OGC endpoint guidance + +- For collections, follow OGC API - Common response structures (`extent`, `links`, stable IDs). +- For coverage responses, follow OGC API - Coverages/CoverageJSON-compatible structures (`domain`, `parameters`, `ranges`). +- Validate query parameters and return structured `InvalidParameterValue` errors. +- Return `NotFound` for unknown collections/processes. ## Design rules + - Keep resource names consistent and stable - Use explicit IDs for process, execution, dataset - Return structured validation errors with actionable messages @@ -23,6 +39,7 @@ description: Design OGC API - Processes style EO execution endpoints and request - Keep response schemas backward compatible ## EO/DHIS2 checks + - Document CRS assumptions and aggregation method semantics - Include preview/dry-run support where feasible - Use `dhis2-python-client` for DHIS2 Web API operations @@ -33,6 +50,7 @@ description: Design OGC API - Processes style EO execution endpoints and request - Prioritize process capabilities that replace current Google Earth Engine-backed functionality ## Output checklist + - Endpoint contract - Example request/response - Error model diff --git a/.github/skills/prd-authoring/SKILL.md b/.github/skills/prd-authoring/SKILL.md index 5ec2131..747552a 100644 --- a/.github/skills/prd-authoring/SKILL.md +++ b/.github/skills/prd-authoring/SKILL.md @@ -35,6 +35,11 @@ description: Draft or refine PRDs for DHIS2 EO API features with clear MVP scope - Includes compatibility and migration implications for `maps-app` and `climate-app` - Explicitly identifies which Google Earth Engine-dependent behavior is replaced by `eo-api` - Calls out standards alignment (OGC/STAC) when applicable +- Reflects current implemented baseline where relevant: + - `/collections`, `/collections/{collection_id}` + - `/collections/{collection_id}/coverage` + - File-driven dataset metadata in `datasets/*.yaml` validated by Pydantic + - Validation/test workflow via `make validate-datasets` and `make test` ## Quality bar diff --git a/PRD.md b/PRD.md index 43292fe..48af8a8 100644 --- a/PRD.md +++ b/PRD.md @@ -1,6 +1,7 @@ # DHIS2 EO API — Product Requirements Document (PRD) ## 1) Overview + DHIS2 EO API is a no-code geospatial data integration platform that enables users to discover, fetch, process, harmonize, and load earth observation and related datasets into DHIS2 and the CHAP Modelling Platform. DHIS2 Maps app and DHIS2 Climate app are core downstream consumers of this API, with `eo-api` replacing functionality currently sourced from Google Earth Engine. @@ -8,7 +9,9 @@ DHIS2 Maps app and DHIS2 Climate app are core downstream consumers of this API, This PRD defines the MVP scope for the hackathon and a near-term path toward a production-ready platform. ## 2) Problem Statement + Current EO data workflows are fragmented across tools and scripts, making them hard to repeat, schedule, and maintain. Teams need a unified API that supports: + - Dataset discovery - On-demand processing - Aggregation to DHIS2 org units @@ -16,6 +19,7 @@ Current EO data workflows are fragmented across tools and scripts, making them h - Optional custom pre/post-processing ## 3) Goals + - Provide a unified API for EO data retrieval and processing. - Enable no-code workflows comparable to DHIS2 Climate Tools, using existing DHIS2 EO libraries. - Support map-serving and analytics use cases without Google Earth Engine lock-in. @@ -23,18 +27,22 @@ Current EO data workflows are fragmented across tools and scripts, making them h - Deliver an MVP that proves core end-to-end flows during the hackathon. ## 4) Non-Goals (MVP) + - Full enterprise IAM/SSO implementation. - Comprehensive billing/tenancy model. - Complete OGC suite compliance beyond selected process endpoints. - Replacing all existing tooling in one release. ## 5) Users and Key User Stories + ### Primary users + - DHIS2 implementers and analysts - Climate/health data teams - GIS/data engineering teams ### User stories + - User A: Import daily temperature and precipitation into DHIS2 on a user-defined schedule, aggregated to org units. - User B: Import annual population data, automatically aggregated to org units. - User C: Visualize high-resolution population data in DHIS2 Maps with meaningful density-based styles. @@ -42,11 +50,14 @@ Current EO data workflows are fragmented across tools and scripts, making them h - User E: Add custom pre/post-processing (e.g., consecutive rainy days) before import. ## 6) Functional Requirements + ### FR1 — Unified data/process API + - Expose a single API surface for dataset listing, request submission, processing, and retrieval. - Use `dhis2eo` as the default EO/climate processing integration library. ### FR2 — Core process execution + - Support process discovery and execution using an OGC API - Processes-aligned model. - Minimum endpoints: - `GET /processes` @@ -54,6 +65,7 @@ Current EO data workflows are fragmented across tools and scripts, making them h - `POST /processes/{process-id}/execution` ### FR3 — Raster and tiling capabilities + - Support on-the-fly image tiling and styling from raster sources (COGs/Zarr where feasible). - Enable: - Value retrieval at a location @@ -61,30 +73,52 @@ Current EO data workflows are fragmented across tools and scripts, making them h - Ensure parity for the core map/preview capabilities currently implemented with Google Earth Engine for DHIS2 Maps and Climate clients. ### FR4 — Dataset discovery endpoint + - Provide endpoint(s) to list available datasets for DHIS2 Maps and related clients. - Prefer STAC-compatible metadata where possible. +### FR10 — OGC Collections and Coverages baseline + +- Implement OGC API - Common collection discovery endpoints: + - `GET /collections` + - `GET /collections/{collection_id}` +- Implement OGC API - Coverages baseline endpoint: + - `GET /collections/{collection_id}/coverage` +- Support key coverage query parameters (`bbox`, `datetime`, `range-subset`, `f`) with structured validation errors. + +### FR11 — File-driven dataset catalog + +- Store dataset definitions as one YAML file per dataset in top-level `datasets/`. +- Validate dataset definitions via Pydantic before use. +- Keep dataset schema and examples documented in `datasets/README.md`. + ### FR8 — Consumer app compatibility + - API contracts and outputs must support DHIS2 Maps app (https://github.com/dhis2/maps-app) and DHIS2 Climate app (https://github.com/dhis2/climate-app). - Changes to EO API contracts should be assessed for impact on both apps before release. ### FR5 — Scheduling and orchestration + - Allow fixed-interval runs for recurring ingestion. - Support simple pipeline orchestration with optional pre/post-processing step hooks. ### FR6 — DHIS2 integration + - Push processed/aggregated outputs to DHIS2 database through the DHIS2 Web API. - Use `dhis2-python-client` as the default DHIS2 Web API integration library. ### FR9 — Caching and configuration storage + - Support file-based caching of downloaded and/or intermediate processed data when needed for performance, resiliency, or replay. - Support use of DHIS2 Data Store for storing EO API configuration metadata where appropriate. ### FR7 — Upstream library evolution + - Treat `dhis2-python-client` and `dhis2eo` as strategic dependencies that can be changed to fulfill `eo-api` requirements. - When required functionality is missing, define and implement upstream changes rather than introducing long-term local forks in `eo-api`. ## 7) Non-Functional Requirements + - Reliability: Handle simultaneous and long-running requests. - Extensibility: Process catalog must support adding new EO pipelines with minimal API changes. - Interoperability: Align with open geospatial standards where practical (OGC API, STAC). @@ -93,6 +127,7 @@ Current EO data workflows are fragmented across tools and scripts, making them h - Dependency sustainability: Upstream contributions to `dhis2-python-client` and `dhis2eo` should preserve backward compatibility where feasible. ## 8) Proposed Technical Direction + - API framework: FastAPI - Process API: pygeoapi (OGC API - Processes) - Raster/tile API: TiTiler (`/cog/*`, `/stac/*`) @@ -105,25 +140,34 @@ Current EO data workflows are fragmented across tools and scripts, making them h - Deployment: Docker-based services ## 9) MVP Scope (Hackathon) + ### In scope + - Draft unified API interface +- OGC collection discovery (`/collections`, `/collections/{collection_id}`) +- OGC coverage baseline (`/collections/{collection_id}/coverage`) for gridded datasets (CHIRPS, ERA5-Land) +- File-driven dataset definitions (`datasets/*.yaml`) with schema validation - Process catalog + at least one executable process flow - Climate variable import path (temperature/precipitation) aggregated to org units - Preview of data for org unit - Basic scheduled run capability (or simulated scheduler integration) ### Out of scope + - Full production-grade authz/authn stack - Broad catalog of EO sources - Advanced UI beyond thin client integration points ## 10) Success Metrics + - Time-to-first-ingestion: User can configure and run first import quickly. - Pipeline success rate for scheduled runs. - Latency for preview and aggregation requests within acceptable operational bounds. - Number of reusable process definitions in the process catalog. +- Dataset onboarding time: time to add a new dataset definition YAML and expose it via `/collections`. ## 11) Google Earth Engine Parity Checklist + - [ ] On-the-fly raster tiling available via EO API endpoints for Maps/Climate use cases. - [ ] Styling controls exposed for map visualization workflows used by DHIS2 Maps app. - [ ] Value retrieval at a single location (point query) supported for climate/map inspection. @@ -136,27 +180,35 @@ Current EO data workflows are fragmented across tools and scripts, making them h - [ ] Core Climate app workflows run without Google Earth Engine dependency. ### Parity verification criteria + - Functional parity: Equivalent user-visible outcome for each checklist item in Maps and Climate integrations. - Data parity: Results are within agreed tolerance for value/aggregation comparisons. - Operational parity: Throughput and latency are acceptable for expected production usage. ## 12) Risks and Open Questions + - Should TiTiler and EO API run in same container or separate services? - Should openEO be explored as a strategic integration path? - What level of OGC API - Processes compliance is required for MVP vs production? ## 13) Upstream Contribution Strategy + - Preferred path: implement missing cross-project capabilities in `dhis2-python-client` and/or `dhis2eo`, then consume released versions in `eo-api`. - Avoid permanent private forks; use short-lived patches only when release timing requires temporary workarounds. - Track upstream gaps as explicit requirements with owner, milestone, and compatibility impact. ## 14) Milestones + 1. Domain and technology landscape assessment 2. Unified API draft finalized 3. MVP process flow implemented 4. End-to-end demo: dataset → process → aggregated output → DHIS2 import path ## 15) Acceptance Criteria (MVP) + +- `/collections` and `/collections/{collection_id}` return OGC-compatible collection metadata for configured datasets. +- `/collections/{collection_id}/coverage` returns OGC Coverages-compatible response structures for supported datasets. +- Dataset definitions are managed as YAML files and validated successfully before runtime use. - A user can discover available process(es) and execute one through API. - A climate dataset can be previewed and aggregated to org units. - A recurring run can be configured and triggered on schedule. From 376e3fa71bc483b40c22b6d53ce70e0f828296b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 19:57:10 +0100 Subject: [PATCH 08/13] Add OGC API EDR endpoints --- API_EXAMPLES.md | 50 +++++ datasets/README.md | 32 ++- datasets/chirps-daily.yaml | 11 + datasets/era5-land-daily.yaml | 21 ++ eoapi/datasets.py | 1 + eoapi/endpoints/collections.py | 26 ++- eoapi/endpoints/conformance.py | 39 ++++ eoapi/endpoints/coverages.py | 61 ++---- eoapi/endpoints/edr.py | 315 +++++++++++++++++++++++++++++ eoapi/endpoints/root.py | 41 ++++ main.py | 28 +-- tests/test_conformance_endpoint.py | 23 +++ tests/test_edr_endpoint.py | 87 ++++++++ tests/test_landing_page.py | 21 ++ 14 files changed, 689 insertions(+), 67 deletions(-) create mode 100644 eoapi/endpoints/conformance.py create mode 100644 eoapi/endpoints/edr.py create mode 100644 eoapi/endpoints/root.py create mode 100644 tests/test_conformance_endpoint.py create mode 100644 tests/test_edr_endpoint.py create mode 100644 tests/test_landing_page.py diff --git a/API_EXAMPLES.md b/API_EXAMPLES.md index 4822c46..2490647 100644 --- a/API_EXAMPLES.md +++ b/API_EXAMPLES.md @@ -4,8 +4,26 @@ Base URL (local): http://127.0.0.1:8000 +OGC landing page: + +http://127.0.0.1:8000/ + +```bash +curl "http://127.0.0.1:8000/" +``` + ## Collections (`/collections`) +Conformance declaration: + +http://127.0.0.1:8000/conformance + +```bash +curl "http://127.0.0.1:8000/conformance" +``` + +Note: values used in `range-subset` and `parameter-name` must match keys in `datasets/.yaml` under `parameters`. + List collections: http://127.0.0.1:8000/collections @@ -52,6 +70,38 @@ http://127.0.0.1:8000/collections/era5-land-daily/coverage?range-subset=2m_tempe curl "http://127.0.0.1:8000/collections/era5-land-daily/coverage?range-subset=2m_temperature" ``` +Get CHIRPS EDR position query: + +http://127.0.0.1:8000/collections/chirps-daily/position?coords=POINT(30%20-1)&datetime=2026-01-31T00:00:00Z¶meter-name=precip + +```bash +curl "http://127.0.0.1:8000/collections/chirps-daily/position?coords=POINT(30%20-1)&datetime=2026-01-31T00:00:00Z¶meter-name=precip" +``` + +Get ERA5-Land EDR position query: + +http://127.0.0.1:8000/collections/era5-land-daily/position?coords=POINT(36.8%20-1.3)¶meter-name=2m_temperature + +```bash +curl "http://127.0.0.1:8000/collections/era5-land-daily/position?coords=POINT(36.8%20-1.3)¶meter-name=2m_temperature" +``` + +Get CHIRPS EDR area query: + +http://127.0.0.1:8000/collections/chirps-daily/area?bbox=30,-5,35,2&datetime=2026-01-31T00:00:00Z¶meter-name=precip + +```bash +curl "http://127.0.0.1:8000/collections/chirps-daily/area?bbox=30,-5,35,2&datetime=2026-01-31T00:00:00Z¶meter-name=precip" +``` + +Get ERA5-Land EDR area query: + +http://127.0.0.1:8000/collections/era5-land-daily/area?bbox=36,-2,38,0¶meter-name=2m_temperature + +```bash +curl "http://127.0.0.1:8000/collections/era5-land-daily/area?bbox=36,-2,38,0¶meter-name=2m_temperature" +``` + ## COG (`/cog`) COG info: diff --git a/datasets/README.md b/datasets/README.md index 8096de1..8405960 100644 --- a/datasets/README.md +++ b/datasets/README.md @@ -2,7 +2,7 @@ This folder contains dataset definitions used by the `/collections` endpoints. -Definitions are loaded from `*.yaml` files and validated by the `DatasetDefinition` Pydantic model in `eoapi/endpoints/collections.py`. +Definitions are loaded from `*.yaml` files and validated by the `DatasetDefinition` Pydantic model in `eoapi/datasets.py`. ## Required schema @@ -15,6 +15,25 @@ Definitions are loaded from `*.yaml` files and validated by the `DatasetDefiniti ## Optional schema - `keywords` (array of strings): tags used for discovery +- `parameters` (object): shared parameter definitions used by both Coverages and EDR endpoints + +### `parameters` object shape + +Each key is a parameter ID (for example `precip` or `2m_temperature`) and value is a CoverageJSON/EDR-compatible parameter object, for example: + +```yaml +parameters: + precip: + type: Parameter + description: + en: Daily precipitation + unit: + label: + en: mm/day + observedProperty: + label: + en: Precipitation +``` ## Example @@ -34,6 +53,17 @@ spatial_bbox: temporal_interval: - 2000-01-01T00:00:00Z - null +parameters: + precip: + type: Parameter + description: + en: Daily precipitation + unit: + label: + en: mm/day + observedProperty: + label: + en: Precipitation ``` ## Current definitions diff --git a/datasets/chirps-daily.yaml b/datasets/chirps-daily.yaml index 97637f2..7a2ff24 100644 --- a/datasets/chirps-daily.yaml +++ b/datasets/chirps-daily.yaml @@ -15,3 +15,14 @@ spatial_bbox: temporal_interval: - 1981-01-01T00:00:00Z - null +parameters: + precip: + type: Parameter + description: + en: Daily precipitation + unit: + label: + en: mm/day + observedProperty: + label: + en: Precipitation diff --git a/datasets/era5-land-daily.yaml b/datasets/era5-land-daily.yaml index 5617269..d0f5b46 100644 --- a/datasets/era5-land-daily.yaml +++ b/datasets/era5-land-daily.yaml @@ -15,3 +15,24 @@ spatial_bbox: temporal_interval: - 1950-01-01T00:00:00Z - null +parameters: + 2m_temperature: + type: Parameter + description: + en: 2m air temperature + unit: + label: + en: K + observedProperty: + label: + en: 2m temperature + total_precipitation: + type: Parameter + description: + en: Total precipitation + unit: + label: + en: m + observedProperty: + label: + en: Total precipitation diff --git a/eoapi/datasets.py b/eoapi/datasets.py index 99ac55e..7ff0340 100644 --- a/eoapi/datasets.py +++ b/eoapi/datasets.py @@ -15,6 +15,7 @@ class DatasetDefinition(BaseModel): keywords: list[str] = Field(default_factory=list) spatial_bbox: tuple[float, float, float, float] temporal_interval: tuple[str, str | None] + parameters: dict[str, dict] = Field(default_factory=dict) @field_validator("temporal_interval", mode="before") @classmethod diff --git a/eoapi/endpoints/collections.py b/eoapi/endpoints/collections.py index cc9ca5e..a5a8dd9 100644 --- a/eoapi/endpoints/collections.py +++ b/eoapi/endpoints/collections.py @@ -5,6 +5,8 @@ from eoapi.datasets import DatasetDefinition, load_datasets from eoapi.endpoints.constants import CRS84, OGC_RELTYPES_BASE from eoapi.endpoints.errors import not_found +from eoapi.endpoints.coverages import router as coverages_router +from eoapi.endpoints.edr import router as edr_router router = APIRouter(tags=["Collections"]) @@ -47,6 +49,18 @@ def _collection_links(request: Request, collection_id: str) -> list[dict]: "title": "Collection coverage", "href": url_join(collection_url, "coverage"), }, + { + "rel": f"{OGC_RELTYPES_BASE}/data", + "type": "application/json", + "title": "Collection EDR position query", + "href": url_join(collection_url, "position"), + }, + { + "rel": f"{OGC_RELTYPES_BASE}/data", + "type": "application/json", + "title": "Collection EDR area query", + "href": url_join(collection_url, "area"), + }, ] @@ -98,9 +112,13 @@ def get_collections(request: Request) -> dict: } -@router.get("/collections/{collection_id}") -def get_collection(collection_id: str, request: Request) -> dict: - dataset = load_datasets().get(collection_id) +@router.get("/collections/{collectionId}") +def get_collection(collectionId: str, request: Request) -> dict: + dataset = load_datasets().get(collectionId) if dataset is None: - raise not_found("Collection", collection_id) + raise not_found("Collection", collectionId) return _build_collection(request, dataset) + + +router.include_router(coverages_router, tags=["Collections"]) +router.include_router(edr_router, tags=["Collections"]) diff --git a/eoapi/endpoints/conformance.py b/eoapi/endpoints/conformance.py new file mode 100644 index 0000000..9983823 --- /dev/null +++ b/eoapi/endpoints/conformance.py @@ -0,0 +1,39 @@ +from fastapi import APIRouter, Request + +from pygeoapi.util import url_join + +router = APIRouter(tags=["Conformance"]) + +CONFORMANCE_CLASSES = [ + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/core", + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/landing-page", + "http://www.opengis.net/spec/ogcapi-common-1/1.0/conf/json", + "http://www.opengis.net/spec/ogcapi-common-2/1.0/conf/collections", + "http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/core", + "http://www.opengis.net/spec/ogcapi-coverages-1/1.0/conf/coveragejson", + "http://www.opengis.net/spec/ogcapi-edr-1/1.1/conf/core", + "http://www.opengis.net/spec/ogcapi-edr-1/1.1/conf/position", + "http://www.opengis.net/spec/ogcapi-edr-1/1.1/conf/area", +] + + +@router.get("/conformance") +def get_conformance(request: Request) -> dict: + base = str(request.base_url).rstrip("/") + return { + "conformsTo": CONFORMANCE_CLASSES, + "links": [ + { + "rel": "self", + "type": "application/json", + "title": "Conformance declaration", + "href": url_join(base, "conformance"), + }, + { + "rel": "root", + "type": "application/json", + "title": "API root", + "href": url_join(base, "/"), + }, + ], + } diff --git a/eoapi/endpoints/coverages.py b/eoapi/endpoints/coverages.py index b225049..9285fad 100644 --- a/eoapi/endpoints/coverages.py +++ b/eoapi/endpoints/coverages.py @@ -1,6 +1,6 @@ from datetime import date -from fastapi import APIRouter, HTTPException, Query, Request +from fastapi import APIRouter, Query, Request from dhis2eo.data.cds.era5_land import hourly as era5_land_hourly from dhis2eo.data.cds.era5_land import monthly as era5_land_monthly @@ -8,36 +8,11 @@ from pygeoapi.api import FORMAT_TYPES, F_JSON from pygeoapi.util import url_join -from eoapi.datasets import load_datasets +from eoapi.datasets import DatasetDefinition, load_datasets from eoapi.endpoints.constants import CRS84 from eoapi.endpoints.errors import invalid_parameter, not_found -router = APIRouter(tags=["Coverages"]) - -COVERAGE_PARAMETERS: dict[str, dict[str, dict]] = { - "chirps-daily": { - "precip": { - "type": "Parameter", - "description": {"en": "Daily precipitation"}, - "unit": {"label": {"en": "mm/day"}}, - "observedProperty": {"label": {"en": "Precipitation"}}, - } - }, - "era5-land-daily": { - "2m_temperature": { - "type": "Parameter", - "description": {"en": "2m air temperature"}, - "unit": {"label": {"en": "K"}}, - "observedProperty": {"label": {"en": "2m temperature"}}, - }, - "total_precipitation": { - "type": "Parameter", - "description": {"en": "Total precipitation"}, - "unit": {"label": {"en": "m"}}, - "observedProperty": {"label": {"en": "Total precipitation"}}, - }, - }, -} +router = APIRouter() def _base_url(request: Request) -> str: @@ -75,8 +50,11 @@ def _parse_datetime(datetime_value: str | None, fallback_start: str) -> str: return datetime_value -def _select_parameters(collection_id: str, range_subset: str | None) -> dict[str, dict]: - available = COVERAGE_PARAMETERS.get(collection_id, {}) +def _select_parameters(dataset: DatasetDefinition, range_subset: str | None) -> dict[str, dict]: + available = dataset.parameters + if not available: + raise invalid_parameter(f"No parameters configured for collection '{dataset.id}'") + if not range_subset: return available @@ -90,6 +68,7 @@ def _select_parameters(collection_id: str, range_subset: str | None) -> dict[str def _resolve_dhis2eo_source( collection_id: str, + parameters: dict[str, dict], datetime_value: str, bbox: tuple[float, float, float, float], ) -> dict: @@ -113,7 +92,7 @@ def _resolve_dhis2eo_source( era5_land_hourly.download.__name__, era5_land_monthly.download.__name__, ], - "variables": list(COVERAGE_PARAMETERS[collection_id].keys()), + "variables": list(parameters.keys()), "bbox": list(bbox), "note": "ERA5-Land source data is resolved via CDS download workflows in dhis2eo.", } @@ -150,26 +129,30 @@ def _coverage_links(request: Request, collection_id: str) -> list[dict]: ] -@router.get("/collections/{collection_id}/coverage") +@router.get("/collections/{collectionId}/coverage") def get_collection_coverage( - collection_id: str, + collectionId: str, request: Request, bbox: str | None = None, datetime_value: str | None = Query(default=None, alias="datetime"), - range_subset: str | None = Query(default=None, alias="range-subset"), + range_subset: str | None = Query( + default=None, + alias="range-subset", + description="Comma-separated parameter IDs. Must match keys under datasets/.yaml -> parameters", + ), output_format: str = Query(default=F_JSON, alias="f"), ) -> dict: if output_format not in {F_JSON, "covjson"}: raise invalid_parameter("Only f=json and f=covjson are currently supported") - dataset = load_datasets().get(collection_id) + dataset = load_datasets().get(collectionId) if dataset is None: - raise not_found("Collection", collection_id) + raise not_found("Collection", collectionId) bbox_values = _parse_bbox(bbox, dataset.spatial_bbox) time_value = _parse_datetime(datetime_value, dataset.temporal_interval[0]) - parameters = _select_parameters(collection_id, range_subset) - source = _resolve_dhis2eo_source(collection_id, time_value, bbox_values) + parameters = _select_parameters(dataset, range_subset) + source = _resolve_dhis2eo_source(collectionId, parameters, time_value, bbox_values) ranges = { parameter_name: { @@ -213,6 +196,6 @@ def get_collection_coverage( }, "parameters": parameters, "ranges": ranges, - "links": _coverage_links(request, collection_id), + "links": _coverage_links(request, collectionId), "source": source, } diff --git a/eoapi/endpoints/edr.py b/eoapi/endpoints/edr.py new file mode 100644 index 0000000..db68486 --- /dev/null +++ b/eoapi/endpoints/edr.py @@ -0,0 +1,315 @@ +from datetime import date +import re + +from fastapi import APIRouter, Query, Request + +from dhis2eo.data.cds.era5_land import hourly as era5_land_hourly +from dhis2eo.data.cds.era5_land import monthly as era5_land_monthly +from dhis2eo.data.chc.chirps3 import daily as chirps3_daily +from pygeoapi.api import FORMAT_TYPES, F_JSON +from pygeoapi.util import url_join + +from eoapi.datasets import DatasetDefinition, load_datasets +from eoapi.endpoints.constants import CRS84 +from eoapi.endpoints.errors import invalid_parameter, not_found + +router = APIRouter() + +POINT_PATTERN = re.compile( + r"^POINT\s*\(\s*(?P-?\d+(?:\.\d+)?)\s+(?P-?\d+(?:\.\d+)?)\s*\)$", + re.IGNORECASE, +) + +def _base_url(request: Request) -> str: + return str(request.base_url).rstrip("/") + + +def _parse_point_coords(coords: str) -> tuple[float, float]: + match = POINT_PATTERN.match(coords.strip()) + if not match: + raise invalid_parameter("coords must be a WKT POINT like POINT(30 -1)") + + x = float(match.group("x")) + y = float(match.group("y")) + return (x, y) + + +def _parse_bbox( + bbox: str, +) -> tuple[float, float, float, float]: + try: + values = tuple(float(part.strip()) for part in bbox.split(",")) + except ValueError as exc: + raise invalid_parameter("bbox must contain 4 comma-separated numbers") from exc + + if len(values) != 4: + raise invalid_parameter("bbox must contain 4 comma-separated numbers") + + minx, miny, maxx, maxy = values + if minx >= maxx or miny >= maxy: + raise invalid_parameter("bbox must follow minx,miny,maxx,maxy with min < max") + + return values + + +def _parse_datetime(datetime_value: str | None, fallback_start: str) -> str: + if not datetime_value: + return fallback_start + + if "/" in datetime_value: + start, _, _ = datetime_value.partition("/") + if start in {"", ".."}: + return fallback_start + return start + + return datetime_value + + +def _select_parameters(dataset: DatasetDefinition, parameter_name: str | None) -> dict[str, dict]: + available = dataset.parameters + if not available: + raise invalid_parameter(f"No parameters configured for collection '{dataset.id}'") + + if not parameter_name: + return available + + requested = [parameter.strip() for parameter in parameter_name.split(",") if parameter.strip()] + unknown = [parameter for parameter in requested if parameter not in available] + if unknown: + raise invalid_parameter(f"Unknown parameter-name value(s): {', '.join(unknown)}") + + return {parameter: available[parameter] for parameter in requested} + + +def _resolve_dhis2eo_source( + collection_id: str, + parameters: dict[str, dict], + datetime_value: str, + coords: tuple[float, float], +) -> dict: + if collection_id == "chirps-daily": + try: + sample_day = date.fromisoformat(datetime_value[:10]) + except ValueError as exc: + raise invalid_parameter("datetime must be an ISO 8601 date or datetime") from exc + + return { + "backend": "dhis2eo.data.chc.chirps3.daily", + "resolver": "url_for_day", + "source_url": chirps3_daily.url_for_day(sample_day), + "point": [coords[0], coords[1]], + } + + if collection_id == "era5-land-daily": + return { + "backend": "dhis2eo.data.cds.era5_land", + "resolver": [ + era5_land_hourly.download.__name__, + era5_land_monthly.download.__name__, + ], + "variables": list(parameters.keys()), + "point": [coords[0], coords[1]], + "note": "ERA5-Land point query is resolved through CDS workflows in dhis2eo.", + } + + return { + "backend": "dhis2eo", + "point": [coords[0], coords[1]], + } + + +def _resolve_dhis2eo_source_for_bbox( + collection_id: str, + parameters: dict[str, dict], + datetime_value: str, + bbox: tuple[float, float, float, float], +) -> dict: + if collection_id == "chirps-daily": + try: + sample_day = date.fromisoformat(datetime_value[:10]) + except ValueError as exc: + raise invalid_parameter("datetime must be an ISO 8601 date or datetime") from exc + + return { + "backend": "dhis2eo.data.chc.chirps3.daily", + "resolver": "url_for_day", + "source_url": chirps3_daily.url_for_day(sample_day), + "bbox": list(bbox), + } + + if collection_id == "era5-land-daily": + return { + "backend": "dhis2eo.data.cds.era5_land", + "resolver": [ + era5_land_hourly.download.__name__, + era5_land_monthly.download.__name__, + ], + "variables": list(parameters.keys()), + "bbox": list(bbox), + "note": "ERA5-Land area query is resolved through CDS workflows in dhis2eo.", + } + + return { + "backend": "dhis2eo", + "bbox": list(bbox), + } + + +def _bbox_polygon(bbox: tuple[float, float, float, float]) -> list[list[float]]: + minx, miny, maxx, maxy = bbox + return [ + [minx, miny], + [maxx, miny], + [maxx, maxy], + [minx, maxy], + [minx, miny], + ] + + +def _position_links(request: Request, collection_id: str, coords: str) -> list[dict]: + base = _base_url(request) + collection_url = url_join(base, "collections", collection_id) + position_url = url_join(collection_url, "position") + return [ + { + "rel": "self", + "type": FORMAT_TYPES[F_JSON], + "title": "EDR position query", + "href": f"{position_url}?coords={coords}", + }, + { + "rel": "collection", + "type": FORMAT_TYPES[F_JSON], + "title": "Collection metadata", + "href": collection_url, + }, + { + "rel": "root", + "type": FORMAT_TYPES[F_JSON], + "title": "API root", + "href": url_join(base, "/"), + }, + ] + + +def _area_links(request: Request, collection_id: str, bbox: str) -> list[dict]: + base = _base_url(request) + collection_url = url_join(base, "collections", collection_id) + area_url = url_join(collection_url, "area") + return [ + { + "rel": "self", + "type": FORMAT_TYPES[F_JSON], + "title": "EDR area query", + "href": f"{area_url}?bbox={bbox}", + }, + { + "rel": "collection", + "type": FORMAT_TYPES[F_JSON], + "title": "Collection metadata", + "href": collection_url, + }, + { + "rel": "root", + "type": FORMAT_TYPES[F_JSON], + "title": "API root", + "href": url_join(base, "/"), + }, + ] + + +@router.get("/collections/{collectionId}/position") +def get_collection_position( + collectionId: str, + request: Request, + coords: str = Query(..., description="WKT POINT, e.g. POINT(30 -1)"), + datetime_value: str | None = Query(default=None, alias="datetime"), + parameter_name: str | None = Query( + default=None, + alias="parameter-name", + description="Comma-separated parameter IDs. Must match keys under datasets/.yaml -> parameters", + ), + output_format: str = Query(default=F_JSON, alias="f"), +) -> dict: + if output_format not in {F_JSON, "geojson"}: + raise invalid_parameter("Only f=json and f=geojson are currently supported") + + dataset = load_datasets().get(collectionId) + if dataset is None: + raise not_found("Collection", collectionId) + + point = _parse_point_coords(coords) + time_value = _parse_datetime(datetime_value, dataset.temporal_interval[0]) + parameters = _select_parameters(dataset, parameter_name) + source = _resolve_dhis2eo_source(collectionId, parameters, time_value, point) + + return { + "type": "FeatureCollection", + "title": dataset.title, + "features": [ + { + "type": "Feature", + "geometry": {"type": "Point", "coordinates": [point[0], point[1]]}, + "properties": { + "collection": collectionId, + "datetime": time_value, + "crs": CRS84, + "parameters": list(parameters.keys()), + "values": {parameter: None for parameter in parameters.keys()}, + }, + } + ], + "parameters": parameters, + "links": _position_links(request, collectionId, coords), + "source": source, + } + + +@router.get("/collections/{collectionId}/area") +def get_collection_area( + collectionId: str, + request: Request, + bbox: str = Query(..., description="Area bbox as minx,miny,maxx,maxy in CRS84"), + datetime_value: str | None = Query(default=None, alias="datetime"), + parameter_name: str | None = Query( + default=None, + alias="parameter-name", + description="Comma-separated parameter IDs. Must match keys under datasets/.yaml -> parameters", + ), + output_format: str = Query(default=F_JSON, alias="f"), +) -> dict: + if output_format not in {F_JSON, "geojson"}: + raise invalid_parameter("Only f=json and f=geojson are currently supported") + + dataset = load_datasets().get(collectionId) + if dataset is None: + raise not_found("Collection", collectionId) + + area_bbox = _parse_bbox(bbox) + time_value = _parse_datetime(datetime_value, dataset.temporal_interval[0]) + parameters = _select_parameters(dataset, parameter_name) + source = _resolve_dhis2eo_source_for_bbox(collectionId, parameters, time_value, area_bbox) + + return { + "type": "FeatureCollection", + "title": dataset.title, + "features": [ + { + "type": "Feature", + "geometry": { + "type": "Polygon", + "coordinates": [_bbox_polygon(area_bbox)], + }, + "properties": { + "collection": collectionId, + "datetime": time_value, + "crs": CRS84, + "parameters": list(parameters.keys()), + "aggregates": {parameter: None for parameter in parameters.keys()}, + }, + } + ], + "parameters": parameters, + "links": _area_links(request, collectionId, bbox), + "source": source, + } diff --git a/eoapi/endpoints/root.py b/eoapi/endpoints/root.py new file mode 100644 index 0000000..440848a --- /dev/null +++ b/eoapi/endpoints/root.py @@ -0,0 +1,41 @@ +from fastapi import APIRouter, Request + +from pygeoapi.api import FORMAT_TYPES, F_JSON +from pygeoapi.util import url_join + +router = APIRouter(tags=["Landing Page"]) + + +@router.get("/") +def read_index(request: Request) -> dict: + base = str(request.base_url).rstrip("/") + return { + "title": "DHIS2 EO API", + "description": "OGC-aligned Earth Observation API for DHIS2 and CHAP.", + "links": [ + { + "rel": "self", + "type": FORMAT_TYPES[F_JSON], + "title": "This document", + "href": url_join(base, "/"), + }, + { + "rel": "conformance", + "type": FORMAT_TYPES[F_JSON], + "title": "Conformance", + "href": url_join(base, "conformance"), + }, + { + "rel": "data", + "type": FORMAT_TYPES[F_JSON], + "title": "Collections", + "href": url_join(base, "collections"), + }, + { + "rel": "service-doc", + "type": "text/html", + "title": "OpenAPI docs", + "href": url_join(base, "docs"), + }, + ], + } diff --git a/main.py b/main.py index d08aeaa..a0ceba2 100644 --- a/main.py +++ b/main.py @@ -1,8 +1,9 @@ from fastapi import FastAPI -from titiler.core.factory import (TilerFactory, MultiBaseTilerFactory) +from titiler.core.factory import (TilerFactory) from rio_tiler.io import STACReader from eoapi.endpoints.collections import router as collections_router -from eoapi.endpoints.coverages import router as coverages_router +from eoapi.endpoints.conformance import router as conformance_router +from eoapi.endpoints.root import router as root_router from starlette.middleware.cors import CORSMiddleware @@ -24,28 +25,9 @@ # Create a TilerFactory for Cloud-Optimized GeoTIFFs cog = TilerFactory() +app.include_router(root_router) +app.include_router(conformance_router) app.include_router(collections_router) -app.include_router(coverages_router) # Register all the COG endpoints automatically app.include_router(cog.router, prefix="/cog", tags=["Cloud Optimized GeoTIFF"]) - -stac = MultiBaseTilerFactory( - reader=STACReader, - router_prefix="/stac", - add_ogc_maps=True, - # extensions=[stacViewerExtension(), stacRenderExtension(), wmtsExtension()], - # enable_telemetry=api_settings.telemetry_enabled, - # templates=titiler_templates, -) - -app.include_router( - stac.router, - prefix="/stac", - tags=["SpatioTemporal Asset Catalog"], -) - -# Optional: Add a welcome message for the root endpoint -@app.get("/") -def read_index(): - return {"message": "Welcome to DHIS2 EO API"} \ No newline at end of file diff --git a/tests/test_conformance_endpoint.py b/tests/test_conformance_endpoint.py new file mode 100644 index 0000000..c11f52a --- /dev/null +++ b/tests/test_conformance_endpoint.py @@ -0,0 +1,23 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.conformance import CONFORMANCE_CLASSES +from eoapi.endpoints.conformance import router as conformance_router + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(conformance_router) + return TestClient(app) + + +def test_conformance_endpoint_returns_classes() -> None: + client = create_client() + + response = client.get("/conformance") + + assert response.status_code == 200 + payload = response.json() + assert payload["conformsTo"] == CONFORMANCE_CLASSES + assert any(link["rel"] == "self" for link in payload["links"]) + assert any(link["rel"] == "root" for link in payload["links"]) diff --git a/tests/test_edr_endpoint.py b/tests/test_edr_endpoint.py new file mode 100644 index 0000000..af862c7 --- /dev/null +++ b/tests/test_edr_endpoint.py @@ -0,0 +1,87 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.collections import router as collections_router +from eoapi.endpoints.coverages import router as coverages_router +from eoapi.endpoints.edr import router as edr_router + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(collections_router) + app.include_router(coverages_router) + app.include_router(edr_router) + return TestClient(app) + + +def test_edr_position_success() -> None: + client = create_client() + + response = client.get( + "/collections/chirps-daily/position", + params={ + "coords": "POINT(30 -1)", + "datetime": "2026-01-31T00:00:00Z", + "parameter-name": "precip", + }, + ) + + assert response.status_code == 200 + payload = response.json() + assert payload["type"] == "FeatureCollection" + assert payload["features"][0]["geometry"]["type"] == "Point" + assert payload["features"][0]["properties"]["parameters"] == ["precip"] + + +def test_edr_position_invalid_coords() -> None: + client = create_client() + + response = client.get( + "/collections/chirps-daily/position", + params={"coords": "30,-1"}, + ) + + assert response.status_code == 400 + assert response.json()["detail"]["code"] == "InvalidParameterValue" + + +def test_edr_position_unknown_collection() -> None: + client = create_client() + + response = client.get( + "/collections/unknown/position", + params={"coords": "POINT(30 -1)"}, + ) + + assert response.status_code == 404 + assert response.json()["detail"]["code"] == "NotFound" + + +def test_edr_area_success() -> None: + client = create_client() + + response = client.get( + "/collections/era5-land-daily/area", + params={ + "bbox": "36,-2,38,0", + "parameter-name": "2m_temperature", + }, + ) + + assert response.status_code == 200 + payload = response.json() + assert payload["type"] == "FeatureCollection" + assert payload["features"][0]["geometry"]["type"] == "Polygon" + assert payload["features"][0]["properties"]["parameters"] == ["2m_temperature"] + + +def test_edr_area_invalid_bbox() -> None: + client = create_client() + + response = client.get( + "/collections/chirps-daily/area", + params={"bbox": "30,-5,30,2"}, + ) + + assert response.status_code == 400 + assert response.json()["detail"]["code"] == "InvalidParameterValue" diff --git a/tests/test_landing_page.py b/tests/test_landing_page.py new file mode 100644 index 0000000..5b7dfe7 --- /dev/null +++ b/tests/test_landing_page.py @@ -0,0 +1,21 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.root import router as root_router + + +app = FastAPI() + +app.include_router(root_router) + + +def test_landing_page_links() -> None: + client = TestClient(app) + + response = client.get("/") + + assert response.status_code == 200 + payload = response.json() + assert payload["title"] == "DHIS2 EO API" + rels = {link["rel"] for link in payload["links"]} + assert {"self", "conformance", "data", "service-doc"}.issubset(rels) From c40a1b8909a31ee12c2fa947c33018dd9cdc2071 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 20:26:16 +0100 Subject: [PATCH 09/13] Refactoring --- .github/copilot-instructions.md | 9 +- .../skills/eo-pipeline-orchestration/SKILL.md | 2 +- .github/skills/eo-process-api-design/SKILL.md | 4 +- .github/skills/prd-authoring/SKILL.md | 6 +- API_EXAMPLES.md | 2 +- PRD.md | 20 +++-- README.md | 13 ++- {datasets => eoapi/datasets}/README.md | 32 ++++++- eoapi/datasets/__init__.py | 18 ++++ eoapi/datasets/base.py | 33 ++++++++ eoapi/{datasets.py => datasets/catalog.py} | 19 ++++- .../datasets/chirps-daily}/chirps-daily.yaml | 0 eoapi/datasets/chirps-daily/resolver.py | 58 +++++++++++++ .../era5-land-daily}/era5-land-daily.yaml | 0 eoapi/datasets/era5-land-daily/resolver.py | 55 ++++++++++++ eoapi/datasets/resolvers.py | 62 ++++++++++++++ eoapi/endpoints/coverages.py | 46 +++------- eoapi/endpoints/edr.py | 84 ++++++------------- pyproject.toml | 4 +- 19 files changed, 344 insertions(+), 123 deletions(-) rename {datasets => eoapi/datasets}/README.md (56%) create mode 100644 eoapi/datasets/__init__.py create mode 100644 eoapi/datasets/base.py rename eoapi/{datasets.py => datasets/catalog.py} (65%) rename {datasets => eoapi/datasets/chirps-daily}/chirps-daily.yaml (100%) create mode 100644 eoapi/datasets/chirps-daily/resolver.py rename {datasets => eoapi/datasets/era5-land-daily}/era5-land-daily.yaml (100%) create mode 100644 eoapi/datasets/era5-land-daily/resolver.py create mode 100644 eoapi/datasets/resolvers.py diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index c4c5a29..8b6aaba 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -12,16 +12,17 @@ - Dataset discovery is implemented via: - `GET /collections` - - `GET /collections/{collection_id}` + - `GET /collections/{collectionId}` - OGC API - Coverages baseline is implemented via: - - `GET /collections/{collection_id}/coverage` + - `GET /collections/{collectionId}/coverage` - Collections and coverages are split into separate endpoint modules: - `eoapi/endpoints/collections.py` - `eoapi/endpoints/coverages.py` - Shared endpoint constants/errors live in: - `eoapi/endpoints/constants.py` - `eoapi/endpoints/errors.py` -- Dataset metadata is file-driven from top-level `datasets/*.yaml` and validated by Pydantic (`eoapi/datasets.py`). +- Dataset metadata is file-driven from `eoapi/datasets//.yaml` and validated by Pydantic (`eoapi/datasets/catalog.py`). +- Dataset-specific source resolver logic lives in `eoapi/datasets//resolver.py`. - Dataset validation command is available via `make validate-datasets`. - Tests currently include endpoint error contract tests and run via `make test`. @@ -106,4 +107,4 @@ - Update docs when adding endpoints, process parameters, or output schema changes. - Include example requests/responses for new process execution paths. - Keep `README.md` concise and place endpoint examples in `API_EXAMPLES.md`. -- Keep dataset schema documentation in `datasets/README.md`. +- Keep dataset schema documentation in `eoapi/datasets/README.md`. diff --git a/.github/skills/eo-pipeline-orchestration/SKILL.md b/.github/skills/eo-pipeline-orchestration/SKILL.md index 8483108..ae464b2 100644 --- a/.github/skills/eo-pipeline-orchestration/SKILL.md +++ b/.github/skills/eo-pipeline-orchestration/SKILL.md @@ -13,7 +13,7 @@ description: Define scheduled and custom EO data pipelines with optional pre/pos ## Canonical pipeline stages -1. Discover dataset and validate metadata (from `datasets/*.yaml` definitions) +1. Discover dataset and validate metadata (from `eoapi/datasets//.yaml` definitions) 2. Extract data for time/area window 3. Cache source/intermediate artifacts as files when needed 4. Transform and harmonize units/CRS diff --git a/.github/skills/eo-process-api-design/SKILL.md b/.github/skills/eo-process-api-design/SKILL.md index d79e11b..706f06b 100644 --- a/.github/skills/eo-process-api-design/SKILL.md +++ b/.github/skills/eo-process-api-design/SKILL.md @@ -15,9 +15,9 @@ description: Design OGC API - Processes style EO execution endpoints and request - Dataset discovery: - `GET /collections` - - `GET /collections/{collection_id}` + - `GET /collections/{collectionId}` - Coverage retrieval: - - `GET /collections/{collection_id}/coverage` + - `GET /collections/{collectionId}/coverage` - Process execution endpoints (target baseline): - `GET /processes` - `GET /processes/{process-id}` diff --git a/.github/skills/prd-authoring/SKILL.md b/.github/skills/prd-authoring/SKILL.md index 747552a..42e42ba 100644 --- a/.github/skills/prd-authoring/SKILL.md +++ b/.github/skills/prd-authoring/SKILL.md @@ -36,9 +36,9 @@ description: Draft or refine PRDs for DHIS2 EO API features with clear MVP scope - Explicitly identifies which Google Earth Engine-dependent behavior is replaced by `eo-api` - Calls out standards alignment (OGC/STAC) when applicable - Reflects current implemented baseline where relevant: - - `/collections`, `/collections/{collection_id}` - - `/collections/{collection_id}/coverage` - - File-driven dataset metadata in `datasets/*.yaml` validated by Pydantic + - `/collections`, `/collections/{collectionId}` + - `/collections/{collectionId}/coverage` + - File-driven dataset metadata in `eoapi/datasets//.yaml` validated by Pydantic - Validation/test workflow via `make validate-datasets` and `make test` ## Quality bar diff --git a/API_EXAMPLES.md b/API_EXAMPLES.md index 2490647..5714dc9 100644 --- a/API_EXAMPLES.md +++ b/API_EXAMPLES.md @@ -22,7 +22,7 @@ http://127.0.0.1:8000/conformance curl "http://127.0.0.1:8000/conformance" ``` -Note: values used in `range-subset` and `parameter-name` must match keys in `datasets/.yaml` under `parameters`. +Note: values used in `range-subset` and `parameter-name` must match keys in `eoapi/datasets//.yaml` under `parameters`. List collections: diff --git a/PRD.md b/PRD.md index 48af8a8..84a45d6 100644 --- a/PRD.md +++ b/PRD.md @@ -81,16 +81,18 @@ Current EO data workflows are fragmented across tools and scripts, making them h - Implement OGC API - Common collection discovery endpoints: - `GET /collections` - - `GET /collections/{collection_id}` + - `GET /collections/{collectionId}` - Implement OGC API - Coverages baseline endpoint: - - `GET /collections/{collection_id}/coverage` + - `GET /collections/{collectionId}/coverage` - Support key coverage query parameters (`bbox`, `datetime`, `range-subset`, `f`) with structured validation errors. ### FR11 — File-driven dataset catalog -- Store dataset definitions as one YAML file per dataset in top-level `datasets/`. +- Store dataset definitions with one folder per dataset in `eoapi/datasets//`. +- Store metadata as `eoapi/datasets//.yaml`. +- Store dataset source resolver logic as `eoapi/datasets//resolver.py`. - Validate dataset definitions via Pydantic before use. -- Keep dataset schema and examples documented in `datasets/README.md`. +- Keep dataset schema and examples documented in `eoapi/datasets/README.md`. ### FR8 — Consumer app compatibility @@ -144,9 +146,9 @@ Current EO data workflows are fragmented across tools and scripts, making them h ### In scope - Draft unified API interface -- OGC collection discovery (`/collections`, `/collections/{collection_id}`) -- OGC coverage baseline (`/collections/{collection_id}/coverage`) for gridded datasets (CHIRPS, ERA5-Land) -- File-driven dataset definitions (`datasets/*.yaml`) with schema validation +- OGC collection discovery (`/collections`, `/collections/{collectionId}`) +- OGC coverage baseline (`/collections/{collectionId}/coverage`) for gridded datasets (CHIRPS, ERA5-Land) +- File-driven dataset definitions (`eoapi/datasets//.yaml`) with schema validation - Process catalog + at least one executable process flow - Climate variable import path (temperature/precipitation) aggregated to org units - Preview of data for org unit @@ -206,8 +208,8 @@ Current EO data workflows are fragmented across tools and scripts, making them h ## 15) Acceptance Criteria (MVP) -- `/collections` and `/collections/{collection_id}` return OGC-compatible collection metadata for configured datasets. -- `/collections/{collection_id}/coverage` returns OGC Coverages-compatible response structures for supported datasets. +- `/collections` and `/collections/{collectionId}` return OGC-compatible collection metadata for configured datasets. +- `/collections/{collectionId}/coverage` returns OGC Coverages-compatible response structures for supported datasets. - Dataset definitions are managed as YAML files and validated successfully before runtime use. - A user can discover available process(es) and execute one through API. - A climate dataset can be previewed and aggregated to org units. diff --git a/README.md b/README.md index 26932eb..8ba1629 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,17 @@ uvicorn main:app --reload See [`API_EXAMPLES.md`](API_EXAMPLES.md) for docs, collections, STAC, and COG request examples. +## Documentation + +- API usage examples: [`API_EXAMPLES.md`](API_EXAMPLES.md) +- Dataset schema and resolver conventions: [`eoapi/datasets/README.md`](eoapi/datasets/README.md) +- Product requirements and scope: [`PRD.md`](PRD.md) +- Repository coding guidance for AI edits: [`.github/copilot-instructions.md`](.github/copilot-instructions.md) + ## Dataset definitions -Collection metadata for `/collections` is defined in top-level YAML files under `datasets/`. +Collection metadata for `/collections` is defined in YAML files under `eoapi/datasets/`. + +Each dataset uses `eoapi/datasets//.yaml` with matching resolver code in `eoapi/datasets//resolver.py`. -For schema details, examples, and current dataset files, see [`datasets/README.md`](datasets/README.md). +For schema details, examples, and current dataset files, see [`eoapi/datasets/README.md`](eoapi/datasets/README.md). diff --git a/datasets/README.md b/eoapi/datasets/README.md similarity index 56% rename from datasets/README.md rename to eoapi/datasets/README.md index 8405960..bf1e018 100644 --- a/datasets/README.md +++ b/eoapi/datasets/README.md @@ -2,7 +2,19 @@ This folder contains dataset definitions used by the `/collections` endpoints. -Definitions are loaded from `*.yaml` files and validated by the `DatasetDefinition` Pydantic model in `eoapi/datasets.py`. +Definitions are loaded from dataset-specific subfolders and validated by the `DatasetDefinition` Pydantic model in `eoapi/datasets/catalog.py`. + +## Folder layout + +Each dataset has its own folder named after the dataset ID: + +- `eoapi/datasets//.yaml` +- `eoapi/datasets//resolver.py` + +Example: + +- `eoapi/datasets/chirps-daily/chirps-daily.yaml` +- `eoapi/datasets/chirps-daily/resolver.py` ## Required schema @@ -68,5 +80,19 @@ parameters: ## Current definitions -- `chirps-daily.yaml` -- `era5-land-daily.yaml` +- `chirps-daily/chirps-daily.yaml` +- `era5-land-daily/era5-land-daily.yaml` + +## Adding a new dataset resolver module + +When adding a new dataset, create a folder under `eoapi/datasets/` named exactly as the dataset ID and include a `resolver.py` module for dataset-specific source integration logic. + +Expected resolver functions in the module: + +- `coverage_source(datetime_value, parameters, bbox)` +- `position_source(datetime_value, parameters, coords)` +- `area_source(datetime_value, parameters, bbox)` + +These should follow the shared resolver contracts in `eoapi/datasets/base.py`. + +Resolver registration is automatic via `eoapi/datasets/resolvers.py`, which scans dataset folders and loads `resolver.py` by dataset ID. diff --git a/eoapi/datasets/__init__.py b/eoapi/datasets/__init__.py new file mode 100644 index 0000000..46f32d0 --- /dev/null +++ b/eoapi/datasets/__init__.py @@ -0,0 +1,18 @@ +from .catalog import DatasetDefinition, load_datasets +from .base import AreaResolver, BBox, CoverageResolver, ParameterMap, Point, PositionResolver, SourcePayload +from .resolvers import area_resolvers, coverage_resolvers, position_resolvers + +__all__ = [ + "DatasetDefinition", + "load_datasets", + "ParameterMap", + "BBox", + "Point", + "SourcePayload", + "CoverageResolver", + "PositionResolver", + "AreaResolver", + "coverage_resolvers", + "position_resolvers", + "area_resolvers", +] diff --git a/eoapi/datasets/base.py b/eoapi/datasets/base.py new file mode 100644 index 0000000..2a37cd3 --- /dev/null +++ b/eoapi/datasets/base.py @@ -0,0 +1,33 @@ +from typing import Protocol, TypeAlias + +ParameterMap: TypeAlias = dict[str, dict] +BBox: TypeAlias = tuple[float, float, float, float] +Point: TypeAlias = tuple[float, float] +SourcePayload: TypeAlias = dict + + +class CoverageResolver(Protocol): + def __call__( + self, + datetime_value: str, + parameters: ParameterMap, + bbox: BBox, + ) -> SourcePayload: ... + + +class PositionResolver(Protocol): + def __call__( + self, + datetime_value: str, + parameters: ParameterMap, + coords: Point, + ) -> SourcePayload: ... + + +class AreaResolver(Protocol): + def __call__( + self, + datetime_value: str, + parameters: ParameterMap, + bbox: BBox, + ) -> SourcePayload: ... diff --git a/eoapi/datasets.py b/eoapi/datasets/catalog.py similarity index 65% rename from eoapi/datasets.py rename to eoapi/datasets/catalog.py index 7ff0340..aae4019 100644 --- a/eoapi/datasets.py +++ b/eoapi/datasets/catalog.py @@ -1,11 +1,11 @@ +from datetime import datetime from functools import lru_cache from pathlib import Path -from datetime import datetime from pydantic import BaseModel, Field, field_validator import yaml -DATASETS_DIR = Path(__file__).resolve().parents[1] / "datasets" +DATASETS_DIR = Path(__file__).resolve().parent class DatasetDefinition(BaseModel): @@ -40,11 +40,24 @@ def normalize_temporal_interval(cls, value): def load_datasets() -> dict[str, DatasetDefinition]: datasets: dict[str, DatasetDefinition] = {} - for dataset_file in sorted(DATASETS_DIR.glob("*.yml")) + sorted(DATASETS_DIR.glob("*.yaml")): + dataset_dirs = sorted(path for path in DATASETS_DIR.iterdir() if path.is_dir()) + for dataset_dir in dataset_dirs: + yaml_candidates = [dataset_dir / f"{dataset_dir.name}.yml", dataset_dir / f"{dataset_dir.name}.yaml"] + dataset_file = next((candidate for candidate in yaml_candidates if candidate.exists()), None) + if dataset_file is None: + fallback_files = sorted(dataset_dir.glob("*.yml")) + sorted(dataset_dir.glob("*.yaml")) + if not fallback_files: + continue + dataset_file = fallback_files[0] + with dataset_file.open("r", encoding="utf-8") as file_handle: payload = yaml.safe_load(file_handle) or {} dataset = DatasetDefinition.model_validate(payload) + if dataset.id != dataset_dir.name: + raise RuntimeError( + f"Dataset id '{dataset.id}' must match dataset folder name '{dataset_dir.name}'" + ) if dataset.id in datasets: raise RuntimeError(f"Duplicate dataset id found: {dataset.id}") datasets[dataset.id] = dataset diff --git a/datasets/chirps-daily.yaml b/eoapi/datasets/chirps-daily/chirps-daily.yaml similarity index 100% rename from datasets/chirps-daily.yaml rename to eoapi/datasets/chirps-daily/chirps-daily.yaml diff --git a/eoapi/datasets/chirps-daily/resolver.py b/eoapi/datasets/chirps-daily/resolver.py new file mode 100644 index 0000000..f35dc04 --- /dev/null +++ b/eoapi/datasets/chirps-daily/resolver.py @@ -0,0 +1,58 @@ +from datetime import date + +from dhis2eo.data.chc.chirps3 import daily as chirps3_daily + +from eoapi.datasets.base import BBox, ParameterMap, Point, SourcePayload +from eoapi.endpoints.errors import invalid_parameter + + +def _parse_sample_day(datetime_value: str) -> date: + try: + return date.fromisoformat(datetime_value[:10]) + except ValueError as exc: + raise invalid_parameter("datetime must be an ISO 8601 date or datetime") from exc + + +def coverage_source( + datetime_value: str, + parameters: ParameterMap, + bbox: BBox, +) -> SourcePayload: + sample_day = _parse_sample_day(datetime_value) + return { + "backend": "dhis2eo.data.chc.chirps3.daily", + "resolver": "url_for_day", + "source_url": chirps3_daily.url_for_day(sample_day), + "bbox": list(bbox), + "variables": list(parameters.keys()), + } + + +def position_source( + datetime_value: str, + parameters: ParameterMap, + coords: Point, +) -> SourcePayload: + sample_day = _parse_sample_day(datetime_value) + return { + "backend": "dhis2eo.data.chc.chirps3.daily", + "resolver": "url_for_day", + "source_url": chirps3_daily.url_for_day(sample_day), + "point": [coords[0], coords[1]], + "variables": list(parameters.keys()), + } + + +def area_source( + datetime_value: str, + parameters: ParameterMap, + bbox: BBox, +) -> SourcePayload: + sample_day = _parse_sample_day(datetime_value) + return { + "backend": "dhis2eo.data.chc.chirps3.daily", + "resolver": "url_for_day", + "source_url": chirps3_daily.url_for_day(sample_day), + "bbox": list(bbox), + "variables": list(parameters.keys()), + } diff --git a/datasets/era5-land-daily.yaml b/eoapi/datasets/era5-land-daily/era5-land-daily.yaml similarity index 100% rename from datasets/era5-land-daily.yaml rename to eoapi/datasets/era5-land-daily/era5-land-daily.yaml diff --git a/eoapi/datasets/era5-land-daily/resolver.py b/eoapi/datasets/era5-land-daily/resolver.py new file mode 100644 index 0000000..be7a271 --- /dev/null +++ b/eoapi/datasets/era5-land-daily/resolver.py @@ -0,0 +1,55 @@ +from dhis2eo.data.cds.era5_land import hourly as era5_land_hourly +from dhis2eo.data.cds.era5_land import monthly as era5_land_monthly + +from eoapi.datasets.base import BBox, ParameterMap, Point, SourcePayload + + +def coverage_source( + datetime_value: str, + parameters: ParameterMap, + bbox: BBox, +) -> SourcePayload: + return { + "backend": "dhis2eo.data.cds.era5_land", + "resolver": [ + era5_land_hourly.download.__name__, + era5_land_monthly.download.__name__, + ], + "variables": list(parameters.keys()), + "bbox": list(bbox), + "note": "ERA5-Land source data is resolved via CDS download workflows in dhis2eo.", + } + + +def position_source( + datetime_value: str, + parameters: ParameterMap, + coords: Point, +) -> SourcePayload: + return { + "backend": "dhis2eo.data.cds.era5_land", + "resolver": [ + era5_land_hourly.download.__name__, + era5_land_monthly.download.__name__, + ], + "variables": list(parameters.keys()), + "point": [coords[0], coords[1]], + "note": "ERA5-Land point query is resolved through CDS workflows in dhis2eo.", + } + + +def area_source( + datetime_value: str, + parameters: ParameterMap, + bbox: BBox, +) -> SourcePayload: + return { + "backend": "dhis2eo.data.cds.era5_land", + "resolver": [ + era5_land_hourly.download.__name__, + era5_land_monthly.download.__name__, + ], + "variables": list(parameters.keys()), + "bbox": list(bbox), + "note": "ERA5-Land area query is resolved through CDS workflows in dhis2eo.", + } diff --git a/eoapi/datasets/resolvers.py b/eoapi/datasets/resolvers.py new file mode 100644 index 0000000..e4a7b41 --- /dev/null +++ b/eoapi/datasets/resolvers.py @@ -0,0 +1,62 @@ +from functools import lru_cache +from importlib.util import module_from_spec, spec_from_file_location +from pathlib import Path +from types import ModuleType + +from eoapi.datasets.base import AreaResolver, CoverageResolver, PositionResolver +from eoapi.datasets.catalog import DATASETS_DIR + + +def _load_module(module_name: str, module_path: Path) -> ModuleType: + spec = spec_from_file_location(module_name, module_path) + if spec is None or spec.loader is None: + raise RuntimeError(f"Unable to load resolver module from: {module_path}") + + module = module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +@lru_cache(maxsize=1) +def _resolver_modules() -> dict[str, ModuleType]: + modules: dict[str, ModuleType] = {} + + for dataset_dir in sorted(path for path in DATASETS_DIR.iterdir() if path.is_dir()): + resolver_path = dataset_dir / "resolver.py" + if not resolver_path.exists(): + continue + + module_name = f"eoapi.datasets._resolver_{dataset_dir.name.replace('-', '_')}" + modules[dataset_dir.name] = _load_module(module_name, resolver_path) + + return modules + + +@lru_cache(maxsize=1) +def coverage_resolvers() -> dict[str, CoverageResolver]: + resolvers: dict[str, CoverageResolver] = {} + for dataset_id, module in _resolver_modules().items(): + resolver = getattr(module, "coverage_source", None) + if callable(resolver): + resolvers[dataset_id] = resolver + return resolvers + + +@lru_cache(maxsize=1) +def position_resolvers() -> dict[str, PositionResolver]: + resolvers: dict[str, PositionResolver] = {} + for dataset_id, module in _resolver_modules().items(): + resolver = getattr(module, "position_source", None) + if callable(resolver): + resolvers[dataset_id] = resolver + return resolvers + + +@lru_cache(maxsize=1) +def area_resolvers() -> dict[str, AreaResolver]: + resolvers: dict[str, AreaResolver] = {} + for dataset_id, module in _resolver_modules().items(): + resolver = getattr(module, "area_source", None) + if callable(resolver): + resolvers[dataset_id] = resolver + return resolvers diff --git a/eoapi/endpoints/coverages.py b/eoapi/endpoints/coverages.py index 9285fad..ee3b05e 100644 --- a/eoapi/endpoints/coverages.py +++ b/eoapi/endpoints/coverages.py @@ -1,19 +1,20 @@ -from datetime import date - from fastapi import APIRouter, Query, Request -from dhis2eo.data.cds.era5_land import hourly as era5_land_hourly -from dhis2eo.data.cds.era5_land import monthly as era5_land_monthly -from dhis2eo.data.chc.chirps3 import daily as chirps3_daily from pygeoapi.api import FORMAT_TYPES, F_JSON from pygeoapi.util import url_join from eoapi.datasets import DatasetDefinition, load_datasets +from eoapi.datasets.base import BBox, CoverageResolver, ParameterMap, SourcePayload +from eoapi.datasets.resolvers import coverage_resolvers from eoapi.endpoints.constants import CRS84 from eoapi.endpoints.errors import invalid_parameter, not_found router = APIRouter() +COVERAGE_RESOLVERS: dict[str, CoverageResolver] = { + **coverage_resolvers(), +} + def _base_url(request: Request) -> str: return str(request.base_url).rstrip("/") @@ -68,34 +69,13 @@ def _select_parameters(dataset: DatasetDefinition, range_subset: str | None) -> def _resolve_dhis2eo_source( collection_id: str, - parameters: dict[str, dict], + parameters: ParameterMap, datetime_value: str, - bbox: tuple[float, float, float, float], -) -> dict: - if collection_id == "chirps-daily": - try: - sample_day = date.fromisoformat(datetime_value[:10]) - except ValueError as exc: - raise invalid_parameter("datetime must be an ISO 8601 date or datetime") from exc - - return { - "backend": "dhis2eo.data.chc.chirps3.daily", - "resolver": "url_for_day", - "source_url": chirps3_daily.url_for_day(sample_day), - "bbox": list(bbox), - } - - if collection_id == "era5-land-daily": - return { - "backend": "dhis2eo.data.cds.era5_land", - "resolver": [ - era5_land_hourly.download.__name__, - era5_land_monthly.download.__name__, - ], - "variables": list(parameters.keys()), - "bbox": list(bbox), - "note": "ERA5-Land source data is resolved via CDS download workflows in dhis2eo.", - } + bbox: BBox, +) -> SourcePayload: + resolver = COVERAGE_RESOLVERS.get(collection_id) + if resolver is not None: + return resolver(datetime_value, parameters, bbox) return { "backend": "dhis2eo", @@ -138,7 +118,7 @@ def get_collection_coverage( range_subset: str | None = Query( default=None, alias="range-subset", - description="Comma-separated parameter IDs. Must match keys under datasets/.yaml -> parameters", + description="Comma-separated parameter IDs. Must match keys under eoapi/datasets//.yaml -> parameters", ), output_format: str = Query(default=F_JSON, alias="f"), ) -> dict: diff --git a/eoapi/endpoints/edr.py b/eoapi/endpoints/edr.py index db68486..98f343f 100644 --- a/eoapi/endpoints/edr.py +++ b/eoapi/endpoints/edr.py @@ -1,20 +1,26 @@ -from datetime import date import re from fastapi import APIRouter, Query, Request -from dhis2eo.data.cds.era5_land import hourly as era5_land_hourly -from dhis2eo.data.cds.era5_land import monthly as era5_land_monthly -from dhis2eo.data.chc.chirps3 import daily as chirps3_daily from pygeoapi.api import FORMAT_TYPES, F_JSON from pygeoapi.util import url_join from eoapi.datasets import DatasetDefinition, load_datasets +from eoapi.datasets.base import AreaResolver, BBox, ParameterMap, Point, PositionResolver, SourcePayload +from eoapi.datasets.resolvers import area_resolvers, position_resolvers from eoapi.endpoints.constants import CRS84 from eoapi.endpoints.errors import invalid_parameter, not_found router = APIRouter() +POSITION_RESOLVERS: dict[str, PositionResolver] = { + **position_resolvers(), +} + +AREA_RESOLVERS: dict[str, AreaResolver] = { + **area_resolvers(), +} + POINT_PATTERN = re.compile( r"^POINT\s*\(\s*(?P-?\d+(?:\.\d+)?)\s+(?P-?\d+(?:\.\d+)?)\s*\)$", re.IGNORECASE, @@ -83,34 +89,13 @@ def _select_parameters(dataset: DatasetDefinition, parameter_name: str | None) - def _resolve_dhis2eo_source( collection_id: str, - parameters: dict[str, dict], + parameters: ParameterMap, datetime_value: str, - coords: tuple[float, float], -) -> dict: - if collection_id == "chirps-daily": - try: - sample_day = date.fromisoformat(datetime_value[:10]) - except ValueError as exc: - raise invalid_parameter("datetime must be an ISO 8601 date or datetime") from exc - - return { - "backend": "dhis2eo.data.chc.chirps3.daily", - "resolver": "url_for_day", - "source_url": chirps3_daily.url_for_day(sample_day), - "point": [coords[0], coords[1]], - } - - if collection_id == "era5-land-daily": - return { - "backend": "dhis2eo.data.cds.era5_land", - "resolver": [ - era5_land_hourly.download.__name__, - era5_land_monthly.download.__name__, - ], - "variables": list(parameters.keys()), - "point": [coords[0], coords[1]], - "note": "ERA5-Land point query is resolved through CDS workflows in dhis2eo.", - } + coords: Point, +) -> SourcePayload: + resolver = POSITION_RESOLVERS.get(collection_id) + if resolver is not None: + return resolver(datetime_value, parameters, coords) return { "backend": "dhis2eo", @@ -120,34 +105,13 @@ def _resolve_dhis2eo_source( def _resolve_dhis2eo_source_for_bbox( collection_id: str, - parameters: dict[str, dict], + parameters: ParameterMap, datetime_value: str, - bbox: tuple[float, float, float, float], -) -> dict: - if collection_id == "chirps-daily": - try: - sample_day = date.fromisoformat(datetime_value[:10]) - except ValueError as exc: - raise invalid_parameter("datetime must be an ISO 8601 date or datetime") from exc - - return { - "backend": "dhis2eo.data.chc.chirps3.daily", - "resolver": "url_for_day", - "source_url": chirps3_daily.url_for_day(sample_day), - "bbox": list(bbox), - } - - if collection_id == "era5-land-daily": - return { - "backend": "dhis2eo.data.cds.era5_land", - "resolver": [ - era5_land_hourly.download.__name__, - era5_land_monthly.download.__name__, - ], - "variables": list(parameters.keys()), - "bbox": list(bbox), - "note": "ERA5-Land area query is resolved through CDS workflows in dhis2eo.", - } + bbox: BBox, +) -> SourcePayload: + resolver = AREA_RESOLVERS.get(collection_id) + if resolver is not None: + return resolver(datetime_value, parameters, bbox) return { "backend": "dhis2eo", @@ -227,7 +191,7 @@ def get_collection_position( parameter_name: str | None = Query( default=None, alias="parameter-name", - description="Comma-separated parameter IDs. Must match keys under datasets/.yaml -> parameters", + description="Comma-separated parameter IDs. Must match keys under eoapi/datasets//.yaml -> parameters", ), output_format: str = Query(default=F_JSON, alias="f"), ) -> dict: @@ -274,7 +238,7 @@ def get_collection_area( parameter_name: str | None = Query( default=None, alias="parameter-name", - description="Comma-separated parameter IDs. Must match keys under datasets/.yaml -> parameters", + description="Comma-separated parameter IDs. Must match keys under eoapi/datasets//.yaml -> parameters", ), output_format: str = Query(default=F_JSON, alias="f"), ) -> dict: diff --git a/pyproject.toml b/pyproject.toml index cb4cd48..e047d64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -15,5 +15,5 @@ dependencies = [ "dhis2-client @ git+https://github.com/dhis2/dhis2-python-client.git@V0.3.0", ] -[tool.setuptools] -packages = ["eoapi"] \ No newline at end of file +[tool.setuptools.packages.find] +include = ["eoapi*"] \ No newline at end of file From 2a019ad774186747701d006d747f17acbd6f3846 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Mon, 23 Feb 2026 20:29:55 +0100 Subject: [PATCH 10/13] Readme cleaning --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 8ba1629..2cef56b 100644 --- a/README.md +++ b/README.md @@ -41,10 +41,6 @@ uvicorn main:app --reload - `make validate-datasets` — validate all dataset YAML files against the Pydantic schema - `make test` — run Python tests with pytest -## API examples - -See [`API_EXAMPLES.md`](API_EXAMPLES.md) for docs, collections, STAC, and COG request examples. - ## Documentation - API usage examples: [`API_EXAMPLES.md`](API_EXAMPLES.md) From adac1d7fd8f53954b6d46479507f4ba400e8ba32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Tue, 24 Feb 2026 10:09:29 +0100 Subject: [PATCH 11/13] New endpoints --- .cache/state/jobs.json | 1 + .cache/state/schedules.json | 1 + .cache/state/workflows.json | 1 + .../precip_20260101_20260131_2026-01.nc | Bin 0 -> 209174 bytes .../precip_20260131_20260131_2026-01.nc | Bin 0 -> 209174 bytes API_EXAMPLES.md | 300 +++++++ PREFECT_INTEGRATION.md | 150 ++++ PRESENTATION.md | 290 ++++++ PRESENTATION_EXECUTIVE.md | 148 ++++ README.md | 135 +++ XCLIM_INTEGRATION.md | 281 ++++++ eoapi/dhis2_integration.py | 220 +++++ eoapi/endpoints/collections.py | 65 +- eoapi/endpoints/conformance.py | 4 + eoapi/endpoints/coverages.py | 18 + eoapi/endpoints/edr.py | 31 + eoapi/endpoints/features.py | 168 ++++ eoapi/endpoints/processes.py | 837 ++++++++++++++++++ eoapi/endpoints/root.py | 98 ++ eoapi/endpoints/schedules.py | 310 +++++++ eoapi/endpoints/workflows.py | 161 ++++ eoapi/external_ogc.py | 264 ++++++ eoapi/jobs.py | 95 ++ eoapi/orchestration/prefect.py | 90 ++ eoapi/scheduler_runtime.py | 112 +++ eoapi/schedules.py | 87 ++ eoapi/state_store.py | 62 ++ eoapi/workflows.py | 82 ++ main.py | 136 ++- pyproject.toml | 2 + tests/test_collections_federation.py | 75 ++ tests/test_coverages_federation.py | 64 ++ tests/test_edr_endpoint.py | 88 ++ tests/test_external_ogc_config.py | 76 ++ tests/test_features_endpoint.py | 58 ++ tests/test_landing_page.py | 5 + tests/test_processes_endpoint.py | 255 ++++++ tests/test_scheduler_runtime.py | 45 + tests/test_schedules_endpoint.py | 227 +++++ tests/test_state_store.py | 21 + tests/test_workflows_endpoint.py | 80 ++ uv.lock | 302 +++++++ webapp/app.js | 345 ++++++++ webapp/index.html | 196 ++++ webapp/styles.css | 114 +++ 45 files changed, 6098 insertions(+), 2 deletions(-) create mode 100644 .cache/state/jobs.json create mode 100644 .cache/state/schedules.json create mode 100644 .cache/state/workflows.json create mode 100644 .cache/xclim/chirps-daily/precip/precip_20260101_20260131_2026-01.nc create mode 100644 .cache/xclim/chirps-daily/precip/precip_20260131_20260131_2026-01.nc create mode 100644 PREFECT_INTEGRATION.md create mode 100644 PRESENTATION.md create mode 100644 PRESENTATION_EXECUTIVE.md create mode 100644 XCLIM_INTEGRATION.md create mode 100644 eoapi/dhis2_integration.py create mode 100644 eoapi/endpoints/features.py create mode 100644 eoapi/endpoints/processes.py create mode 100644 eoapi/endpoints/schedules.py create mode 100644 eoapi/endpoints/workflows.py create mode 100644 eoapi/external_ogc.py create mode 100644 eoapi/jobs.py create mode 100644 eoapi/orchestration/prefect.py create mode 100644 eoapi/scheduler_runtime.py create mode 100644 eoapi/schedules.py create mode 100644 eoapi/state_store.py create mode 100644 eoapi/workflows.py create mode 100644 tests/test_collections_federation.py create mode 100644 tests/test_coverages_federation.py create mode 100644 tests/test_external_ogc_config.py create mode 100644 tests/test_features_endpoint.py create mode 100644 tests/test_processes_endpoint.py create mode 100644 tests/test_scheduler_runtime.py create mode 100644 tests/test_schedules_endpoint.py create mode 100644 tests/test_state_store.py create mode 100644 tests/test_workflows_endpoint.py create mode 100644 webapp/app.js create mode 100644 webapp/index.html create mode 100644 webapp/styles.css diff --git a/.cache/state/jobs.json b/.cache/state/jobs.json new file mode 100644 index 0000000..e847465 --- /dev/null +++ b/.cache/state/jobs.json @@ -0,0 +1 @@ +{"c4e10ad3-03a8-4ccd-b64e-4b36da4ced28": {"jobId": "c4e10ad3-03a8-4ccd-b64e-4b36da4ced28", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:58:59.188643Z", "updated": "2026-02-23T21:58:59.188643Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "7fd59008-4d1c-471c-b3b6-959e14b69edd": {"jobId": "7fd59008-4d1c-471c-b3b6-959e14b69edd", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:58:59.202771Z", "updated": "2026-02-23T21:58:59.202771Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "e3e1dbbc-c230-44e9-8c09-067057cf68d9": {"jobId": "e3e1dbbc-c230-44e9-8c09-067057cf68d9", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.590659Z", "updated": "2026-02-23T21:59:01.590659Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "b6a5a683-f18a-4af5-aeca-4a539e028e67": {"jobId": "b6a5a683-f18a-4af5-aeca-4a539e028e67", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.602127Z", "updated": "2026-02-23T21:59:01.602127Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "c50ec201-9057-44f3-b102-37203efb8682": {"jobId": "c50ec201-9057-44f3-b102-37203efb8682", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.607210Z", "updated": "2026-02-23T21:59:01.607210Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "98e09e8a-fc6c-4f0b-b227-c7bfe30d8675": {"jobId": "98e09e8a-fc6c-4f0b-b227-c7bfe30d8675", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.620520Z", "updated": "2026-02-23T21:59:01.620520Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d": {"jobId": "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.632737Z", "updated": "2026-02-23T21:59:01.632737Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "9ed82292-1c23-4a6f-8077-561c8d431e5a": {"jobId": "9ed82292-1c23-4a6f-8077-561c8d431e5a", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T21:59:01.656924Z", "updated": "2026-02-23T21:59:01.657957Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "865232a5-c544-4120-a2b7-47c8f2a27806": {"jobId": "865232a5-c544-4120-a2b7-47c8f2a27806", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.665259Z", "updated": "2026-02-23T21:59:01.666993Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "8337900a-0fc6-4f53-a13e-89540fb03d2e": {"jobId": "8337900a-0fc6-4f53-a13e-89540fb03d2e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.677649Z", "updated": "2026-02-23T21:59:01.677649Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "2f057f66-9e2f-417a-a416-18a788cc2c4a": {"jobId": "2f057f66-9e2f-417a-a416-18a788cc2c4a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.688591Z", "updated": "2026-02-23T21:59:01.688591Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "75de8c95-32fd-4e9a-91a6-756110b67124": {"jobId": "75de8c95-32fd-4e9a-91a6-756110b67124", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:02.163691Z", "updated": "2026-02-23T21:59:02.163691Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "bdebbf54-ca89-48f2-b2a6-3492d2b7676c": {"jobId": "bdebbf54-ca89-48f2-b2a6-3492d2b7676c", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:02:58.655213Z", "updated": "2026-02-23T22:02:58.655213Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "78c36058-d757-4dad-92fa-f8703a052d41": {"jobId": "78c36058-d757-4dad-92fa-f8703a052d41", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:02:58.669440Z", "updated": "2026-02-23T22:02:58.669440Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "af6c1ed5-0a33-47ae-aef6-9e17653cf0a4": {"jobId": "af6c1ed5-0a33-47ae-aef6-9e17653cf0a4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:00.948460Z", "updated": "2026-02-23T22:03:00.948460Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "c6398375-2a54-47dc-a910-7d6942cc290d": {"jobId": "c6398375-2a54-47dc-a910-7d6942cc290d", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:00.963801Z", "updated": "2026-02-23T22:03:00.963801Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "33118ebd-6849-4b47-b61d-a59b3b9747a3": {"jobId": "33118ebd-6849-4b47-b61d-a59b3b9747a3", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.108286Z", "updated": "2026-02-23T22:03:01.108286Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1a111b92-83f4-44a6-9bcd-c9d7c05b7032": {"jobId": "1a111b92-83f4-44a6-9bcd-c9d7c05b7032", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.242058Z", "updated": "2026-02-23T22:03:01.242058Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8ae1afa0-88d9-493a-89e7-d118c6651e43": {"jobId": "8ae1afa0-88d9-493a-89e7-d118c6651e43", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.347704Z", "updated": "2026-02-23T22:03:01.347704Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fef7a2ef-eda6-42b0-a95d-da21341ab899": {"jobId": "fef7a2ef-eda6-42b0-a95d-da21341ab899", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:03:01.375491Z", "updated": "2026-02-23T22:03:01.377348Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "785832c4-e2a6-43d1-a64a-53d3148f18a9": {"jobId": "785832c4-e2a6-43d1-a64a-53d3148f18a9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.385768Z", "updated": "2026-02-23T22:03:01.388980Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "d42e8fc4-1023-453c-9aae-8c33141ca838": {"jobId": "d42e8fc4-1023-453c-9aae-8c33141ca838", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.501817Z", "updated": "2026-02-23T22:03:01.501817Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "6b0eb5cb-57c9-4945-88b8-029123af9a2d": {"jobId": "6b0eb5cb-57c9-4945-88b8-029123af9a2d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.649712Z", "updated": "2026-02-23T22:03:01.649712Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2187b12b-1dc3-486c-906f-5d5d79a650b4": {"jobId": "2187b12b-1dc3-486c-906f-5d5d79a650b4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.863133Z", "updated": "2026-02-23T22:03:01.863133Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "e7b8935b-cdf0-40e4-a12c-3e0cb94e7fe1": {"jobId": "e7b8935b-cdf0-40e4-a12c-3e0cb94e7fe1", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:32.137243Z", "updated": "2026-02-23T22:03:32.137243Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "589b3193-0684-43bf-83ce-164e22b5866d": {"jobId": "589b3193-0684-43bf-83ce-164e22b5866d", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:32.153159Z", "updated": "2026-02-23T22:03:32.153159Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "1a897341-a4d7-4ed8-827e-a8c70e12743b": {"jobId": "1a897341-a4d7-4ed8-827e-a8c70e12743b", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.420141Z", "updated": "2026-02-23T22:03:34.420141Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "0a34d07d-f3e2-4ce4-9ed1-2e068d448d65": {"jobId": "0a34d07d-f3e2-4ce4-9ed1-2e068d448d65", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.435985Z", "updated": "2026-02-23T22:03:34.435985Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "ba464088-1fa7-46b4-839e-8a6daceae41e": {"jobId": "ba464088-1fa7-46b4-839e-8a6daceae41e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.570403Z", "updated": "2026-02-23T22:03:34.570403Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "6b2d03e9-9e31-42f4-80f4-8d1b27442c78": {"jobId": "6b2d03e9-9e31-42f4-80f4-8d1b27442c78", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.695656Z", "updated": "2026-02-23T22:03:34.695656Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5d45d9ce-795c-4615-b973-33cc358c1327": {"jobId": "5d45d9ce-795c-4615-b973-33cc358c1327", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.805109Z", "updated": "2026-02-23T22:03:34.805109Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4c2dae6b-dbff-4591-91ca-5a679a4cd52f": {"jobId": "4c2dae6b-dbff-4591-91ca-5a679a4cd52f", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:03:34.833666Z", "updated": "2026-02-23T22:03:34.836522Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "c2c62770-2bef-4f4f-9118-84b217b504f0": {"jobId": "c2c62770-2bef-4f4f-9118-84b217b504f0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.846117Z", "updated": "2026-02-23T22:03:34.849465Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "d6098fe4-5916-4d3b-b540-de1076f51c8d": {"jobId": "d6098fe4-5916-4d3b-b540-de1076f51c8d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.960970Z", "updated": "2026-02-23T22:03:34.960970Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2462ff1e-4093-490c-bef6-eacb3b094e1f": {"jobId": "2462ff1e-4093-490c-bef6-eacb3b094e1f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:35.106651Z", "updated": "2026-02-23T22:03:35.106651Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b7920d20-1954-44e2-81d2-e76bf4f03e90": {"jobId": "b7920d20-1954-44e2-81d2-e76bf4f03e90", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:35.319641Z", "updated": "2026-02-23T22:03:35.319641Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "446976dc-2fba-4de9-b94d-9d066fdc0c4e": {"jobId": "446976dc-2fba-4de9-b94d-9d066fdc0c4e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:06.462908Z", "updated": "2026-02-23T22:04:06.462908Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "0ed8ec84-c466-41e3-9591-0553c77975a9": {"jobId": "0ed8ec84-c466-41e3-9591-0553c77975a9", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:06.479128Z", "updated": "2026-02-23T22:04:06.479128Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "b78441e3-a9f1-437c-a279-15518692ac62": {"jobId": "b78441e3-a9f1-437c-a279-15518692ac62", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.742026Z", "updated": "2026-02-23T22:04:08.742026Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "69a12038-bcd5-4e8b-a545-0c6f6d3d2a52": {"jobId": "69a12038-bcd5-4e8b-a545-0c6f6d3d2a52", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.756654Z", "updated": "2026-02-23T22:04:08.756654Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "41bac021-d432-437f-85dc-bba5cb0757a6": {"jobId": "41bac021-d432-437f-85dc-bba5cb0757a6", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.885064Z", "updated": "2026-02-23T22:04:08.885064Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5442f975-e3e8-4627-9737-b0ed509543c8": {"jobId": "5442f975-e3e8-4627-9737-b0ed509543c8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.010488Z", "updated": "2026-02-23T22:04:09.010488Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5f68bea6-8dd8-421e-98d7-0cc70d496462": {"jobId": "5f68bea6-8dd8-421e-98d7-0cc70d496462", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.122398Z", "updated": "2026-02-23T22:04:09.122398Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4": {"jobId": "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:04:09.153630Z", "updated": "2026-02-23T22:04:09.157440Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "67480820-6c57-4fd5-a991-1f7ddfd0ee56": {"jobId": "67480820-6c57-4fd5-a991-1f7ddfd0ee56", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.167290Z", "updated": "2026-02-23T22:04:09.171405Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "fb84e869-28c5-4187-b963-62a0f0ddb0d0": {"jobId": "fb84e869-28c5-4187-b963-62a0f0ddb0d0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.286819Z", "updated": "2026-02-23T22:04:09.286819Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5d9f7eba-2303-4efa-aa2c-30f93fc6971a": {"jobId": "5d9f7eba-2303-4efa-aa2c-30f93fc6971a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.471642Z", "updated": "2026-02-23T22:04:09.471642Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "697f0d2d-d86a-4bfe-8dac-aa80a6b5df7f": {"jobId": "697f0d2d-d86a-4bfe-8dac-aa80a6b5df7f", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.691847Z", "updated": "2026-02-23T22:04:09.691847Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "bab696ee-5483-4c82-bf44-e457c5f0ea69": {"jobId": "bab696ee-5483-4c82-bf44-e457c5f0ea69", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:23.547932Z", "updated": "2026-02-23T22:05:23.547932Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "370b5752-bb53-44e5-b373-96d014ead43f": {"jobId": "370b5752-bb53-44e5-b373-96d014ead43f", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:23.564772Z", "updated": "2026-02-23T22:05:23.564772Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "d9d78be7-a46e-4236-a815-f65e42cab9fe": {"jobId": "d9d78be7-a46e-4236-a815-f65e42cab9fe", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.819681Z", "updated": "2026-02-23T22:05:25.819681Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "d9248c76-d0b1-4107-8739-d26e01dd859c": {"jobId": "d9248c76-d0b1-4107-8739-d26e01dd859c", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.835593Z", "updated": "2026-02-23T22:05:25.835593Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "23ee0b0c-c1f0-4be4-83d3-c82e8fe98ae7": {"jobId": "23ee0b0c-c1f0-4be4-83d3-c82e8fe98ae7", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.939376Z", "updated": "2026-02-23T22:05:25.939376Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "48b4c768-bbaf-47a8-aeb7-44e697067cb9": {"jobId": "48b4c768-bbaf-47a8-aeb7-44e697067cb9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.102926Z", "updated": "2026-02-23T22:05:26.102926Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "052828cb-fe04-4107-8168-bf626dc3d2d4": {"jobId": "052828cb-fe04-4107-8168-bf626dc3d2d4", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.213041Z", "updated": "2026-02-23T22:05:26.213041Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "057a6900-c6e4-4ee7-b392-16cc852a7beb": {"jobId": "057a6900-c6e4-4ee7-b392-16cc852a7beb", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:05:26.244912Z", "updated": "2026-02-23T22:05:26.249375Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "f07f0036-8f43-4d12-8811-7a3e6603228b": {"jobId": "f07f0036-8f43-4d12-8811-7a3e6603228b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.260482Z", "updated": "2026-02-23T22:05:26.265682Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff": {"jobId": "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.380473Z", "updated": "2026-02-23T22:05:26.380473Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b232896b-2721-46b8-abc8-9761a40f9d22": {"jobId": "b232896b-2721-46b8-abc8-9761a40f9d22", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.527434Z", "updated": "2026-02-23T22:05:26.527434Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1f2bf79d-8181-490d-a45e-9438e38b45c6": {"jobId": "1f2bf79d-8181-490d-a45e-9438e38b45c6", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.742199Z", "updated": "2026-02-23T22:05:26.742199Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "6df02f8b-df42-41dd-b987-a06dbeaf5539": {"jobId": "6df02f8b-df42-41dd-b987-a06dbeaf5539", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:17.263363Z", "updated": "2026-02-23T22:06:17.263363Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8ea3e465-f7a8-4b71-8375-38f65fcf63ca": {"jobId": "8ea3e465-f7a8-4b71-8375-38f65fcf63ca", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:17.295123Z", "updated": "2026-02-23T22:06:17.295123Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "444c5c43-cbdd-409f-b180-e8b339f8ef11": {"jobId": "444c5c43-cbdd-409f-b180-e8b339f8ef11", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.520179Z", "updated": "2026-02-23T22:06:19.520179Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "ebc38efc-530c-444c-bb0f-a9b22912944c": {"jobId": "ebc38efc-530c-444c-bb0f-a9b22912944c", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.536100Z", "updated": "2026-02-23T22:06:19.536100Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "973f8a9e-f220-436f-91b2-6507e96b615a": {"jobId": "973f8a9e-f220-436f-91b2-6507e96b615a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.666645Z", "updated": "2026-02-23T22:06:19.666645Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ab19876c-d13d-4c37-82f5-af575b863ae9": {"jobId": "ab19876c-d13d-4c37-82f5-af575b863ae9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.795408Z", "updated": "2026-02-23T22:06:19.795408Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bb27b64c-2cda-41ab-8e2b-b23ff462de71": {"jobId": "bb27b64c-2cda-41ab-8e2b-b23ff462de71", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.907708Z", "updated": "2026-02-23T22:06:19.907708Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d0cd71f3-2aff-4345-8804-6451bd9d78bd": {"jobId": "d0cd71f3-2aff-4345-8804-6451bd9d78bd", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:06:19.940310Z", "updated": "2026-02-23T22:06:19.945539Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "4c120e2c-3b8e-471c-a944-d4fe46e6544d": {"jobId": "4c120e2c-3b8e-471c-a944-d4fe46e6544d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.965760Z", "updated": "2026-02-23T22:06:19.972003Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "a0138e99-87f4-4213-b003-53e4435d2191": {"jobId": "a0138e99-87f4-4213-b003-53e4435d2191", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.085244Z", "updated": "2026-02-23T22:06:20.085244Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "67ffa0a9-35fe-4780-b5e7-17cebd8321c3": {"jobId": "67ffa0a9-35fe-4780-b5e7-17cebd8321c3", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.234581Z", "updated": "2026-02-23T22:06:20.234581Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1640da1c-e8fe-4aaf-b8d6-5f4441a05f4d": {"jobId": "1640da1c-e8fe-4aaf-b8d6-5f4441a05f4d", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.456531Z", "updated": "2026-02-23T22:06:20.456531Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "1bea47ea-b78c-4c37-ad4a-4bc4731dc493": {"jobId": "1bea47ea-b78c-4c37-ad4a-4bc4731dc493", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:07.539027Z", "updated": "2026-02-23T22:07:07.539027Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1277fe9e-4a99-4014-8c55-66804e616440": {"jobId": "1277fe9e-4a99-4014-8c55-66804e616440", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:07.558215Z", "updated": "2026-02-23T22:07:07.558215Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "267b8300-765d-40e3-9ec2-5d6478f47892": {"jobId": "267b8300-765d-40e3-9ec2-5d6478f47892", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.804460Z", "updated": "2026-02-23T22:07:09.804460Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "cdefce12-bd1d-4828-a27d-0960d104c6fa": {"jobId": "cdefce12-bd1d-4828-a27d-0960d104c6fa", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.821632Z", "updated": "2026-02-23T22:07:09.821632Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "092d45de-2992-4688-9eea-5e47bef48651": {"jobId": "092d45de-2992-4688-9eea-5e47bef48651", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.928469Z", "updated": "2026-02-23T22:07:09.928469Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "55481550-c20d-404f-888b-972569e1a21d": {"jobId": "55481550-c20d-404f-888b-972569e1a21d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.096984Z", "updated": "2026-02-23T22:07:10.096984Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "db8c46c0-4252-4091-89b6-7bcac3da7ab2": {"jobId": "db8c46c0-4252-4091-89b6-7bcac3da7ab2", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.207616Z", "updated": "2026-02-23T22:07:10.207616Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "36ad61d8-3b1a-4fa3-bc58-b801c12e6980": {"jobId": "36ad61d8-3b1a-4fa3-bc58-b801c12e6980", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:07:10.241678Z", "updated": "2026-02-23T22:07:10.247863Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "7c89eaf6-cad3-42bf-82b7-0159b289ab4d": {"jobId": "7c89eaf6-cad3-42bf-82b7-0159b289ab4d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.260512Z", "updated": "2026-02-23T22:07:10.267134Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "07711cbe-a49b-43ec-b9f5-a47ff809a637": {"jobId": "07711cbe-a49b-43ec-b9f5-a47ff809a637", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.381958Z", "updated": "2026-02-23T22:07:10.381958Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b60ed6da-a124-49f0-a4ac-d52c8d79cb70": {"jobId": "b60ed6da-a124-49f0-a4ac-d52c8d79cb70", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.534954Z", "updated": "2026-02-23T22:07:10.534954Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b7198527-3cd1-4105-ad05-e96e3eb2dc0b": {"jobId": "b7198527-3cd1-4105-ad05-e96e3eb2dc0b", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.756754Z", "updated": "2026-02-23T22:07:10.756754Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "8c44185b-b5d3-48be-9786-fd8949a4eec0": {"jobId": "8c44185b-b5d3-48be-9786-fd8949a4eec0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:23.056931Z", "updated": "2026-02-23T22:08:23.056931Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "159d008c-2cbe-43dc-9da0-d476df8f8912": {"jobId": "159d008c-2cbe-43dc-9da0-d476df8f8912", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:23.078203Z", "updated": "2026-02-23T22:08:23.078203Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "4fefa042-d0f2-40d5-878e-65410620d408": {"jobId": "4fefa042-d0f2-40d5-878e-65410620d408", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.348486Z", "updated": "2026-02-23T22:08:25.348486Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "a47f73c7-ce37-48c9-af73-11760b35e296": {"jobId": "a47f73c7-ce37-48c9-af73-11760b35e296", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.366760Z", "updated": "2026-02-23T22:08:25.366760Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "9be31308-883e-4f46-927f-8faf8a43795d": {"jobId": "9be31308-883e-4f46-927f-8faf8a43795d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.476319Z", "updated": "2026-02-23T22:08:25.476319Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b10443b2-5b5c-4a8a-9d3d-7fba142e87c8": {"jobId": "b10443b2-5b5c-4a8a-9d3d-7fba142e87c8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.648456Z", "updated": "2026-02-23T22:08:25.648456Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1df779b8-aa1c-439f-a5d7-3525fb54dc77": {"jobId": "1df779b8-aa1c-439f-a5d7-3525fb54dc77", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.758845Z", "updated": "2026-02-23T22:08:25.758845Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33": {"jobId": "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:08:25.793139Z", "updated": "2026-02-23T22:08:25.800459Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "2da98086-c89d-49cb-bac4-5a2f63c02d3b": {"jobId": "2da98086-c89d-49cb-bac4-5a2f63c02d3b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.814740Z", "updated": "2026-02-23T22:08:25.822762Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "e3f2a3ef-efb8-4a71-a892-437463f84e13": {"jobId": "e3f2a3ef-efb8-4a71-a892-437463f84e13", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.940926Z", "updated": "2026-02-23T22:08:25.940926Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c8e8832f-a05e-4ae1-89bc-418391552a31": {"jobId": "c8e8832f-a05e-4ae1-89bc-418391552a31", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:26.094254Z", "updated": "2026-02-23T22:08:26.094254Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "3491be0a-69f9-4f9a-924c-79fbcb7404a5": {"jobId": "3491be0a-69f9-4f9a-924c-79fbcb7404a5", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:26.312951Z", "updated": "2026-02-23T22:08:26.312951Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "b78a5896-d88d-4592-bc98-36dd20426679": {"jobId": "b78a5896-d88d-4592-bc98-36dd20426679", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:08.677668Z", "updated": "2026-02-23T22:10:08.677668Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c842962b-c87d-4787-bbed-499da0a0e659": {"jobId": "c842962b-c87d-4787-bbed-499da0a0e659", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:08.698047Z", "updated": "2026-02-23T22:10:08.698047Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "9ffc08f6-24de-4744-9f55-5416c269c284": {"jobId": "9ffc08f6-24de-4744-9f55-5416c269c284", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:10.975367Z", "updated": "2026-02-23T22:10:10.975367Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "33140241-39cf-4963-9a9f-c4068665dbdb": {"jobId": "33140241-39cf-4963-9a9f-c4068665dbdb", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:10.995315Z", "updated": "2026-02-23T22:10:10.995315Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "51621767-7943-48df-a074-9f29f6c2374d": {"jobId": "51621767-7943-48df-a074-9f29f6c2374d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.106175Z", "updated": "2026-02-23T22:10:11.106175Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d3119749-3e84-489c-b36c-de752ff0f44f": {"jobId": "d3119749-3e84-489c-b36c-de752ff0f44f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.269887Z", "updated": "2026-02-23T22:10:11.269887Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "48cc3a56-6df8-42b6-a1cd-ab380a687d17": {"jobId": "48cc3a56-6df8-42b6-a1cd-ab380a687d17", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.379628Z", "updated": "2026-02-23T22:10:11.379628Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "672705fa-17df-48d3-9dfe-89edd3033977": {"jobId": "672705fa-17df-48d3-9dfe-89edd3033977", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:10:11.415532Z", "updated": "2026-02-23T22:10:11.423246Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "62523329-5a27-4557-ae52-b3a3668cf8b9": {"jobId": "62523329-5a27-4557-ae52-b3a3668cf8b9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.438093Z", "updated": "2026-02-23T22:10:11.447351Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "3bc40154-66d2-44b8-bf8a-3c931d7ce92a": {"jobId": "3bc40154-66d2-44b8-bf8a-3c931d7ce92a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.565043Z", "updated": "2026-02-23T22:10:11.565043Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "aa3f467e-d50a-4120-b9b0-0e2d121f169e": {"jobId": "aa3f467e-d50a-4120-b9b0-0e2d121f169e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.717150Z", "updated": "2026-02-23T22:10:11.717150Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d59d5ce4-e5a1-4087-91df-f5f957b056ef": {"jobId": "d59d5ce4-e5a1-4087-91df-f5f957b056ef", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.933145Z", "updated": "2026-02-23T22:10:11.933145Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "277592bc-6939-4806-af05-87c7bf533d5f": {"jobId": "277592bc-6939-4806-af05-87c7bf533d5f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:24.503021Z", "updated": "2026-02-23T22:12:24.503021Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7006c679-b227-4022-9c35-3e2cfc85b0f4": {"jobId": "7006c679-b227-4022-9c35-3e2cfc85b0f4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:24.525639Z", "updated": "2026-02-23T22:12:24.525639Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "8b551dab-da4c-49ad-99ad-beafe80eebb1": {"jobId": "8b551dab-da4c-49ad-99ad-beafe80eebb1", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:26.896434Z", "updated": "2026-02-23T22:12:26.896434Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "a771c412-cd8d-481f-86c5-60973c502cf2": {"jobId": "a771c412-cd8d-481f-86c5-60973c502cf2", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:26.917174Z", "updated": "2026-02-23T22:12:26.917174Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "895fa56d-a56a-45a0-bcac-1ba7cb072f9d": {"jobId": "895fa56d-a56a-45a0-bcac-1ba7cb072f9d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.031192Z", "updated": "2026-02-23T22:12:27.031192Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b878b07e-4d0c-4452-8ad0-b7d2e014b415": {"jobId": "b878b07e-4d0c-4452-8ad0-b7d2e014b415", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.214706Z", "updated": "2026-02-23T22:12:27.214706Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4c59c2e2-a55c-475e-8f49-8060b0070c15": {"jobId": "4c59c2e2-a55c-475e-8f49-8060b0070c15", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.331969Z", "updated": "2026-02-23T22:12:27.331969Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "743ddcec-4c43-49cf-a3d7-a79fd07d203c": {"jobId": "743ddcec-4c43-49cf-a3d7-a79fd07d203c", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:12:27.370127Z", "updated": "2026-02-23T22:12:27.378919Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "048b97d2-321b-412b-8add-8bfc73947d10": {"jobId": "048b97d2-321b-412b-8add-8bfc73947d10", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.395188Z", "updated": "2026-02-23T22:12:27.405120Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "faaa0822-0996-42aa-9b4a-09db3b38b253": {"jobId": "faaa0822-0996-42aa-9b4a-09db3b38b253", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.528860Z", "updated": "2026-02-23T22:12:27.528860Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2f62167a-3bab-496e-b408-f1078f023253": {"jobId": "2f62167a-3bab-496e-b408-f1078f023253", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.680510Z", "updated": "2026-02-23T22:12:27.680510Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c60578bb-1943-4a06-ba54-ef1f73aa7a31": {"jobId": "c60578bb-1943-4a06-ba54-ef1f73aa7a31", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.896422Z", "updated": "2026-02-23T22:12:27.896422Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "ddd7182d-c5e7-4708-9d27-6c44c59101e6": {"jobId": "ddd7182d-c5e7-4708-9d27-6c44c59101e6", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:52.476895Z", "updated": "2026-02-23T22:13:52.476895Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "dce96d73-0dd2-433a-ab9f-50708fd76735": {"jobId": "dce96d73-0dd2-433a-ab9f-50708fd76735", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:52.499440Z", "updated": "2026-02-23T22:13:52.499440Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "efadd460-9f5d-40e6-b6d2-7f962b324388": {"jobId": "efadd460-9f5d-40e6-b6d2-7f962b324388", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.763632Z", "updated": "2026-02-23T22:13:54.763632Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "9cf3a3f0-f611-41c1-9deb-94268951ce28": {"jobId": "9cf3a3f0-f611-41c1-9deb-94268951ce28", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.785857Z", "updated": "2026-02-23T22:13:54.785857Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "245ec5ef-e750-45ae-8a6e-4b05fd695da7": {"jobId": "245ec5ef-e750-45ae-8a6e-4b05fd695da7", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.893765Z", "updated": "2026-02-23T22:13:54.893765Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "dc3129a8-db7b-4354-bcb5-3beb9df098af": {"jobId": "dc3129a8-db7b-4354-bcb5-3beb9df098af", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.067514Z", "updated": "2026-02-23T22:13:55.067514Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "421d8036-8bb8-4d19-8ab2-16b12114c03f": {"jobId": "421d8036-8bb8-4d19-8ab2-16b12114c03f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.183339Z", "updated": "2026-02-23T22:13:55.183339Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1f0946fe-d7cf-4ff5-ae38-ea332be556f8": {"jobId": "1f0946fe-d7cf-4ff5-ae38-ea332be556f8", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:13:55.221492Z", "updated": "2026-02-23T22:13:55.231516Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "d407d400-5ed4-4dee-9d95-749ef70bfa2d": {"jobId": "d407d400-5ed4-4dee-9d95-749ef70bfa2d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.247933Z", "updated": "2026-02-23T22:13:55.258441Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "89f1748d-a2ff-4fb4-bad4-034af929932e": {"jobId": "89f1748d-a2ff-4fb4-bad4-034af929932e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.373387Z", "updated": "2026-02-23T22:13:55.373387Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fef322d8-8a06-4091-b962-2f6f616cbb71": {"jobId": "fef322d8-8a06-4091-b962-2f6f616cbb71", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.536523Z", "updated": "2026-02-23T22:13:55.536523Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "200b0ab7-b566-4c98-9639-9c019adc4af5": {"jobId": "200b0ab7-b566-4c98-9639-9c019adc4af5", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.767251Z", "updated": "2026-02-23T22:13:55.767251Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "9de477f4-e0ab-44c3-8b0d-a785df5ace6b": {"jobId": "9de477f4-e0ab-44c3-8b0d-a785df5ace6b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:37.450246Z", "updated": "2026-02-23T22:15:37.450246Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2716eab1-7e96-4ecc-a47b-b12890300ed0": {"jobId": "2716eab1-7e96-4ecc-a47b-b12890300ed0", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:37.473495Z", "updated": "2026-02-23T22:15:37.473495Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "affe6d5d-97ce-4762-b4dc-18a8c62bd933": {"jobId": "affe6d5d-97ce-4762-b4dc-18a8c62bd933", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.721512Z", "updated": "2026-02-23T22:15:39.721512Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "5d6a4802-d6fc-4e15-be23-cb55cd6d43fa": {"jobId": "5d6a4802-d6fc-4e15-be23-cb55cd6d43fa", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.743320Z", "updated": "2026-02-23T22:15:39.743320Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "881249ed-7649-49a0-a8d2-ea5d453387b2": {"jobId": "881249ed-7649-49a0-a8d2-ea5d453387b2", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.852155Z", "updated": "2026-02-23T22:15:39.852155Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "09078395-6734-4aa0-804d-342d533f5a08": {"jobId": "09078395-6734-4aa0-804d-342d533f5a08", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.016212Z", "updated": "2026-02-23T22:15:40.016212Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ac76a665-136a-4730-9228-dceb0a828f85": {"jobId": "ac76a665-136a-4730-9228-dceb0a828f85", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.130039Z", "updated": "2026-02-23T22:15:40.130039Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "101a1fa5-3a6b-4923-8b3d-08497fc2cde3": {"jobId": "101a1fa5-3a6b-4923-8b3d-08497fc2cde3", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:15:40.171547Z", "updated": "2026-02-23T22:15:40.182169Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "90649d63-8edc-4d9e-aac5-1b3a6fd2f954": {"jobId": "90649d63-8edc-4d9e-aac5-1b3a6fd2f954", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.200090Z", "updated": "2026-02-23T22:15:40.211787Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b": {"jobId": "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.332893Z", "updated": "2026-02-23T22:15:40.332893Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "e3dee3c1-f3d9-4340-a412-48964442a29b": {"jobId": "e3dee3c1-f3d9-4340-a412-48964442a29b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.497073Z", "updated": "2026-02-23T22:15:40.497073Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "a44b6fc3-3b43-4b6c-ac09-4c2bbd973e37": {"jobId": "a44b6fc3-3b43-4b6c-ac09-4c2bbd973e37", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.733179Z", "updated": "2026-02-23T22:15:40.733179Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "c102da24-1bac-4567-af7f-39a0eff270f4": {"jobId": "c102da24-1bac-4567-af7f-39a0eff270f4", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:53.998689Z", "updated": "2026-02-23T22:16:53.998689Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7b2b7e4b-b1c1-45d7-a382-78b3f72cb077": {"jobId": "7b2b7e4b-b1c1-45d7-a382-78b3f72cb077", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:54.024575Z", "updated": "2026-02-23T22:16:54.024575Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "1a8a2412-5b27-40da-a8f0-94f680e026b4": {"jobId": "1a8a2412-5b27-40da-a8f0-94f680e026b4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.296999Z", "updated": "2026-02-23T22:16:56.296999Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "ec28d8a2-6234-471f-b96f-7c1731d18a0f": {"jobId": "ec28d8a2-6234-471f-b96f-7c1731d18a0f", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.320203Z", "updated": "2026-02-23T22:16:56.320203Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "0dc16554-7eaf-497c-9a1e-4efc286ba872": {"jobId": "0dc16554-7eaf-497c-9a1e-4efc286ba872", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.432278Z", "updated": "2026-02-23T22:16:56.432278Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8e276ac9-189f-432d-adec-b7ab74ea6590": {"jobId": "8e276ac9-189f-432d-adec-b7ab74ea6590", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.602095Z", "updated": "2026-02-23T22:16:56.602095Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9": {"jobId": "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.720377Z", "updated": "2026-02-23T22:16:56.720377Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4e30a788-c134-463a-bdbb-f88b4b5615c9": {"jobId": "4e30a788-c134-463a-bdbb-f88b4b5615c9", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:16:56.760958Z", "updated": "2026-02-23T22:16:56.772441Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "336d659f-b4f7-4a49-a7d0-a5ec78dc25d8": {"jobId": "336d659f-b4f7-4a49-a7d0-a5ec78dc25d8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.791195Z", "updated": "2026-02-23T22:16:56.803752Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "9a34fb59-d815-4107-9c6b-d3207704d83a": {"jobId": "9a34fb59-d815-4107-9c6b-d3207704d83a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.926163Z", "updated": "2026-02-23T22:16:56.926163Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "56c4347f-b16f-40db-9f64-b0239711faac": {"jobId": "56c4347f-b16f-40db-9f64-b0239711faac", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:57.053777Z", "updated": "2026-02-23T22:16:57.053777Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fbe518c3-121e-4097-8a28-322ddee317e7": {"jobId": "fbe518c3-121e-4097-8a28-322ddee317e7", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:57.304091Z", "updated": "2026-02-23T22:16:57.304091Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "cba3a8e8-2dd3-48c3-ad24-822320428aef": {"jobId": "cba3a8e8-2dd3-48c3-ad24-822320428aef", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:06.883459Z", "updated": "2026-02-23T22:18:06.883459Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "40e9fb81-f7f8-48c9-a83c-bf1ce068c960": {"jobId": "40e9fb81-f7f8-48c9-a83c-bf1ce068c960", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:06.910504Z", "updated": "2026-02-23T22:18:06.910504Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "33ff2a20-5a20-4bf0-a70c-dda4f52753e3": {"jobId": "33ff2a20-5a20-4bf0-a70c-dda4f52753e3", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.164136Z", "updated": "2026-02-23T22:18:09.164136Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "798f2a1a-3d44-4778-9552-5eef336a799e": {"jobId": "798f2a1a-3d44-4778-9552-5eef336a799e", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.186896Z", "updated": "2026-02-23T22:18:09.186896Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "426ebad3-da3e-4748-93c0-f7286de43ce8": {"jobId": "426ebad3-da3e-4748-93c0-f7286de43ce8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.295646Z", "updated": "2026-02-23T22:18:09.295646Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4eb5c271-dee4-4f16-9740-141f3ac0e5fa": {"jobId": "4eb5c271-dee4-4f16-9740-141f3ac0e5fa", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.470972Z", "updated": "2026-02-23T22:18:09.470972Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bef54659-7bfc-4c67-b172-1722edcea9cb": {"jobId": "bef54659-7bfc-4c67-b172-1722edcea9cb", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.590918Z", "updated": "2026-02-23T22:18:09.590918Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2ad476b8-a2a6-4783-948e-42087f50a7e4": {"jobId": "2ad476b8-a2a6-4783-948e-42087f50a7e4", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:18:09.635442Z", "updated": "2026-02-23T22:18:09.647649Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "81cfc65f-344c-43da-a0ac-d002ec25c0ed": {"jobId": "81cfc65f-344c-43da-a0ac-d002ec25c0ed", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.667508Z", "updated": "2026-02-23T22:18:09.680422Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "50f69ac8-ca39-4892-bf3c-2921221183b8": {"jobId": "50f69ac8-ca39-4892-bf3c-2921221183b8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.799866Z", "updated": "2026-02-23T22:18:09.799866Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "503e7d84-be48-4fa8-a809-ce44b23325ab": {"jobId": "503e7d84-be48-4fa8-a809-ce44b23325ab", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.925723Z", "updated": "2026-02-23T22:18:09.925723Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c0e21843-e0a2-42a1-806f-faf8b325ab93": {"jobId": "c0e21843-e0a2-42a1-806f-faf8b325ab93", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:10.182289Z", "updated": "2026-02-23T22:18:10.182289Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}} \ No newline at end of file diff --git a/.cache/state/schedules.json b/.cache/state/schedules.json new file mode 100644 index 0000000..2e2e561 --- /dev/null +++ b/.cache/state/schedules.json @@ -0,0 +1 @@ +{"5cfbf7d5-2c31-493e-aa81-ceb20d13db0e": {"scheduleId": "5cfbf7d5-2c31-493e-aa81-ceb20d13db0e", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.631345Z", "updated": "2026-02-23T21:59:01.633759Z", "lastRunAt": "2026-02-23T21:59:01.633759Z", "lastRunJobId": "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d"}, "b19d087c-73de-4421-88d5-9bc6c29d166b": {"scheduleId": "b19d087c-73de-4421-88d5-9bc6c29d166b", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.640858Z", "updated": "2026-02-23T21:59:01.640858Z", "lastRunAt": null, "lastRunJobId": null}, "195d2328-245f-4573-8e5c-a0d18bb6e027": {"scheduleId": "195d2328-245f-4573-8e5c-a0d18bb6e027", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.648433Z", "updated": "2026-02-23T21:59:01.648433Z", "lastRunAt": null, "lastRunJobId": null}, "0c2f0ab1-d72f-4a85-b0bb-1806c151de48": {"scheduleId": "0c2f0ab1-d72f-4a85-b0bb-1806c151de48", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.655548Z", "updated": "2026-02-23T21:59:01.658990Z", "lastRunAt": "2026-02-23T21:59:01.658990Z", "lastRunJobId": "9ed82292-1c23-4a6f-8077-561c8d431e5a"}, "4daf8538-91de-43c1-ab4f-717d5390230a": {"scheduleId": "4daf8538-91de-43c1-ab4f-717d5390230a", "processId": "workflow", "workflowId": "70a148c9-4c30-4ff4-bdc1-d793853cca5b", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T21:59:01.676128Z", "updated": "2026-02-23T21:59:01.679007Z", "lastRunAt": "2026-02-23T21:59:01.679007Z", "lastRunJobId": "8337900a-0fc6-4f53-a13e-89540fb03d2e"}, "287ad6fc-135a-427b-8c6e-68bedf3a0434": {"scheduleId": "287ad6fc-135a-427b-8c6e-68bedf3a0434", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.254541Z", "updated": "2026-02-23T22:03:01.349695Z", "lastRunAt": "2026-02-23T22:03:01.349695Z", "lastRunJobId": "8ae1afa0-88d9-493a-89e7-d118c6651e43"}, "85e67015-5094-4cee-9ff7-5b25276d71d4": {"scheduleId": "85e67015-5094-4cee-9ff7-5b25276d71d4", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.357868Z", "updated": "2026-02-23T22:03:01.357868Z", "lastRunAt": null, "lastRunJobId": null}, "522c7ff1-709f-487a-b6e7-8e3c258f8b3e": {"scheduleId": "522c7ff1-709f-487a-b6e7-8e3c258f8b3e", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.366100Z", "updated": "2026-02-23T22:03:01.366100Z", "lastRunAt": null, "lastRunJobId": null}, "ccad9e3e-cfd3-4ca2-8d82-9ab18dc746d2": {"scheduleId": "ccad9e3e-cfd3-4ca2-8d82-9ab18dc746d2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.373832Z", "updated": "2026-02-23T22:03:01.379077Z", "lastRunAt": "2026-02-23T22:03:01.379077Z", "lastRunJobId": "fef7a2ef-eda6-42b0-a95d-da21341ab899"}, "26a09350-cc9a-4070-b44c-35a9290d3382": {"scheduleId": "26a09350-cc9a-4070-b44c-35a9290d3382", "processId": "workflow", "workflowId": "5919d4fa-644f-4ffc-8541-d258e987b379", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:03:01.400343Z", "updated": "2026-02-23T22:03:01.504385Z", "lastRunAt": "2026-02-23T22:03:01.504385Z", "lastRunJobId": "d42e8fc4-1023-453c-9aae-8c33141ca838"}, "e002f589-33e2-4689-ab75-55ad752772aa": {"scheduleId": "e002f589-33e2-4689-ab75-55ad752772aa", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.709891Z", "updated": "2026-02-23T22:03:34.808021Z", "lastRunAt": "2026-02-23T22:03:34.808021Z", "lastRunJobId": "5d45d9ce-795c-4615-b973-33cc358c1327"}, "4d02c489-5f53-4ee8-a340-f287e39e8dda": {"scheduleId": "4d02c489-5f53-4ee8-a340-f287e39e8dda", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.816852Z", "updated": "2026-02-23T22:03:34.816852Z", "lastRunAt": null, "lastRunJobId": null}, "b307747d-4327-4a51-9d58-f8b54b25fe38": {"scheduleId": "b307747d-4327-4a51-9d58-f8b54b25fe38", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.824292Z", "updated": "2026-02-23T22:03:34.824292Z", "lastRunAt": null, "lastRunJobId": null}, "2ee41b9f-753d-449b-ae0c-cb6dc0c4a4bd": {"scheduleId": "2ee41b9f-753d-449b-ae0c-cb6dc0c4a4bd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.831948Z", "updated": "2026-02-23T22:03:34.839113Z", "lastRunAt": "2026-02-23T22:03:34.839113Z", "lastRunJobId": "4c2dae6b-dbff-4591-91ca-5a679a4cd52f"}, "8f76daef-6165-483f-8254-a4b61c506d8c": {"scheduleId": "8f76daef-6165-483f-8254-a4b61c506d8c", "processId": "workflow", "workflowId": "90ee914e-925d-4775-bbdb-8489f79e6b2d", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:03:34.860159Z", "updated": "2026-02-23T22:03:34.964368Z", "lastRunAt": "2026-02-23T22:03:34.964368Z", "lastRunJobId": "d6098fe4-5916-4d3b-b540-de1076f51c8d"}, "2adddf18-8041-4049-91ca-e82706bb4bd5": {"scheduleId": "2adddf18-8041-4049-91ca-e82706bb4bd5", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.025807Z", "updated": "2026-02-23T22:04:09.126220Z", "lastRunAt": "2026-02-23T22:04:09.126220Z", "lastRunJobId": "5f68bea6-8dd8-421e-98d7-0cc70d496462"}, "4ced4308-4f5c-4c9d-8ee0-7bf0fdbebe7d": {"scheduleId": "4ced4308-4f5c-4c9d-8ee0-7bf0fdbebe7d", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.135097Z", "updated": "2026-02-23T22:04:09.135097Z", "lastRunAt": null, "lastRunJobId": null}, "c0109e78-5124-4a5c-9ebd-f715c0d63e10": {"scheduleId": "c0109e78-5124-4a5c-9ebd-f715c0d63e10", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.143459Z", "updated": "2026-02-23T22:04:09.143459Z", "lastRunAt": null, "lastRunJobId": null}, "e9be5417-17c2-4335-8e16-696ef8554757": {"scheduleId": "e9be5417-17c2-4335-8e16-696ef8554757", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.151811Z", "updated": "2026-02-23T22:04:09.160932Z", "lastRunAt": "2026-02-23T22:04:09.160932Z", "lastRunJobId": "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4"}, "d1f00049-3f7b-4f65-bab9-4af6b547f867": {"scheduleId": "d1f00049-3f7b-4f65-bab9-4af6b547f867", "processId": "workflow", "workflowId": "364063da-5825-4303-9736-51baf8692530", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:04:09.183145Z", "updated": "2026-02-23T22:04:09.291053Z", "lastRunAt": "2026-02-23T22:04:09.291053Z", "lastRunJobId": "fb84e869-28c5-4187-b963-62a0f0ddb0d0"}, "687d73de-f481-4b7a-8f23-454efb712e04": {"scheduleId": "687d73de-f481-4b7a-8f23-454efb712e04", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.119079Z", "updated": "2026-02-23T22:05:26.217653Z", "lastRunAt": "2026-02-23T22:05:26.217653Z", "lastRunJobId": "052828cb-fe04-4107-8168-bf626dc3d2d4"}, "fb1bc1c1-fb12-4c5c-a973-4bfdbf6fe5cb": {"scheduleId": "fb1bc1c1-fb12-4c5c-a973-4bfdbf6fe5cb", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.226313Z", "updated": "2026-02-23T22:05:26.226313Z", "lastRunAt": null, "lastRunJobId": null}, "02d9f727-8c86-4c7a-961c-2c4bb8608736": {"scheduleId": "02d9f727-8c86-4c7a-961c-2c4bb8608736", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.234478Z", "updated": "2026-02-23T22:05:26.234478Z", "lastRunAt": null, "lastRunJobId": null}, "dff69560-5acc-47cf-a051-8eeb011f2db7": {"scheduleId": "dff69560-5acc-47cf-a051-8eeb011f2db7", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.242902Z", "updated": "2026-02-23T22:05:26.253967Z", "lastRunAt": "2026-02-23T22:05:26.253967Z", "lastRunJobId": "057a6900-c6e4-4ee7-b392-16cc852a7beb"}, "51f94cf2-b5b6-49a7-bf0c-a537a6aa1b56": {"scheduleId": "51f94cf2-b5b6-49a7-bf0c-a537a6aa1b56", "processId": "workflow", "workflowId": "9be46657-dc95-4197-b520-034877ad53fd", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:05:26.278557Z", "updated": "2026-02-23T22:05:26.385589Z", "lastRunAt": "2026-02-23T22:05:26.385589Z", "lastRunJobId": "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff"}, "af06959e-30ef-49e3-93c8-25e9f3d50313": {"scheduleId": "af06959e-30ef-49e3-93c8-25e9f3d50313", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.812584Z", "updated": "2026-02-23T22:06:19.913115Z", "lastRunAt": "2026-02-23T22:06:19.913115Z", "lastRunJobId": "bb27b64c-2cda-41ab-8e2b-b23ff462de71"}, "bd946b5d-305a-45c4-8869-d4d1d25e6a31": {"scheduleId": "bd946b5d-305a-45c4-8869-d4d1d25e6a31", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.921791Z", "updated": "2026-02-23T22:06:19.921791Z", "lastRunAt": null, "lastRunJobId": null}, "4fcde89a-32f2-445e-84f0-dfa7255070d9": {"scheduleId": "4fcde89a-32f2-445e-84f0-dfa7255070d9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.929875Z", "updated": "2026-02-23T22:06:19.929875Z", "lastRunAt": null, "lastRunJobId": null}, "90677ea1-0ed0-4fda-9b94-8b2fcad101d2": {"scheduleId": "90677ea1-0ed0-4fda-9b94-8b2fcad101d2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.938256Z", "updated": "2026-02-23T22:06:19.950940Z", "lastRunAt": "2026-02-23T22:06:19.950940Z", "lastRunJobId": "d0cd71f3-2aff-4345-8804-6451bd9d78bd"}, "19b99ee9-39ff-48d6-ba66-fc4ab92863ae": {"scheduleId": "19b99ee9-39ff-48d6-ba66-fc4ab92863ae", "processId": "workflow", "workflowId": "5b2d0e9f-a83b-46a1-bac0-93d7693df940", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:06:19.985953Z", "updated": "2026-02-23T22:06:20.091324Z", "lastRunAt": "2026-02-23T22:06:20.091324Z", "lastRunJobId": "a0138e99-87f4-4213-b003-53e4435d2191"}, "82e3bc02-1c6a-4b9b-b2d4-4b8e101fe724": {"scheduleId": "82e3bc02-1c6a-4b9b-b2d4-4b8e101fe724", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.115363Z", "updated": "2026-02-23T22:07:10.213898Z", "lastRunAt": "2026-02-23T22:07:10.213898Z", "lastRunJobId": "db8c46c0-4252-4091-89b6-7bcac3da7ab2"}, "ee39e6f6-db58-4b73-bdf0-2489b8bd875d": {"scheduleId": "ee39e6f6-db58-4b73-bdf0-2489b8bd875d", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.222341Z", "updated": "2026-02-23T22:07:10.222341Z", "lastRunAt": null, "lastRunJobId": null}, "4fe2da51-f1e5-4fb9-af57-60b7aef990b3": {"scheduleId": "4fe2da51-f1e5-4fb9-af57-60b7aef990b3", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.231146Z", "updated": "2026-02-23T22:07:10.231146Z", "lastRunAt": null, "lastRunJobId": null}, "675b3b23-e03f-424d-b9e8-0a1fdcb0cf21": {"scheduleId": "675b3b23-e03f-424d-b9e8-0a1fdcb0cf21", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.239832Z", "updated": "2026-02-23T22:07:10.253859Z", "lastRunAt": "2026-02-23T22:07:10.253859Z", "lastRunJobId": "36ad61d8-3b1a-4fa3-bc58-b801c12e6980"}, "91b646d5-d79d-47fe-899b-8267ad579745": {"scheduleId": "91b646d5-d79d-47fe-899b-8267ad579745", "processId": "workflow", "workflowId": "99f60372-418b-4205-b3e1-0f95b8c47ec3", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:07:10.281216Z", "updated": "2026-02-23T22:07:10.388949Z", "lastRunAt": "2026-02-23T22:07:10.388949Z", "lastRunJobId": "07711cbe-a49b-43ec-b9f5-a47ff809a637"}, "d8aef236-4b7d-40db-b379-b24e9b78b458": {"scheduleId": "d8aef236-4b7d-40db-b379-b24e9b78b458", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.668009Z", "updated": "2026-02-23T22:08:25.765997Z", "lastRunAt": "2026-02-23T22:08:25.765997Z", "lastRunJobId": "1df779b8-aa1c-439f-a5d7-3525fb54dc77"}, "c563a474-3ee3-4622-bb9e-2b0216a1bc6a": {"scheduleId": "c563a474-3ee3-4622-bb9e-2b0216a1bc6a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.774336Z", "updated": "2026-02-23T22:08:25.774336Z", "lastRunAt": null, "lastRunJobId": null}, "c33608bb-5677-4e2b-8cd4-1953c538d4ba": {"scheduleId": "c33608bb-5677-4e2b-8cd4-1953c538d4ba", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.782572Z", "updated": "2026-02-23T22:08:25.782572Z", "lastRunAt": null, "lastRunJobId": null}, "f7b1e808-e37d-4524-95da-bcd725fee8f2": {"scheduleId": "f7b1e808-e37d-4524-95da-bcd725fee8f2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.791049Z", "updated": "2026-02-23T22:08:25.807702Z", "lastRunAt": "2026-02-23T22:08:25.807702Z", "lastRunJobId": "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33"}, "730b4b89-b173-454b-8266-3e926815ac8b": {"scheduleId": "730b4b89-b173-454b-8266-3e926815ac8b", "processId": "workflow", "workflowId": "d122ebc8-c984-41dc-a867-25507acedb91", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:08:25.838704Z", "updated": "2026-02-23T22:08:25.949015Z", "lastRunAt": "2026-02-23T22:08:25.949015Z", "lastRunJobId": "e3f2a3ef-efb8-4a71-a892-437463f84e13"}, "610d77ed-461b-4e3e-b435-a6f66758894b": {"scheduleId": "610d77ed-461b-4e3e-b435-a6f66758894b", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.289695Z", "updated": "2026-02-23T22:10:11.387875Z", "lastRunAt": "2026-02-23T22:10:11.387875Z", "lastRunJobId": "48cc3a56-6df8-42b6-a1cd-ab380a687d17"}, "8dc5d3d9-29bb-49bc-b6f8-d59852317d84": {"scheduleId": "8dc5d3d9-29bb-49bc-b6f8-d59852317d84", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.396699Z", "updated": "2026-02-23T22:10:11.396699Z", "lastRunAt": null, "lastRunJobId": null}, "beddb641-b328-4b72-b140-311e8191bf8a": {"scheduleId": "beddb641-b328-4b72-b140-311e8191bf8a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.405166Z", "updated": "2026-02-23T22:10:11.405166Z", "lastRunAt": null, "lastRunJobId": null}, "a6b28e0a-a35e-4a34-b71f-a90d035603bc": {"scheduleId": "a6b28e0a-a35e-4a34-b71f-a90d035603bc", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.413250Z", "updated": "2026-02-23T22:10:11.431385Z", "lastRunAt": "2026-02-23T22:10:11.431385Z", "lastRunJobId": "672705fa-17df-48d3-9dfe-89edd3033977"}, "623057f2-056c-45c2-8f76-103c68bb1184": {"scheduleId": "623057f2-056c-45c2-8f76-103c68bb1184", "processId": "workflow", "workflowId": "8615178b-17c8-434f-842b-e9f13b745301", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:10:11.463710Z", "updated": "2026-02-23T22:10:11.573987Z", "lastRunAt": "2026-02-23T22:10:11.573987Z", "lastRunJobId": "3bc40154-66d2-44b8-bf8a-3c931d7ce92a"}, "622341b1-38a3-4af0-858a-2300012d59a7": {"scheduleId": "622341b1-38a3-4af0-858a-2300012d59a7", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.237291Z", "updated": "2026-02-23T22:12:27.340850Z", "lastRunAt": "2026-02-23T22:12:27.340850Z", "lastRunJobId": "4c59c2e2-a55c-475e-8f49-8060b0070c15"}, "99925ea5-18a8-424a-b7da-d73bd335dc75": {"scheduleId": "99925ea5-18a8-424a-b7da-d73bd335dc75", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.350371Z", "updated": "2026-02-23T22:12:27.350371Z", "lastRunAt": null, "lastRunJobId": null}, "c67b9ab1-0dc1-48a5-aec1-20489807497a": {"scheduleId": "c67b9ab1-0dc1-48a5-aec1-20489807497a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.359375Z", "updated": "2026-02-23T22:12:27.359375Z", "lastRunAt": null, "lastRunJobId": null}, "3cb199b7-50a0-4b65-8b2e-426a1d50fcc9": {"scheduleId": "3cb199b7-50a0-4b65-8b2e-426a1d50fcc9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.367947Z", "updated": "2026-02-23T22:12:27.387899Z", "lastRunAt": "2026-02-23T22:12:27.387899Z", "lastRunJobId": "743ddcec-4c43-49cf-a3d7-a79fd07d203c"}, "ccec39ce-7b47-4fba-b991-a03f2a76fa91": {"scheduleId": "ccec39ce-7b47-4fba-b991-a03f2a76fa91", "processId": "workflow", "workflowId": "696e988e-0e0d-4e2a-8bd2-9e6109ae798d", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:12:27.422585Z", "updated": "2026-02-23T22:12:27.538547Z", "lastRunAt": "2026-02-23T22:12:27.538547Z", "lastRunJobId": "faaa0822-0996-42aa-9b4a-09db3b38b253"}, "8c5aa333-1fbe-4def-871c-67846973a0cd": {"scheduleId": "8c5aa333-1fbe-4def-871c-67846973a0cd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.089768Z", "updated": "2026-02-23T22:13:55.193088Z", "lastRunAt": "2026-02-23T22:13:55.193088Z", "lastRunJobId": "421d8036-8bb8-4d19-8ab2-16b12114c03f"}, "4b60855e-b4f1-47a4-8212-757bede1eae9": {"scheduleId": "4b60855e-b4f1-47a4-8212-757bede1eae9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.201948Z", "updated": "2026-02-23T22:13:55.201948Z", "lastRunAt": null, "lastRunJobId": null}, "56c7219c-2f65-4ecf-9c3b-2637a3721373": {"scheduleId": "56c7219c-2f65-4ecf-9c3b-2637a3721373", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.210517Z", "updated": "2026-02-23T22:13:55.210517Z", "lastRunAt": null, "lastRunJobId": null}, "f097970d-3aea-499b-8378-11f1a649efe6": {"scheduleId": "f097970d-3aea-499b-8378-11f1a649efe6", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.219281Z", "updated": "2026-02-23T22:13:55.241108Z", "lastRunAt": "2026-02-23T22:13:55.241108Z", "lastRunJobId": "1f0946fe-d7cf-4ff5-ae38-ea332be556f8"}, "73ed1631-fa29-4acd-a093-d6f844acda2c": {"scheduleId": "73ed1631-fa29-4acd-a093-d6f844acda2c", "processId": "workflow", "workflowId": "76b22e29-d03d-41cc-8afd-1f6d98c904b8", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:13:55.276114Z", "updated": "2026-02-23T22:13:55.383703Z", "lastRunAt": "2026-02-23T22:13:55.383703Z", "lastRunJobId": "89f1748d-a2ff-4fb4-bad4-034af929932e"}, "719443e3-b9b8-4c98-8513-4eb9f398a68f": {"scheduleId": "719443e3-b9b8-4c98-8513-4eb9f398a68f", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.039255Z", "updated": "2026-02-23T22:15:40.141384Z", "lastRunAt": "2026-02-23T22:15:40.141384Z", "lastRunJobId": "ac76a665-136a-4730-9228-dceb0a828f85"}, "ac016e84-b71a-4570-b097-66e7f56601fd": {"scheduleId": "ac016e84-b71a-4570-b097-66e7f56601fd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.150909Z", "updated": "2026-02-23T22:15:40.150909Z", "lastRunAt": null, "lastRunJobId": null}, "9fef80ef-ee87-4a54-84da-1e49be0823d5": {"scheduleId": "9fef80ef-ee87-4a54-84da-1e49be0823d5", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.160032Z", "updated": "2026-02-23T22:15:40.160032Z", "lastRunAt": null, "lastRunJobId": null}, "bb9b0350-2f4a-4cc3-8d80-2728f5d5f790": {"scheduleId": "bb9b0350-2f4a-4cc3-8d80-2728f5d5f790", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.169187Z", "updated": "2026-02-23T22:15:40.192890Z", "lastRunAt": "2026-02-23T22:15:40.192890Z", "lastRunJobId": "101a1fa5-3a6b-4923-8b3d-08497fc2cde3"}, "c80ba67b-279a-4402-93a1-4f338959a04e": {"scheduleId": "c80ba67b-279a-4402-93a1-4f338959a04e", "processId": "workflow", "workflowId": "f94af166-6944-45d6-b972-4500feec0eec", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:15:40.230848Z", "updated": "2026-02-23T22:15:40.344231Z", "lastRunAt": "2026-02-23T22:15:40.344231Z", "lastRunJobId": "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b"}, "58efaf46-a456-42c4-b649-ea1108f15ea9": {"scheduleId": "58efaf46-a456-42c4-b649-ea1108f15ea9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.626648Z", "updated": "2026-02-23T22:16:56.732055Z", "lastRunAt": "2026-02-23T22:16:56.732055Z", "lastRunJobId": "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9"}, "b7e47eb8-a5c3-4b5f-995d-d11c80819ecb": {"scheduleId": "b7e47eb8-a5c3-4b5f-995d-d11c80819ecb", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.741260Z", "updated": "2026-02-23T22:16:56.741260Z", "lastRunAt": null, "lastRunJobId": null}, "b6886dd9-7b18-403b-ab39-f08b82630146": {"scheduleId": "b6886dd9-7b18-403b-ab39-f08b82630146", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.750007Z", "updated": "2026-02-23T22:16:56.750007Z", "lastRunAt": null, "lastRunJobId": null}, "387c67e0-fadf-4c98-80af-68be8fb71cd1": {"scheduleId": "387c67e0-fadf-4c98-80af-68be8fb71cd1", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.758467Z", "updated": "2026-02-23T22:16:56.783858Z", "lastRunAt": "2026-02-23T22:16:56.783858Z", "lastRunJobId": "4e30a788-c134-463a-bdbb-f88b4b5615c9"}, "ec048ce8-ccdf-4414-8f1e-900235643423": {"scheduleId": "ec048ce8-ccdf-4414-8f1e-900235643423", "processId": "workflow", "workflowId": "ba8a6537-d7a7-4062-b169-bc65113cbb8c", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:16:56.823648Z", "updated": "2026-02-23T22:16:56.938637Z", "lastRunAt": "2026-02-23T22:16:56.938637Z", "lastRunJobId": "9a34fb59-d815-4107-9c6b-d3207704d83a"}, "456d431a-5464-40fd-886c-85a6638ae141": {"scheduleId": "456d431a-5464-40fd-886c-85a6638ae141", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.497375Z", "updated": "2026-02-23T22:18:09.603709Z", "lastRunAt": "2026-02-23T22:18:09.603709Z", "lastRunJobId": "bef54659-7bfc-4c67-b172-1722edcea9cb"}, "6f27c166-ad26-4103-b4fd-0c04d4937464": {"scheduleId": "6f27c166-ad26-4103-b4fd-0c04d4937464", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.614239Z", "updated": "2026-02-23T22:18:09.614239Z", "lastRunAt": null, "lastRunJobId": null}, "86fb93ec-4d8e-496c-8359-ddb8ac1bccb3": {"scheduleId": "86fb93ec-4d8e-496c-8359-ddb8ac1bccb3", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.623851Z", "updated": "2026-02-23T22:18:09.623851Z", "lastRunAt": null, "lastRunJobId": null}, "75f754a7-5bbe-40d9-b05e-26f4b53dac7f": {"scheduleId": "75f754a7-5bbe-40d9-b05e-26f4b53dac7f", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.632760Z", "updated": "2026-02-23T22:18:09.660081Z", "lastRunAt": "2026-02-23T22:18:09.660081Z", "lastRunJobId": "2ad476b8-a2a6-4783-948e-42087f50a7e4"}, "c87d04b7-479a-4038-aa91-5a3806e7ba95": {"scheduleId": "c87d04b7-479a-4038-aa91-5a3806e7ba95", "processId": "workflow", "workflowId": "5a390470-b37d-45b2-9633-8435c0167424", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:18:09.701252Z", "updated": "2026-02-23T22:18:09.813071Z", "lastRunAt": "2026-02-23T22:18:09.813071Z", "lastRunJobId": "50f69ac8-ca39-4892-bf3c-2921221183b8"}} \ No newline at end of file diff --git a/.cache/state/workflows.json b/.cache/state/workflows.json new file mode 100644 index 0000000..79cddb1 --- /dev/null +++ b/.cache/state/workflows.json @@ -0,0 +1 @@ +{"70a148c9-4c30-4ff4-bdc1-d793853cca5b": {"workflowId": "70a148c9-4c30-4ff4-bdc1-d793853cca5b", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T21:59:01.674872Z", "updated": "2026-02-23T21:59:01.678721Z", "lastRunAt": "2026-02-23T21:59:01.678721Z", "lastRunJobIds": ["8337900a-0fc6-4f53-a13e-89540fb03d2e"]}, "5919d4fa-644f-4ffc-8541-d258e987b379": {"workflowId": "5919d4fa-644f-4ffc-8541-d258e987b379", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:03:01.398456Z", "updated": "2026-02-23T22:03:01.503931Z", "lastRunAt": "2026-02-23T22:03:01.503931Z", "lastRunJobIds": ["d42e8fc4-1023-453c-9aae-8c33141ca838"]}, "90ee914e-925d-4775-bbdb-8489f79e6b2d": {"workflowId": "90ee914e-925d-4775-bbdb-8489f79e6b2d", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:03:34.858713Z", "updated": "2026-02-23T22:03:34.964026Z", "lastRunAt": "2026-02-23T22:03:34.964026Z", "lastRunJobIds": ["d6098fe4-5916-4d3b-b540-de1076f51c8d"]}, "364063da-5825-4303-9736-51baf8692530": {"workflowId": "364063da-5825-4303-9736-51baf8692530", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:04:09.181686Z", "updated": "2026-02-23T22:04:09.290683Z", "lastRunAt": "2026-02-23T22:04:09.290683Z", "lastRunJobIds": ["fb84e869-28c5-4187-b963-62a0f0ddb0d0"]}, "9be46657-dc95-4197-b520-034877ad53fd": {"workflowId": "9be46657-dc95-4197-b520-034877ad53fd", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:05:26.277030Z", "updated": "2026-02-23T22:05:26.385208Z", "lastRunAt": "2026-02-23T22:05:26.385208Z", "lastRunJobIds": ["8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff"]}, "5b2d0e9f-a83b-46a1-bac0-93d7693df940": {"workflowId": "5b2d0e9f-a83b-46a1-bac0-93d7693df940", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:06:19.984497Z", "updated": "2026-02-23T22:06:20.090912Z", "lastRunAt": "2026-02-23T22:06:20.090912Z", "lastRunJobIds": ["a0138e99-87f4-4213-b003-53e4435d2191"]}, "99f60372-418b-4205-b3e1-0f95b8c47ec3": {"workflowId": "99f60372-418b-4205-b3e1-0f95b8c47ec3", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:07:10.279699Z", "updated": "2026-02-23T22:07:10.388391Z", "lastRunAt": "2026-02-23T22:07:10.388391Z", "lastRunJobIds": ["07711cbe-a49b-43ec-b9f5-a47ff809a637"]}, "d122ebc8-c984-41dc-a867-25507acedb91": {"workflowId": "d122ebc8-c984-41dc-a867-25507acedb91", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:08:25.837044Z", "updated": "2026-02-23T22:08:25.948539Z", "lastRunAt": "2026-02-23T22:08:25.948539Z", "lastRunJobIds": ["e3f2a3ef-efb8-4a71-a892-437463f84e13"]}, "8615178b-17c8-434f-842b-e9f13b745301": {"workflowId": "8615178b-17c8-434f-842b-e9f13b745301", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:10:11.462031Z", "updated": "2026-02-23T22:10:11.573452Z", "lastRunAt": "2026-02-23T22:10:11.573452Z", "lastRunJobIds": ["3bc40154-66d2-44b8-bf8a-3c931d7ce92a"]}, "696e988e-0e0d-4e2a-8bd2-9e6109ae798d": {"workflowId": "696e988e-0e0d-4e2a-8bd2-9e6109ae798d", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:12:27.421003Z", "updated": "2026-02-23T22:12:27.537998Z", "lastRunAt": "2026-02-23T22:12:27.537998Z", "lastRunJobIds": ["faaa0822-0996-42aa-9b4a-09db3b38b253"]}, "76b22e29-d03d-41cc-8afd-1f6d98c904b8": {"workflowId": "76b22e29-d03d-41cc-8afd-1f6d98c904b8", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:13:55.274478Z", "updated": "2026-02-23T22:13:55.383149Z", "lastRunAt": "2026-02-23T22:13:55.383149Z", "lastRunJobIds": ["89f1748d-a2ff-4fb4-bad4-034af929932e"]}, "f94af166-6944-45d6-b972-4500feec0eec": {"workflowId": "f94af166-6944-45d6-b972-4500feec0eec", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:15:40.229164Z", "updated": "2026-02-23T22:15:40.343668Z", "lastRunAt": "2026-02-23T22:15:40.343668Z", "lastRunJobIds": ["a0aa8517-0ec2-4b4a-86c0-5645c4077a6b"]}, "ba8a6537-d7a7-4062-b169-bc65113cbb8c": {"workflowId": "ba8a6537-d7a7-4062-b169-bc65113cbb8c", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:16:56.821962Z", "updated": "2026-02-23T22:16:56.938046Z", "lastRunAt": "2026-02-23T22:16:56.938046Z", "lastRunJobIds": ["9a34fb59-d815-4107-9c6b-d3207704d83a"]}, "5a390470-b37d-45b2-9633-8435c0167424": {"workflowId": "5a390470-b37d-45b2-9633-8435c0167424", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:18:09.699497Z", "updated": "2026-02-23T22:18:09.812445Z", "lastRunAt": "2026-02-23T22:18:09.812445Z", "lastRunJobIds": ["50f69ac8-ca39-4892-bf3c-2921221183b8"]}} \ No newline at end of file diff --git a/.cache/xclim/chirps-daily/precip/precip_20260101_20260131_2026-01.nc b/.cache/xclim/chirps-daily/precip/precip_20260101_20260131_2026-01.nc new file mode 100644 index 0000000000000000000000000000000000000000..94d21968ed1149ab647a2b4f333278e564e6fadc GIT binary patch literal 209174 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�g;OLBMsPTm)S7Mq|er=}uJ9H89dQG#aP> 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�g;OLBMsPTm)S7Mq|er=}uJ9H89dQG#aP> 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 im+*+lu7*2e?cfXEc!rH$HEW}@", + "dryRun": true + } + } + }' +``` + +Execute xclim CDD process (dry-run): + +http://127.0.0.1:8000/processes/xclim-cdd/execution + +```bash +curl -X POST "http://127.0.0.1:8000/processes/xclim-cdd/execution" \ + -H "Content-Type: application/json" \ + -d '{ + "inputs": { + "datasetId": "chirps-daily", + "parameter": "precip", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": { "value": 1.0, "unit": "mm/day" }, + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + }' +``` + +Execute xclim warm-days process (dry-run): + +http://127.0.0.1:8000/processes/xclim-warm-days/execution + +```bash +curl -X POST "http://127.0.0.1:8000/processes/xclim-warm-days/execution" \ + -H "Content-Type: application/json" \ + -d '{ + "inputs": { + "datasetId": "era5-land-daily", + "parameter": "2m_temperature", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": { "value": 35.0, "unit": "degC" }, + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + }' +``` + +Check job status (replace ``): + +http://127.0.0.1:8000/jobs/ + +```bash +curl "http://127.0.0.1:8000/jobs/" +``` + +Get aggregated result features from a job (replace ``): + +http://127.0.0.1:8000/features/aggregated-results/items?jobId= + +```bash +curl "http://127.0.0.1:8000/features/aggregated-results/items?jobId=" +``` + +## Workflows (`/workflows`) + +Create a custom workflow with two steps: + +http://127.0.0.1:8000/workflows + +```bash +curl -X POST "http://127.0.0.1:8000/workflows" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "climate-indicators-workflow", + "steps": [ + { + "name": "aggregate-precip", + "processId": "eo-aggregate-import", + "payload": { + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + } + }, + { + "name": "cdd", + "processId": "xclim-cdd", + "payload": { + "inputs": { + "datasetId": "chirps-daily", + "parameter": "precip", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": { "value": 1.0, "unit": "mm/day" }, + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + } + } + ] + }' +``` + +List workflows: + +http://127.0.0.1:8000/workflows + +```bash +curl "http://127.0.0.1:8000/workflows" +``` + +Run a workflow immediately (replace ``): + +http://127.0.0.1:8000/workflows//run + +```bash +curl -X POST "http://127.0.0.1:8000/workflows//run" +``` + +## Schedules (`/schedules`) + +Schedules allow user-defined recurring execution of `eo-aggregate-import` (for example nightly imports). + +Create a nightly schedule: + +http://127.0.0.1:8000/schedules + +```bash +curl -X POST "http://127.0.0.1:8000/schedules" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "nightly-precip-import", + "cron": "0 0 * * *", + "timezone": "UTC", + "enabled": true, + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + }' +``` + +Create a workflow-target schedule (replace ``): + +http://127.0.0.1:8000/schedules + +```bash +curl -X POST "http://127.0.0.1:8000/schedules" \ + -H "Content-Type: application/json" \ + -d '{ + "name": "nightly-workflow-run", + "cron": "0 0 * * *", + "timezone": "UTC", + "enabled": true, + "workflowId": "" + }' +``` + +List schedules: + +http://127.0.0.1:8000/schedules + +```bash +curl "http://127.0.0.1:8000/schedules" +``` + +Run a schedule immediately (replace ``): + +http://127.0.0.1:8000/schedules//run + +```bash +curl -X POST "http://127.0.0.1:8000/schedules//run" +``` + +Trigger schedule from orchestrator callback (replace ``): + +http://127.0.0.1:8000/schedules//callback + +Requires server env var `EOAPI_SCHEDULER_TOKEN` and header `X-Scheduler-Token`. + +```bash +curl -X POST "http://127.0.0.1:8000/schedules//callback" \ + -H "X-Scheduler-Token: " +``` + ## COG (`/cog`) COG info: diff --git a/PREFECT_INTEGRATION.md b/PREFECT_INTEGRATION.md new file mode 100644 index 0000000..d8eed2e --- /dev/null +++ b/PREFECT_INTEGRATION.md @@ -0,0 +1,150 @@ +# Prefect Integration (Minimal Design) + +This document proposes a minimal way to integrate Prefect orchestration into `eo-api` for no-code scheduled and long-running EO workflows. + +**Constraint:** This project uses only open-source Prefect (self-hosted). Paid managed services are out of scope. + +## 1) Scope and intent + +- Keep `eo-api` as API/control plane. +- Use Prefect as orchestration plane for: + - API-triggered process executions + - recurring schedules (daily/monthly/yearly) +- Preserve current OGC-aligned API contracts and existing `/jobs/{jobId}` model. +- Reuse `dhis2eo` and `dhis2-client` inside flow/task steps. + +## 2) Why Prefect for this project + +- Python-native flow definitions align with current FastAPI codebase. +- Lower operational overhead than Airflow for early-stage product development. +- Good fit for API-triggered runs and dynamic parameters from process execution requests. +- Built-in state model can be translated cleanly into API job states. + +## 3) Minimal architecture + +Components: + +- `eo-api` (FastAPI) + - validates process execution payloads + - creates stable `jobId` + - triggers Prefect deployment/flow run + - exposes status/result via `/jobs/{jobId}` +- Self-hosted Prefect server + workers (open-source deployment) + - executes EO pipeline flows +- Shared storage/cache + - intermediate EO files and result artifacts +- State mapping store + - maps `jobId` ↔ `flow_run_id` + +Suggested mapping fields: + +- `jobId` (API) +- `flowName` (Prefect flow/deployment) +- `flowRunId` (Prefect) +- `status` (`queued|running|succeeded|failed`) +- `progress` (0–100) +- `resultRef` (artifact path/link) + +## 4) Flow boundary and task contract + +Recommended flow name: + +- `eo_aggregate_import_v1` + +Recommended tasks: + +1. `validate_inputs` +2. `load_org_units` +3. `extract_source_data` +4. `aggregate_to_org_units` +5. `build_dhis2_payload` +6. `import_to_dhis2` +7. `publish_results` + +Task IO contract: + +- Inputs: `jobId`, `datasetId`, `parameters`, `datetime/start/end`, `orgUnitLevel`, `aggregation`, `dhis2` options +- Outputs (JSON-serializable): + - `orgUnitCount` + - `rowCount` + - `payloadPreviewPath` + - `importSummary` + - `resultFeaturesPath` + +## 5) API interaction model + +### Trigger from process endpoint + +- Endpoint: `POST /processes/eo-aggregate-import/execution` +- Behavior: + - create `jobId` + - submit Prefect flow run with request inputs + - persist `jobId` ↔ `flowRunId` + - return `202` with monitor/result links + +### Monitor through job endpoint + +- Endpoint: `GET /jobs/{jobId}` +- Behavior: + - lookup `flowRunId` + - fetch Prefect state + - map state to API status + - return status/progress/import summary/result links + +State mapping (minimal): + +- `queued` → Prefect: `Scheduled`, `Pending` +- `running` → Prefect: `Running` +- `succeeded` → Prefect: `Completed` +- `failed` → Prefect: `Failed`, `Crashed`, `Cancelled` + +## 6) Scheduling model + +Use Prefect deployments/schedules for: + +- daily ERA5-Land import +- daily CHIRPS import +- yearly WorldPop refresh + +Each schedule should support parameterized deployment inputs (dataset, period, org unit level, dryRun). + +## 7) Operational controls + +- Retries/backoff per task for transient failures (provider/network). +- Task and flow-level timeouts. +- Idempotent import guardrails (same period/org unit reruns do not duplicate). +- Structured artifacts for payload previews and import summaries. +- `dryRun=true` default for safety in no-code workflows. + +## 8) Security and secret handling + +- Store credentials in self-hosted Prefect blocks/secret store or environment-managed secret backend. +- Do not log sensitive credentials in flow/task logs. +- Redact sensitive fields in API and worker logs. + +## 9) Suggested rollout phases + +Phase 1 (minimal): + +- one Prefect-backed flow for `eo-aggregate-import` +- API trigger + `/jobs/{jobId}` polling +- one scheduled daily ERA5 dry-run deployment + +Phase 2: + +- CHIRPS and WorldPop schedules +- richer progress reporting per step +- payload preview retrieval endpoint + +Phase 3: + +- multi-tenant schedule configuration +- stronger alerting/notification integration +- policy-based retries and escalation + +## 10) Fit with current eo-api direction + +- Supports no-code scheduled workflows without overloading request handlers. +- Keeps endpoint contracts stable for DHIS2 Maps and Climate app paths. +- Aligns with product priority on end-to-end correctness and reproducibility. +- Preserves strategic library usage (`dhis2eo`, `dhis2-client`) with clear task boundaries. diff --git a/PRESENTATION.md b/PRESENTATION.md new file mode 100644 index 0000000..0a92193 --- /dev/null +++ b/PRESENTATION.md @@ -0,0 +1,290 @@ +--- +marp: true +theme: default +paginate: true +title: DHIS2 EO API +--- + +# DHIS2 EO API +## Unified Earth Observation processing for DHIS2 and CHAP + +- Standards-aligned geospatial API for discovery, processing, and ingestion +- Replaces key Google Earth Engine-dependent integration paths +- Built for no-code-friendly operational workflows + +--- + +# Why this API exists + +## Problem +- EO and climate workflows are often fragmented across scripts and tools +- Hard to repeat, schedule, validate, and operationalize at scale + +## Goal +- One API surface for: + - Dataset discovery + - EO processing + - Aggregation to DHIS2 org units + - Import-ready outputs + - Scheduled recurring runs + +--- + +# Who it serves + +- DHIS2 implementers and analysts +- Climate and health data teams +- GIS and data engineering teams +- DHIS2 Maps app and DHIS2 Climate app as primary consumers + +--- + +# Architecture at a glance + +```mermaid +flowchart LR + A[Client / Maps / Climate / Scripts] --> B[FastAPI EO API] + B --> C[Dataset Catalog YAML] + B --> D[EO Processing via dhis2eo + xclim] + B --> E[DHIS2 Web API] + B --> F[Prefect Optional] + B --> G[External OGC Providers Optional] + B --> H[State Store JSON files] +``` + +--- + +# Technology choices + +- API framework: FastAPI +- OGC alignment: pygeoapi patterns +- Raster endpoints: TiTiler COG routes +- EO processing: dhis2eo +- Climate indices: xclim +- Orchestration: Prefect (optional), internal scheduler (optional) +- Persistence: JSON state files (jobs, schedules, workflows) + +--- + +# Core resources and concepts + +- Collections: discover available datasets +- Coverage and EDR queries: inspect raster values and areas +- Processes: executable units of work +- Jobs: async run status and results +- Workflows: multi-step process pipelines +- Schedules: recurring execution of process inputs or workflows + +--- + +# OGC APIs used: what, how, why + +Used in this API: +- **OGC API - Common**: landing page + collection discovery (`/`, `/collections`) +- **OGC API - Coverages**: gridded raster access (`/collections/{id}/coverage`) +- **OGC API - EDR**: direct query patterns for point/area extraction (`/position`, `/area`) +- **OGC API - Features**: vector collections for org units and outputs (`/features/*`) +- **OGC API - Processes (style)**: process catalog + execution (`/processes/*`) + +How they relate: +- `Common` provides dataset identities and link relations +- `Coverages` + `EDR` are complementary views over the same collections +- `Processes` consume collection-based inputs and emit job/output links +- `Features` carries both input geometries and process outputs + +Why this mix: +- Interoperability with geospatial tools and ecosystem clients +- Predictable contracts for DHIS2 Maps/Climate integration +- Composable workflow model (discover → query → process → import) + +--- + +# OGC standards stack (visual) + +```mermaid +flowchart TB + A[OGC API - Common\nDiscovery + Links + Collections] --> B1[OGC API - Coverages\nGridded raster queries] + A --> B2[OGC API - EDR\nPoint/area extraction patterns] + A --> B3[OGC API - Features\nVector collections + outputs] + B1 --> C[OGC API - Processes style\nExecution + jobs + outputs] + B2 --> C + B3 --> C +``` + +- `Common` anchors identities and link relations. +- `Coverages`, `EDR`, and `Features` provide complementary data-access paths. +- `Processes` orchestrates execution over those resources and produces import-ready outputs. + +--- + +# Dataset model + +- File-driven catalog under eoapi/datasets +- One folder per dataset +- YAML metadata validated by Pydantic +- Dataset-specific resolver logic per source +- Enables adding datasets with minimal endpoint changes + +--- + +# Endpoint map + +## Discovery and standards +- GET / +- GET /conformance +- GET /collections +- GET /collections/{collectionId} + +## Data access +- GET /collections/{collectionId}/coverage +- GET /collections/{collectionId}/position +- GET /collections/{collectionId}/area +- GET /features +- GET /features/{collectionId}/items + +## Execution +- GET /processes +- GET /processes/{processId} +- POST /processes/{processId}/execution +- GET /jobs/{jobId} + +## Orchestration +- CRUD /workflows + POST /workflows/{workflowId}/run +- CRUD /schedules + POST /schedules/{scheduleId}/run + +--- + +# How execution works + +1. Client posts process inputs +2. API validates payload and dataset/parameter contracts +3. EO extraction and aggregation run (dhis2eo first, fallback if needed) +4. Output converted to import-ready dataValues +5. DHIS2 import is executed or simulated (dry run) +6. Job status and outputs are persisted and queryable + +--- + +# Supported process catalog + +- eo-aggregate-import +- xclim-cdd (consecutive dry days) +- xclim-cwd (consecutive wet days) +- xclim-warm-days + +Each process produces: +- Import summary +- Feature outputs +- Traceable job status + +--- + +# DHIS2 integration behavior + +- Live integration enabled via environment variables +- Org units can be fetched directly from DHIS2 +- Process outputs are converted to DHIS2 dataValueSets payloads +- Dry-run mode validates and previews without committing writes +- Safe fallback behavior for local/dev when DHIS2 is not configured + +--- + +# Workflow orchestration + +- Workflows store ordered process steps +- Each step executes using the same process contracts +- Run returns all step job IDs for traceability +- Schedules can target: + - Process inputs + - Or a saved workflow ID + +--- + +# Scheduling options + +## Internal scheduler +- Poll-based cron worker built into API process +- Runs enabled schedules at due times + +## Prefect integration +- Optional offloading of schedule runs to Prefect deployments +- Job status can sync from Prefect flow states + +--- + +# External OGC federation + +- Merge external providers into local collections catalog +- Federated collection IDs: ext:{providerId}:{sourceCollectionId} +- Proxy coverage and EDR operations to upstream services +- Per-provider controls: + - Auth headers and API keys + - Timeouts and retries + - Allowed operations (coverage, position, area) + +--- + +# Runtime operations and safety + +- Persistent state for jobs, schedules, workflows +- Runtime summary exposed on landing page for operators +- Configurable CORS origins +- Optional API key guard for write routes +- Clear endpoint error contracts (NotFound, InvalidParameterValue, etc.) + +--- + +# Typical demo flow + +1. Discover datasets with GET /collections +2. Inspect one dataset with GET /collections/{id} +3. Preview data using coverage/position/area +4. Execute eo-aggregate-import in dry run +5. Check job via GET /jobs/{jobId} +6. View features via GET /features/aggregated-results/items?jobId=... +7. Create workflow and run it +8. Add schedule for recurring execution + +--- + +# What is production-ready now + +- Core API surface and contracts +- Multi-process execution including xclim +- Workflow and schedule orchestration +- Optional Prefect integration +- External OGC federation with hardening controls +- Durable local state persistence + +--- + +# Next steps to scale further + +- Add metrics dashboards and alerting around scheduler/import failures +- Expand DHIS2 mapping options for multi-data-element scenarios +- Strengthen deployment profile (container, secrets, env templates) +- Add comparison benchmarks against existing GEE-based pipelines + +--- + +# Quick start for this demo + +- Install dependencies: make sync +- Run API: make run +- Open docs: /docs +- Open examples: API_EXAMPLES.md +- Open demo UI: /example-app + +--- + +# Closing + +DHIS2 EO API provides a practical, standards-aligned bridge from EO data to DHIS2 operations: + +- Discover +- Process +- Validate +- Schedule +- Import + +All through one coherent API. diff --git a/PRESENTATION_EXECUTIVE.md b/PRESENTATION_EXECUTIVE.md new file mode 100644 index 0000000..169a362 --- /dev/null +++ b/PRESENTATION_EXECUTIVE.md @@ -0,0 +1,148 @@ +--- +marp: true +theme: default +paginate: true +title: DHIS2 EO API — Executive Brief +--- + +# DHIS2 EO API +## Executive Brief (10 slides) + +- Unified API for Earth Observation data into DHIS2 and CHAP +- Standards-aligned, operational, and no-code-friendly +- Built to reduce dependence on fragmented scripts and GEE-only paths + +--- + +# 1) Why this matters + +- Climate and EO workflows are often brittle and hard to repeat +- Teams need one reliable interface for discovery, processing, and import +- This API turns EO pipelines into auditable, schedulable operations + +--- + +# 2) What the API delivers + +- Dataset discovery (`/collections`) +- Data preview (`/coverage`, `/position`, `/area`) +- Process execution (`/processes/*/execution`) +- Async job tracking (`/jobs/{jobId}`) +- Workflow + schedule orchestration (`/workflows`, `/schedules`) + +--- + +# 3) How it works end-to-end + +```mermaid +flowchart LR + A[Client / DHIS2 Apps] --> B[EO API] + B --> C[Dataset catalog + resolvers] + B --> D[dhis2eo + xclim processing] + B --> E[Import-ready dataValues] + E --> F[DHIS2 Web API] + B --> G[Jobs/Workflows/Schedules state] +``` + +--- + +# 4) OGC APIs used: what, how, why + +Used in this API: +- **OGC API - Common**: landing page + collection discovery (`/`, `/collections`) +- **OGC API - Coverages**: gridded raster access (`/collections/{id}/coverage`) +- **OGC API - EDR**: direct query patterns for point/area extraction (`/position`, `/area`) +- **OGC API - Features**: vector collections for org units and outputs (`/features/*`) +- **OGC API - Processes (style)**: process catalog + execution (`/processes/*`) + +How they relate: +- `Common` provides dataset identities and links +- `Coverages` + `EDR` are complementary views over the same collections +- `Processes` consume collection-driven inputs and publish job/output links +- `Features` carries both input geometries (org units) and process outputs + +Why this mix: +- Interoperability with geospatial tools and clients +- Predictable contracts for DHIS2 Maps/Climate integration +- Composable architecture (discover → query → process → import) + +--- + +# OGC standards stack (visual) + +```mermaid +flowchart TB + A[OGC API - Common\nDiscovery + Links + Collections] --> B1[OGC API - Coverages\nGridded raster queries] + A --> B2[OGC API - EDR\nPoint/area extraction patterns] + A --> B3[OGC API - Features\nVector collections + outputs] + B1 --> C[OGC API - Processes style\nExecution + jobs + outputs] + B2 --> C + B3 --> C +``` + +- `Common` anchors identities and link relations. +- `Coverages`, `EDR`, and `Features` provide complementary data-access paths. +- `Processes` orchestrates execution over those resources and produces import-ready outputs. + +--- + +# 5) Process capabilities today + +- `eo-aggregate-import` +- `xclim-cdd` +- `xclim-cwd` +- `xclim-warm-days` + +Outputs include: +- Import summary +- Feature-level results +- Traceable job state + +--- + +# 6) Orchestration options + +- Saved multi-step workflows (`/workflows`) +- Recurring schedules (`/schedules`) +- Internal cron worker for built-in recurring runs +- Optional Prefect integration for external orchestration and status sync + +--- + +# 7) Operational resilience + +- Durable local persistence for jobs/schedules/workflows +- Runtime summary at landing page (`GET /`) for operator visibility +- Configurable CORS and optional API-key write protection +- Clear error contracts for fast debugging + +--- + +# 8) Federation and extensibility + +- External OGC providers can be merged into local catalog +- Provider-level auth, timeout, retry, and operation toggles +- File-driven dataset onboarding keeps extension cost low + +--- + +# 9) Demo storyline (5 minutes) + +1. Discover datasets (`GET /collections`) +2. Preview climate data (`/coverage` or `/position`) +3. Execute dry-run import process +4. Track job + inspect feature results +5. Run workflow and attach schedule + +--- + +# 10) Key takeaway + +DHIS2 EO API is now a practical integration backbone for EO/climate operations: + +- Discover confidently +- Process consistently +- Schedule reliably +- Import safely into DHIS2 + +Ready for incremental production hardening and broader dataset/process expansion. diff --git a/README.md b/README.md index 2cef56b..20e0fd1 100644 --- a/README.md +++ b/README.md @@ -41,13 +41,148 @@ uvicorn main:app --reload - `make validate-datasets` — validate all dataset YAML files against the Pydantic schema - `make test` — run Python tests with pytest +## Example frontend app + +A minimal browser UI is available at: + +- `http://127.0.0.1:8000/example-app` + +This app demonstrates creating and running scheduled imports (for example nightly precipitation/temperature imports aggregated to org units) using the API endpoints. + ## Documentation - API usage examples: [`API_EXAMPLES.md`](API_EXAMPLES.md) + - Runtime summary example for `GET /`: [`API_EXAMPLES.md#landing-page-runtime-summary`](API_EXAMPLES.md#landing-page-runtime-summary) +- Project presentation deck: [`PRESENTATION.md`](PRESENTATION.md) +- Executive presentation deck (10 slides): [`PRESENTATION_EXECUTIVE.md`](PRESENTATION_EXECUTIVE.md) - Dataset schema and resolver conventions: [`eoapi/datasets/README.md`](eoapi/datasets/README.md) - Product requirements and scope: [`PRD.md`](PRD.md) +- Prefect orchestration design: [`PREFECT_INTEGRATION.md`](PREFECT_INTEGRATION.md) +- xclim indicator integration design: [`XCLIM_INTEGRATION.md`](XCLIM_INTEGRATION.md) - Repository coding guidance for AI edits: [`.github/copilot-instructions.md`](.github/copilot-instructions.md) +## Prefect runtime configuration + +To enable Prefect-backed schedule runs (`POST /schedules/{scheduleId}/run`), set: + +- `EOAPI_PREFECT_ENABLED=true` +- `EOAPI_PREFECT_API_URL=` +- `EOAPI_PREFECT_DEPLOYMENT_ID=` +- `EOAPI_PREFECT_API_KEY=` + +If Prefect is disabled (or unavailable), schedule runs fall back to local in-process execution. + +## Internal scheduler runtime + +Recurring schedules can also run from an internal cron worker in this API process. + +- `EOAPI_INTERNAL_SCHEDULER_ENABLED` (optional, default `true`) +- `EOAPI_INTERNAL_SCHEDULER_POLL_SECONDS` (optional, default `30`) + +## DHIS2 runtime configuration + +To enable live DHIS2 org-unit retrieval and `dataValueSets` import: + +- `EOAPI_DHIS2_BASE_URL=` +- Either `EOAPI_DHIS2_TOKEN=` +- Or `EOAPI_DHIS2_USERNAME=` and `EOAPI_DHIS2_PASSWORD=` +- Optional: `EOAPI_DHIS2_TIMEOUT_SECONDS=20` + +Behavior: + +- If DHIS2 is configured, org units are fetched from DHIS2 for `/features/dhis2-org-units/items`. +- If DHIS2 is not configured or unavailable, built-in sample org units are used as fallback. +- Process imports (`dryRun=false`) send `dataValues` to DHIS2 `POST /api/dataValueSets`. +- Process imports (`dryRun=true`) are validated locally and return import-ready payload summaries without writing to DHIS2. + +## State persistence + +Jobs, schedules, and workflows now persist to JSON state files. + +- `EOAPI_STATE_DIR` (optional, default `.cache/state`) +- `EOAPI_STATE_PERSIST` (optional, default `true`; set `false` to disable persistence) + +## API security and CORS + +- `EOAPI_CORS_ORIGINS` (optional, default `*`) comma-separated allowed origins +- `EOAPI_API_KEY` (optional): if set, write operations (`POST`, `PATCH`, `PUT`, `DELETE`) require `X-API-Key` header + +## External OGC federation (collections) + +To merge external OGC API - Common collections into local `/collections`, set: + +- `EOAPI_EXTERNAL_OGC_SERVICES=` + +Example: + +```json +[ + { + "id": "demo-provider", + "title": "Demo OGC Provider", + "url": "https://example-ogc.test", + "headers": { + "X-Client-Id": "eo-api" + }, + "apiKeyEnv": "DEMO_OGC_API_KEY", + "authScheme": "Bearer", + "timeoutSeconds": 20, + "retries": 1, + "operations": ["coverage", "position"] + } +] +``` + +Provider config fields: + +- `headers` (optional): static headers to include in upstream requests. +- `apiKeyEnv` (optional): environment variable name containing upstream API key/token. +- `authScheme` (optional, default `Bearer`): used in `Authorization` header as ` `; use `none` to send token without a scheme. +- `timeoutSeconds` (optional, default `20`): request timeout per upstream call. +- `retries` (optional, default `0`): number of retries for transient upstream/network failures. +- `operations` (optional): explicit allowlist for proxied operations; supported values are `coverage`, `position`, `area`. If omitted, all operations are allowed. If any unknown value is provided, that provider config is rejected. + +Current behavior: + +- `/collections` returns local + external collections. +- External collections use federated IDs: `ext::`. +- `/collections/{collectionId}` supports those federated external IDs. +- `/collections/{collectionId}/coverage` proxies to upstream for federated IDs. +- `/collections/{collectionId}/position` and `/collections/{collectionId}/area` proxy to upstream for federated IDs. + +## Workflow JSON schema (MVP) + +Custom workflows are created via `POST /workflows` using this shape: + +```json +{ + "name": "climate-indicators-workflow", + "steps": [ + { + "name": "aggregate-step", + "processId": "eo-aggregate-import", + "payload": { + "inputs": { "...": "process-specific inputs" } + } + }, + { + "name": "indicator-step", + "processId": "xclim-cdd", + "payload": { + "inputs": { "...": "process-specific inputs" } + } + } + ] +} +``` + +Notes: + +- `steps` run sequentially in the order provided. +- `processId` must match an existing process ID from `GET /processes`. +- `payload.inputs` must match the target process execution contract. +- Schedules can target either aggregate-import inputs or a `workflowId`. + ## Dataset definitions Collection metadata for `/collections` is defined in YAML files under `eoapi/datasets/`. diff --git a/XCLIM_INTEGRATION.md b/XCLIM_INTEGRATION.md new file mode 100644 index 0000000..c03b5bc --- /dev/null +++ b/XCLIM_INTEGRATION.md @@ -0,0 +1,281 @@ +# xclim Integration (Implemented Baseline + Next Steps) + +This document captures the implemented baseline for `xclim` integration in `eo-api` and the next phases toward broader indicator coverage and orchestration hardening. + +## 0) Current baseline status + +Implemented in API: + +- Process IDs exposed under `/processes`: + - `xclim-cdd` + - `xclim-cwd` + - `xclim-warm-days` +- Execution endpoint support: + - `POST /processes/{processId}/execution` +- Job monitoring reuse: + - `GET /jobs/{jobId}` + +Current execution behavior: + +- Uses lazy imports of `xclim`, `xarray`, `numpy`, and `pandas`. +- Validates required inputs (dataset/parameter/start/end/threshold/orgUnitLevel). +- Requires explicit units (precipitation in mm-based units, warm-days in Celsius units). +- Extracts EO source data through `dhis2eo` download helpers: + - CHIRPS: `dhis2eo.data.chc.chirps3.daily.download` + - ERA5-Land: `dhis2eo.data.cds.era5_land.hourly.download` +- Opens downloaded NetCDF outputs with `xarray`, derives daily series, and computes per-org-unit indicators. +- Produces import-ready feature payload shape + `importSummary` using existing job/result patterns. +- Includes deterministic synthetic fallback only when EO extraction fails at runtime (for example provider or credential issues). + +Runtime cache: + +- Downloaded EO files are cached under `EOAPI_XCLIM_CACHE_DIR` (default: `.cache/xclim`). + +## 1) Goals + +- Add standards-based indicator processes on top of existing EO ingestion workflows. +- Keep current raw import flows unchanged. +- Expose indicators through OGC API - Processes style endpoints. +- Produce DHIS2-ready outputs via existing `dhis2-client` integration path. + +## 2) Why xclim here + +- Provides standardized climate indices with explicit semantics and parameters. +- Reduces one-off custom indicator logic. +- Works directly with `xarray`, which fits existing EO data handling patterns. + +## 3) Scope for first phase (2–3 indicators) + +Start with indicators that map directly to climate-health use cases: + +1. **Consecutive Dry Days (CDD)** + - Typical use: drought stress monitoring. + - Inputs: daily precipitation, threshold (for example 1 mm/day), time range. + +2. **Consecutive Wet Days (CWD)** + - Typical use: flood/vector suitability signal. + - Inputs: daily precipitation, threshold, time range. + +3. **Warm Days Above Threshold** + - Typical use: heat stress indicator. + - Inputs: daily 2m temperature, threshold (for example 35°C), time range. + +These three provide immediate value while keeping compute and validation scope manageable. + +## 4) Process catalog additions + +Process IDs (implemented): + +- `xclim-cdd` +- `xclim-cwd` +- `xclim-warm-days` + +Endpoints (implemented): + +- `GET /processes` +- `GET /processes/{processId}` +- `POST /processes/{processId}/execution` +- `GET /jobs/{jobId}` + +## 5) Proposed execution contract + +Common request fields: + +- `datasetId` (`chirps-daily` or `era5-land-daily`) +- `parameter` (`precip` or `2m_temperature`) +- `start`, `end` +- `orgUnitLevel` or `featureCollectionId` +- `threshold` (unit explicit) +- `aggregation` (usually `sum` or `mean` for post-index rollups) +- `dhis2`: + - `dataElementId` + - `dryRun` (default `true`) + +Common output fields: + +- `indicatorName` +- `period` +- `orgUnitCount` +- `importSummary` +- link to result features and payload preview + +## 6) Data and unit handling requirements + +- Require explicit units in process inputs (for example `degC`, `mm/day`). +- Reject ambiguous or missing units. +- Avoid silent conversions. +- Document assumptions in process descriptions. + +Unit examples: + +- ERA5-Land temperature is often Kelvin in source workflows; convert explicitly before threshold logic. +- Precipitation threshold units must match transformed daily precipitation units. + +## 7) Pipeline placement + +Insert `xclim` after EO extraction and before DHIS2 payload generation: + +1. Extract EO source data (`dhis2eo`) +2. Harmonize units/CRS/time axis +3. Compute `xclim` indicator on gridded data +4. Aggregate indicator result to org units +5. Build DHIS2 payload +6. Import (or dry-run) + +This keeps EO extraction concerns separate from indicator logic. + +## 8) Validation strategy + +For each indicator process, add deterministic tests for: + +- threshold boundary behavior +- missing/nodata handling +- unit mismatch rejection +- expected period formatting for DHIS2 payloads +- process contract errors (`InvalidParameterValue`, `NotFound`) + +## 9) Incremental rollout + +Phase 1: + +- add `xclim-cdd` and `xclim-warm-days` +- dry-run imports only by default +- process contract + deterministic tests + +Phase 2: + +- add `xclim-cwd` +- enable scheduled runs through existing schedule/orchestrator path +- add payload preview endpoint if not already enabled + +Phase 3: + +- evaluate additional indices (for example hot spell duration, percentile-based extremes) +- add bias-adjustment entry points where needed + +## 10) Example process payloads + +### `xclim-cdd` + +```json +{ + "inputs": { + "datasetId": "chirps-daily", + "parameter": "precip", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": { "value": 1.0, "unit": "mm/day" }, + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } +} +``` + +### `xclim-warm-days` + +```json +{ + "inputs": { + "datasetId": "era5-land-daily", + "parameter": "2m_temperature", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": { "value": 35.0, "unit": "degC" }, + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } +} +``` + +## 11) Dependency and packaging note + +`xclim` is now added as a project dependency. Keep CI/environment checks focused on compatibility across the `xclim` + `xarray` + `numpy` stack. + +## 12) Copy/paste workflow example + +Use this to create a custom workflow that runs aggregate import first, then CDD and warm-days indicators. + +```json +{ + "name": "climate-indicators-monthly-workflow", + "steps": [ + { + "name": "aggregate-precip", + "processId": "eo-aggregate-import", + "payload": { + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + } + }, + { + "name": "cdd", + "processId": "xclim-cdd", + "payload": { + "inputs": { + "datasetId": "chirps-daily", + "parameter": "precip", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": { "value": 1.0, "unit": "mm/day" }, + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + } + }, + { + "name": "warm-days", + "processId": "xclim-warm-days", + "payload": { + "inputs": { + "datasetId": "era5-land-daily", + "parameter": "2m_temperature", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": { "value": 35.0, "unit": "degC" }, + "dhis2": { + "dataElementId": "", + "dryRun": true + } + } + } + } + ] +} +``` + +Suggested API flow: + +1. `POST /workflows` with the JSON above. +2. `POST /workflows/{workflowId}/run` for immediate execution. +3. `POST /schedules` with `workflowId` for recurring execution. + +Workflow-target schedule payload example: + +```json +{ + "name": "nightly-climate-workflow", + "cron": "0 0 * * *", + "timezone": "UTC", + "enabled": true, + "workflowId": "" +} +``` diff --git a/eoapi/dhis2_integration.py b/eoapi/dhis2_integration.py new file mode 100644 index 0000000..b370c25 --- /dev/null +++ b/eoapi/dhis2_integration.py @@ -0,0 +1,220 @@ +import json +import os +from datetime import UTC, datetime +from typing import Any +from urllib.error import HTTPError, URLError +from urllib.parse import urlencode +from urllib.request import Request, urlopen + + +def _base_url() -> str | None: + raw = os.getenv("EOAPI_DHIS2_BASE_URL", "").strip().rstrip("/") + return raw or None + + +def _auth_token() -> str | None: + raw = os.getenv("EOAPI_DHIS2_TOKEN", "").strip() + return raw or None + + +def _basic_credentials() -> tuple[str, str] | None: + username = os.getenv("EOAPI_DHIS2_USERNAME", "").strip() + password = os.getenv("EOAPI_DHIS2_PASSWORD", "").strip() + if username and password: + return (username, password) + return None + + +def dhis2_configured() -> bool: + return _base_url() is not None and (_auth_token() is not None or _basic_credentials() is not None) + + +def _timeout() -> float: + raw = os.getenv("EOAPI_DHIS2_TIMEOUT_SECONDS", "20").strip() + try: + timeout = float(raw) + except ValueError: + timeout = 20.0 + return timeout if timeout > 0 else 20.0 + + +def _auth_headers() -> dict[str, str]: + headers = {"Accept": "application/json", "Content-Type": "application/json"} + token = _auth_token() + if token: + headers["Authorization"] = f"Bearer {token}" + return headers + + credentials = _basic_credentials() + if credentials is None: + return headers + + import base64 + + encoded = base64.b64encode(f"{credentials[0]}:{credentials[1]}".encode("utf-8")).decode("ascii") + headers["Authorization"] = f"Basic {encoded}" + return headers + + +def _request_json(method: str, path: str, payload: dict[str, Any] | None = None) -> dict[str, Any] | None: + base = _base_url() + if base is None: + return None + + request = Request( + url=f"{base}{path}", + method=method, + data=json.dumps(payload).encode("utf-8") if payload is not None else None, + ) + for key, value in _auth_headers().items(): + request.add_header(key, value) + + try: + with urlopen(request, timeout=_timeout()) as response: + body = response.read().decode("utf-8") + if not body: + return {} + parsed = json.loads(body) + return parsed if isinstance(parsed, dict) else {} + except (HTTPError, URLError, json.JSONDecodeError): + return None + + +def _extract_import_counts(payload: dict[str, Any] | None, dry_run: bool, fallback_count: int) -> dict[str, Any]: + if not isinstance(payload, dict): + return { + "imported": fallback_count, + "updated": 0, + "ignored": 0, + "deleted": 0, + "dryRun": dry_run, + "source": "simulated", + } + + counts = payload.get("response", {}).get("importCount") + if not isinstance(counts, dict): + counts = payload.get("importCount") + + if not isinstance(counts, dict): + return { + "imported": fallback_count, + "updated": 0, + "ignored": 0, + "deleted": 0, + "dryRun": dry_run, + "source": "simulated", + } + + return { + "imported": int(counts.get("imported", 0)), + "updated": int(counts.get("updated", 0)), + "ignored": int(counts.get("ignored", 0)), + "deleted": int(counts.get("deleted", 0)), + "dryRun": dry_run, + "source": "dhis2", + } + + +def import_data_values_to_dhis2(data_values: list[dict[str, Any]], *, dry_run: bool) -> dict[str, Any]: + if dry_run: + return { + "imported": 0, + "updated": 0, + "ignored": len(data_values), + "deleted": 0, + "dryRun": True, + "source": "dry-run", + } + + if not data_values: + return { + "imported": 0, + "updated": 0, + "ignored": 0, + "deleted": 0, + "dryRun": False, + "source": "dhis2", + } + + if not dhis2_configured(): + return { + "imported": len(data_values), + "updated": 0, + "ignored": 0, + "deleted": 0, + "dryRun": False, + "source": "simulated", + } + + request_payload = { + "dataValues": data_values, + } + response_payload = _request_json( + "POST", + f"/api/dataValueSets?importStrategy=CREATE_AND_UPDATE&dryRun={'true' if dry_run else 'false'}&preheatCache=true&skipAudit=true&async=false", + payload=request_payload, + ) + return _extract_import_counts(response_payload, dry_run=dry_run, fallback_count=len(data_values)) + + +def _to_feature(ou_id: str, name: str, level: int, geometry: dict[str, Any]) -> dict[str, Any] | None: + if not isinstance(geometry, dict) or "type" not in geometry or "coordinates" not in geometry: + return None + + return { + "type": "Feature", + "id": ou_id, + "geometry": geometry, + "properties": { + "name": name, + "level": level, + }, + } + + +def fetch_org_units_from_dhis2(level: int) -> list[dict[str, Any]]: + if not dhis2_configured(): + return [] + + params = urlencode( + { + "fields": "id,name,level,geometry", + "filter": f"level:eq:{level}", + "paging": "false", + } + ) + payload = _request_json("GET", f"/api/organisationUnits?{params}") + if not isinstance(payload, dict): + return [] + + units = payload.get("organisationUnits", []) + if not isinstance(units, list): + return [] + + features: list[dict[str, Any]] = [] + for item in units: + if not isinstance(item, dict): + continue + ou_id = str(item.get("id", "")).strip() + name = str(item.get("name", "")).strip() or ou_id + if not ou_id: + continue + + geometry = item.get("geometry") + feature = _to_feature(ou_id, name, level, geometry) + if feature is not None: + features.append(feature) + + return features + + +def iso_to_dhis2_period(datetime_value: str) -> str: + normalized = datetime_value.strip() + try: + if normalized.endswith("Z"): + parsed = datetime.fromisoformat(normalized.replace("Z", "+00:00")) + else: + parsed = datetime.fromisoformat(normalized) + return parsed.astimezone(UTC).strftime("%Y%m%d") + except ValueError: + return normalized[:10].replace("-", "") diff --git a/eoapi/endpoints/collections.py b/eoapi/endpoints/collections.py index a5a8dd9..7503a7e 100644 --- a/eoapi/endpoints/collections.py +++ b/eoapi/endpoints/collections.py @@ -5,6 +5,7 @@ from eoapi.datasets import DatasetDefinition, load_datasets from eoapi.endpoints.constants import CRS84, OGC_RELTYPES_BASE from eoapi.endpoints.errors import not_found +from eoapi.external_ogc import get_external_collection, list_external_collections, parse_federated_collection_id from eoapi.endpoints.coverages import router as coverages_router from eoapi.endpoints.edr import router as edr_router @@ -87,14 +88,70 @@ def _build_collection(request: Request, dataset: DatasetDefinition) -> dict: } +def _external_collection_links(request: Request, collection_id: str, source_url: str | None) -> list[dict]: + base = _base_url(request) + collections_url = url_join(base, "collections") + collection_url = url_join(collections_url, collection_id) + + links = [ + { + "rel": "self", + "type": "application/json", + "title": "This collection", + "href": collection_url, + }, + { + "rel": "root", + "type": "application/json", + "title": "API root", + "href": url_join(base, "/"), + }, + { + "rel": "parent", + "type": "application/json", + "title": "Collections", + "href": collections_url, + }, + ] + + if source_url: + links.append( + { + "rel": "source", + "type": "application/json", + "title": "Upstream collection", + "href": source_url, + } + ) + + return links + + +def _normalize_external_collection(request: Request, collection: dict) -> dict: + federation = collection.get("federation", {}) if isinstance(collection.get("federation"), dict) else {} + source_url = None + provider_url = federation.get("providerUrl") + source_collection_id = federation.get("sourceCollectionId") + if isinstance(provider_url, str) and isinstance(source_collection_id, str): + source_url = url_join(provider_url.rstrip("/"), "collections", source_collection_id) + + return { + **collection, + "links": _external_collection_links(request, collection["id"], source_url), + } + + @router.get("/collections") def get_collections(request: Request) -> dict: base = _base_url(request) collections_url = url_join(base, "collections") datasets = load_datasets() + local_collections = [_build_collection(request, dataset) for dataset in datasets.values()] + external_collections = [_normalize_external_collection(request, item) for item in list_external_collections()] + return { - "collections": [_build_collection(request, dataset) for dataset in datasets.values()], + "collections": local_collections + external_collections, "links": [ { "rel": "self", @@ -114,6 +171,12 @@ def get_collections(request: Request) -> dict: @router.get("/collections/{collectionId}") def get_collection(collectionId: str, request: Request) -> dict: + if parse_federated_collection_id(collectionId) is not None: + external_collection = get_external_collection(collectionId) + if external_collection is None: + raise not_found("Collection", collectionId) + return _normalize_external_collection(request, external_collection) + dataset = load_datasets().get(collectionId) if dataset is None: raise not_found("Collection", collectionId) diff --git a/eoapi/endpoints/conformance.py b/eoapi/endpoints/conformance.py index 9983823..a7a4b64 100644 --- a/eoapi/endpoints/conformance.py +++ b/eoapi/endpoints/conformance.py @@ -14,6 +14,10 @@ "http://www.opengis.net/spec/ogcapi-edr-1/1.1/conf/core", "http://www.opengis.net/spec/ogcapi-edr-1/1.1/conf/position", "http://www.opengis.net/spec/ogcapi-edr-1/1.1/conf/area", + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/core", + "http://www.opengis.net/spec/ogcapi-features-1/1.0/conf/geojson", + "http://www.opengis.net/spec/ogcapi-processes-1/1.0/conf/core", + "http://www.opengis.net/spec/ogcapi-processes-1/1.0/conf/json", ] diff --git a/eoapi/endpoints/coverages.py b/eoapi/endpoints/coverages.py index ee3b05e..dea6a43 100644 --- a/eoapi/endpoints/coverages.py +++ b/eoapi/endpoints/coverages.py @@ -8,6 +8,11 @@ from eoapi.datasets.resolvers import coverage_resolvers from eoapi.endpoints.constants import CRS84 from eoapi.endpoints.errors import invalid_parameter, not_found +from eoapi.external_ogc import ( + is_external_operation_enabled, + parse_federated_collection_id, + proxy_external_collection_request, +) router = APIRouter() @@ -122,6 +127,19 @@ def get_collection_coverage( ), output_format: str = Query(default=F_JSON, alias="f"), ) -> dict: + if parse_federated_collection_id(collectionId) is not None: + operation_enabled = is_external_operation_enabled(collectionId, "coverage") + if operation_enabled is False: + raise invalid_parameter("coverage operation is disabled for this external provider") + proxied = proxy_external_collection_request( + collection_id=collectionId, + operation="coverage", + query_params=list(request.query_params.multi_items()), + ) + if proxied is None: + raise not_found("Collection", collectionId) + return proxied + if output_format not in {F_JSON, "covjson"}: raise invalid_parameter("Only f=json and f=covjson are currently supported") diff --git a/eoapi/endpoints/edr.py b/eoapi/endpoints/edr.py index 98f343f..442e40b 100644 --- a/eoapi/endpoints/edr.py +++ b/eoapi/endpoints/edr.py @@ -10,6 +10,11 @@ from eoapi.datasets.resolvers import area_resolvers, position_resolvers from eoapi.endpoints.constants import CRS84 from eoapi.endpoints.errors import invalid_parameter, not_found +from eoapi.external_ogc import ( + is_external_operation_enabled, + parse_federated_collection_id, + proxy_external_collection_request, +) router = APIRouter() @@ -195,6 +200,19 @@ def get_collection_position( ), output_format: str = Query(default=F_JSON, alias="f"), ) -> dict: + if parse_federated_collection_id(collectionId) is not None: + operation_enabled = is_external_operation_enabled(collectionId, "position") + if operation_enabled is False: + raise invalid_parameter("position operation is disabled for this external provider") + proxied = proxy_external_collection_request( + collection_id=collectionId, + operation="position", + query_params=list(request.query_params.multi_items()), + ) + if proxied is None: + raise not_found("Collection", collectionId) + return proxied + if output_format not in {F_JSON, "geojson"}: raise invalid_parameter("Only f=json and f=geojson are currently supported") @@ -242,6 +260,19 @@ def get_collection_area( ), output_format: str = Query(default=F_JSON, alias="f"), ) -> dict: + if parse_federated_collection_id(collectionId) is not None: + operation_enabled = is_external_operation_enabled(collectionId, "area") + if operation_enabled is False: + raise invalid_parameter("area operation is disabled for this external provider") + proxied = proxy_external_collection_request( + collection_id=collectionId, + operation="area", + query_params=list(request.query_params.multi_items()), + ) + if proxied is None: + raise not_found("Collection", collectionId) + return proxied + if output_format not in {F_JSON, "geojson"}: raise invalid_parameter("Only f=json and f=geojson are currently supported") diff --git a/eoapi/endpoints/features.py b/eoapi/endpoints/features.py new file mode 100644 index 0000000..76c5384 --- /dev/null +++ b/eoapi/endpoints/features.py @@ -0,0 +1,168 @@ +from typing import Any + +from fastapi import APIRouter, Query, Request + +from pygeoapi.api import FORMAT_TYPES, F_JSON +from pygeoapi.util import url_join + +from eoapi.dhis2_integration import fetch_org_units_from_dhis2 +from eoapi.endpoints.constants import CRS84 +from eoapi.endpoints.errors import invalid_parameter, not_found +from eoapi.jobs import get_job + +router = APIRouter(tags=["Features"]) + + +ORG_UNIT_FEATURES: list[dict[str, Any]] = [ + { + "type": "Feature", + "id": "O6uvpzGd5pu", + "geometry": { + "type": "Polygon", + "coordinates": [[[ -11.64, 8.42], [-11.50, 8.42], [-11.50, 8.55], [-11.64, 8.55], [-11.64, 8.42]]], + }, + "properties": {"name": "Bo", "level": 2}, + }, + { + "type": "Feature", + "id": "fdc6uOvgoji", + "geometry": { + "type": "Polygon", + "coordinates": [[[-13.30, 8.80], [-13.10, 8.80], [-13.10, 9.00], [-13.30, 9.00], [-13.30, 8.80]]], + }, + "properties": {"name": "Bombali", "level": 2}, + }, + { + "type": "Feature", + "id": "lc3eMKXaEfw", + "geometry": { + "type": "Polygon", + "coordinates": [[[-12.40, 7.00], [-12.10, 7.00], [-12.10, 7.25], [-12.40, 7.25], [-12.40, 7.00]]], + }, + "properties": {"name": "Bonthe", "level": 2}, + }, +] + + +def _base_url(request: Request) -> str: + return str(request.base_url).rstrip("/") + + +def _parse_bbox(bbox: str | None) -> tuple[float, float, float, float] | None: + if bbox is None: + return None + + try: + values = tuple(float(part.strip()) for part in bbox.split(",")) + except ValueError as exc: + raise invalid_parameter("bbox must contain 4 comma-separated numbers") from exc + + if len(values) != 4: + raise invalid_parameter("bbox must contain 4 comma-separated numbers") + + minx, miny, maxx, maxy = values + if minx >= maxx or miny >= maxy: + raise invalid_parameter("bbox must follow minx,miny,maxx,maxy with min < max") + + return values + + +def _feature_bbox(feature: dict[str, Any]) -> tuple[float, float, float, float]: + ring = feature["geometry"]["coordinates"][0] + xs = [point[0] for point in ring] + ys = [point[1] for point in ring] + return (min(xs), min(ys), max(xs), max(ys)) + + +def _intersects(a: tuple[float, float, float, float], b: tuple[float, float, float, float]) -> bool: + return not (a[2] < b[0] or a[0] > b[2] or a[3] < b[1] or a[1] > b[3]) + + +def org_unit_items(level: int = 2, bbox: tuple[float, float, float, float] | None = None) -> list[dict[str, Any]]: + dhis2_features = fetch_org_units_from_dhis2(level) + features = dhis2_features or [feature for feature in ORG_UNIT_FEATURES if feature["properties"].get("level") == level] + if bbox is not None: + features = [feature for feature in features if _intersects(_feature_bbox(feature), bbox)] + return features + + +@router.get("/features") +def get_feature_collections(request: Request) -> dict[str, Any]: + base = _base_url(request) + features_url = url_join(base, "features") + return { + "collections": [ + { + "id": "dhis2-org-units", + "title": "DHIS2 organisation units", + "description": "Organisation unit features from DHIS2-compatible structure.", + "itemType": "feature", + "crs": [CRS84], + "links": [ + { + "rel": "items", + "type": FORMAT_TYPES[F_JSON], + "title": "Feature items", + "href": url_join(base, "features", "dhis2-org-units", "items"), + } + ], + }, + { + "id": "aggregated-results", + "title": "Aggregated process results", + "description": "Feature collection generated by process executions.", + "itemType": "feature", + "crs": [CRS84], + "links": [ + { + "rel": "items", + "type": FORMAT_TYPES[F_JSON], + "title": "Feature items", + "href": url_join(base, "features", "aggregated-results", "items"), + } + ], + }, + ], + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": features_url}, + {"rel": "root", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "/")}, + ], + } + + +@router.get("/features/{collectionId}/items") +def get_feature_items( + collectionId: str, + request: Request, + level: int = Query(default=2, ge=1), + bbox: str | None = None, + jobId: str | None = None, +) -> dict[str, Any]: + base = _base_url(request) + items_url = url_join(base, "features", collectionId, "items") + + if collectionId == "dhis2-org-units": + bbox_values = _parse_bbox(bbox) + features = org_unit_items(level=level, bbox=bbox_values) + elif collectionId == "aggregated-results": + if not jobId: + raise invalid_parameter("jobId is required for aggregated-results") + job = get_job(jobId) + if job is None: + raise not_found("Job", jobId) + features = job["outputs"].get("features", []) + else: + raise not_found("Feature collection", collectionId) + + return { + "type": "FeatureCollection", + "timeStamp": jobId or "current", + "numberMatched": len(features), + "numberReturned": len(features), + "features": features, + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": items_url}, + {"rel": "collection", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "features")}, + {"rel": "root", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "/")}, + ], + } diff --git a/eoapi/endpoints/processes.py b/eoapi/endpoints/processes.py new file mode 100644 index 0000000..eb97f71 --- /dev/null +++ b/eoapi/endpoints/processes.py @@ -0,0 +1,837 @@ +from datetime import date +import logging +import os +from pathlib import Path +from typing import Any, Literal + +from fastapi import APIRouter, Request +from pydantic import BaseModel, Field, ValidationError + +from pygeoapi.api import FORMAT_TYPES, F_JSON +from pygeoapi.util import url_join + +from eoapi.datasets import load_datasets +from eoapi.dhis2_integration import import_data_values_to_dhis2, iso_to_dhis2_period +from eoapi.endpoints.errors import invalid_parameter, not_found +from eoapi.endpoints.features import org_unit_items +from eoapi.jobs import create_job, get_job, update_job +from eoapi.orchestration.prefect import get_flow_run, prefect_enabled, prefect_state_to_job_status + +router = APIRouter(tags=["Processes"]) +logger = logging.getLogger(__name__) + +AGGREGATE_PROCESS_ID = "eo-aggregate-import" +XCLIM_CDD_PROCESS_ID = "xclim-cdd" +XCLIM_CWD_PROCESS_ID = "xclim-cwd" +XCLIM_WARM_DAYS_PROCESS_ID = "xclim-warm-days" + +XCLIM_PROCESS_IDS = { + XCLIM_CDD_PROCESS_ID, + XCLIM_CWD_PROCESS_ID, + XCLIM_WARM_DAYS_PROCESS_ID, +} + +TIME_DIM_CANDIDATES = ("time", "valid_time") +X_DIM_CANDIDATES = ("x", "lon", "longitude") +Y_DIM_CANDIDATES = ("y", "lat", "latitude") + + +class DHIS2ImportOptions(BaseModel): + dataElementId: str = Field(min_length=1) + dataElementMap: dict[str, str] | None = None + dryRun: bool = True + + +class AggregateImportInputs(BaseModel): + datasetId: str = Field(min_length=1) + parameters: list[str] | None = None + datetime: str | None = None + start: str | None = None + end: str | None = None + orgUnitLevel: int = Field(default=2, ge=1) + aggregation: Literal["mean", "sum", "min", "max"] = "mean" + dhis2: DHIS2ImportOptions + + +class ThresholdInput(BaseModel): + value: float + unit: str = Field(min_length=1) + + +class XclimIndicatorInputs(BaseModel): + datasetId: str = Field(min_length=1) + parameter: str = Field(min_length=1) + start: date + end: date + orgUnitLevel: int = Field(default=2, ge=1) + threshold: ThresholdInput + dhis2: DHIS2ImportOptions + + +class ExecuteRequest(BaseModel): + inputs: dict[str, Any] + + +def _base_url(request: Request) -> str: + return str(request.base_url).rstrip("/") + + +def _select_parameters(dataset_id: str, requested: list[str] | None) -> list[str]: + dataset = load_datasets().get(dataset_id) + if dataset is None: + raise not_found("Collection", dataset_id) + + available = list(dataset.parameters.keys()) + if not available: + raise invalid_parameter(f"No parameters configured for collection '{dataset.id}'") + + if not requested: + return available + + unknown = [parameter for parameter in requested if parameter not in dataset.parameters] + if unknown: + raise invalid_parameter(f"Unknown parameter(s): {', '.join(unknown)}") + + return requested + + +def _value_for(index: int, parameter: str, aggregation: str) -> float: + base = (index + 1) * (len(parameter) + 1) + if aggregation == "sum": + return round(base * 1.5, 4) + if aggregation == "min": + return round(base * 0.5, 4) + if aggregation == "max": + return round(base * 2.0, 4) + return round(base * 1.0, 4) + + +def _build_aggregate_data_values( + features: list[dict[str, Any]], + *, + default_data_element_id: str, + data_element_map: dict[str, str] | None, + period: str, +) -> list[dict[str, Any]]: + payload: list[dict[str, Any]] = [] + for feature in features: + org_unit = feature["properties"].get("orgUnit") + values = feature["properties"].get("values", {}) + if not isinstance(org_unit, str) or not isinstance(values, dict): + continue + + for parameter_id, value in values.items(): + mapped_data_element = (data_element_map or {}).get(parameter_id, default_data_element_id) + if not mapped_data_element: + continue + payload.append( + { + "dataElement": mapped_data_element, + "orgUnit": org_unit, + "period": period, + "value": value, + } + ) + + return payload + + +def _build_indicator_data_values( + features: list[dict[str, Any]], + *, + data_element_id: str, + period: str, +) -> list[dict[str, Any]]: + payload: list[dict[str, Any]] = [] + for feature in features: + properties = feature.get("properties", {}) + if not isinstance(properties, dict): + continue + + org_unit = properties.get("orgUnit") + value = properties.get("value") + if not isinstance(org_unit, str) or value is None: + continue + + payload.append( + { + "dataElement": data_element_id, + "orgUnit": org_unit, + "period": period, + "value": value, + } + ) + + return payload + + +def _coerce_date(value: str) -> date: + try: + return date.fromisoformat(value[:10]) + except ValueError as exc: + raise invalid_parameter(f"Invalid date value '{value}'") from exc + + +def _aggregate_series_values(values: list[float], aggregation: str) -> float: + if not values: + return 0.0 + + if aggregation == "sum": + return round(sum(values), 4) + if aggregation == "min": + return round(min(values), 4) + if aggregation == "max": + return round(max(values), 4) + return round(sum(values) / len(values), 4) + + +def _extract_aggregate_values_from_dhis2eo( + *, + dataset_id: str, + parameters: list[str], + start: date, + end: date, + aggregation: str, + org_units: list[dict[str, Any]], +) -> dict[str, dict[str, float]]: + try: + import numpy as np + import pandas as pd + import xarray as xr + except ImportError as exc: + raise RuntimeError("Missing xarray/pandas/numpy dependencies for aggregate extraction") from exc + + values_by_org: dict[str, dict[str, float]] = {feature["id"]: {} for feature in org_units} + + for parameter in parameters: + series_by_org = _extract_org_unit_series( + dataset_id=dataset_id, + parameter=parameter, + start=start, + end=end, + org_units=org_units, + np=np, + pd=pd, + xr=xr, + ) + + for org_id, series in series_by_org.items(): + loaded = series.load() + raw = loaded.values + flat = [float(value) for value in raw.flatten().tolist() if value is not None] + values_by_org.setdefault(org_id, {})[parameter] = _aggregate_series_values(flat, aggregation) + + return values_by_org + + +def _parse_process_inputs(process_id: str, payload: ExecuteRequest) -> AggregateImportInputs | XclimIndicatorInputs: + try: + if process_id == AGGREGATE_PROCESS_ID: + return AggregateImportInputs.model_validate(payload.inputs) + if process_id in XCLIM_PROCESS_IDS: + return XclimIndicatorInputs.model_validate(payload.inputs) + except ValidationError as exc: + raise invalid_parameter(f"Invalid process inputs: {exc.errors()}") from exc + + raise not_found("Process", process_id) + + +def _process_definition(process_id: str, base: str) -> dict[str, Any]: + descriptions = { + AGGREGATE_PROCESS_ID: { + "title": "EO aggregate and DHIS2 import", + "description": "Aggregate EO dataset values to DHIS2 org units and import as dataValueSets.", + }, + XCLIM_CDD_PROCESS_ID: { + "title": "xclim consecutive dry days (CDD)", + "description": "Compute xclim CDD over org units using daily precipitation and import-ready outputs.", + }, + XCLIM_CWD_PROCESS_ID: { + "title": "xclim consecutive wet days (CWD)", + "description": "Compute xclim CWD over org units using daily precipitation and import-ready outputs.", + }, + XCLIM_WARM_DAYS_PROCESS_ID: { + "title": "xclim warm days above threshold", + "description": "Compute number of warm days above threshold over org units and import-ready outputs.", + }, + } + meta = descriptions[process_id] + + return { + "id": process_id, + "title": meta["title"], + "description": meta["description"], + "jobControlOptions": ["async-execute"], + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "processes", process_id)}, + { + "rel": "execute", + "type": FORMAT_TYPES[F_JSON], + "href": url_join(base, "processes", process_id, "execution"), + }, + ], + } + + +def _validate_xclim_inputs(process_id: str, inputs: XclimIndicatorInputs) -> None: + if inputs.start > inputs.end: + raise invalid_parameter("Input 'start' must be before or equal to 'end'") + + datasets = load_datasets() + dataset = datasets.get(inputs.datasetId) + if dataset is None: + raise not_found("Collection", inputs.datasetId) + + if inputs.parameter not in dataset.parameters: + raise invalid_parameter(f"Unknown parameter '{inputs.parameter}' for collection '{inputs.datasetId}'") + + threshold_unit = inputs.threshold.unit.lower() + if process_id in {XCLIM_CDD_PROCESS_ID, XCLIM_CWD_PROCESS_ID} and "mm" not in threshold_unit: + raise invalid_parameter("Precipitation threshold unit must include 'mm' (for example 'mm/day')") + if process_id == XCLIM_WARM_DAYS_PROCESS_ID and ("degc" not in threshold_unit and "c" != threshold_unit): + raise invalid_parameter("Warm-days threshold unit must be Celsius (for example 'degC')") + + +def _run_xclim(process_id: str, inputs: XclimIndicatorInputs) -> dict[str, Any]: + _validate_xclim_inputs(process_id, inputs) + + try: + import numpy as np + import pandas as pd + import xarray as xr + from xclim import indices as xci + except ImportError as exc: + raise invalid_parameter( + "xclim execution dependencies are missing. Install optional runtime dependencies for xclim integration." + ) from exc + + org_units = org_unit_items(level=inputs.orgUnitLevel) + if not org_units: + raise invalid_parameter(f"No org unit features found for level {inputs.orgUnitLevel}") + + threshold = f"{inputs.threshold.value} {inputs.threshold.unit}" + uses_dhis2eo_source = True + try: + org_unit_series = _extract_org_unit_series( + dataset_id=inputs.datasetId, + parameter=inputs.parameter, + start=inputs.start, + end=inputs.end, + org_units=org_units, + np=np, + pd=pd, + xr=xr, + ) + except Exception as exc: + logger.warning("Falling back to synthetic xclim source after extraction failure: %s", exc) + uses_dhis2eo_source = False + org_unit_series = _synthetic_org_unit_series( + process_id=process_id, + start=inputs.start, + end=inputs.end, + org_units=org_units, + np=np, + pd=pd, + xr=xr, + ) + + result_features: list[dict[str, Any]] = [] + + for feature in org_units: + series = org_unit_series.get(feature["id"]) + if series is None: + continue + + if process_id in {XCLIM_CDD_PROCESS_ID, XCLIM_CWD_PROCESS_ID}: + if process_id == XCLIM_CDD_PROCESS_ID: + indicator = xci.maximum_consecutive_dry_days(series, thresh=threshold, freq="YS") + else: + indicator = xci.maximum_consecutive_wet_days(series, thresh=threshold, freq="YS") + else: + indicator = xci.tx_days_above(series, thresh=threshold, freq="YS") + + if "time" in indicator.dims: + scalar = indicator.isel(time=-1).load() + else: + scalar = indicator.load() + value = float(scalar.item()) + + result_features.append( + { + "type": "Feature", + "id": feature["id"], + "geometry": feature["geometry"], + "properties": { + "orgUnit": feature["id"], + "datasetId": inputs.datasetId, + "indicator": process_id, + "parameter": inputs.parameter, + "start": inputs.start.isoformat(), + "end": inputs.end.isoformat(), + "source": "dhis2eo" if uses_dhis2eo_source else "synthetic-fallback", + "threshold": inputs.threshold.model_dump(), + "value": round(value, 4), + }, + } + ) + + period = inputs.end.strftime("%Y%m%d") + data_values = _build_indicator_data_values( + result_features, + data_element_id=inputs.dhis2.dataElementId, + period=period, + ) + import_summary = import_data_values_to_dhis2(data_values, dry_run=inputs.dhis2.dryRun) + outputs = { + "importSummary": import_summary, + "features": result_features, + } + return create_job(process_id, inputs.model_dump(mode="json"), outputs) + + +def _synthetic_org_unit_series( + process_id: str, + start: date, + end: date, + org_units: list[dict[str, Any]], + np: Any, + pd: Any, + xr: Any, +) -> dict[str, Any]: + times = pd.date_range(start.isoformat(), end.isoformat(), freq="D") + if len(times) == 0: + raise invalid_parameter("The selected period did not produce any daily timesteps") + + values_by_org_unit: dict[str, Any] = {} + for index, feature in enumerate(org_units): + if process_id in {XCLIM_CDD_PROCESS_ID, XCLIM_CWD_PROCESS_ID}: + base = 0.5 + (index % 4) + signal = base + (np.arange(len(times)) % 6) * 0.35 + series = xr.DataArray( + signal, + coords={"time": times}, + dims=["time"], + attrs={"units": "mm/day"}, + ) + else: + base = 22.0 + (index % 5) + signal = base + (np.arange(len(times)) % 9) * 1.4 + series = xr.DataArray( + signal, + coords={"time": times}, + dims=["time"], + attrs={"units": "degC"}, + ) + + values_by_org_unit[feature["id"]] = series + + return values_by_org_unit + + +def _extract_org_unit_series( + dataset_id: str, + parameter: str, + start: date, + end: date, + org_units: list[dict[str, Any]], + np: Any, + pd: Any, + xr: Any, +) -> dict[str, Any]: + da = _extract_dataarray_with_dhis2eo(dataset_id, parameter, start, end, org_units, xr) + da = _prepare_dataarray_for_parameter(da, parameter, pd) + + x_dim, y_dim = _spatial_dims(da) + values_by_org_unit: dict[str, Any] = {} + + for feature in org_units: + minx, miny, maxx, maxy = _feature_bounds(feature) + clipped = da + if x_dim: + clipped = _slice_dim(clipped, x_dim, minx, maxx) + if y_dim: + clipped = _slice_dim(clipped, y_dim, miny, maxy) + + if x_dim and y_dim: + series = clipped.mean(dim=[y_dim, x_dim], skipna=True) + elif x_dim: + series = clipped.mean(dim=[x_dim], skipna=True) + elif y_dim: + series = clipped.mean(dim=[y_dim], skipna=True) + else: + series = clipped + + if "time" not in series.dims: + time_values = pd.date_range(start.isoformat(), end.isoformat(), freq="D") + expanded = xr.DataArray( + np.repeat(float(series.item()), len(time_values)), + coords={"time": time_values}, + dims=["time"], + attrs=series.attrs, + ) + series = expanded + + values_by_org_unit[feature["id"]] = series + + return values_by_org_unit + + +def _extract_dataarray_with_dhis2eo( + dataset_id: str, + parameter: str, + start: date, + end: date, + org_units: list[dict[str, Any]], + xr: Any, +) -> Any: + bbox = _org_units_bbox(org_units) + cache_dir = _xclim_cache_dir(dataset_id, parameter) + prefix = f"{parameter}_{start.isoformat()}_{end.isoformat()}".replace("-", "") + + if dataset_id == "chirps-daily": + from dhis2eo.data.chc.chirps3 import daily as chirps_daily + + files = chirps_daily.download( + start=start.isoformat(), + end=end.isoformat(), + bbox=bbox, + dirname=str(cache_dir), + prefix=prefix, + var_name="precip", + overwrite=False, + ) + paths = [str(path) for path in files if Path(path).exists()] + if not paths: + raise RuntimeError("No CHIRPS files were downloaded") + + dataset = xr.open_mfdataset(paths, combine="by_coords") + return _dataset_dataarray(dataset, preferred=[parameter, "precip"]) + + if dataset_id == "era5-land-daily": + from dhis2eo.data.cds.era5_land import hourly as era5_hourly + + variable = "total_precipitation" if parameter == "precip" else parameter + files = era5_hourly.download( + start=start.isoformat(), + end=end.isoformat(), + bbox=bbox, + dirname=str(cache_dir), + prefix=prefix, + variables=[variable], + overwrite=False, + ) + paths = [str(path) for path in files if Path(path).exists()] + if not paths: + raise RuntimeError("No ERA5-Land files were downloaded") + + dataset = xr.open_mfdataset(paths, combine="by_coords") + return _dataset_dataarray(dataset, preferred=[parameter, variable, "t2m", "tp"]) + + raise RuntimeError(f"No dhis2eo extractor configured for dataset '{dataset_id}'") + + +def _dataset_dataarray(dataset: Any, preferred: list[str]) -> Any: + for name in preferred: + if name in dataset.data_vars: + da = dataset[name] + da.name = name + return da + + first_name = next(iter(dataset.data_vars.keys()), None) + if first_name is None: + raise RuntimeError("Downloaded dataset has no data variables") + da = dataset[first_name] + da.name = first_name + return da + + +def _prepare_dataarray_for_parameter(da: Any, parameter: str, pd: Any) -> Any: + time_dim = _time_dim(da) + if time_dim != "time": + da = da.rename({time_dim: "time"}) + + da = da.sortby("time") + units = str(da.attrs.get("units", "")).lower() + + if parameter in {"precip", "total_precipitation"}: + da = da.resample(time="1D").sum(skipna=True) + if units == "m": + da = da * 1000.0 + da.attrs["units"] = "mm/day" + elif "mm" in units: + da.attrs["units"] = "mm/day" + else: + da.attrs["units"] = da.attrs.get("units", "mm/day") + else: + da = da.resample(time="1D").mean(skipna=True) + if units in {"k", "kelvin"}: + da = da - 273.15 + da.attrs["units"] = "degC" + elif units in {"c", "degc", "°c"}: + da.attrs["units"] = "degC" + + return da + + +def _org_units_bbox(org_units: list[dict[str, Any]]) -> tuple[float, float, float, float]: + bounds = [_feature_bounds(feature) for feature in org_units] + minx = min(bound[0] for bound in bounds) + miny = min(bound[1] for bound in bounds) + maxx = max(bound[2] for bound in bounds) + maxy = max(bound[3] for bound in bounds) + return (minx, miny, maxx, maxy) + + +def _feature_bounds(feature: dict[str, Any]) -> tuple[float, float, float, float]: + coordinates = feature.get("geometry", {}).get("coordinates", []) + if not coordinates: + return (-180.0, -90.0, 180.0, 90.0) + ring = coordinates[0] + xs = [point[0] for point in ring] + ys = [point[1] for point in ring] + return (min(xs), min(ys), max(xs), max(ys)) + + +def _xclim_cache_dir(dataset_id: str, parameter: str) -> Path: + root = Path(os.getenv("EOAPI_XCLIM_CACHE_DIR", ".cache/xclim")) + path = root / dataset_id / parameter + path.mkdir(parents=True, exist_ok=True) + return path + + +def _time_dim(da: Any) -> str: + for dim in TIME_DIM_CANDIDATES: + if dim in da.dims: + return dim + raise RuntimeError(f"No time dimension found in data array dims={da.dims}") + + +def _spatial_dims(da: Any) -> tuple[str | None, str | None]: + x_dim = next((dim for dim in X_DIM_CANDIDATES if dim in da.dims), None) + y_dim = next((dim for dim in Y_DIM_CANDIDATES if dim in da.dims), None) + return x_dim, y_dim + + +def _slice_dim(da: Any, dim: str, lower: float, upper: float) -> Any: + coords = da[dim].values + if len(coords) == 0: + return da + if coords[0] <= coords[-1]: + return da.sel({dim: slice(lower, upper)}) + return da.sel({dim: slice(upper, lower)}) + + +def _sync_prefect_job(job: dict[str, Any]) -> dict[str, Any]: + execution = job.get("execution") or {} + if execution.get("source") != "prefect": + return job + + flow_run_id = execution.get("flowRunId") + if not flow_run_id or not prefect_enabled(): + return job + + try: + flow_run = get_flow_run(flow_run_id) + except RuntimeError: + return job + + state = flow_run.get("state") or {} + mapped_status = prefect_state_to_job_status(state.get("type")) + progress = 0 + if mapped_status == "running": + progress = 50 + elif mapped_status in {"succeeded", "failed"}: + progress = 100 + + updated = update_job( + job["jobId"], + { + "status": mapped_status, + "progress": progress, + "execution": { + **execution, + "state": state, + }, + }, + ) + return updated or job + + +def run_aggregate_import(inputs: AggregateImportInputs) -> dict[str, Any]: + parameters = _select_parameters(inputs.datasetId, inputs.parameters) + org_units = org_unit_items(level=inputs.orgUnitLevel) + if not org_units: + raise invalid_parameter(f"No org unit features found for level {inputs.orgUnitLevel}") + + dataset = load_datasets()[inputs.datasetId] + effective_time = inputs.datetime or inputs.start or dataset.temporal_interval[0] + + aggregate_start = inputs.start or inputs.datetime or dataset.temporal_interval[0] + aggregate_end = inputs.end or inputs.datetime or aggregate_start + + values_by_org: dict[str, dict[str, float]] = {} + value_source = "dhis2eo" + try: + values_by_org = _extract_aggregate_values_from_dhis2eo( + dataset_id=inputs.datasetId, + parameters=parameters, + start=_coerce_date(aggregate_start), + end=_coerce_date(aggregate_end), + aggregation=inputs.aggregation, + org_units=org_units, + ) + except Exception as exc: + logger.warning("Falling back to synthetic aggregate source after extraction failure: %s", exc) + value_source = "synthetic-fallback" + + result_features: list[dict[str, Any]] = [] + for index, feature in enumerate(org_units): + values = values_by_org.get(feature["id"]) + if values is None: + values = { + parameter: _value_for(index, parameter, inputs.aggregation) + for parameter in parameters + } + + result_features.append( + { + "type": "Feature", + "id": feature["id"], + "geometry": feature["geometry"], + "properties": { + "orgUnit": feature["id"], + "datasetId": inputs.datasetId, + "datetime": effective_time, + "aggregation": inputs.aggregation, + "source": value_source, + "values": values, + }, + } + ) + + period = iso_to_dhis2_period(effective_time) + data_values = _build_aggregate_data_values( + result_features, + default_data_element_id=inputs.dhis2.dataElementId, + data_element_map=inputs.dhis2.dataElementMap, + period=period, + ) + import_summary = import_data_values_to_dhis2(data_values, dry_run=inputs.dhis2.dryRun) + outputs = { + "importSummary": import_summary, + "features": result_features, + } + return create_job(AGGREGATE_PROCESS_ID, inputs.model_dump(), outputs) + + +def run_process(process_id: str, inputs: dict[str, Any]) -> dict[str, Any]: + parsed_inputs = _parse_process_inputs(process_id, ExecuteRequest(inputs=inputs)) + if isinstance(parsed_inputs, AggregateImportInputs): + return run_aggregate_import(parsed_inputs) + return _run_xclim(process_id, parsed_inputs) + + +@router.get("/processes") +def get_processes(request: Request) -> dict[str, Any]: + base = _base_url(request) + process_ids = [ + AGGREGATE_PROCESS_ID, + XCLIM_CDD_PROCESS_ID, + XCLIM_CWD_PROCESS_ID, + XCLIM_WARM_DAYS_PROCESS_ID, + ] + + return { + "processes": [ + { + "id": process_id, + "title": _process_definition(process_id, base)["title"], + "description": _process_definition(process_id, base)["description"], + "links": [ + { + "rel": "process", + "type": FORMAT_TYPES[F_JSON], + "href": url_join(base, "processes", process_id), + } + ], + } + for process_id in process_ids + ], + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "processes")}, + {"rel": "root", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "/")}, + ], + } + + +@router.get("/processes/{processId}") +def get_process(processId: str, request: Request) -> dict[str, Any]: + if processId not in { + AGGREGATE_PROCESS_ID, + XCLIM_CDD_PROCESS_ID, + XCLIM_CWD_PROCESS_ID, + XCLIM_WARM_DAYS_PROCESS_ID, + }: + raise not_found("Process", processId) + + base = _base_url(request) + return _process_definition(processId, base) + + +@router.post("/processes/{processId}/execution", status_code=202) +def execute_process(processId: str, payload: ExecuteRequest, request: Request) -> dict[str, Any]: + job = run_process(processId, payload.inputs) + + base = _base_url(request) + return { + "jobId": job["jobId"], + "processId": processId, + "status": "queued", + "links": [ + {"rel": "monitor", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "jobs", job["jobId"])}, + { + "rel": "results", + "type": FORMAT_TYPES[F_JSON], + "href": f"{url_join(base, 'features', 'aggregated-results', 'items')}?jobId={job['jobId']}", + }, + ], + } + + +@router.get("/jobs/{jobId}") +def get_job_status(jobId: str, request: Request) -> dict[str, Any]: + job = get_job(jobId) + if job is None: + raise not_found("Job", jobId) + + job = _sync_prefect_job(job) + import_summary = (job.get("outputs") or {}).get( + "importSummary", + { + "imported": 0, + "updated": 0, + "ignored": 0, + "deleted": 0, + "dryRun": True, + }, + ) + + base = _base_url(request) + return { + "jobId": job["jobId"], + "processId": job["processId"], + "status": job["status"], + "progress": job["progress"], + "created": job["created"], + "updated": job["updated"], + "importSummary": import_summary, + "execution": job.get("execution"), + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "jobs", jobId)}, + { + "rel": "results", + "type": FORMAT_TYPES[F_JSON], + "href": f"{url_join(base, 'features', 'aggregated-results', 'items')}?jobId={jobId}", + }, + ], + } diff --git a/eoapi/endpoints/root.py b/eoapi/endpoints/root.py index 440848a..54c25ee 100644 --- a/eoapi/endpoints/root.py +++ b/eoapi/endpoints/root.py @@ -1,17 +1,91 @@ +import os +from urllib.parse import urlparse + from fastapi import APIRouter, Request from pygeoapi.api import FORMAT_TYPES, F_JSON from pygeoapi.util import url_join +from eoapi.dhis2_integration import dhis2_configured +from eoapi.state_store import STATE_DIR_ENV, STATE_PERSIST_ENV + router = APIRouter(tags=["Landing Page"]) +def _cors_origins() -> list[str]: + raw = os.getenv("EOAPI_CORS_ORIGINS", "*").strip() + if not raw: + return ["*"] + return [origin.strip() for origin in raw.split(",") if origin.strip()] + + +def _api_key_required() -> bool: + return bool(os.getenv("EOAPI_API_KEY", "").strip()) + + +def _internal_scheduler_enabled() -> bool: + raw = os.getenv("EOAPI_INTERNAL_SCHEDULER_ENABLED", "true").strip().lower() + return raw not in {"0", "false", "no", "off"} + + +def _state_persistence_enabled() -> bool: + raw = os.getenv(STATE_PERSIST_ENV, "true").strip().lower() + return raw not in {"0", "false", "no", "off"} + + +def _state_directory() -> str: + return os.getenv(STATE_DIR_ENV, ".cache/state").strip() or ".cache/state" + + +def _dhis2_auth_mode() -> str: + if os.getenv("EOAPI_DHIS2_TOKEN", "").strip(): + return "token" + + if os.getenv("EOAPI_DHIS2_USERNAME", "").strip() and os.getenv("EOAPI_DHIS2_PASSWORD", "").strip(): + return "basic" + + return "none" + + +def _dhis2_host() -> str: + base = os.getenv("EOAPI_DHIS2_BASE_URL", "").strip() + if not base: + return "unset" + + parsed = urlparse(base) + return parsed.netloc or parsed.path or "configured" + + +def _runtime_summary() -> dict: + cors = _cors_origins() + return { + "cors": { + "mode": "wildcard" if cors == ["*"] else "restricted", + "origins": len(cors), + }, + "apiKeyRequired": _api_key_required(), + "dhis2": { + "configured": dhis2_configured(), + "host": _dhis2_host(), + "authMode": _dhis2_auth_mode(), + }, + "state": { + "persistenceEnabled": _state_persistence_enabled(), + "directory": _state_directory(), + }, + "internalScheduler": { + "enabled": _internal_scheduler_enabled(), + }, + } + + @router.get("/") def read_index(request: Request) -> dict: base = str(request.base_url).rstrip("/") return { "title": "DHIS2 EO API", "description": "OGC-aligned Earth Observation API for DHIS2 and CHAP.", + "runtime": _runtime_summary(), "links": [ { "rel": "self", @@ -31,11 +105,35 @@ def read_index(request: Request) -> dict: "title": "Collections", "href": url_join(base, "collections"), }, + { + "rel": "data", + "type": FORMAT_TYPES[F_JSON], + "title": "Feature collections", + "href": url_join(base, "features"), + }, + { + "rel": "processes", + "type": FORMAT_TYPES[F_JSON], + "title": "Processes", + "href": url_join(base, "processes"), + }, + { + "rel": "processes", + "type": FORMAT_TYPES[F_JSON], + "title": "Workflows", + "href": url_join(base, "workflows"), + }, { "rel": "service-doc", "type": "text/html", "title": "OpenAPI docs", "href": url_join(base, "docs"), }, + { + "rel": "service", + "type": "text/html", + "title": "Example frontend app", + "href": url_join(base, "example-app"), + }, ], } diff --git a/eoapi/endpoints/schedules.py b/eoapi/endpoints/schedules.py new file mode 100644 index 0000000..a7bf60b --- /dev/null +++ b/eoapi/endpoints/schedules.py @@ -0,0 +1,310 @@ +import os +from secrets import compare_digest +from typing import Any + +from fastapi import APIRouter, Header, HTTPException, Request, Response +from pydantic import BaseModel, Field, model_validator + +from pygeoapi.api import FORMAT_TYPES, F_JSON +from pygeoapi.util import url_join + +from eoapi.endpoints.errors import not_found +from eoapi.endpoints.processes import AGGREGATE_PROCESS_ID, AggregateImportInputs, run_aggregate_import +from eoapi.endpoints.workflows import run_workflow_by_id +from eoapi.jobs import create_pending_job, update_job +from eoapi.orchestration.prefect import prefect_enabled, submit_aggregate_import_run +from eoapi.schedules import ( + create_schedule, + delete_schedule, + get_schedule, + list_schedules, + mark_schedule_run, + update_schedule, +) + +router = APIRouter(tags=["Schedules"]) + + +class ScheduleCreateRequest(BaseModel): + name: str = Field(min_length=1) + cron: str = Field(min_length=1, description="Cron expression, e.g. 0 0 * * *") + timezone: str = Field(default="UTC", min_length=1) + enabled: bool = True + inputs: AggregateImportInputs | None = None + workflowId: str | None = Field(default=None, min_length=1) + + @model_validator(mode="after") + def validate_target(self) -> "ScheduleCreateRequest": + if self.inputs is None and self.workflowId is None: + raise ValueError("Either 'inputs' or 'workflowId' is required") + if self.inputs is not None and self.workflowId is not None: + raise ValueError("Provide only one of 'inputs' or 'workflowId'") + return self + + +class ScheduleUpdateRequest(BaseModel): + name: str | None = Field(default=None, min_length=1) + cron: str | None = Field(default=None, min_length=1) + timezone: str | None = Field(default=None, min_length=1) + enabled: bool | None = None + inputs: AggregateImportInputs | None = None + workflowId: str | None = Field(default=None, min_length=1) + + +def _base_url(request: Request) -> str: + return str(request.base_url).rstrip("/") + + +def _schedule_response(request: Request, schedule: dict[str, Any]) -> dict[str, Any]: + base = _base_url(request) + schedule_url = url_join(base, "schedules", schedule["scheduleId"]) + links = [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": schedule_url}, + {"rel": "run", "type": FORMAT_TYPES[F_JSON], "href": url_join(schedule_url, "run")}, + {"rel": "run", "type": FORMAT_TYPES[F_JSON], "href": url_join(schedule_url, "callback")}, + ] + + if schedule.get("workflowId"): + links.append( + { + "rel": "process", + "type": FORMAT_TYPES[F_JSON], + "href": url_join(base, "workflows", schedule["workflowId"]), + } + ) + else: + links.append( + { + "rel": "process", + "type": FORMAT_TYPES[F_JSON], + "href": url_join(base, "processes", AGGREGATE_PROCESS_ID), + } + ) + + return { + **schedule, + "links": links, + } + + +def execute_schedule_target(schedule_id: str, trigger: str) -> dict[str, Any]: + schedule = get_schedule(schedule_id) + if schedule is None: + raise not_found("Schedule", schedule_id) + + workflow_id = schedule.get("workflowId") + inputs_payload = schedule.get("inputs") + + execution_source = "local" + flow_run_id: str | None = None + job_ids: list[str] = [] + + if workflow_id: + workflow_result = run_workflow_by_id(workflow_id) + job_ids = workflow_result["jobIds"] + if not job_ids: + raise HTTPException( + status_code=400, + detail={ + "code": "InvalidParameterValue", + "description": "Workflow did not produce any job runs", + }, + ) + selected_job_id = job_ids[-1] + mark_schedule_run(schedule_id, selected_job_id) + return { + "scheduleId": schedule_id, + "workflowId": workflow_id, + "jobId": selected_job_id, + "jobIds": job_ids, + "status": "queued", + "trigger": trigger, + "execution": { + "source": "workflow", + "flowRunId": None, + }, + } + + if inputs_payload is None: + raise HTTPException( + status_code=400, + detail={ + "code": "InvalidParameterValue", + "description": "Schedule target is missing; provide inputs or workflowId", + }, + ) + + inputs = AggregateImportInputs.model_validate(inputs_payload) + + if prefect_enabled(): + pending_job = create_pending_job( + AGGREGATE_PROCESS_ID, + inputs.model_dump(), + source="prefect", + ) + try: + flow_run = submit_aggregate_import_run( + schedule_id=schedule_id, + payload_inputs=inputs.model_dump(mode="json"), + trigger=trigger, + eoapi_job_id=pending_job["jobId"], + ) + flow_run_id = flow_run.get("id") + update_job( + pending_job["jobId"], + { + "execution": { + "source": "prefect", + "flowRunId": flow_run_id, + }, + "status": "queued", + "progress": 0, + }, + ) + job = pending_job + execution_source = "prefect" + except RuntimeError: + # fall back to local execution to keep schedule runs operational in case Prefect is unavailable + job = run_aggregate_import(inputs) + update_job( + pending_job["jobId"], + { + "status": "failed", + "progress": 100, + }, + ) + else: + job = run_aggregate_import(inputs) + + mark_schedule_run(schedule_id, job["jobId"]) + return { + "scheduleId": schedule_id, + "jobId": job["jobId"], + "status": "queued", + "trigger": trigger, + "execution": { + "source": execution_source, + "flowRunId": flow_run_id, + }, + } + + +def _run_schedule_now(schedule_id: str, request: Request, trigger: str) -> dict[str, Any]: + payload = execute_schedule_target(schedule_id, trigger) + selected_job_id = payload["jobId"] + base = _base_url(request) + return { + **payload, + "links": [ + {"rel": "monitor", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "jobs", selected_job_id)}, + { + "rel": "results", + "type": FORMAT_TYPES[F_JSON], + "href": f"{url_join(base, 'features', 'aggregated-results', 'items')}?jobId={selected_job_id}", + }, + ], + } + + +def _assert_scheduler_callback_authorized(token: str | None) -> None: + expected = os.getenv("EOAPI_SCHEDULER_TOKEN") + if not expected: + raise HTTPException( + status_code=503, + detail={ + "code": "ServiceUnavailable", + "description": "Scheduler callback is not configured; set EOAPI_SCHEDULER_TOKEN", + }, + ) + + if token is None or not compare_digest(token, expected): + raise HTTPException( + status_code=403, + detail={ + "code": "Forbidden", + "description": "Invalid scheduler callback token", + }, + ) + + +@router.get("/schedules") +def get_schedules(request: Request) -> dict[str, Any]: + base = _base_url(request) + schedules = [_schedule_response(request, schedule) for schedule in list_schedules()] + return { + "schedules": schedules, + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "schedules")}, + {"rel": "root", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "/")}, + ], + } + + +@router.post("/schedules", status_code=201) +def post_schedule(payload: ScheduleCreateRequest, request: Request) -> dict[str, Any]: + process_id = "workflow" if payload.workflowId else AGGREGATE_PROCESS_ID + schedule = create_schedule( + { + "processId": process_id, + "workflowId": payload.workflowId, + "name": payload.name, + "cron": payload.cron, + "timezone": payload.timezone, + "enabled": payload.enabled, + "inputs": payload.inputs.model_dump() if payload.inputs else None, + } + ) + return _schedule_response(request, schedule) + + +@router.get("/schedules/{scheduleId}") +def get_schedule_by_id(scheduleId: str, request: Request) -> dict[str, Any]: + schedule = get_schedule(scheduleId) + if schedule is None: + raise not_found("Schedule", scheduleId) + return _schedule_response(request, schedule) + + +@router.patch("/schedules/{scheduleId}") +def patch_schedule(scheduleId: str, payload: ScheduleUpdateRequest, request: Request) -> dict[str, Any]: + updates = payload.model_dump(exclude_unset=True) + if "inputs" in updates and updates["inputs"] is not None: + updates["inputs"] = updates["inputs"].model_dump() + + if updates.get("workflowId") is not None: + updates["processId"] = "workflow" + if "inputs" not in updates: + updates["inputs"] = None + elif updates.get("inputs") is not None: + updates["processId"] = AGGREGATE_PROCESS_ID + if "workflowId" not in updates: + updates["workflowId"] = None + + schedule = update_schedule(scheduleId, updates) + if schedule is None: + raise not_found("Schedule", scheduleId) + + return _schedule_response(request, schedule) + + +@router.delete("/schedules/{scheduleId}", status_code=204) +def remove_schedule(scheduleId: str) -> Response: + deleted = delete_schedule(scheduleId) + if not deleted: + raise not_found("Schedule", scheduleId) + return Response(status_code=204) + + +@router.post("/schedules/{scheduleId}/run", status_code=202) +def run_schedule(scheduleId: str, request: Request) -> dict[str, Any]: + return _run_schedule_now(scheduleId, request, trigger="manual") + + +@router.post("/schedules/{scheduleId}/callback", status_code=202) +def callback_schedule( + scheduleId: str, + request: Request, + x_scheduler_token: str | None = Header(default=None, alias="X-Scheduler-Token"), +) -> dict[str, Any]: + _assert_scheduler_callback_authorized(x_scheduler_token) + return _run_schedule_now(scheduleId, request, trigger="scheduler-callback") diff --git a/eoapi/endpoints/workflows.py b/eoapi/endpoints/workflows.py new file mode 100644 index 0000000..472a1fa --- /dev/null +++ b/eoapi/endpoints/workflows.py @@ -0,0 +1,161 @@ +from typing import Any + +from fastapi import APIRouter, Request +from pydantic import BaseModel, Field + +from pygeoapi.api import FORMAT_TYPES, F_JSON +from pygeoapi.util import url_join + +from eoapi.endpoints.errors import invalid_parameter, not_found +from eoapi.endpoints.processes import run_process +from eoapi.workflows import ( + create_workflow, + delete_workflow, + get_workflow, + list_workflows, + mark_workflow_run, + update_workflow, +) + +router = APIRouter(tags=["Workflows"]) + + +class WorkflowStep(BaseModel): + name: str | None = Field(default=None, min_length=1) + processId: str = Field(min_length=1) + payload: dict[str, Any] + + +class WorkflowCreateRequest(BaseModel): + name: str = Field(min_length=1) + steps: list[WorkflowStep] = Field(min_length=1) + + +class WorkflowUpdateRequest(BaseModel): + name: str | None = Field(default=None, min_length=1) + steps: list[WorkflowStep] | None = None + + +def _base_url(request: Request) -> str: + return str(request.base_url).rstrip("/") + + +def _workflow_response(request: Request, workflow: dict[str, Any]) -> dict[str, Any]: + base = _base_url(request) + workflow_url = url_join(base, "workflows", workflow["workflowId"]) + return { + **workflow, + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": workflow_url}, + {"rel": "run", "type": FORMAT_TYPES[F_JSON], "href": url_join(workflow_url, "run")}, + ], + } + + +def run_workflow_by_id(workflow_id: str) -> dict[str, Any]: + workflow = get_workflow(workflow_id) + if workflow is None: + raise not_found("Workflow", workflow_id) + + steps = workflow.get("steps") or [] + if not steps: + raise invalid_parameter("Workflow has no steps") + + job_ids: list[str] = [] + step_results: list[dict[str, Any]] = [] + for index, step in enumerate(steps): + process_id = step.get("processId") + payload = step.get("payload") or {} + if process_id is None: + raise invalid_parameter(f"Workflow step {index + 1} is missing processId") + + inputs = payload.get("inputs") + if not isinstance(inputs, dict): + raise invalid_parameter(f"Workflow step {index + 1} payload must include object field 'inputs'") + + job = run_process(process_id, inputs) + job_ids.append(job["jobId"]) + step_results.append( + { + "step": step.get("name") or f"step-{index + 1}", + "processId": process_id, + "jobId": job["jobId"], + "status": job["status"], + } + ) + + mark_workflow_run(workflow_id, job_ids) + return { + "workflowId": workflow_id, + "status": "queued", + "jobIds": job_ids, + "steps": step_results, + } + + +@router.get("/workflows") +def get_workflows(request: Request) -> dict[str, Any]: + base = _base_url(request) + workflows = [_workflow_response(request, workflow) for workflow in list_workflows()] + return { + "workflows": workflows, + "links": [ + {"rel": "self", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "workflows")}, + {"rel": "root", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "/")}, + ], + } + + +@router.post("/workflows", status_code=201) +def post_workflow(payload: WorkflowCreateRequest, request: Request) -> dict[str, Any]: + workflow = create_workflow( + { + "name": payload.name, + "steps": [step.model_dump() for step in payload.steps], + } + ) + return _workflow_response(request, workflow) + + +@router.get("/workflows/{workflowId}") +def get_workflow_by_id(workflowId: str, request: Request) -> dict[str, Any]: + workflow = get_workflow(workflowId) + if workflow is None: + raise not_found("Workflow", workflowId) + return _workflow_response(request, workflow) + + +@router.patch("/workflows/{workflowId}") +def patch_workflow(workflowId: str, payload: WorkflowUpdateRequest, request: Request) -> dict[str, Any]: + updates = payload.model_dump(exclude_unset=True) + if "steps" in updates and updates["steps"] is not None: + updates["steps"] = [WorkflowStep.model_validate(step).model_dump() for step in updates["steps"]] + + workflow = update_workflow(workflowId, updates) + if workflow is None: + raise not_found("Workflow", workflowId) + + return _workflow_response(request, workflow) + + +@router.delete("/workflows/{workflowId}", status_code=204) +def remove_workflow(workflowId: str) -> None: + deleted = delete_workflow(workflowId) + if not deleted: + raise not_found("Workflow", workflowId) + + +@router.post("/workflows/{workflowId}/run", status_code=202) +def run_workflow(workflowId: str, request: Request) -> dict[str, Any]: + result = run_workflow_by_id(workflowId) + base = _base_url(request) + last_job_id = result["jobIds"][-1] if result["jobIds"] else None + + links = [] + if last_job_id: + links.append({"rel": "monitor", "type": FORMAT_TYPES[F_JSON], "href": url_join(base, "jobs", last_job_id)}) + + return { + **result, + "links": links, + } diff --git a/eoapi/external_ogc.py b/eoapi/external_ogc.py new file mode 100644 index 0000000..fd2c5f1 --- /dev/null +++ b/eoapi/external_ogc.py @@ -0,0 +1,264 @@ +import json +import os +from dataclasses import dataclass +from typing import Any +from urllib.error import HTTPError, URLError +from urllib.parse import quote, urlencode +from urllib.request import Request, urlopen + + +FEDERATED_PREFIX = "ext" +SUPPORTED_PROXY_OPERATIONS = {"coverage", "position", "area"} + + +@dataclass(frozen=True) +class ExternalOGCProvider: + id: str + url: str + title: str | None = None + headers: dict[str, str] | None = None + api_key_env: str | None = None + auth_scheme: str = "Bearer" + timeout_seconds: float = 20.0 + retries: int = 0 + operations: tuple[str, ...] | None = None + + +def federated_collection_id(provider_id: str, collection_id: str) -> str: + return f"{FEDERATED_PREFIX}:{provider_id}:{collection_id}" + + +def parse_federated_collection_id(collection_id: str) -> tuple[str, str] | None: + parts = collection_id.split(":", 2) + if len(parts) != 3 or parts[0] != FEDERATED_PREFIX: + return None + return (parts[1], parts[2]) + + +def _provider_headers(provider: ExternalOGCProvider | None) -> dict[str, str]: + headers = {"Accept": "application/json"} + if provider is None: + return headers + + for key, value in (provider.headers or {}).items(): + if key and value: + headers[str(key)] = str(value) + + if provider.api_key_env: + api_key = os.getenv(provider.api_key_env, "").strip() + if api_key: + scheme = provider.auth_scheme.strip() if provider.auth_scheme else "Bearer" + if scheme.lower() == "none": + headers["Authorization"] = api_key + else: + headers["Authorization"] = f"{scheme} {api_key}" + + return headers + + +def _fetch_json(url: str, provider: ExternalOGCProvider | None = None) -> dict[str, Any]: + request = Request(url=url, method="GET") + for key, value in _provider_headers(provider).items(): + request.add_header(key, value) + + timeout = provider.timeout_seconds if provider is not None else 20.0 + retries = provider.retries if provider is not None else 0 + attempts = max(1, retries + 1) + + for attempt in range(attempts): + try: + with urlopen(request, timeout=timeout) as response: + return json.loads(response.read().decode("utf-8")) + except (HTTPError, URLError, json.JSONDecodeError): + if attempt + 1 >= attempts: + return {} + + return {} + + +def load_external_providers() -> list[ExternalOGCProvider]: + raw = os.getenv("EOAPI_EXTERNAL_OGC_SERVICES", "").strip() + if not raw: + return [] + + try: + payload = json.loads(raw) + except json.JSONDecodeError: + return [] + + if not isinstance(payload, list): + return [] + + providers: list[ExternalOGCProvider] = [] + for item in payload: + if not isinstance(item, dict): + continue + provider_id = str(item.get("id", "")).strip() + url = str(item.get("url", "")).strip().rstrip("/") + if not provider_id or not url: + continue + title = str(item.get("title", "")).strip() or None + raw_headers = item.get("headers") + headers = None + if isinstance(raw_headers, dict): + headers = {str(key): str(value) for key, value in raw_headers.items() if key and value is not None} + + api_key_env = str(item.get("apiKeyEnv", "")).strip() or None + auth_scheme = str(item.get("authScheme", "Bearer")).strip() or "Bearer" + + timeout_seconds = item.get("timeoutSeconds", 20) + try: + timeout_seconds = float(timeout_seconds) + except (TypeError, ValueError): + timeout_seconds = 20.0 + if timeout_seconds <= 0: + timeout_seconds = 20.0 + + retries = item.get("retries", 0) + try: + retries = int(retries) + except (TypeError, ValueError): + retries = 0 + if retries < 0: + retries = 0 + + operations = None + raw_operations = item.get("operations") + if isinstance(raw_operations, list): + normalized = sorted({str(value).strip().lower() for value in raw_operations if str(value).strip()}) + if any(value not in SUPPORTED_PROXY_OPERATIONS for value in normalized): + continue + operations = tuple(normalized) + + providers.append( + ExternalOGCProvider( + id=provider_id, + url=url, + title=title, + headers=headers, + api_key_env=api_key_env, + auth_scheme=auth_scheme, + timeout_seconds=timeout_seconds, + retries=retries, + operations=operations, + ) + ) + + return providers + + +def get_external_provider(provider_id: str) -> ExternalOGCProvider | None: + return next((item for item in load_external_providers() if item.id == provider_id), None) + + +def get_external_provider_for_collection_id(collection_id: str) -> tuple[ExternalOGCProvider, str] | None: + parsed = parse_federated_collection_id(collection_id) + if parsed is None: + return None + + provider_id, source_collection_id = parsed + provider = get_external_provider(provider_id) + if provider is None: + return None + + return (provider, source_collection_id) + + +def is_external_operation_enabled(collection_id: str, operation: str) -> bool | None: + resolved = get_external_provider_for_collection_id(collection_id) + if resolved is None: + return None + + provider, _ = resolved + if provider.operations is None: + return True + + return operation in provider.operations + + +def list_external_collections() -> list[dict[str, Any]]: + items: list[dict[str, Any]] = [] + for provider in load_external_providers(): + payload = _fetch_json(f"{provider.url}/collections", provider=provider) + collections = payload.get("collections", []) if isinstance(payload, dict) else [] + if not isinstance(collections, list): + continue + + for collection in collections: + if not isinstance(collection, dict): + continue + raw_id = str(collection.get("id", "")).strip() + if not raw_id: + continue + items.append( + { + **collection, + "id": federated_collection_id(provider.id, raw_id), + "federation": { + "providerId": provider.id, + "providerTitle": provider.title, + "providerUrl": provider.url, + "sourceCollectionId": raw_id, + }, + } + ) + + return items + + +def get_external_collection(collection_id: str) -> dict[str, Any] | None: + resolved = get_external_provider_for_collection_id(collection_id) + if resolved is None: + return None + + provider, source_collection_id = resolved + + encoded_id = quote(source_collection_id, safe="") + payload = _fetch_json(f"{provider.url}/collections/{encoded_id}", provider=provider) + if not isinstance(payload, dict) or not payload.get("id"): + return None + + return { + **payload, + "id": federated_collection_id(provider.id, source_collection_id), + "federation": { + "providerId": provider.id, + "providerTitle": provider.title, + "providerUrl": provider.url, + "sourceCollectionId": source_collection_id, + }, + } + + +def proxy_external_collection_request( + collection_id: str, + operation: str, + query_params: list[tuple[str, str]], +) -> dict[str, Any] | None: + resolved = get_external_provider_for_collection_id(collection_id) + if resolved is None: + return None + + provider, source_collection_id = resolved + + encoded_id = quote(source_collection_id, safe="") + filtered_query = [(key, value) for key, value in query_params if key] + query_string = urlencode(filtered_query, doseq=True) + url = f"{provider.url}/collections/{encoded_id}/{operation}" + if query_string: + url = f"{url}?{query_string}" + + payload = _fetch_json(url, provider=provider) + if not isinstance(payload, dict) or not payload: + return None + + return { + **payload, + "federation": { + "providerId": provider.id, + "providerTitle": provider.title, + "providerUrl": provider.url, + "sourceCollectionId": source_collection_id, + "operation": operation, + }, + } diff --git a/eoapi/jobs.py b/eoapi/jobs.py new file mode 100644 index 0000000..cd6a36c --- /dev/null +++ b/eoapi/jobs.py @@ -0,0 +1,95 @@ +from datetime import UTC, datetime +from threading import Lock +from typing import Any +from uuid import uuid4 + +from eoapi.state_store import load_state_map, save_state_map + + +_JOBS: dict[str, dict[str, Any]] = load_state_map("jobs") +_LOCK = Lock() + + +def _now_iso() -> str: + return datetime.now(UTC).isoformat().replace("+00:00", "Z") + + +def create_job(process_id: str, inputs: dict[str, Any], outputs: dict[str, Any]) -> dict[str, Any]: + job_id = str(uuid4()) + timestamp = _now_iso() + job = { + "jobId": job_id, + "processId": process_id, + "status": "succeeded", + "progress": 100, + "created": timestamp, + "updated": timestamp, + "inputs": inputs, + "outputs": outputs, + } + + with _LOCK: + _JOBS[job_id] = job + save_state_map("jobs", _JOBS) + + return job + + +def create_pending_job( + process_id: str, + inputs: dict[str, Any], + *, + source: str, + flow_run_id: str | None = None, +) -> dict[str, Any]: + job_id = str(uuid4()) + timestamp = _now_iso() + job = { + "jobId": job_id, + "processId": process_id, + "status": "queued", + "progress": 0, + "created": timestamp, + "updated": timestamp, + "inputs": inputs, + "outputs": { + "importSummary": { + "imported": 0, + "updated": 0, + "ignored": 0, + "deleted": 0, + "dryRun": bool(inputs.get("dhis2", {}).get("dryRun", True)), + }, + "features": [], + }, + "execution": { + "source": source, + "flowRunId": flow_run_id, + }, + } + + with _LOCK: + _JOBS[job_id] = job + save_state_map("jobs", _JOBS) + + return job + + +def update_job(job_id: str, updates: dict[str, Any]) -> dict[str, Any] | None: + with _LOCK: + job = _JOBS.get(job_id) + if job is None: + return None + + for key, value in updates.items(): + if value is not None: + job[key] = value + + job["updated"] = _now_iso() + save_state_map("jobs", _JOBS) + return job + + +def get_job(job_id: str) -> dict[str, Any] | None: + with _LOCK: + return _JOBS.get(job_id) diff --git a/eoapi/orchestration/prefect.py b/eoapi/orchestration/prefect.py new file mode 100644 index 0000000..eac273e --- /dev/null +++ b/eoapi/orchestration/prefect.py @@ -0,0 +1,90 @@ +import os +from typing import Any +from urllib.error import HTTPError, URLError +from urllib.request import Request, urlopen +import json + + +def prefect_enabled() -> bool: + return os.getenv("EOAPI_PREFECT_ENABLED", "false").lower() in {"1", "true", "yes", "on"} + + +def _prefect_api_url() -> str: + value = os.getenv("EOAPI_PREFECT_API_URL", "").strip() + if not value: + raise RuntimeError("EOAPI_PREFECT_API_URL is required when EOAPI_PREFECT_ENABLED=true") + return value.rstrip("/") + + +def _prefect_headers() -> dict[str, str]: + headers = { + "Content-Type": "application/json", + } + api_key = os.getenv("EOAPI_PREFECT_API_KEY", "").strip() + if api_key: + headers["Authorization"] = f"Bearer {api_key}" + return headers + + +def _json_request(method: str, path: str, payload: dict[str, Any] | None = None) -> dict[str, Any]: + url = f"{_prefect_api_url()}{path}" + data = None + if payload is not None: + data = json.dumps(payload).encode("utf-8") + + request = Request(url=url, data=data, method=method) + for key, value in _prefect_headers().items(): + request.add_header(key, value) + + try: + with urlopen(request, timeout=20) as response: + body = response.read().decode("utf-8") + return json.loads(body) if body else {} + except HTTPError as exc: + detail = exc.read().decode("utf-8") if exc.fp else str(exc) + raise RuntimeError(f"Prefect API error ({exc.code}): {detail}") from exc + except URLError as exc: + raise RuntimeError(f"Unable to reach Prefect API: {exc.reason}") from exc + + +def submit_aggregate_import_run( + schedule_id: str, + payload_inputs: dict[str, Any], + trigger: str, + eoapi_job_id: str, +) -> dict[str, Any]: + deployment_id = os.getenv("EOAPI_PREFECT_DEPLOYMENT_ID", "").strip() + if not deployment_id: + raise RuntimeError("EOAPI_PREFECT_DEPLOYMENT_ID is required when EOAPI_PREFECT_ENABLED=true") + + flow_run_payload = { + "name": f"eoapi-{schedule_id}-{eoapi_job_id}", + "parameters": { + "jobId": eoapi_job_id, + "scheduleId": schedule_id, + "trigger": trigger, + "inputs": payload_inputs, + }, + "tags": ["eoapi", "schedule", trigger], + } + return _json_request("POST", f"/api/deployments/{deployment_id}/create_flow_run", flow_run_payload) + + +def get_flow_run(flow_run_id: str) -> dict[str, Any]: + return _json_request("GET", f"/api/flow_runs/{flow_run_id}") + + +def prefect_state_to_job_status(state_type: str | None) -> str: + if not state_type: + return "queued" + + normalized = state_type.upper() + if normalized in {"PENDING", "SCHEDULED", "LATE", "PAUSED"}: + return "queued" + if normalized in {"RUNNING", "CANCELLING"}: + return "running" + if normalized in {"COMPLETED"}: + return "succeeded" + if normalized in {"FAILED", "CRASHED", "CANCELLED"}: + return "failed" + return "queued" diff --git a/eoapi/scheduler_runtime.py b/eoapi/scheduler_runtime.py new file mode 100644 index 0000000..bb3ab24 --- /dev/null +++ b/eoapi/scheduler_runtime.py @@ -0,0 +1,112 @@ +import logging +import os +from datetime import UTC, datetime +from threading import Event, Thread + +from eoapi.endpoints.schedules import execute_schedule_target +from eoapi.schedules import list_schedules + +logger = logging.getLogger(__name__) + +_THREAD: Thread | None = None +_STOP_EVENT = Event() + + +def _enabled() -> bool: + raw = os.getenv("EOAPI_INTERNAL_SCHEDULER_ENABLED", "true").strip().lower() + return raw not in {"0", "false", "no", "off"} + + +def _poll_seconds() -> float: + raw = os.getenv("EOAPI_INTERNAL_SCHEDULER_POLL_SECONDS", "30").strip() + try: + value = float(raw) + except ValueError: + value = 30.0 + return value if value > 0 else 30.0 + + +def _parse_iso(value: str | None) -> datetime | None: + if not value: + return None + try: + normalized = value.replace("Z", "+00:00") + parsed = datetime.fromisoformat(normalized) + if parsed.tzinfo is None: + return parsed.replace(tzinfo=UTC) + return parsed.astimezone(UTC) + except ValueError: + return None + + +def _schedule_due(schedule: dict, now_utc: datetime) -> bool: + if not schedule.get("enabled", True): + return False + + cron = str(schedule.get("cron", "")).strip() + if not cron: + return False + + try: + croniter_module = __import__("croniter", fromlist=["croniter"]) + croniter = getattr(croniter_module, "croniter") + from zoneinfo import ZoneInfo + except ImportError: + return False + + timezone_name = str(schedule.get("timezone", "UTC") or "UTC") + try: + timezone = ZoneInfo(timezone_name) + except Exception: + timezone = ZoneInfo("UTC") + + anchor = _parse_iso(schedule.get("lastRunAt")) or _parse_iso(schedule.get("created")) + if anchor is None: + anchor = now_utc + + anchor_tz = anchor.astimezone(timezone) + now_tz = now_utc.astimezone(timezone) + + try: + next_run = croniter(cron, anchor_tz).get_next(datetime) + except Exception: + return False + + return next_run <= now_tz + + +def poll_scheduler_once(now_utc: datetime | None = None) -> None: + if not _enabled(): + return + + current = now_utc or datetime.now(UTC) + for schedule in list_schedules(): + if not _schedule_due(schedule, current): + continue + schedule_id = schedule.get("scheduleId") + if not schedule_id: + continue + try: + execute_schedule_target(str(schedule_id), trigger="internal-cron") + except Exception as exc: + logger.warning("Internal scheduler failed for schedule %s: %s", schedule_id, exc) + + +def _worker() -> None: + while not _STOP_EVENT.is_set(): + poll_scheduler_once() + _STOP_EVENT.wait(timeout=_poll_seconds()) + + +def start_internal_scheduler() -> None: + global _THREAD + if _THREAD is not None and _THREAD.is_alive(): + return + + _STOP_EVENT.clear() + _THREAD = Thread(target=_worker, daemon=True, name="eoapi-internal-scheduler") + _THREAD.start() + + +def stop_internal_scheduler() -> None: + _STOP_EVENT.set() diff --git a/eoapi/schedules.py b/eoapi/schedules.py new file mode 100644 index 0000000..281d423 --- /dev/null +++ b/eoapi/schedules.py @@ -0,0 +1,87 @@ +from datetime import UTC, datetime +from threading import Lock +from typing import Any +from uuid import uuid4 + +from eoapi.state_store import load_state_map, save_state_map + + +_SCHEDULES: dict[str, dict[str, Any]] = load_state_map("schedules") +_LOCK = Lock() + + +def _now_iso() -> str: + return datetime.now(UTC).isoformat().replace("+00:00", "Z") + + +def create_schedule(payload: dict[str, Any]) -> dict[str, Any]: + schedule_id = str(uuid4()) + timestamp = _now_iso() + schedule = { + "scheduleId": schedule_id, + "processId": payload["processId"], + "workflowId": payload.get("workflowId"), + "name": payload["name"], + "cron": payload["cron"], + "timezone": payload["timezone"], + "enabled": payload["enabled"], + "inputs": payload["inputs"], + "created": timestamp, + "updated": timestamp, + "lastRunAt": None, + "lastRunJobId": None, + } + + with _LOCK: + _SCHEDULES[schedule_id] = schedule + save_state_map("schedules", _SCHEDULES) + + return schedule + + +def list_schedules() -> list[dict[str, Any]]: + with _LOCK: + return list(_SCHEDULES.values()) + + +def get_schedule(schedule_id: str) -> dict[str, Any] | None: + with _LOCK: + return _SCHEDULES.get(schedule_id) + + +def update_schedule(schedule_id: str, updates: dict[str, Any]) -> dict[str, Any] | None: + with _LOCK: + schedule = _SCHEDULES.get(schedule_id) + if schedule is None: + return None + + for key, value in updates.items(): + if value is not None: + schedule[key] = value + + schedule["updated"] = _now_iso() + save_state_map("schedules", _SCHEDULES) + return schedule + + +def delete_schedule(schedule_id: str) -> bool: + with _LOCK: + if schedule_id not in _SCHEDULES: + return False + del _SCHEDULES[schedule_id] + save_state_map("schedules", _SCHEDULES) + return True + + +def mark_schedule_run(schedule_id: str, job_id: str) -> dict[str, Any] | None: + with _LOCK: + schedule = _SCHEDULES.get(schedule_id) + if schedule is None: + return None + + timestamp = _now_iso() + schedule["lastRunAt"] = timestamp + schedule["lastRunJobId"] = job_id + schedule["updated"] = timestamp + save_state_map("schedules", _SCHEDULES) + return schedule diff --git a/eoapi/state_store.py b/eoapi/state_store.py new file mode 100644 index 0000000..2c42aa5 --- /dev/null +++ b/eoapi/state_store.py @@ -0,0 +1,62 @@ +import json +import os +from pathlib import Path +from tempfile import NamedTemporaryFile +from typing import Any + + +STATE_DIR_ENV = "EOAPI_STATE_DIR" +STATE_PERSIST_ENV = "EOAPI_STATE_PERSIST" + + +def _state_enabled() -> bool: + raw = os.getenv(STATE_PERSIST_ENV, "true").strip().lower() + return raw not in {"0", "false", "no", "off"} + + +def _state_dir() -> Path: + return Path(os.getenv(STATE_DIR_ENV, ".cache/state")) + + +def _state_file(name: str) -> Path: + return _state_dir() / f"{name}.json" + + +def load_state_map(name: str) -> dict[str, dict[str, Any]]: + if not _state_enabled(): + return {} + + path = _state_file(name) + if not path.exists(): + return {} + + try: + payload = json.loads(path.read_text(encoding="utf-8")) + except (OSError, json.JSONDecodeError): + return {} + + if not isinstance(payload, dict): + return {} + + return {str(key): value for key, value in payload.items() if isinstance(value, dict)} + + +def save_state_map(name: str, payload: dict[str, dict[str, Any]]) -> None: + if not _state_enabled(): + return + + state_dir = _state_dir() + try: + state_dir.mkdir(parents=True, exist_ok=True) + except OSError: + return + + path = _state_file(name) + + try: + with NamedTemporaryFile("w", delete=False, dir=state_dir, encoding="utf-8") as tmp: + json.dump(payload, tmp, ensure_ascii=False) + tmp_path = Path(tmp.name) + tmp_path.replace(path) + except OSError: + return diff --git a/eoapi/workflows.py b/eoapi/workflows.py new file mode 100644 index 0000000..baf2ea8 --- /dev/null +++ b/eoapi/workflows.py @@ -0,0 +1,82 @@ +from datetime import UTC, datetime +from threading import Lock +from typing import Any +from uuid import uuid4 + +from eoapi.state_store import load_state_map, save_state_map + + +_WORKFLOWS: dict[str, dict[str, Any]] = load_state_map("workflows") +_LOCK = Lock() + + +def _now_iso() -> str: + return datetime.now(UTC).isoformat().replace("+00:00", "Z") + + +def create_workflow(payload: dict[str, Any]) -> dict[str, Any]: + workflow_id = str(uuid4()) + timestamp = _now_iso() + workflow = { + "workflowId": workflow_id, + "name": payload["name"], + "steps": payload["steps"], + "created": timestamp, + "updated": timestamp, + "lastRunAt": None, + "lastRunJobIds": [], + } + + with _LOCK: + _WORKFLOWS[workflow_id] = workflow + save_state_map("workflows", _WORKFLOWS) + + return workflow + + +def list_workflows() -> list[dict[str, Any]]: + with _LOCK: + return list(_WORKFLOWS.values()) + + +def get_workflow(workflow_id: str) -> dict[str, Any] | None: + with _LOCK: + return _WORKFLOWS.get(workflow_id) + + +def update_workflow(workflow_id: str, updates: dict[str, Any]) -> dict[str, Any] | None: + with _LOCK: + workflow = _WORKFLOWS.get(workflow_id) + if workflow is None: + return None + + for key, value in updates.items(): + if value is not None: + workflow[key] = value + + workflow["updated"] = _now_iso() + save_state_map("workflows", _WORKFLOWS) + return workflow + + +def delete_workflow(workflow_id: str) -> bool: + with _LOCK: + if workflow_id not in _WORKFLOWS: + return False + del _WORKFLOWS[workflow_id] + save_state_map("workflows", _WORKFLOWS) + return True + + +def mark_workflow_run(workflow_id: str, job_ids: list[str]) -> dict[str, Any] | None: + with _LOCK: + workflow = _WORKFLOWS.get(workflow_id) + if workflow is None: + return None + + timestamp = _now_iso() + workflow["lastRunAt"] = timestamp + workflow["lastRunJobIds"] = job_ids + workflow["updated"] = timestamp + save_state_map("workflows", _WORKFLOWS) + return workflow diff --git a/main.py b/main.py index a0ceba2..ccd327a 100644 --- a/main.py +++ b/main.py @@ -1,13 +1,107 @@ +import os +import logging +from urllib.parse import urlparse from fastapi import FastAPI +from fastapi import Request +from fastapi.responses import JSONResponse +from fastapi.staticfiles import StaticFiles +from pathlib import Path from titiler.core.factory import (TilerFactory) from rio_tiler.io import STACReader from eoapi.endpoints.collections import router as collections_router from eoapi.endpoints.conformance import router as conformance_router +from eoapi.endpoints.features import router as features_router +from eoapi.endpoints.processes import router as processes_router from eoapi.endpoints.root import router as root_router +from eoapi.endpoints.schedules import router as schedules_router +from eoapi.endpoints.workflows import router as workflows_router +from eoapi.dhis2_integration import dhis2_configured +from eoapi.scheduler_runtime import start_internal_scheduler, stop_internal_scheduler +from eoapi.state_store import STATE_DIR_ENV, STATE_PERSIST_ENV from starlette.middleware.cors import CORSMiddleware app = FastAPI() +logger = logging.getLogger(__name__) + + +def _cors_origins() -> list[str]: + raw = os.getenv("EOAPI_CORS_ORIGINS", "*").strip() + if not raw: + return ["*"] + return [origin.strip() for origin in raw.split(",") if origin.strip()] + + +def _api_key_required() -> str | None: + token = os.getenv("EOAPI_API_KEY", "").strip() + return token or None + + +def _internal_scheduler_enabled() -> bool: + raw = os.getenv("EOAPI_INTERNAL_SCHEDULER_ENABLED", "true").strip().lower() + return raw not in {"0", "false", "no", "off"} + + +def _internal_scheduler_poll_seconds() -> float: + raw = os.getenv("EOAPI_INTERNAL_SCHEDULER_POLL_SECONDS", "30").strip() + try: + value = float(raw) + except ValueError: + value = 30.0 + return value if value > 0 else 30.0 + + +def _state_persistence_enabled() -> bool: + raw = os.getenv(STATE_PERSIST_ENV, "true").strip().lower() + return raw not in {"0", "false", "no", "off"} + + +def _state_directory() -> str: + return os.getenv(STATE_DIR_ENV, ".cache/state").strip() or ".cache/state" + + +def _dhis2_auth_mode() -> str: + if os.getenv("EOAPI_DHIS2_TOKEN", "").strip(): + return "token" + + if os.getenv("EOAPI_DHIS2_USERNAME", "").strip() and os.getenv("EOAPI_DHIS2_PASSWORD", "").strip(): + return "basic" + + return "none" + + +def _dhis2_host() -> str: + base = os.getenv("EOAPI_DHIS2_BASE_URL", "").strip() + if not base: + return "unset" + + parsed = urlparse(base) + return parsed.netloc or parsed.path or "configured" + + +def _log_startup_configuration() -> None: + cors = _cors_origins() + logger.info( + "Startup config: cors=%s apiKeyRequired=%s", + "*" if cors == ["*"] else f"{len(cors)} origins", + _api_key_required() is not None, + ) + logger.info( + "Startup config: dhis2 configured=%s host=%s authMode=%s", + dhis2_configured(), + _dhis2_host(), + _dhis2_auth_mode(), + ) + logger.info( + "Startup config: statePersistence=%s stateDir=%s", + _state_persistence_enabled(), + _state_directory(), + ) + logger.info( + "Startup config: internalScheduler=%s pollSeconds=%s", + _internal_scheduler_enabled(), + _internal_scheduler_poll_seconds(), + ) # Bsed on: # https://developmentseed.org/titiler/user_guide/getting_started/#4-create-your-titiler-application @@ -16,18 +110,58 @@ # Add CORS middleware app.add_middleware( CORSMiddleware, - allow_origins=["*"], # Allows all origins (for development - be more specific in production) + allow_origins=_cors_origins(), allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) + +@app.middleware("http") +async def _optional_api_key_guard(request: Request, call_next): + expected = _api_key_required() + if expected is None: + return await call_next(request) + + if request.method in {"POST", "PATCH", "DELETE", "PUT"}: + provided = request.headers.get("X-API-Key", "") + if provided != expected: + return JSONResponse( + status_code=403, + content={ + "detail": { + "code": "Forbidden", + "description": "Invalid or missing API key", + } + }, + ) + + return await call_next(request) + # Create a TilerFactory for Cloud-Optimized GeoTIFFs cog = TilerFactory() app.include_router(root_router) app.include_router(conformance_router) app.include_router(collections_router) +app.include_router(features_router) +app.include_router(processes_router) +app.include_router(workflows_router) +app.include_router(schedules_router) # Register all the COG endpoints automatically app.include_router(cog.router, prefix="/cog", tags=["Cloud Optimized GeoTIFF"]) + +webapp_dir = Path(__file__).resolve().parent / "webapp" +app.mount("/example-app", StaticFiles(directory=str(webapp_dir), html=True), name="example-app") + + +@app.on_event("startup") +def _on_startup() -> None: + _log_startup_configuration() + start_internal_scheduler() + + +@app.on_event("shutdown") +def _on_shutdown() -> None: + stop_internal_scheduler() diff --git a/pyproject.toml b/pyproject.toml index e047d64..0ccbfa6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,7 +10,9 @@ dependencies = [ "titiler-core>=1.2.0", "uvicorn>=0.41.0", "pygeoapi>=0.22.0", + "croniter>=2.0.5", "pyyaml>=6.0", + "xclim>=0.58.1", "dhis2eo @ git+https://github.com/dhis2/dhis2eo.git@v1.1.0", "dhis2-client @ git+https://github.com/dhis2/dhis2-python-client.git@V0.3.0", ] diff --git a/tests/test_collections_federation.py b/tests/test_collections_federation.py new file mode 100644 index 0000000..e92f4db --- /dev/null +++ b/tests/test_collections_federation.py @@ -0,0 +1,75 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.collections import router as collections_router + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(collections_router) + return TestClient(app) + + +def test_collections_includes_external_federated_entries(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.collections.list_external_collections", + lambda: [ + { + "id": "ext:demo-provider:rainfall-collection", + "title": "External Rainfall", + "description": "Remote OGC collection", + "keywords": ["external"], + "extent": { + "spatial": {"bbox": [[-10.0, -10.0, 10.0, 10.0]]}, + "temporal": {"interval": [["2020-01-01T00:00:00Z", None]]}, + }, + "itemType": "coverage", + "federation": { + "providerId": "demo-provider", + "providerUrl": "https://example-ogc.test", + "sourceCollectionId": "rainfall-collection", + }, + } + ], + ) + + response = client.get("/collections") + + assert response.status_code == 200 + payload = response.json() + ids = {collection["id"] for collection in payload["collections"]} + assert "chirps-daily" in ids + assert "ext:demo-provider:rainfall-collection" in ids + + +def test_get_external_collection_details(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.collections.get_external_collection", + lambda collection_id: { + "id": collection_id, + "title": "External Rainfall", + "description": "Remote OGC collection", + "extent": { + "spatial": {"bbox": [[-10.0, -10.0, 10.0, 10.0]]}, + "temporal": {"interval": [["2020-01-01T00:00:00Z", None]]}, + }, + "itemType": "coverage", + "federation": { + "providerId": "demo-provider", + "providerUrl": "https://example-ogc.test", + "sourceCollectionId": "rainfall-collection", + }, + }, + ) + + response = client.get("/collections/ext:demo-provider:rainfall-collection") + + assert response.status_code == 200 + payload = response.json() + assert payload["id"] == "ext:demo-provider:rainfall-collection" + rels = {link["rel"] for link in payload["links"]} + assert "source" in rels diff --git a/tests/test_coverages_federation.py b/tests/test_coverages_federation.py new file mode 100644 index 0000000..59b4d3a --- /dev/null +++ b/tests/test_coverages_federation.py @@ -0,0 +1,64 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.collections import router as collections_router +from eoapi.endpoints.coverages import router as coverages_router + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(collections_router) + app.include_router(coverages_router) + return TestClient(app) + + +def test_external_coverage_proxy_success(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.coverages.proxy_external_collection_request", + lambda collection_id, operation, query_params: { + "type": "Coverage", + "title": "External coverage", + "federation": { + "providerId": "demo-provider", + "sourceCollectionId": "rainfall-collection", + "operation": operation, + }, + }, + ) + + response = client.get("/collections/ext:demo-provider:rainfall-collection/coverage", params={"f": "json"}) + + assert response.status_code == 200 + payload = response.json() + assert payload["type"] == "Coverage" + assert payload["federation"]["operation"] == "coverage" + + +def test_external_coverage_proxy_not_found(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.coverages.proxy_external_collection_request", + lambda collection_id, operation, query_params: None, + ) + + response = client.get("/collections/ext:demo-provider:missing-collection/coverage") + + assert response.status_code == 404 + assert response.json()["detail"]["code"] == "NotFound" + + +def test_external_coverage_proxy_disabled_operation(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.coverages.is_external_operation_enabled", + lambda collection_id, operation: False, + ) + + response = client.get("/collections/ext:demo-provider:rainfall-collection/coverage") + + assert response.status_code == 400 + assert response.json()["detail"]["code"] == "InvalidParameterValue" diff --git a/tests/test_edr_endpoint.py b/tests/test_edr_endpoint.py index af862c7..b04f6b6 100644 --- a/tests/test_edr_endpoint.py +++ b/tests/test_edr_endpoint.py @@ -85,3 +85,91 @@ def test_edr_area_invalid_bbox() -> None: assert response.status_code == 400 assert response.json()["detail"]["code"] == "InvalidParameterValue" + + +def test_external_edr_position_proxy_success(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.edr.proxy_external_collection_request", + lambda collection_id, operation, query_params: { + "type": "FeatureCollection", + "features": [], + "federation": { + "providerId": "demo-provider", + "sourceCollectionId": "rainfall-collection", + "operation": operation, + }, + }, + ) + + response = client.get( + "/collections/ext:demo-provider:rainfall-collection/position", + params={"coords": "POINT(30 -1)", "f": "json"}, + ) + + assert response.status_code == 200 + payload = response.json() + assert payload["type"] == "FeatureCollection" + assert payload["federation"]["operation"] == "position" + + +def test_external_edr_area_proxy_success(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.edr.proxy_external_collection_request", + lambda collection_id, operation, query_params: { + "type": "FeatureCollection", + "features": [], + "federation": { + "providerId": "demo-provider", + "sourceCollectionId": "rainfall-collection", + "operation": operation, + }, + }, + ) + + response = client.get( + "/collections/ext:demo-provider:rainfall-collection/area", + params={"bbox": "30,-5,35,2", "f": "json"}, + ) + + assert response.status_code == 200 + payload = response.json() + assert payload["type"] == "FeatureCollection" + assert payload["federation"]["operation"] == "area" + + +def test_external_edr_position_proxy_disabled_operation(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.edr.is_external_operation_enabled", + lambda collection_id, operation: False, + ) + + response = client.get( + "/collections/ext:demo-provider:rainfall-collection/position", + params={"coords": "POINT(30 -1)", "f": "json"}, + ) + + assert response.status_code == 400 + assert response.json()["detail"]["code"] == "InvalidParameterValue" + + +def test_external_edr_area_proxy_disabled_operation(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.edr.is_external_operation_enabled", + lambda collection_id, operation: False, + ) + + response = client.get( + "/collections/ext:demo-provider:rainfall-collection/area", + params={"bbox": "30,-5,35,2", "f": "json"}, + ) + + assert response.status_code == 400 + assert response.json()["detail"]["code"] == "InvalidParameterValue" diff --git a/tests/test_external_ogc_config.py b/tests/test_external_ogc_config.py new file mode 100644 index 0000000..92a0f93 --- /dev/null +++ b/tests/test_external_ogc_config.py @@ -0,0 +1,76 @@ +from urllib.error import URLError + +from eoapi.external_ogc import _fetch_json, load_external_providers + + +class _Response: + def __init__(self, payload: bytes): + self._payload = payload + + def read(self) -> bytes: + return self._payload + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc, tb): + return False + + +def test_load_external_provider_auth_and_retry_settings(monkeypatch) -> None: + monkeypatch.setenv( + "EOAPI_EXTERNAL_OGC_SERVICES", + '[{"id":"demo","url":"https://example.test","headers":{"X-Custom":"abc"},"apiKeyEnv":"DEMO_API_KEY","authScheme":"Token","timeoutSeconds":7,"retries":2,"operations":["coverage","position"]}]', + ) + + providers = load_external_providers() + + assert len(providers) == 1 + provider = providers[0] + assert provider.id == "demo" + assert provider.headers == {"X-Custom": "abc"} + assert provider.api_key_env == "DEMO_API_KEY" + assert provider.auth_scheme == "Token" + assert provider.timeout_seconds == 7.0 + assert provider.retries == 2 + assert provider.operations == ("coverage", "position") + + +def test_fetch_json_applies_headers_timeout_and_retries(monkeypatch) -> None: + monkeypatch.setenv("DEMO_API_KEY", "secret-value") + + monkeypatch.setenv( + "EOAPI_EXTERNAL_OGC_SERVICES", + '[{"id":"demo","url":"https://example.test","headers":{"X-Custom":"abc"},"apiKeyEnv":"DEMO_API_KEY","authScheme":"Token","timeoutSeconds":3,"retries":1}]', + ) + provider = load_external_providers()[0] + + calls: list[tuple[object, float]] = [] + + def fake_urlopen(request, timeout): + calls.append((request, timeout)) + if len(calls) == 1: + raise URLError("temporary") + return _Response(b'{"collections": []}') + + monkeypatch.setattr("eoapi.external_ogc.urlopen", fake_urlopen) + + payload = _fetch_json("https://example.test/collections", provider=provider) + + assert payload == {"collections": []} + assert len(calls) == 2 + request, timeout = calls[0] + assert timeout == 3.0 + assert request.headers["X-custom"] == "abc" + assert request.headers["Authorization"] == "Token secret-value" + + +def test_load_external_provider_rejects_unknown_operations(monkeypatch) -> None: + monkeypatch.setenv( + "EOAPI_EXTERNAL_OGC_SERVICES", + '[{"id":"demo","url":"https://example.test","operations":["coverage","timeseries"]}]', + ) + + providers = load_external_providers() + + assert providers == [] diff --git a/tests/test_features_endpoint.py b/tests/test_features_endpoint.py new file mode 100644 index 0000000..7cc117b --- /dev/null +++ b/tests/test_features_endpoint.py @@ -0,0 +1,58 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.features import router as features_router + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(features_router) + return TestClient(app) + + +def test_features_collections_list() -> None: + client = create_client() + + response = client.get("/features") + + assert response.status_code == 200 + payload = response.json() + ids = {collection["id"] for collection in payload["collections"]} + assert {"dhis2-org-units", "aggregated-results"}.issubset(ids) + + +def test_features_org_units_items() -> None: + client = create_client() + + response = client.get("/features/dhis2-org-units/items", params={"level": 2}) + + assert response.status_code == 200 + payload = response.json() + assert payload["type"] == "FeatureCollection" + assert payload["numberReturned"] >= 1 + + +def test_features_org_units_items_from_dhis2(monkeypatch) -> None: + client = create_client() + + monkeypatch.setattr( + "eoapi.endpoints.features.fetch_org_units_from_dhis2", + lambda level: [ + { + "type": "Feature", + "id": "ou-demo", + "geometry": { + "type": "Polygon", + "coordinates": [[[10.0, 10.0], [11.0, 10.0], [11.0, 11.0], [10.0, 11.0], [10.0, 10.0]]], + }, + "properties": {"name": "Demo", "level": level}, + } + ], + ) + + response = client.get("/features/dhis2-org-units/items", params={"level": 2}) + + assert response.status_code == 200 + payload = response.json() + assert payload["numberReturned"] == 1 + assert payload["features"][0]["id"] == "ou-demo" diff --git a/tests/test_landing_page.py b/tests/test_landing_page.py index 5b7dfe7..3d840c1 100644 --- a/tests/test_landing_page.py +++ b/tests/test_landing_page.py @@ -17,5 +17,10 @@ def test_landing_page_links() -> None: assert response.status_code == 200 payload = response.json() assert payload["title"] == "DHIS2 EO API" + runtime = payload["runtime"] + assert "dhis2" in runtime + assert "state" in runtime + assert "internalScheduler" in runtime + assert "apiKeyRequired" in runtime rels = {link["rel"] for link in payload["links"]} assert {"self", "conformance", "data", "service-doc"}.issubset(rels) diff --git a/tests/test_processes_endpoint.py b/tests/test_processes_endpoint.py new file mode 100644 index 0000000..deaee49 --- /dev/null +++ b/tests/test_processes_endpoint.py @@ -0,0 +1,255 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient +import pandas as pd +import xarray as xr + +from eoapi.endpoints.features import router as features_router +from eoapi.endpoints.processes import router as processes_router +from eoapi.jobs import create_job + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(features_router) + app.include_router(processes_router) + return TestClient(app) + + +def test_process_execution_and_job_status() -> None: + client = create_client() + + execute_response = client.post( + "/processes/eo-aggregate-import/execution", + json={ + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": { + "dataElementId": "abc123", + "dryRun": True, + }, + } + }, + ) + + assert execute_response.status_code == 202 + execute_payload = execute_response.json() + assert execute_payload["processId"] == "eo-aggregate-import" + + job_id = execute_payload["jobId"] + job_response = client.get(f"/jobs/{job_id}") + assert job_response.status_code == 200 + + job_payload = job_response.json() + assert job_payload["status"] == "succeeded" + assert job_payload["importSummary"]["dryRun"] is True + + features_response = client.get("/features/aggregated-results/items", params={"jobId": job_id}) + assert features_response.status_code == 200 + features_payload = features_response.json() + assert features_payload["type"] == "FeatureCollection" + assert features_payload["numberReturned"] >= 1 + + +def test_process_unknown_id() -> None: + client = create_client() + + response = client.get("/processes/unknown") + + assert response.status_code == 404 + assert response.json()["detail"]["code"] == "NotFound" + + +def test_process_list_includes_xclim_processes() -> None: + client = create_client() + + response = client.get("/processes") + + assert response.status_code == 200 + payload = response.json() + process_ids = {process["id"] for process in payload["processes"]} + assert "eo-aggregate-import" in process_ids + assert "xclim-cdd" in process_ids + assert "xclim-cwd" in process_ids + assert "xclim-warm-days" in process_ids + + +def test_xclim_execution_dispatch(monkeypatch) -> None: + client = create_client() + + def fake_run_xclim(process_id, inputs): + outputs = { + "importSummary": { + "imported": 0, + "updated": 0, + "ignored": 1, + "deleted": 0, + "dryRun": True, + }, + "features": [ + { + "type": "Feature", + "id": "org-demo", + "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, + "properties": {"orgUnit": "org-demo", "value": 4.0}, + } + ], + } + return create_job(process_id, inputs.model_dump(mode="json"), outputs) + + monkeypatch.setattr("eoapi.endpoints.processes._run_xclim", fake_run_xclim) + + execute_response = client.post( + "/processes/xclim-cdd/execution", + json={ + "inputs": { + "datasetId": "chirps-daily", + "parameter": "precip", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": {"value": 1.0, "unit": "mm/day"}, + "dhis2": { + "dataElementId": "abc123", + "dryRun": True, + }, + } + }, + ) + + assert execute_response.status_code == 202 + payload = execute_response.json() + assert payload["processId"] == "xclim-cdd" + + job_response = client.get(f"/jobs/{payload['jobId']}") + assert job_response.status_code == 200 + assert job_response.json()["processId"] == "xclim-cdd" + + +def test_xclim_uses_dhis2eo_series_when_available(monkeypatch) -> None: + client = create_client() + + def fake_extract_org_unit_series(**kwargs): + times = pd.date_range("2026-01-01", "2026-01-31", freq="D") + ids = [feature["id"] for feature in kwargs["org_units"]] + return { + org_unit_id: xr.DataArray( + [0.4 + (index % 3) * 0.2 for index, _ in enumerate(times)], + coords={"time": times}, + dims=["time"], + attrs={"units": "mm/day"}, + ) + for org_unit_id in ids + } + + monkeypatch.setattr("eoapi.endpoints.processes._extract_org_unit_series", fake_extract_org_unit_series) + + execute_response = client.post( + "/processes/xclim-cdd/execution", + json={ + "inputs": { + "datasetId": "chirps-daily", + "parameter": "precip", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": {"value": 1.0, "unit": "mm/day"}, + "dhis2": { + "dataElementId": "abc123", + "dryRun": True, + }, + } + }, + ) + + assert execute_response.status_code == 202 + job_id = execute_response.json()["jobId"] + features_response = client.get("/features/aggregated-results/items", params={"jobId": job_id}) + assert features_response.status_code == 200 + + payload = features_response.json() + assert payload["features"] + assert payload["features"][0]["properties"]["source"] == "dhis2eo" + + +def test_xclim_falls_back_to_synthetic_on_extractor_error(monkeypatch) -> None: + client = create_client() + + def fail_extract_org_unit_series(**kwargs): + raise RuntimeError("network unavailable") + + monkeypatch.setattr("eoapi.endpoints.processes._extract_org_unit_series", fail_extract_org_unit_series) + + execute_response = client.post( + "/processes/xclim-warm-days/execution", + json={ + "inputs": { + "datasetId": "era5-land-daily", + "parameter": "2m_temperature", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": {"value": 35.0, "unit": "degC"}, + "dhis2": { + "dataElementId": "abc123", + "dryRun": True, + }, + } + }, + ) + + assert execute_response.status_code == 202 + job_id = execute_response.json()["jobId"] + features_response = client.get("/features/aggregated-results/items", params={"jobId": job_id}) + assert features_response.status_code == 200 + + payload = features_response.json() + assert payload["features"] + assert payload["features"][0]["properties"]["source"] == "synthetic-fallback" + + +def test_aggregate_process_uses_dhis2_import_adapter(monkeypatch) -> None: + client = create_client() + + def fake_import(data_values, dry_run): + assert dry_run is False + assert len(data_values) >= 1 + return { + "imported": len(data_values), + "updated": 0, + "ignored": 0, + "deleted": 0, + "dryRun": False, + "source": "dhis2", + } + + monkeypatch.setattr("eoapi.endpoints.processes.import_data_values_to_dhis2", fake_import) + + execute_response = client.post( + "/processes/eo-aggregate-import/execution", + json={ + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": { + "dataElementId": "abc123", + "dryRun": False, + }, + } + }, + ) + + assert execute_response.status_code == 202 + job_id = execute_response.json()["jobId"] + + job_response = client.get(f"/jobs/{job_id}") + assert job_response.status_code == 200 + payload = job_response.json() + assert payload["importSummary"]["dryRun"] is False + assert payload["importSummary"]["source"] == "dhis2" diff --git a/tests/test_scheduler_runtime.py b/tests/test_scheduler_runtime.py new file mode 100644 index 0000000..5096699 --- /dev/null +++ b/tests/test_scheduler_runtime.py @@ -0,0 +1,45 @@ +from datetime import UTC, datetime + +from eoapi.scheduler_runtime import poll_scheduler_once + + +def test_poll_scheduler_once_triggers_due_schedule(monkeypatch) -> None: + monkeypatch.setenv("EOAPI_INTERNAL_SCHEDULER_ENABLED", "true") + + calls: list[tuple[str, str]] = [] + + monkeypatch.setattr( + "eoapi.scheduler_runtime.list_schedules", + lambda: [ + { + "scheduleId": "sch-1", + "enabled": True, + "cron": "* * * * *", + "timezone": "UTC", + "created": "2026-01-01T00:00:00Z", + "lastRunAt": "2026-01-01T00:00:00Z", + } + ], + ) + monkeypatch.setattr( + "eoapi.scheduler_runtime.execute_schedule_target", + lambda schedule_id, trigger: calls.append((schedule_id, trigger)), + ) + + poll_scheduler_once(now_utc=datetime(2026, 1, 1, 0, 2, tzinfo=UTC)) + + assert calls == [("sch-1", "internal-cron")] + + +def test_poll_scheduler_once_noop_when_disabled(monkeypatch) -> None: + monkeypatch.setenv("EOAPI_INTERNAL_SCHEDULER_ENABLED", "false") + + calls: list[tuple[str, str]] = [] + monkeypatch.setattr( + "eoapi.scheduler_runtime.execute_schedule_target", + lambda schedule_id, trigger: calls.append((schedule_id, trigger)), + ) + + poll_scheduler_once(now_utc=datetime(2026, 1, 1, 0, 2, tzinfo=UTC)) + + assert calls == [] diff --git a/tests/test_schedules_endpoint.py b/tests/test_schedules_endpoint.py new file mode 100644 index 0000000..2ca2084 --- /dev/null +++ b/tests/test_schedules_endpoint.py @@ -0,0 +1,227 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.features import router as features_router +from eoapi.endpoints.processes import router as processes_router +from eoapi.endpoints.schedules import router as schedules_router +from eoapi.endpoints.workflows import router as workflows_router +from eoapi.jobs import create_pending_job + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(features_router) + app.include_router(processes_router) + app.include_router(workflows_router) + app.include_router(schedules_router) + return TestClient(app) + + +def _create_schedule(client: TestClient) -> str: + response = client.post( + "/schedules", + json={ + "name": "nightly-precip-import", + "cron": "0 0 * * *", + "timezone": "UTC", + "enabled": True, + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": { + "dataElementId": "abc123", + "dryRun": True, + }, + }, + }, + ) + assert response.status_code == 201 + return response.json()["scheduleId"] + + +def test_schedule_crud_and_run() -> None: + client = create_client() + + schedule_id = _create_schedule(client) + + list_response = client.get("/schedules") + assert list_response.status_code == 200 + assert any(item["scheduleId"] == schedule_id for item in list_response.json()["schedules"]) + + get_response = client.get(f"/schedules/{schedule_id}") + assert get_response.status_code == 200 + assert get_response.json()["name"] == "nightly-precip-import" + + patch_response = client.patch( + f"/schedules/{schedule_id}", + json={"enabled": False}, + ) + assert patch_response.status_code == 200 + assert patch_response.json()["enabled"] is False + + run_response = client.post(f"/schedules/{schedule_id}/run") + assert run_response.status_code == 202 + job_id = run_response.json()["jobId"] + + job_response = client.get(f"/jobs/{job_id}") + assert job_response.status_code == 200 + assert job_response.json()["status"] == "succeeded" + + get_after_run = client.get(f"/schedules/{schedule_id}") + assert get_after_run.status_code == 200 + assert get_after_run.json()["lastRunJobId"] == job_id + + delete_response = client.delete(f"/schedules/{schedule_id}") + assert delete_response.status_code == 204 + + not_found_response = client.get(f"/schedules/{schedule_id}") + assert not_found_response.status_code == 404 + + +def test_schedule_callback_runs_job(monkeypatch) -> None: + client = create_client() + monkeypatch.setenv("EOAPI_SCHEDULER_TOKEN", "secret-token") + + schedule_id = _create_schedule(client) + + callback_response = client.post( + f"/schedules/{schedule_id}/callback", + headers={"X-Scheduler-Token": "secret-token"}, + ) + assert callback_response.status_code == 202 + callback_payload = callback_response.json() + assert callback_payload["trigger"] == "scheduler-callback" + + job_id = callback_payload["jobId"] + job_response = client.get(f"/jobs/{job_id}") + assert job_response.status_code == 200 + assert job_response.json()["status"] == "succeeded" + + +def test_schedule_callback_invalid_token(monkeypatch) -> None: + client = create_client() + monkeypatch.setenv("EOAPI_SCHEDULER_TOKEN", "secret-token") + + schedule_id = _create_schedule(client) + response = client.post( + f"/schedules/{schedule_id}/callback", + headers={"X-Scheduler-Token": "wrong-token"}, + ) + + assert response.status_code == 403 + assert response.json()["detail"]["code"] == "Forbidden" + + +def test_schedule_callback_missing_server_token(monkeypatch) -> None: + client = create_client() + monkeypatch.delenv("EOAPI_SCHEDULER_TOKEN", raising=False) + + schedule_id = _create_schedule(client) + response = client.post( + f"/schedules/{schedule_id}/callback", + headers={"X-Scheduler-Token": "any-value"}, + ) + + assert response.status_code == 503 + assert response.json()["detail"]["code"] == "ServiceUnavailable" + + +def test_schedule_run_uses_prefect_when_enabled(monkeypatch) -> None: + client = create_client() + monkeypatch.setenv("EOAPI_PREFECT_ENABLED", "true") + monkeypatch.setenv("EOAPI_PREFECT_API_URL", "http://prefect.local") + monkeypatch.setenv("EOAPI_PREFECT_DEPLOYMENT_ID", "dep-123") + + def fake_submit(schedule_id, payload_inputs, trigger, eoapi_job_id): + assert schedule_id + assert payload_inputs["datasetId"] == "chirps-daily" + assert trigger == "manual" + assert eoapi_job_id + return {"id": "flow-run-1"} + + monkeypatch.setattr("eoapi.endpoints.schedules.submit_aggregate_import_run", fake_submit) + + schedule_id = _create_schedule(client) + run_response = client.post(f"/schedules/{schedule_id}/run") + + assert run_response.status_code == 202 + run_payload = run_response.json() + assert run_payload["execution"]["source"] == "prefect" + assert run_payload["execution"]["flowRunId"] == "flow-run-1" + + +def test_job_status_syncs_prefect_state(monkeypatch) -> None: + client = create_client() + monkeypatch.setenv("EOAPI_PREFECT_ENABLED", "true") + + job = create_pending_job( + "eo-aggregate-import", + inputs={"dhis2": {"dryRun": True}}, + source="prefect", + flow_run_id="flow-run-2", + ) + + def fake_get_flow_run(flow_run_id): + assert flow_run_id == "flow-run-2" + return {"state": {"type": "COMPLETED", "name": "Completed"}} + + monkeypatch.setattr("eoapi.endpoints.processes.get_flow_run", fake_get_flow_run) + + job_response = client.get(f"/jobs/{job['jobId']}") + assert job_response.status_code == 200 + payload = job_response.json() + assert payload["status"] == "succeeded" + assert payload["progress"] == 100 + assert payload["execution"]["source"] == "prefect" + + +def test_schedule_run_for_workflow_target() -> None: + client = create_client() + + workflow_response = client.post( + "/workflows", + json={ + "name": "scheduled-workflow", + "steps": [ + { + "name": "aggregate", + "processId": "eo-aggregate-import", + "payload": { + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": {"dataElementId": "abc123", "dryRun": True}, + } + }, + } + ], + }, + ) + assert workflow_response.status_code == 201 + workflow_id = workflow_response.json()["workflowId"] + + schedule_response = client.post( + "/schedules", + json={ + "name": "nightly-workflow", + "cron": "0 0 * * *", + "timezone": "UTC", + "enabled": True, + "workflowId": workflow_id, + }, + ) + assert schedule_response.status_code == 201 + schedule_id = schedule_response.json()["scheduleId"] + + run_response = client.post(f"/schedules/{schedule_id}/run") + assert run_response.status_code == 202 + run_payload = run_response.json() + assert run_payload["workflowId"] == workflow_id + assert run_payload["execution"]["source"] == "workflow" + assert len(run_payload["jobIds"]) == 1 diff --git a/tests/test_state_store.py b/tests/test_state_store.py new file mode 100644 index 0000000..61a8f95 --- /dev/null +++ b/tests/test_state_store.py @@ -0,0 +1,21 @@ +from eoapi.state_store import load_state_map, save_state_map + + +def test_state_store_roundtrip(tmp_path, monkeypatch) -> None: + monkeypatch.setenv("EOAPI_STATE_DIR", str(tmp_path)) + monkeypatch.setenv("EOAPI_STATE_PERSIST", "true") + + save_state_map("jobs", {"a": {"jobId": "a"}}) + loaded = load_state_map("jobs") + + assert loaded == {"a": {"jobId": "a"}} + + +def test_state_store_disabled(tmp_path, monkeypatch) -> None: + monkeypatch.setenv("EOAPI_STATE_DIR", str(tmp_path)) + monkeypatch.setenv("EOAPI_STATE_PERSIST", "false") + + save_state_map("jobs", {"a": {"jobId": "a"}}) + loaded = load_state_map("jobs") + + assert loaded == {} diff --git a/tests/test_workflows_endpoint.py b/tests/test_workflows_endpoint.py new file mode 100644 index 0000000..6806eba --- /dev/null +++ b/tests/test_workflows_endpoint.py @@ -0,0 +1,80 @@ +from fastapi import FastAPI +from fastapi.testclient import TestClient + +from eoapi.endpoints.features import router as features_router +from eoapi.endpoints.processes import router as processes_router +from eoapi.endpoints.workflows import router as workflows_router + + +def create_client() -> TestClient: + app = FastAPI() + app.include_router(features_router) + app.include_router(processes_router) + app.include_router(workflows_router) + return TestClient(app) + + +def test_workflow_crud_and_run() -> None: + client = create_client() + + create_response = client.post( + "/workflows", + json={ + "name": "climate-workflow", + "steps": [ + { + "name": "aggregate", + "processId": "eo-aggregate-import", + "payload": { + "inputs": { + "datasetId": "chirps-daily", + "parameters": ["precip"], + "datetime": "2026-01-31T00:00:00Z", + "orgUnitLevel": 2, + "aggregation": "mean", + "dhis2": {"dataElementId": "abc123", "dryRun": True}, + } + }, + }, + { + "name": "cdd", + "processId": "xclim-cdd", + "payload": { + "inputs": { + "datasetId": "chirps-daily", + "parameter": "precip", + "start": "2026-01-01", + "end": "2026-01-31", + "orgUnitLevel": 2, + "threshold": {"value": 1.0, "unit": "mm/day"}, + "dhis2": {"dataElementId": "abc123", "dryRun": True}, + } + }, + }, + ], + }, + ) + + assert create_response.status_code == 201 + workflow_id = create_response.json()["workflowId"] + + list_response = client.get("/workflows") + assert list_response.status_code == 200 + assert any(item["workflowId"] == workflow_id for item in list_response.json()["workflows"]) + + run_response = client.post(f"/workflows/{workflow_id}/run") + assert run_response.status_code == 202 + run_payload = run_response.json() + assert run_payload["workflowId"] == workflow_id + assert len(run_payload["jobIds"]) == 2 + + get_response = client.get(f"/workflows/{workflow_id}") + assert get_response.status_code == 200 + get_payload = get_response.json() + assert get_payload["lastRunJobIds"] == run_payload["jobIds"] + + delete_response = client.delete(f"/workflows/{workflow_id}") + assert delete_response.status_code == 204 + + missing_response = client.get(f"/workflows/{workflow_id}") + assert missing_response.status_code == 404 diff --git a/uv.lock b/uv.lock index 203301a..658d722 100644 --- a/uv.lock +++ b/uv.lock @@ -81,6 +81,54 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/10/cb/f2ad4230dc2eb1a74edf38f1a38b9b52277f75bef262d8908e60d957e13c/blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc", size = 8458, upload-time = "2024-11-08T17:25:46.184Z" }, ] +[[package]] +name = "boltons" +version = "25.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/63/54/71a94d8e02da9a865587fb3fff100cb0fc7aa9f4d5ed9ed3a591216ddcc7/boltons-25.0.0.tar.gz", hash = "sha256:e110fbdc30b7b9868cb604e3f71d4722dd8f4dcb4a5ddd06028ba8f1ab0b5ace", size = 246294, upload-time = "2025-02-03T05:57:59.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/45/7f/0e961cf3908bc4c1c3e027de2794f867c6c89fb4916fc7dba295a0e80a2d/boltons-25.0.0-py3-none-any.whl", hash = "sha256:dc9fb38bf28985715497d1b54d00b62ea866eca3938938ea9043e254a3a6ca62", size = 194210, upload-time = "2025-02-03T05:57:56.705Z" }, +] + +[[package]] +name = "bottleneck" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/14/d8/6d641573e210768816023a64966d66463f2ce9fc9945fa03290c8a18f87c/bottleneck-1.6.0.tar.gz", hash = "sha256:028d46ee4b025ad9ab4d79924113816f825f62b17b87c9e1d0d8ce144a4a0e31", size = 104311, upload-time = "2025-09-08T16:30:38.617Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/1a/e117cd5ff7056126d3291deb29ac8066476e60b852555b95beb3fc9d62a0/bottleneck-1.6.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d015de414ca016ebe56440bdf5d3d1204085080527a3c51f5b7b7a3e704fe6fd", size = 100521, upload-time = "2025-09-08T16:30:03.89Z" }, + { url = "https://files.pythonhosted.org/packages/bd/22/05555a9752357e24caa1cd92324d1a7fdde6386aab162fcc451f8f8eedc2/bottleneck-1.6.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:456757c9525b0b12356f472e38020ed4b76b18375fd76e055f8d33fb62956f5e", size = 377719, upload-time = "2025-09-08T16:30:05.135Z" }, + { url = "https://files.pythonhosted.org/packages/11/ee/76593af47097d9633109bed04dbcf2170707dd84313ca29f436f9234bc51/bottleneck-1.6.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1c65254d51b6063c55f6272f175e867e2078342ae75f74be29d6612e9627b2c0", size = 368577, upload-time = "2025-09-08T16:30:06.387Z" }, + { url = "https://files.pythonhosted.org/packages/f9/f7/4dcacaf637d2b8d89ea746c74159adda43858d47358978880614c3fa4391/bottleneck-1.6.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a172322895fbb79c6127474f1b0db0866895f0b804a18d5c6b841fea093927fe", size = 361441, upload-time = "2025-09-08T16:30:07.613Z" }, + { url = "https://files.pythonhosted.org/packages/05/34/21eb1eb1c42cb7be2872d0647c292fc75768d14e1f0db66bf907b24b2464/bottleneck-1.6.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d5e81b642eb0d5a5bf00312598d7ed142d389728b694322a118c26813f3d1fa9", size = 373416, upload-time = "2025-09-08T16:30:08.899Z" }, + { url = "https://files.pythonhosted.org/packages/48/cb/7957ff40367a151139b5f1854616bf92e578f10804d226fbcdecfd73aead/bottleneck-1.6.0-cp313-cp313-win32.whl", hash = "sha256:543d3a89d22880cd322e44caff859af6c0489657bf9897977d1f5d3d3f77299c", size = 108029, upload-time = "2025-09-08T16:30:09.909Z" }, + { url = "https://files.pythonhosted.org/packages/90/a8/735df4156fa5595501d5d96a6ee102f49c13d2ce9e2a287ad51806bc3ba0/bottleneck-1.6.0-cp313-cp313-win_amd64.whl", hash = "sha256:48a44307d604ceb81e256903e5d57d3adb96a461b1d3c6a69baa2c67e823bd36", size = 113497, upload-time = "2025-09-08T16:30:10.82Z" }, + { url = "https://files.pythonhosted.org/packages/c7/5c/8c1260df8ade7cebc2a8af513a27082b5e36aa4a5fb762d56ea6d969d893/bottleneck-1.6.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:547e6715115867c4657c9ae8cc5ddac1fec8fdad66690be3a322a7488721b06b", size = 101606, upload-time = "2025-09-08T16:30:11.935Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ea/f03e2944e91ee962922c834ed21e5be6d067c8395681f5dc6c67a0a26853/bottleneck-1.6.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5e4a4a6e05b6f014c307969129e10d1a0afd18f3a2c127b085532a4a76677aef", size = 391804, upload-time = "2025-09-08T16:30:13.13Z" }, + { url = "https://files.pythonhosted.org/packages/0b/58/2b356b8a81eb97637dccee6cf58237198dd828890e38be9afb4e5e58e38e/bottleneck-1.6.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2baae0d1589b4a520b2f9cf03528c0c8b20717b3f05675e212ec2200cf628f12", size = 383443, upload-time = "2025-09-08T16:30:14.318Z" }, + { url = "https://files.pythonhosted.org/packages/55/52/cf7d09ed3736ad0d50c624787f9b580ae3206494d95cc0f4814b93eef728/bottleneck-1.6.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:2e407139b322f01d8d5b6b2e8091b810f48a25c7fa5c678cfcdc420dfe8aea0a", size = 375458, upload-time = "2025-09-08T16:30:15.379Z" }, + { url = "https://files.pythonhosted.org/packages/c4/e9/7c87a34a24e339860064f20fac49f6738e94f1717bc8726b9c47705601d8/bottleneck-1.6.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1adefb89b92aba6de9c6ea871d99bcd29d519f4fb012cc5197917813b4fc2c7f", size = 386384, upload-time = "2025-09-08T16:30:17.012Z" }, + { url = "https://files.pythonhosted.org/packages/59/57/db51855e18a47671801180be748939b4c9422a0544849af1919116346b5f/bottleneck-1.6.0-cp313-cp313t-win32.whl", hash = "sha256:64b8690393494074923780f6abdf5f5577d844b9d9689725d1575a936e74e5f0", size = 109448, upload-time = "2025-09-08T16:30:18.076Z" }, + { url = "https://files.pythonhosted.org/packages/bd/1e/683c090b624f13a5bf88a0be2241dc301e98b2fb72a45812a7ae6e456cc4/bottleneck-1.6.0-cp313-cp313t-win_amd64.whl", hash = "sha256:cb67247f65dcdf62af947c76c6c8b77d9f0ead442cac0edbaa17850d6da4e48d", size = 115190, upload-time = "2025-09-08T16:30:19.106Z" }, + { url = "https://files.pythonhosted.org/packages/77/e2/eb7c08964a3f3c4719f98795ccd21807ee9dd3071a0f9ad652a5f19196ff/bottleneck-1.6.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:98f1d789042511a0f042b3bdcd2903e8567e956d3aa3be189cce3746daeb8550", size = 100544, upload-time = "2025-09-08T16:30:20.22Z" }, + { url = "https://files.pythonhosted.org/packages/99/ec/c6f3be848f37689f481797ce7d9807d5f69a199d7fc0e46044f9b708c468/bottleneck-1.6.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1fad24c99e39ad7623fc2a76d37feb26bd32e4dd170885edf4dbf4bfce2199a3", size = 378315, upload-time = "2025-09-08T16:30:21.409Z" }, + { url = "https://files.pythonhosted.org/packages/bf/8f/2d6600836e2ea8f14fcefac592dc83497e5b88d381470c958cb9cdf88706/bottleneck-1.6.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:643e61e50a6f993debc399b495a1609a55b3bd76b057e433e4089505d9f605c7", size = 368978, upload-time = "2025-09-08T16:30:23.458Z" }, + { url = "https://files.pythonhosted.org/packages/9b/b5/bf72b49f5040212873b985feef5050015645e0a02204b591e1d265fc522a/bottleneck-1.6.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa668efbe4c6b200524ea0ebd537212da9b9801287138016fdf64119d6fcf201", size = 362074, upload-time = "2025-09-08T16:30:24.71Z" }, + { url = "https://files.pythonhosted.org/packages/1d/c8/c4891a0604eb680031390182c6e264247e3a9a8d067d654362245396fadf/bottleneck-1.6.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9f7dd35262e89e28fedd79d45022394b1fa1aceb61d2e747c6d6842e50546daa", size = 374019, upload-time = "2025-09-08T16:30:26.438Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2d/ed096f8d1b9147e84914045dd89bc64e3c32eee49b862d1e20d573a9ab0d/bottleneck-1.6.0-cp314-cp314-win32.whl", hash = "sha256:bd90bec3c470b7fdfafc2fbdcd7a1c55a4e57b5cdad88d40eea5bc9bab759bf1", size = 110173, upload-time = "2025-09-08T16:30:27.521Z" }, + { url = "https://files.pythonhosted.org/packages/33/70/1414acb6ae378a15063cfb19a0a39d69d1b6baae1120a64d2b069902549b/bottleneck-1.6.0-cp314-cp314-win_amd64.whl", hash = "sha256:b43b6d36a62ffdedc6368cf9a708e4d0a30d98656c2b5f33d88894e1bcfd6857", size = 115899, upload-time = "2025-09-08T16:30:28.524Z" }, + { url = "https://files.pythonhosted.org/packages/4e/ed/4570b5d8c1c85ce3c54963ebc37472231ed54f0b0d8dbb5dde14303f775f/bottleneck-1.6.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:53296707a8e195b5dcaa804b714bd222b5e446bd93cd496008122277eb43fa87", size = 101615, upload-time = "2025-09-08T16:30:29.556Z" }, + { url = "https://files.pythonhosted.org/packages/2d/93/c148faa07ae91f266be1f3fad1fde95aa2449e12937f3f3df2dd720b86e0/bottleneck-1.6.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6df19cc48a83efd70f6d6874332aa31c3f5ca06a98b782449064abbd564cf0e", size = 392411, upload-time = "2025-09-08T16:30:31.186Z" }, + { url = "https://files.pythonhosted.org/packages/6e/1c/e6ad221d345a059e7efb2ad1d46a22d9fdae0486faef70555766e1123966/bottleneck-1.6.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96bb3a52cb3c0aadfedce3106f93ab940a49c9d35cd4ed612e031f6deb27e80f", size = 384022, upload-time = "2025-09-08T16:30:32.364Z" }, + { url = "https://files.pythonhosted.org/packages/4f/40/5b15c01eb8c59d59bc84c94d01d3d30797c961f10ec190f53c27e05d62ab/bottleneck-1.6.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d1db9e831b69d5595b12e79aeb04cb02873db35576467c8dd26cdc1ee6b74581", size = 376004, upload-time = "2025-09-08T16:30:33.731Z" }, + { url = "https://files.pythonhosted.org/packages/74/f6/cb228f5949553a5c01d1d5a3c933f0216d78540d9e0bf8dd4343bb449681/bottleneck-1.6.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:4dd7ac619570865fcb7a0e8925df418005f076286ad2c702dd0f447231d7a055", size = 386909, upload-time = "2025-09-08T16:30:34.973Z" }, + { url = "https://files.pythonhosted.org/packages/09/9a/425065c37a67a9120bf53290371579b83d05bf46f3212cce65d8c01d470a/bottleneck-1.6.0-cp314-cp314t-win32.whl", hash = "sha256:7fb694165df95d428fe00b98b9ea7d126ef786c4a4b7d43ae2530248396cadcb", size = 111636, upload-time = "2025-09-08T16:30:36.044Z" }, + { url = "https://files.pythonhosted.org/packages/ad/23/c41006e42909ec5114a8961818412310aa54646d1eae0495dbff3598a095/bottleneck-1.6.0-cp314-cp314t-win_amd64.whl", hash = "sha256:174b80930ce82bd8456c67f1abb28a5975c68db49d254783ce2cb6983b4fea40", size = 117611, upload-time = "2025-09-08T16:30:37.055Z" }, +] + [[package]] name = "cachetools" version = "7.0.1" @@ -133,6 +181,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e6/ad/3cc14f097111b4de0040c83a525973216457bbeeb63739ef1ed275c1c021/certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c", size = 152900, upload-time = "2026-01-04T02:42:40.15Z" }, ] +[[package]] +name = "cf-xarray" +version = "0.10.11" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "xarray" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e3/78/f4f38e7ea6221773ea48d85c00d529b1fdc7378a1a1b77c2b77661446a0b/cf_xarray-0.10.11.tar.gz", hash = "sha256:e10ee37b0ed3ba36f42346360f2bc070c690ddc73bb9dcdd9463b3a221453be3", size = 686693, upload-time = "2026-02-03T19:17:42.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/65/ce/5c4f4660da5521d90bea62cdf8396d7e4ce4a00513e218d267b97f9ea453/cf_xarray-0.10.11-py3-none-any.whl", hash = "sha256:c47fff625766c69a66fedef368d9787acb0819b32d8bd022f8b045089b42109a", size = 78421, upload-time = "2026-02-03T19:17:40.431Z" }, +] + [[package]] name = "cffi" version = "2.0.0" @@ -391,6 +451,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fe/53/63d707d9de41aab3c51faa4f0e9234c36ee8c63f56c90c3ae23a01976e81/convertdate-2.4.1-py3-none-any.whl", hash = "sha256:0622acf8bc600956b937e8dd7cee36ba035669b62d2db224bf130af1fc84f754", size = 48440, upload-time = "2026-02-08T00:37:52.405Z" }, ] +[[package]] +name = "croniter" +version = "6.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "python-dateutil" }, + { name = "pytz" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/2f/44d1ae153a0e27be56be43465e5cb39b9650c781e001e7864389deb25090/croniter-6.0.0.tar.gz", hash = "sha256:37c504b313956114a983ece2c2b07790b1f1094fe9d81cc94739214748255577", size = 64481, upload-time = "2024-12-17T17:17:47.32Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/4b/290b4c3efd6417a8b0c284896de19b1d5855e6dbdb97d2a35e68fa42de85/croniter-6.0.0-py2.py3-none-any.whl", hash = "sha256:2f878c3856f17896979b2a4379ba1f09c83e374931ea15cc835c5dd2eee9b368", size = 25468, upload-time = "2024-12-17T17:17:45.359Z" }, +] + [[package]] name = "cycler" version = "0.12.1" @@ -418,6 +491,11 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/e5/23/d39ccc4ed76222db31530b0a7d38876fdb7673e23f838e8d8f0ed4651a4f/dask-2026.1.2-py3-none-any.whl", hash = "sha256:46a0cf3b8d87f78a3d2e6b145aea4418a6d6d606fe6a16c79bd8ca2bb862bc91", size = 1482084, upload-time = "2026-01-30T21:04:18.363Z" }, ] +[package.optional-dependencies] +array = [ + { name = "numpy" }, +] + [[package]] name = "dateparser" version = "1.3.0" @@ -583,22 +661,26 @@ name = "eo-api" version = "0.1.0" source = { editable = "." } dependencies = [ + { name = "croniter" }, { name = "dhis2-client" }, { name = "dhis2eo" }, { name = "pygeoapi" }, { name = "pyyaml" }, { name = "titiler-core" }, { name = "uvicorn" }, + { name = "xclim" }, ] [package.metadata] requires-dist = [ + { name = "croniter", specifier = ">=2.0.5" }, { name = "dhis2-client", git = "https://github.com/dhis2/dhis2-python-client.git?rev=V0.3.0" }, { name = "dhis2eo", git = "https://github.com/dhis2/dhis2eo.git?rev=v1.1.0" }, { name = "pygeoapi", specifier = ">=0.22.0" }, { name = "pyyaml", specifier = ">=6.0" }, { name = "titiler-core", specifier = ">=1.2.0" }, { name = "uvicorn", specifier = ">=0.41.0" }, + { name = "xclim", specifier = ">=0.58.1" }, ] [[package]] @@ -845,6 +927,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, ] +[[package]] +name = "joblib" +version = "1.5.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/41/f2/d34e8b3a08a9cc79a50b2208a93dce981fe615b64d5a4d4abee421d898df/joblib-1.5.3.tar.gz", hash = "sha256:8561a3269e6801106863fd0d6d84bb737be9e7631e33aaed3fb9ce5953688da3", size = 331603, upload-time = "2025-12-15T08:41:46.427Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7b/91/984aca2ec129e2757d1e4e3c81c3fcda9d0f85b74670a094cc443d9ee949/joblib-1.5.3-py3-none-any.whl", hash = "sha256:5fc3c5039fc5ca8c0276333a188bbd59d6b7ab37fe6632daa76bc7f9ec18e713", size = 309071, upload-time = "2025-12-15T08:41:44.973Z" }, +] + [[package]] name = "jsonschema" version = "4.26.0" @@ -940,6 +1031,22 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/82/3d/14ce75ef66813643812f3093ab17e46d3a206942ce7376d31ec2d36229e7/lark-1.3.1-py3-none-any.whl", hash = "sha256:c629b661023a014c37da873b4ff58a817398d12635d3bbb2c5a03be7fe5d1e12", size = 113151, upload-time = "2025-10-27T18:25:54.882Z" }, ] +[[package]] +name = "llvmlite" +version = "0.46.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/74/cd/08ae687ba099c7e3d21fe2ea536500563ef1943c5105bf6ab4ee3829f68e/llvmlite-0.46.0.tar.gz", hash = "sha256:227c9fd6d09dce2783c18b754b7cd9d9b3b3515210c46acc2d3c5badd9870ceb", size = 193456, upload-time = "2025-12-08T18:15:36.295Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e6/ff/3eba7eb0aed4b6fca37125387cd417e8c458e750621fce56d2c541f67fa8/llvmlite-0.46.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:30b60892d034bc560e0ec6654737aaa74e5ca327bd8114d82136aa071d611172", size = 37232767, upload-time = "2025-12-08T18:15:13.22Z" }, + { url = "https://files.pythonhosted.org/packages/0e/54/737755c0a91558364b9200702c3c9c15d70ed63f9b98a2c32f1c2aa1f3ba/llvmlite-0.46.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6cc19b051753368a9c9f31dc041299059ee91aceec81bd57b0e385e5d5bf1a54", size = 56275176, upload-time = "2025-12-08T18:15:16.339Z" }, + { url = "https://files.pythonhosted.org/packages/e6/91/14f32e1d70905c1c0aa4e6609ab5d705c3183116ca02ac6df2091868413a/llvmlite-0.46.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bca185892908f9ede48c0acd547fe4dc1bafefb8a4967d47db6cf664f9332d12", size = 55128629, upload-time = "2025-12-08T18:15:19.493Z" }, + { url = "https://files.pythonhosted.org/packages/4a/a7/d526ae86708cea531935ae777b6dbcabe7db52718e6401e0fb9c5edea80e/llvmlite-0.46.0-cp313-cp313-win_amd64.whl", hash = "sha256:67438fd30e12349ebb054d86a5a1a57fd5e87d264d2451bcfafbbbaa25b82a35", size = 38138941, upload-time = "2025-12-08T18:15:22.536Z" }, + { url = "https://files.pythonhosted.org/packages/95/ae/af0ffb724814cc2ea64445acad05f71cff5f799bb7efb22e47ee99340dbc/llvmlite-0.46.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:d252edfb9f4ac1fcf20652258e3f102b26b03eef738dc8a6ffdab7d7d341d547", size = 37232768, upload-time = "2025-12-08T18:15:25.055Z" }, + { url = "https://files.pythonhosted.org/packages/c9/19/5018e5352019be753b7b07f7759cdabb69ca5779fea2494be8839270df4c/llvmlite-0.46.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:379fdd1c59badeff8982cb47e4694a6143bec3bb49aa10a466e095410522064d", size = 56275173, upload-time = "2025-12-08T18:15:28.109Z" }, + { url = "https://files.pythonhosted.org/packages/9f/c9/d57877759d707e84c082163c543853245f91b70c804115a5010532890f18/llvmlite-0.46.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e8cbfff7f6db0fa2c771ad24154e2a7e457c2444d7673e6de06b8b698c3b269", size = 55128628, upload-time = "2025-12-08T18:15:31.098Z" }, + { url = "https://files.pythonhosted.org/packages/30/a8/e61a8c2b3cc7a597073d9cde1fcbb567e9d827f1db30c93cf80422eac70d/llvmlite-0.46.0-cp314-cp314-win_amd64.whl", hash = "sha256:7821eda3ec1f18050f981819756631d60b6d7ab1a6cf806d9efefbe3f4082d61", size = 39153056, upload-time = "2025-12-08T18:15:33.938Z" }, +] + [[package]] name = "locket" version = "1.0.0" @@ -1163,6 +1270,26 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/af/2e/39d5e9179c543f2e6e149a65908f83afd9b6d64379a90789b323111761db/netcdf4-1.7.4-cp314-cp314t-win_arm64.whl", hash = "sha256:034220887d48da032cb2db5958f69759dbb04eb33e279ec6390571d4aea734fe", size = 2531682, upload-time = "2026-01-05T02:27:37.062Z" }, ] +[[package]] +name = "numba" +version = "0.64.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "llvmlite" }, + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/23/c9/a0fb41787d01d621046138da30f6c2100d80857bf34b3390dd68040f27a3/numba-0.64.0.tar.gz", hash = "sha256:95e7300af648baa3308127b1955b52ce6d11889d16e8cfe637b4f85d2fca52b1", size = 2765679, upload-time = "2026-02-18T18:41:20.974Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/52/80/2734de90f9300a6e2503b35ee50d9599926b90cbb7ac54f9e40074cd07f1/numba-0.64.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:3bab2c872194dcd985f1153b70782ec0fbbe348fffef340264eacd3a76d59fd6", size = 2683392, upload-time = "2026-02-18T18:41:06.563Z" }, + { url = "https://files.pythonhosted.org/packages/42/e8/14b5853ebefd5b37723ef365c5318a30ce0702d39057eaa8d7d76392859d/numba-0.64.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:703a246c60832cad231d2e73c1182f25bf3cc8b699759ec8fe58a2dbc689a70c", size = 3812245, upload-time = "2026-02-18T18:41:07.963Z" }, + { url = "https://files.pythonhosted.org/packages/8a/a2/f60dc6c96d19b7185144265a5fbf01c14993d37ff4cd324b09d0212aa7ce/numba-0.64.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7e2e49a7900ee971d32af7609adc0cfe6aa7477c6f6cccdf6d8138538cf7756f", size = 3511328, upload-time = "2026-02-18T18:41:09.504Z" }, + { url = "https://files.pythonhosted.org/packages/9c/2a/fe7003ea7e7237ee7014f8eaeeb7b0d228a2db22572ca85bab2648cf52cb/numba-0.64.0-cp313-cp313-win_amd64.whl", hash = "sha256:396f43c3f77e78d7ec84cdfc6b04969c78f8f169351b3c4db814b97e7acf4245", size = 2752668, upload-time = "2026-02-18T18:41:11.455Z" }, + { url = "https://files.pythonhosted.org/packages/3d/8a/77d26afe0988c592dd97cb8d4e80bfb3dfc7dbdacfca7d74a7c5c81dd8c2/numba-0.64.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:f565d55eaeff382cbc86c63c8c610347453af3d1e7afb2b6569aac1c9b5c93ce", size = 2683590, upload-time = "2026-02-18T18:41:12.897Z" }, + { url = "https://files.pythonhosted.org/packages/8e/4b/600b8b7cdbc7f9cebee9ea3d13bb70052a79baf28944024ffcb59f0712e3/numba-0.64.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9b55169b18892c783f85e9ad9e6f5297a6d12967e4414e6b71361086025ff0bb", size = 3781163, upload-time = "2026-02-18T18:41:15.377Z" }, + { url = "https://files.pythonhosted.org/packages/ff/73/53f2d32bfa45b7175e9944f6b816d8c32840178c3eee9325033db5bf838e/numba-0.64.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:196bcafa02c9dd1707e068434f6d5cedde0feb787e3432f7f1f0e993cc336c4c", size = 3481172, upload-time = "2026-02-18T18:41:17.281Z" }, + { url = "https://files.pythonhosted.org/packages/b5/00/aebd2f7f1e11e38814bb96e95a27580817a7b340608d3ac085fdbab83174/numba-0.64.0-cp314-cp314-win_amd64.whl", hash = "sha256:213e9acbe7f1c05090592e79020315c1749dd52517b90e94c517dca3f014d4a1", size = 2754700, upload-time = "2026-02-18T18:41:19.277Z" }, +] + [[package]] name = "numexpr" version = "2.14.1" @@ -1415,6 +1542,42 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, ] +[[package]] +name = "pyarrow" +version = "23.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/88/22/134986a4cc224d593c1afde5494d18ff629393d74cc2eddb176669f234a4/pyarrow-23.0.1.tar.gz", hash = "sha256:b8c5873e33440b2bc2f4a79d2b47017a89c5a24116c055625e6f2ee50523f019", size = 1167336, upload-time = "2026-02-16T10:14:12.39Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/10/2cbe4c6f0fb83d2de37249567373d64327a5e4d8db72f486db42875b08f6/pyarrow-23.0.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6b8fda694640b00e8af3c824f99f789e836720aa8c9379fb435d4c4953a756b8", size = 34210066, upload-time = "2026-02-16T10:10:45.487Z" }, + { url = "https://files.pythonhosted.org/packages/cb/4f/679fa7e84dadbaca7a65f7cdba8d6c83febbd93ca12fa4adf40ba3b6362b/pyarrow-23.0.1-cp313-cp313-macosx_12_0_x86_64.whl", hash = "sha256:8ff51b1addc469b9444b7c6f3548e19dc931b172ab234e995a60aea9f6e6025f", size = 35825526, upload-time = "2026-02-16T10:10:52.266Z" }, + { url = "https://files.pythonhosted.org/packages/f9/63/d2747d930882c9d661e9398eefc54f15696547b8983aaaf11d4a2e8b5426/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:71c5be5cbf1e1cb6169d2a0980850bccb558ddc9b747b6206435313c47c37677", size = 44473279, upload-time = "2026-02-16T10:11:01.557Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/10a48b5e238de6d562a411af6467e71e7aedbc9b87f8d3a35f1560ae30fb/pyarrow-23.0.1-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:9b6f4f17b43bc39d56fec96e53fe89d94bac3eb134137964371b45352d40d0c2", size = 47585798, upload-time = "2026-02-16T10:11:09.401Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/476943001c54ef078dbf9542280e22741219a184a0632862bca4feccd666/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9fc13fc6c403d1337acab46a2c4346ca6c9dec5780c3c697cf8abfd5e19b6b37", size = 48179446, upload-time = "2026-02-16T10:11:17.781Z" }, + { url = "https://files.pythonhosted.org/packages/4b/b6/5dd0c47b335fcd8edba9bfab78ad961bd0fd55ebe53468cc393f45e0be60/pyarrow-23.0.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c16ed4f53247fa3ffb12a14d236de4213a4415d127fe9cebed33d51671113e2", size = 50623972, upload-time = "2026-02-16T10:11:26.185Z" }, + { url = "https://files.pythonhosted.org/packages/d5/09/a532297c9591a727d67760e2e756b83905dd89adb365a7f6e9c72578bcc1/pyarrow-23.0.1-cp313-cp313-win_amd64.whl", hash = "sha256:cecfb12ef629cf6be0b1887f9f86463b0dd3dc3195ae6224e74006be4736035a", size = 27540749, upload-time = "2026-02-16T10:12:23.297Z" }, + { url = "https://files.pythonhosted.org/packages/a5/8e/38749c4b1303e6ae76b3c80618f84861ae0c55dd3c2273842ea6f8258233/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:29f7f7419a0e30264ea261fdc0e5fe63ce5a6095003db2945d7cd78df391a7e1", size = 34471544, upload-time = "2026-02-16T10:11:32.535Z" }, + { url = "https://files.pythonhosted.org/packages/a3/73/f237b2bc8c669212f842bcfd842b04fc8d936bfc9d471630569132dc920d/pyarrow-23.0.1-cp313-cp313t-macosx_12_0_x86_64.whl", hash = "sha256:33d648dc25b51fd8055c19e4261e813dfc4d2427f068bcecc8b53d01b81b0500", size = 35949911, upload-time = "2026-02-16T10:11:39.813Z" }, + { url = "https://files.pythonhosted.org/packages/0c/86/b912195eee0903b5611bf596833def7d146ab2d301afeb4b722c57ffc966/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_aarch64.whl", hash = "sha256:cd395abf8f91c673dd3589cadc8cc1ee4e8674fa61b2e923c8dd215d9c7d1f41", size = 44520337, upload-time = "2026-02-16T10:11:47.764Z" }, + { url = "https://files.pythonhosted.org/packages/69/c2/f2a717fb824f62d0be952ea724b4f6f9372a17eed6f704b5c9526f12f2f1/pyarrow-23.0.1-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:00be9576d970c31defb5c32eb72ef585bf600ef6d0a82d5eccaae96639cf9d07", size = 47548944, upload-time = "2026-02-16T10:11:56.607Z" }, + { url = "https://files.pythonhosted.org/packages/84/a7/90007d476b9f0dc308e3bc57b832d004f848fd6c0da601375d20d92d1519/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c2139549494445609f35a5cda4eb94e2c9e4d704ce60a095b342f82460c73a83", size = 48236269, upload-time = "2026-02-16T10:12:04.47Z" }, + { url = "https://files.pythonhosted.org/packages/b0/3f/b16fab3e77709856eb6ac328ce35f57a6d4a18462c7ca5186ef31b45e0e0/pyarrow-23.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:7044b442f184d84e2351e5084600f0d7343d6117aabcbc1ac78eb1ae11eb4125", size = 50604794, upload-time = "2026-02-16T10:12:11.797Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a1/22df0620a9fac31d68397a75465c344e83c3dfe521f7612aea33e27ab6c0/pyarrow-23.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:a35581e856a2fafa12f3f54fce4331862b1cfb0bef5758347a858a4aa9d6bae8", size = 27660642, upload-time = "2026-02-16T10:12:17.746Z" }, + { url = "https://files.pythonhosted.org/packages/8d/1b/6da9a89583ce7b23ac611f183ae4843cd3a6cf54f079549b0e8c14031e73/pyarrow-23.0.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:5df1161da23636a70838099d4aaa65142777185cc0cdba4037a18cee7d8db9ca", size = 34238755, upload-time = "2026-02-16T10:12:32.819Z" }, + { url = "https://files.pythonhosted.org/packages/ae/b5/d58a241fbe324dbaeb8df07be6af8752c846192d78d2272e551098f74e88/pyarrow-23.0.1-cp314-cp314-macosx_12_0_x86_64.whl", hash = "sha256:fa8e51cb04b9f8c9c5ace6bab63af9a1f88d35c0d6cbf53e8c17c098552285e1", size = 35847826, upload-time = "2026-02-16T10:12:38.949Z" }, + { url = "https://files.pythonhosted.org/packages/54/a5/8cbc83f04aba433ca7b331b38f39e000efd9f0c7ce47128670e737542996/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_aarch64.whl", hash = "sha256:0b95a3994f015be13c63148fef8832e8a23938128c185ee951c98908a696e0eb", size = 44536859, upload-time = "2026-02-16T10:12:45.467Z" }, + { url = "https://files.pythonhosted.org/packages/36/2e/c0f017c405fcdc252dbccafbe05e36b0d0eb1ea9a958f081e01c6972927f/pyarrow-23.0.1-cp314-cp314-manylinux_2_28_x86_64.whl", hash = "sha256:4982d71350b1a6e5cfe1af742c53dfb759b11ce14141870d05d9e540d13bc5d1", size = 47614443, upload-time = "2026-02-16T10:12:55.525Z" }, + { url = "https://files.pythonhosted.org/packages/af/6b/2314a78057912f5627afa13ba43809d9d653e6630859618b0fd81a4e0759/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c250248f1fe266db627921c89b47b7c06fee0489ad95b04d50353537d74d6886", size = 48232991, upload-time = "2026-02-16T10:13:04.729Z" }, + { url = "https://files.pythonhosted.org/packages/40/f2/1bcb1d3be3460832ef3370d621142216e15a2c7c62602a4ea19ec240dd64/pyarrow-23.0.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5f4763b83c11c16e5f4c15601ba6dfa849e20723b46aa2617cb4bffe8768479f", size = 50645077, upload-time = "2026-02-16T10:13:14.147Z" }, + { url = "https://files.pythonhosted.org/packages/eb/3f/b1da7b61cd66566a4d4c8383d376c606d1c34a906c3f1cb35c479f59d1aa/pyarrow-23.0.1-cp314-cp314-win_amd64.whl", hash = "sha256:3a4c85ef66c134161987c17b147d6bffdca4566f9a4c1d81a0a01cdf08414ea5", size = 28234271, upload-time = "2026-02-16T10:14:09.397Z" }, + { url = "https://files.pythonhosted.org/packages/b5/78/07f67434e910a0f7323269be7bfbf58699bd0c1d080b18a1ab49ba943fe8/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:17cd28e906c18af486a499422740298c52d7c6795344ea5002a7720b4eadf16d", size = 34488692, upload-time = "2026-02-16T10:13:21.541Z" }, + { url = "https://files.pythonhosted.org/packages/50/76/34cf7ae93ece1f740a04910d9f7e80ba166b9b4ab9596a953e9e62b90fe1/pyarrow-23.0.1-cp314-cp314t-macosx_12_0_x86_64.whl", hash = "sha256:76e823d0e86b4fb5e1cf4a58d293036e678b5a4b03539be933d3b31f9406859f", size = 35964383, upload-time = "2026-02-16T10:13:28.63Z" }, + { url = "https://files.pythonhosted.org/packages/46/90/459b827238936d4244214be7c684e1b366a63f8c78c380807ae25ed92199/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_aarch64.whl", hash = "sha256:a62e1899e3078bf65943078b3ad2a6ddcacf2373bc06379aac61b1e548a75814", size = 44538119, upload-time = "2026-02-16T10:13:35.506Z" }, + { url = "https://files.pythonhosted.org/packages/28/a1/93a71ae5881e99d1f9de1d4554a87be37da11cd6b152239fb5bd924fdc64/pyarrow-23.0.1-cp314-cp314t-manylinux_2_28_x86_64.whl", hash = "sha256:df088e8f640c9fae3b1f495b3c64755c4e719091caf250f3a74d095ddf3c836d", size = 47571199, upload-time = "2026-02-16T10:13:42.504Z" }, + { url = "https://files.pythonhosted.org/packages/88/a3/d2c462d4ef313521eaf2eff04d204ac60775263f1fb08c374b543f79f610/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:46718a220d64677c93bc243af1d44b55998255427588e400677d7192671845c7", size = 48259435, upload-time = "2026-02-16T10:13:49.226Z" }, + { url = "https://files.pythonhosted.org/packages/cc/f1/11a544b8c3d38a759eb3fbb022039117fd633e9a7b19e4841cc3da091915/pyarrow-23.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a09f3876e87f48bc2f13583ab551f0379e5dfb83210391e68ace404181a20690", size = 50629149, upload-time = "2026-02-16T10:13:57.238Z" }, + { url = "https://files.pythonhosted.org/packages/50/f2/c0e76a0b451ffdf0cf788932e182758eb7558953f4f27f1aff8e2518b653/pyarrow-23.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:527e8d899f14bd15b740cd5a54ad56b7f98044955373a17179d5956ddb93d9ce", size = 28365807, upload-time = "2026-02-16T10:14:03.892Z" }, +] + [[package]] name = "pycparser" version = "3.0" @@ -1970,6 +2133,95 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d0/02/fa464cdfbe6b26e0600b62c528b72d8608f5cc49f96b8d6e38c95d60c676/rpds_py-0.30.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27f4b0e92de5bfbc6f86e43959e6edd1425c33b5e69aab0984a72047f2bcf1e3", size = 226532, upload-time = "2025-11-30T20:24:14.634Z" }, ] +[[package]] +name = "scikit-learn" +version = "1.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "joblib" }, + { name = "numpy" }, + { name = "scipy" }, + { name = "threadpoolctl" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0e/d4/40988bf3b8e34feec1d0e6a051446b1f66225f8529b9309becaeef62b6c4/scikit_learn-1.8.0.tar.gz", hash = "sha256:9bccbb3b40e3de10351f8f5068e105d0f4083b1a65fa07b6634fbc401a6287fd", size = 7335585, upload-time = "2025-12-10T07:08:53.618Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/03/aa/e22e0768512ce9255eba34775be2e85c2048da73da1193e841707f8f039c/scikit_learn-1.8.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d6ae97234d5d7079dc0040990a6f7aeb97cb7fa7e8945f1999a429b23569e0a", size = 8513770, upload-time = "2025-12-10T07:08:03.251Z" }, + { url = "https://files.pythonhosted.org/packages/58/37/31b83b2594105f61a381fc74ca19e8780ee923be2d496fcd8d2e1147bd99/scikit_learn-1.8.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:edec98c5e7c128328124a029bceb09eda2d526997780fef8d65e9a69eead963e", size = 8044458, upload-time = "2025-12-10T07:08:05.336Z" }, + { url = "https://files.pythonhosted.org/packages/2d/5a/3f1caed8765f33eabb723596666da4ebbf43d11e96550fb18bdec42b467b/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:74b66d8689d52ed04c271e1329f0c61635bcaf5b926db9b12d58914cdc01fe57", size = 8610341, upload-time = "2025-12-10T07:08:07.732Z" }, + { url = "https://files.pythonhosted.org/packages/38/cf/06896db3f71c75902a8e9943b444a56e727418f6b4b4a90c98c934f51ed4/scikit_learn-1.8.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8fdf95767f989b0cfedb85f7ed8ca215d4be728031f56ff5a519ee1e3276dc2e", size = 8900022, upload-time = "2025-12-10T07:08:09.862Z" }, + { url = "https://files.pythonhosted.org/packages/1c/f9/9b7563caf3ec8873e17a31401858efab6b39a882daf6c1bfa88879c0aa11/scikit_learn-1.8.0-cp313-cp313-win_amd64.whl", hash = "sha256:2de443b9373b3b615aec1bb57f9baa6bb3a9bd093f1269ba95c17d870422b271", size = 7989409, upload-time = "2025-12-10T07:08:12.028Z" }, + { url = "https://files.pythonhosted.org/packages/49/bd/1f4001503650e72c4f6009ac0c4413cb17d2d601cef6f71c0453da2732fc/scikit_learn-1.8.0-cp313-cp313-win_arm64.whl", hash = "sha256:eddde82a035681427cbedded4e6eff5e57fa59216c2e3e90b10b19ab1d0a65c3", size = 7619760, upload-time = "2025-12-10T07:08:13.688Z" }, + { url = "https://files.pythonhosted.org/packages/d2/7d/a630359fc9dcc95496588c8d8e3245cc8fd81980251079bc09c70d41d951/scikit_learn-1.8.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7cc267b6108f0a1499a734167282c00c4ebf61328566b55ef262d48e9849c735", size = 8826045, upload-time = "2025-12-10T07:08:15.215Z" }, + { url = "https://files.pythonhosted.org/packages/cc/56/a0c86f6930cfcd1c7054a2bc417e26960bb88d32444fe7f71d5c2cfae891/scikit_learn-1.8.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:fe1c011a640a9f0791146011dfd3c7d9669785f9fed2b2a5f9e207536cf5c2fd", size = 8420324, upload-time = "2025-12-10T07:08:17.561Z" }, + { url = "https://files.pythonhosted.org/packages/46/1e/05962ea1cebc1cf3876667ecb14c283ef755bf409993c5946ade3b77e303/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:72358cce49465d140cc4e7792015bb1f0296a9742d5622c67e31399b75468b9e", size = 8680651, upload-time = "2025-12-10T07:08:19.952Z" }, + { url = "https://files.pythonhosted.org/packages/fe/56/a85473cd75f200c9759e3a5f0bcab2d116c92a8a02ee08ccd73b870f8bb4/scikit_learn-1.8.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:80832434a6cc114f5219211eec13dcbc16c2bac0e31ef64c6d346cde3cf054cb", size = 8925045, upload-time = "2025-12-10T07:08:22.11Z" }, + { url = "https://files.pythonhosted.org/packages/cc/b7/64d8cfa896c64435ae57f4917a548d7ac7a44762ff9802f75a79b77cb633/scikit_learn-1.8.0-cp313-cp313t-win_amd64.whl", hash = "sha256:ee787491dbfe082d9c3013f01f5991658b0f38aa8177e4cd4bf434c58f551702", size = 8507994, upload-time = "2025-12-10T07:08:23.943Z" }, + { url = "https://files.pythonhosted.org/packages/5e/37/e192ea709551799379958b4c4771ec507347027bb7c942662c7fbeba31cb/scikit_learn-1.8.0-cp313-cp313t-win_arm64.whl", hash = "sha256:bf97c10a3f5a7543f9b88cbf488d33d175e9146115a451ae34568597ba33dcde", size = 7869518, upload-time = "2025-12-10T07:08:25.71Z" }, + { url = "https://files.pythonhosted.org/packages/24/05/1af2c186174cc92dcab2233f327336058c077d38f6fe2aceb08e6ab4d509/scikit_learn-1.8.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c22a2da7a198c28dd1a6e1136f19c830beab7fdca5b3e5c8bba8394f8a5c45b3", size = 8528667, upload-time = "2025-12-10T07:08:27.541Z" }, + { url = "https://files.pythonhosted.org/packages/a8/25/01c0af38fe969473fb292bba9dc2b8f9b451f3112ff242c647fee3d0dfe7/scikit_learn-1.8.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:6b595b07a03069a2b1740dc08c2299993850ea81cce4fe19b2421e0c970de6b7", size = 8066524, upload-time = "2025-12-10T07:08:29.822Z" }, + { url = "https://files.pythonhosted.org/packages/be/ce/a0623350aa0b68647333940ee46fe45086c6060ec604874e38e9ab7d8e6c/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:29ffc74089f3d5e87dfca4c2c8450f88bdc61b0fc6ed5d267f3988f19a1309f6", size = 8657133, upload-time = "2025-12-10T07:08:31.865Z" }, + { url = "https://files.pythonhosted.org/packages/b8/cb/861b41341d6f1245e6ca80b1c1a8c4dfce43255b03df034429089ca2a2c5/scikit_learn-1.8.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb65db5d7531bccf3a4f6bec3462223bea71384e2cda41da0f10b7c292b9e7c4", size = 8923223, upload-time = "2025-12-10T07:08:34.166Z" }, + { url = "https://files.pythonhosted.org/packages/76/18/a8def8f91b18cd1ba6e05dbe02540168cb24d47e8dcf69e8d00b7da42a08/scikit_learn-1.8.0-cp314-cp314-win_amd64.whl", hash = "sha256:56079a99c20d230e873ea40753102102734c5953366972a71d5cb39a32bc40c6", size = 8096518, upload-time = "2025-12-10T07:08:36.339Z" }, + { url = "https://files.pythonhosted.org/packages/d1/77/482076a678458307f0deb44e29891d6022617b2a64c840c725495bee343f/scikit_learn-1.8.0-cp314-cp314-win_arm64.whl", hash = "sha256:3bad7565bc9cf37ce19a7c0d107742b320c1285df7aab1a6e2d28780df167242", size = 7754546, upload-time = "2025-12-10T07:08:38.128Z" }, + { url = "https://files.pythonhosted.org/packages/2d/d1/ef294ca754826daa043b2a104e59960abfab4cf653891037d19dd5b6f3cf/scikit_learn-1.8.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:4511be56637e46c25721e83d1a9cea9614e7badc7040c4d573d75fbe257d6fd7", size = 8848305, upload-time = "2025-12-10T07:08:41.013Z" }, + { url = "https://files.pythonhosted.org/packages/5b/e2/b1f8b05138ee813b8e1a4149f2f0d289547e60851fd1bb268886915adbda/scikit_learn-1.8.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:a69525355a641bf8ef136a7fa447672fb54fe8d60cab5538d9eb7c6438543fb9", size = 8432257, upload-time = "2025-12-10T07:08:42.873Z" }, + { url = "https://files.pythonhosted.org/packages/26/11/c32b2138a85dcb0c99f6afd13a70a951bfdff8a6ab42d8160522542fb647/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c2656924ec73e5939c76ac4c8b026fc203b83d8900362eb2599d8aee80e4880f", size = 8678673, upload-time = "2025-12-10T07:08:45.362Z" }, + { url = "https://files.pythonhosted.org/packages/c7/57/51f2384575bdec454f4fe4e7a919d696c9ebce914590abf3e52d47607ab8/scikit_learn-1.8.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15fc3b5d19cc2be65404786857f2e13c70c83dd4782676dd6814e3b89dc8f5b9", size = 8922467, upload-time = "2025-12-10T07:08:47.408Z" }, + { url = "https://files.pythonhosted.org/packages/35/4d/748c9e2872637a57981a04adc038dacaa16ba8ca887b23e34953f0b3f742/scikit_learn-1.8.0-cp314-cp314t-win_amd64.whl", hash = "sha256:00d6f1d66fbcf4eba6e356e1420d33cc06c70a45bb1363cd6f6a8e4ebbbdece2", size = 8774395, upload-time = "2025-12-10T07:08:49.337Z" }, + { url = "https://files.pythonhosted.org/packages/60/22/d7b2ebe4704a5e50790ba089d5c2ae308ab6bb852719e6c3bd4f04c3a363/scikit_learn-1.8.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f28dd15c6bb0b66ba09728cf09fd8736c304be29409bd8445a080c1280619e8c", size = 8002647, upload-time = "2025-12-10T07:08:51.601Z" }, +] + +[[package]] +name = "scipy" +version = "1.17.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/7a/97/5a3609c4f8d58b039179648e62dd220f89864f56f7357f5d4f45c29eb2cc/scipy-1.17.1.tar.gz", hash = "sha256:95d8e012d8cb8816c226aef832200b1d45109ed4464303e997c5b13122b297c0", size = 30573822, upload-time = "2026-02-23T00:26:24.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/27/07ee1b57b65e92645f219b37148a7e7928b82e2b5dbeccecb4dff7c64f0b/scipy-1.17.1-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:5e3c5c011904115f88a39308379c17f91546f77c1667cea98739fe0fccea804c", size = 31590199, upload-time = "2026-02-23T00:19:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/ec/ae/db19f8ab842e9b724bf5dbb7db29302a91f1e55bc4d04b1025d6d605a2c5/scipy-1.17.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:6fac755ca3d2c3edcb22f479fceaa241704111414831ddd3bc6056e18516892f", size = 28154001, upload-time = "2026-02-23T00:19:22.241Z" }, + { url = "https://files.pythonhosted.org/packages/5b/58/3ce96251560107b381cbd6e8413c483bbb1228a6b919fa8652b0d4090e7f/scipy-1.17.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:7ff200bf9d24f2e4d5dc6ee8c3ac64d739d3a89e2326ba68aaf6c4a2b838fd7d", size = 20325719, upload-time = "2026-02-23T00:19:26.329Z" }, + { url = "https://files.pythonhosted.org/packages/b2/83/15087d945e0e4d48ce2377498abf5ad171ae013232ae31d06f336e64c999/scipy-1.17.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:4b400bdc6f79fa02a4d86640310dde87a21fba0c979efff5248908c6f15fad1b", size = 22683595, upload-time = "2026-02-23T00:19:30.304Z" }, + { url = "https://files.pythonhosted.org/packages/b4/e0/e58fbde4a1a594c8be8114eb4aac1a55bcd6587047efc18a61eb1f5c0d30/scipy-1.17.1-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b64ca7d4aee0102a97f3ba22124052b4bd2152522355073580bf4845e2550b6", size = 32896429, upload-time = "2026-02-23T00:19:35.536Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5f/f17563f28ff03c7b6799c50d01d5d856a1d55f2676f537ca8d28c7f627cd/scipy-1.17.1-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:581b2264fc0aa555f3f435a5944da7504ea3a065d7029ad60e7c3d1ae09c5464", size = 35203952, upload-time = "2026-02-23T00:19:42.259Z" }, + { url = "https://files.pythonhosted.org/packages/8d/a5/9afd17de24f657fdfe4df9a3f1ea049b39aef7c06000c13db1530d81ccca/scipy-1.17.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:beeda3d4ae615106d7094f7e7cef6218392e4465cc95d25f900bebabfded0950", size = 34979063, upload-time = "2026-02-23T00:19:47.547Z" }, + { url = "https://files.pythonhosted.org/packages/8b/13/88b1d2384b424bf7c924f2038c1c409f8d88bb2a8d49d097861dd64a57b2/scipy-1.17.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6609bc224e9568f65064cfa72edc0f24ee6655b47575954ec6339534b2798369", size = 37598449, upload-time = "2026-02-23T00:19:53.238Z" }, + { url = "https://files.pythonhosted.org/packages/35/e5/d6d0e51fc888f692a35134336866341c08655d92614f492c6860dc45bb2c/scipy-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:37425bc9175607b0268f493d79a292c39f9d001a357bebb6b88fdfaff13f6448", size = 36510943, upload-time = "2026-02-23T00:20:50.89Z" }, + { url = "https://files.pythonhosted.org/packages/2a/fd/3be73c564e2a01e690e19cc618811540ba5354c67c8680dce3281123fb79/scipy-1.17.1-cp313-cp313-win_arm64.whl", hash = "sha256:5cf36e801231b6a2059bf354720274b7558746f3b1a4efb43fcf557ccd484a87", size = 24545621, upload-time = "2026-02-23T00:20:55.871Z" }, + { url = "https://files.pythonhosted.org/packages/6f/6b/17787db8b8114933a66f9dcc479a8272e4b4da75fe03b0c282f7b0ade8cd/scipy-1.17.1-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:d59c30000a16d8edc7e64152e30220bfbd724c9bbb08368c054e24c651314f0a", size = 31936708, upload-time = "2026-02-23T00:19:58.694Z" }, + { url = "https://files.pythonhosted.org/packages/38/2e/524405c2b6392765ab1e2b722a41d5da33dc5c7b7278184a8ad29b6cb206/scipy-1.17.1-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:010f4333c96c9bb1a4516269e33cb5917b08ef2166d5556ca2fd9f082a9e6ea0", size = 28570135, upload-time = "2026-02-23T00:20:03.934Z" }, + { url = "https://files.pythonhosted.org/packages/fd/c3/5bd7199f4ea8556c0c8e39f04ccb014ac37d1468e6cfa6a95c6b3562b76e/scipy-1.17.1-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2ceb2d3e01c5f1d83c4189737a42d9cb2fc38a6eeed225e7515eef71ad301dce", size = 20741977, upload-time = "2026-02-23T00:20:07.935Z" }, + { url = "https://files.pythonhosted.org/packages/d9/b8/8ccd9b766ad14c78386599708eb745f6b44f08400a5fd0ade7cf89b6fc93/scipy-1.17.1-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:844e165636711ef41f80b4103ed234181646b98a53c8f05da12ca5ca289134f6", size = 23029601, upload-time = "2026-02-23T00:20:12.161Z" }, + { url = "https://files.pythonhosted.org/packages/6d/a0/3cb6f4d2fb3e17428ad2880333cac878909ad1a89f678527b5328b93c1d4/scipy-1.17.1-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:158dd96d2207e21c966063e1635b1063cd7787b627b6f07305315dd73d9c679e", size = 33019667, upload-time = "2026-02-23T00:20:17.208Z" }, + { url = "https://files.pythonhosted.org/packages/f3/c3/2d834a5ac7bf3a0c806ad1508efc02dda3c8c61472a56132d7894c312dea/scipy-1.17.1-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:74cbb80d93260fe2ffa334efa24cb8f2f0f622a9b9febf8b483c0b865bfb3475", size = 35264159, upload-time = "2026-02-23T00:20:23.087Z" }, + { url = "https://files.pythonhosted.org/packages/4d/77/d3ed4becfdbd217c52062fafe35a72388d1bd82c2d0ba5ca19d6fcc93e11/scipy-1.17.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:dbc12c9f3d185f5c737d801da555fb74b3dcfa1a50b66a1a93e09190f41fab50", size = 35102771, upload-time = "2026-02-23T00:20:28.636Z" }, + { url = "https://files.pythonhosted.org/packages/bd/12/d19da97efde68ca1ee5538bb261d5d2c062f0c055575128f11a2730e3ac1/scipy-1.17.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:94055a11dfebe37c656e70317e1996dc197e1a15bbcc351bcdd4610e128fe1ca", size = 37665910, upload-time = "2026-02-23T00:20:34.743Z" }, + { url = "https://files.pythonhosted.org/packages/06/1c/1172a88d507a4baaf72c5a09bb6c018fe2ae0ab622e5830b703a46cc9e44/scipy-1.17.1-cp313-cp313t-win_amd64.whl", hash = "sha256:e30bdeaa5deed6bc27b4cc490823cd0347d7dae09119b8803ae576ea0ce52e4c", size = 36562980, upload-time = "2026-02-23T00:20:40.575Z" }, + { url = "https://files.pythonhosted.org/packages/70/b0/eb757336e5a76dfa7911f63252e3b7d1de00935d7705cf772db5b45ec238/scipy-1.17.1-cp313-cp313t-win_arm64.whl", hash = "sha256:a720477885a9d2411f94a93d16f9d89bad0f28ca23c3f8daa521e2dcc3f44d49", size = 24856543, upload-time = "2026-02-23T00:20:45.313Z" }, + { url = "https://files.pythonhosted.org/packages/cf/83/333afb452af6f0fd70414dc04f898647ee1423979ce02efa75c3b0f2c28e/scipy-1.17.1-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:a48a72c77a310327f6a3a920092fa2b8fd03d7deaa60f093038f22d98e096717", size = 31584510, upload-time = "2026-02-23T00:21:01.015Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a6/d05a85fd51daeb2e4ea71d102f15b34fedca8e931af02594193ae4fd25f7/scipy-1.17.1-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:45abad819184f07240d8a696117a7aacd39787af9e0b719d00285549ed19a1e9", size = 28170131, upload-time = "2026-02-23T00:21:05.888Z" }, + { url = "https://files.pythonhosted.org/packages/db/7b/8624a203326675d7746a254083a187398090a179335b2e4a20e2ddc46e83/scipy-1.17.1-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:3fd1fcdab3ea951b610dc4cef356d416d5802991e7e32b5254828d342f7b7e0b", size = 20342032, upload-time = "2026-02-23T00:21:09.904Z" }, + { url = "https://files.pythonhosted.org/packages/c9/35/2c342897c00775d688d8ff3987aced3426858fd89d5a0e26e020b660b301/scipy-1.17.1-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7bdf2da170b67fdf10bca777614b1c7d96ae3ca5794fd9587dce41eb2966e866", size = 22678766, upload-time = "2026-02-23T00:21:14.313Z" }, + { url = "https://files.pythonhosted.org/packages/ef/f2/7cdb8eb308a1a6ae1e19f945913c82c23c0c442a462a46480ce487fdc0ac/scipy-1.17.1-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:adb2642e060a6549c343603a3851ba76ef0b74cc8c079a9a58121c7ec9fe2350", size = 32957007, upload-time = "2026-02-23T00:21:19.663Z" }, + { url = "https://files.pythonhosted.org/packages/0b/2e/7eea398450457ecb54e18e9d10110993fa65561c4f3add5e8eccd2b9cd41/scipy-1.17.1-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eee2cfda04c00a857206a4330f0c5e3e56535494e30ca445eb19ec624ae75118", size = 35221333, upload-time = "2026-02-23T00:21:25.278Z" }, + { url = "https://files.pythonhosted.org/packages/d9/77/5b8509d03b77f093a0d52e606d3c4f79e8b06d1d38c441dacb1e26cacf46/scipy-1.17.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:d2650c1fb97e184d12d8ba010493ee7b322864f7d3d00d3f9bb97d9c21de4068", size = 35042066, upload-time = "2026-02-23T00:21:31.358Z" }, + { url = "https://files.pythonhosted.org/packages/f9/df/18f80fb99df40b4070328d5ae5c596f2f00fffb50167e31439e932f29e7d/scipy-1.17.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:08b900519463543aa604a06bec02461558a6e1cef8fdbb8098f77a48a83c8118", size = 37612763, upload-time = "2026-02-23T00:21:37.247Z" }, + { url = "https://files.pythonhosted.org/packages/4b/39/f0e8ea762a764a9dc52aa7dabcfad51a354819de1f0d4652b6a1122424d6/scipy-1.17.1-cp314-cp314-win_amd64.whl", hash = "sha256:3877ac408e14da24a6196de0ddcace62092bfc12a83823e92e49e40747e52c19", size = 37290984, upload-time = "2026-02-23T00:22:35.023Z" }, + { url = "https://files.pythonhosted.org/packages/7c/56/fe201e3b0f93d1a8bcf75d3379affd228a63d7e2d80ab45467a74b494947/scipy-1.17.1-cp314-cp314-win_arm64.whl", hash = "sha256:f8885db0bc2bffa59d5c1b72fad7a6a92d3e80e7257f967dd81abb553a90d293", size = 25192877, upload-time = "2026-02-23T00:22:39.798Z" }, + { url = "https://files.pythonhosted.org/packages/96/ad/f8c414e121f82e02d76f310f16db9899c4fcde36710329502a6b2a3c0392/scipy-1.17.1-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:1cc682cea2ae55524432f3cdff9e9a3be743d52a7443d0cba9017c23c87ae2f6", size = 31949750, upload-time = "2026-02-23T00:21:42.289Z" }, + { url = "https://files.pythonhosted.org/packages/7c/b0/c741e8865d61b67c81e255f4f0a832846c064e426636cd7de84e74d209be/scipy-1.17.1-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:2040ad4d1795a0ae89bfc7e8429677f365d45aa9fd5e4587cf1ea737f927b4a1", size = 28585858, upload-time = "2026-02-23T00:21:47.706Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1b/3985219c6177866628fa7c2595bfd23f193ceebbe472c98a08824b9466ff/scipy-1.17.1-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:131f5aaea57602008f9822e2115029b55d4b5f7c070287699fe45c661d051e39", size = 20757723, upload-time = "2026-02-23T00:21:52.039Z" }, + { url = "https://files.pythonhosted.org/packages/c0/19/2a04aa25050d656d6f7b9e7b685cc83d6957fb101665bfd9369ca6534563/scipy-1.17.1-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9cdc1a2fcfd5c52cfb3045feb399f7b3ce822abdde3a193a6b9a60b3cb5854ca", size = 23043098, upload-time = "2026-02-23T00:21:56.185Z" }, + { url = "https://files.pythonhosted.org/packages/86/f1/3383beb9b5d0dbddd030335bf8a8b32d4317185efe495374f134d8be6cce/scipy-1.17.1-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6e3dcd57ab780c741fde8dc68619de988b966db759a3c3152e8e9142c26295ad", size = 33030397, upload-time = "2026-02-23T00:22:01.404Z" }, + { url = "https://files.pythonhosted.org/packages/41/68/8f21e8a65a5a03f25a79165ec9d2b28c00e66dc80546cf5eb803aeeff35b/scipy-1.17.1-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a9956e4d4f4a301ebf6cde39850333a6b6110799d470dbbb1e25326ac447f52a", size = 35281163, upload-time = "2026-02-23T00:22:07.024Z" }, + { url = "https://files.pythonhosted.org/packages/84/8d/c8a5e19479554007a5632ed7529e665c315ae7492b4f946b0deb39870e39/scipy-1.17.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:a4328d245944d09fd639771de275701ccadf5f781ba0ff092ad141e017eccda4", size = 35116291, upload-time = "2026-02-23T00:22:12.585Z" }, + { url = "https://files.pythonhosted.org/packages/52/52/e57eceff0e342a1f50e274264ed47497b59e6a4e3118808ee58ddda7b74a/scipy-1.17.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:a77cbd07b940d326d39a1d1b37817e2ee4d79cb30e7338f3d0cddffae70fcaa2", size = 37682317, upload-time = "2026-02-23T00:22:18.513Z" }, + { url = "https://files.pythonhosted.org/packages/11/2f/b29eafe4a3fbc3d6de9662b36e028d5f039e72d345e05c250e121a230dd4/scipy-1.17.1-cp314-cp314t-win_amd64.whl", hash = "sha256:eb092099205ef62cd1782b006658db09e2fed75bffcae7cc0d44052d8aa0f484", size = 37345327, upload-time = "2026-02-23T00:22:24.442Z" }, + { url = "https://files.pythonhosted.org/packages/07/39/338d9219c4e87f3e708f18857ecd24d22a0c3094752393319553096b98af/scipy-1.17.1-cp314-cp314t-win_arm64.whl", hash = "sha256:200e1050faffacc162be6a486a984a0497866ec54149a01270adc8a59b7c7d21", size = 25489165, upload-time = "2026-02-23T00:22:29.563Z" }, +] + [[package]] name = "shapely" version = "2.1.2" @@ -2091,6 +2343,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/81/0d/13d1d239a25cbfb19e740db83143e95c772a1fe10202dda4b76792b114dd/starlette-0.52.1-py3-none-any.whl", hash = "sha256:0029d43eb3d273bc4f83a08720b4912ea4b071087a3b48db01b7c839f7954d74", size = 74272, upload-time = "2026-01-18T13:34:09.188Z" }, ] +[[package]] +name = "threadpoolctl" +version = "3.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b7/4d/08c89e34946fce2aec4fbb45c9016efd5f4d7f24af8e5d93296e935631d8/threadpoolctl-3.6.0.tar.gz", hash = "sha256:8ab8b4aa3491d812b623328249fab5302a68d2d71745c8a4c719a2fcaba9f44e", size = 21274, upload-time = "2025-03-13T13:49:23.031Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/d5/f9a850d79b0851d1d4ef6456097579a9005b31fea68726a4ae5f2d82ddd9/threadpoolctl-3.6.0-py3-none-any.whl", hash = "sha256:43a0b8fd5a2928500110039e43a5eed8480b918967083ea48dc3ab9f13c4a7fb", size = 18638, upload-time = "2025-03-13T13:49:21.846Z" }, +] + [[package]] name = "tinydb" version = "4.8.2" @@ -2231,3 +2492,44 @@ sdist = { url = "https://files.pythonhosted.org/packages/d3/af/7b945f331ba8911fd wheels = [ { url = "https://files.pythonhosted.org/packages/d5/e4/62a677feefde05b12a70a4fc9bdc8558010182a801fbcab68cb56c2b0986/xarray-2025.12.0-py3-none-any.whl", hash = "sha256:9e77e820474dbbe4c6c2954d0da6342aa484e33adaa96ab916b15a786181e970", size = 1381742, upload-time = "2025-12-05T21:51:20.841Z" }, ] + +[[package]] +name = "xclim" +version = "0.60.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "boltons" }, + { name = "bottleneck" }, + { name = "cf-xarray" }, + { name = "cftime" }, + { name = "click" }, + { name = "dask", extra = ["array"] }, + { name = "filelock" }, + { name = "numba" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pandas" }, + { name = "pint" }, + { name = "pyarrow" }, + { name = "pyyaml" }, + { name = "scikit-learn" }, + { name = "scipy" }, + { name = "xarray" }, + { name = "yamale" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1e/68/eb89c903ff70b1c2d0b2d0b9e8948bd13f1148cbb132a8ea077370db2fb5/xclim-0.60.0.tar.gz", hash = "sha256:9ebefc07d8b4e2ec90edbc98df575c141ba8d0ee6133ef3ec2c2a79cf51178d2", size = 897292, upload-time = "2026-01-23T16:38:00.442Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ef/9f/b199b8741f5a481c5ed15b7fe3f2e55d7cfc737c87b2f770465d33541cff/xclim-0.60.0-py3-none-any.whl", hash = "sha256:3140f530bec0e765df222877f5631b6caee241a44d8fcb25bfea3a90d15328b0", size = 382551, upload-time = "2026-01-23T16:37:58.237Z" }, +] + +[[package]] +name = "yamale" +version = "6.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pyyaml" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/da/64/9e5de0e829920b848dcf5fe3ff64936d83cc7471babd264588b08bca97e0/yamale-6.1.0.tar.gz", hash = "sha256:fd435aa7b830c73e89a9ef548c0ace2d3d8dc3e5e180e6b57ff70b31495672fd", size = 42402, upload-time = "2025-11-20T16:52:30.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c9/fc/cbad39af7e761525077690ddff1ae19ace7e2f54552e90fb848a43a270fa/yamale-6.1.0-py3-none-any.whl", hash = "sha256:7e109c9d83e3a7e42703516cb2b70b9c7aa5b7a738019c4a6c202b6b0b9096c5", size = 58215, upload-time = "2025-11-20T16:52:28.806Z" }, +] diff --git a/webapp/app.js b/webapp/app.js new file mode 100644 index 0000000..0445dde --- /dev/null +++ b/webapp/app.js @@ -0,0 +1,345 @@ +const output = document.getElementById("output"); +const jobOutput = document.getElementById("job-output"); +const schedulesBody = document.getElementById("schedules-body"); +const workflowsBody = document.getElementById("workflows-body"); +const datasetSelect = document.getElementById("datasetId"); +const scheduleWorkflowSelect = document.getElementById("schedule-workflow-id"); +const parameterHelp = document.getElementById("parameter-help"); + +function write(message, data) { + const line = data ? `${message}\n${JSON.stringify(data, null, 2)}` : message; + output.textContent = line; +} + +async function request(path, options = {}) { + const response = await fetch(path, { + headers: { "Content-Type": "application/json", ...(options.headers || {}) }, + ...options, + }); + + const data = await response.json().catch(() => ({})); + if (!response.ok) { + throw new Error( + data?.detail?.description || response.statusText || "Request failed", + ); + } + + return data; +} + +async function loadCollections() { + const data = await request("/collections"); + const collections = data.collections || []; + datasetSelect.innerHTML = ""; + collections.forEach((collection) => { + const option = document.createElement("option"); + option.value = collection.id; + option.textContent = `${collection.id} — ${collection.title}`; + datasetSelect.appendChild(option); + }); + + if (collections.length > 0) { + datasetSelect.value = collections[0].id; + await loadParameterHint(collections[0].id); + } +} + +async function loadParameterHint(datasetId) { + try { + const cov = await request(`/collections/${datasetId}/coverage`); + const keys = Object.keys(cov.parameters || {}); + if (keys.length) { + parameterHelp.textContent = `Available parameters for ${datasetId}: ${keys.join(", ")}`; + document.getElementById("parameters").value = keys.join(","); + } else { + parameterHelp.textContent = `No parameter metadata found for ${datasetId}.`; + } + } catch (error) { + parameterHelp.textContent = `Could not load parameters: ${error.message}`; + } +} + +function scheduleRow(schedule) { + const tr = document.createElement("tr"); + tr.innerHTML = ` + ${schedule.name} + ${schedule.cron} (${schedule.timezone}) + ${schedule.enabled ? "yes" : "no"} + ${schedule.lastRunJobId || "-"} + + + + + + + `; + return tr; +} + +function workflowRow(workflow) { + const tr = document.createElement("tr"); + tr.innerHTML = ` + ${workflow.name} + ${workflow.steps.length} + ${(workflow.lastRunJobIds || []).join(", ") || "-"} + + + + + `; + return tr; +} + +async function loadWorkflows() { + const data = await request("/workflows"); + const workflows = data.workflows || []; + workflowsBody.innerHTML = ""; + scheduleWorkflowSelect.innerHTML = + ''; + + workflows.forEach((workflow) => { + workflowsBody.appendChild(workflowRow(workflow)); + + const option = document.createElement("option"); + option.value = workflow.workflowId; + option.textContent = `${workflow.name} (${workflow.steps.length} steps)`; + scheduleWorkflowSelect.appendChild(option); + }); +} + +async function createWorkflow(event) { + event.preventDefault(); + + const name = document.getElementById("workflow-name").value.trim(); + const stepsRaw = document.getElementById("workflow-steps").value.trim(); + if (!name) { + write("Workflow name is required"); + return; + } + + let steps; + try { + steps = JSON.parse(stepsRaw); + } catch (error) { + write(`Invalid workflow JSON: ${error.message}`); + return; + } + + if (!Array.isArray(steps) || steps.length === 0) { + write("Workflow steps must be a non-empty array"); + return; + } + + const invalidStep = steps.find( + (step) => + !step || typeof step !== "object" || !step.processId || !step.payload, + ); + if (invalidStep) { + write( + "Each step must include processId and payload. Optional fields: name", + invalidStep, + ); + return; + } + + const workflow = { + name, + steps, + }; + + const created = await request("/workflows", { + method: "POST", + body: JSON.stringify(workflow), + }); + + await loadWorkflows(); + write("Workflow saved", created); +} + +async function runWorkflow(workflowId) { + const result = await request(`/workflows/${workflowId}/run`, { + method: "POST", + }); + + await loadWorkflows(); + write("Workflow run submitted", { + workflowId, + jobIds: result.jobIds, + }); + + if ((result.jobIds || []).length > 0) { + document.getElementById("job-id").value = + result.jobIds[result.jobIds.length - 1]; + } +} + +async function deleteWorkflow(workflowId) { + await request(`/workflows/${workflowId}`, { + method: "DELETE", + }); + + await loadWorkflows(); + write("Workflow deleted", { workflowId }); +} + +async function loadSchedules() { + const data = await request("/schedules"); + schedulesBody.innerHTML = ""; + (data.schedules || []).forEach((schedule) => { + schedulesBody.appendChild(scheduleRow(schedule)); + }); +} + +async function createSchedule(event) { + event.preventDefault(); + + const workflowId = scheduleWorkflowSelect.value || null; + const payload = { + name: document.getElementById("name").value, + cron: document.getElementById("cron").value, + timezone: document.getElementById("timezone").value, + enabled: true, + }; + + if (workflowId) { + payload.workflowId = workflowId; + } else { + payload.inputs = { + datasetId: datasetSelect.value, + parameters: document + .getElementById("parameters") + .value.split(",") + .map((x) => x.trim()) + .filter(Boolean), + datetime: document.getElementById("datetime").value, + orgUnitLevel: Number(document.getElementById("orgUnitLevel").value), + aggregation: document.getElementById("aggregation").value, + dhis2: { + dataElementId: document.getElementById("dataElementId").value, + dryRun: document.getElementById("dryRun").checked, + }, + }; + } + + try { + const data = await request("/schedules", { + method: "POST", + body: JSON.stringify(payload), + }); + write("Schedule created", data); + await loadSchedules(); + } catch (error) { + write(`Failed to create schedule: ${error.message}`); + } +} + +async function runSchedule(scheduleId) { + const data = await request(`/schedules/${scheduleId}/run`, { + method: "POST", + }); + write("Schedule started", data); + document.getElementById("job-id").value = data.jobId; + await loadSchedules(); +} + +async function callbackSchedule(scheduleId) { + const token = document.getElementById("scheduler-token").value; + const headers = token ? { "X-Scheduler-Token": token } : {}; + const data = await request(`/schedules/${scheduleId}/callback`, { + method: "POST", + headers, + }); + write("Scheduler callback started", data); + document.getElementById("job-id").value = data.jobId; + await loadSchedules(); +} + +async function toggleSchedule(scheduleId) { + const current = await request(`/schedules/${scheduleId}`); + const data = await request(`/schedules/${scheduleId}`, { + method: "PATCH", + body: JSON.stringify({ enabled: !current.enabled }), + }); + write("Schedule updated", data); + await loadSchedules(); +} + +async function deleteSchedule(scheduleId) { + await request(`/schedules/${scheduleId}`, { method: "DELETE" }); + write("Schedule deleted"); + await loadSchedules(); +} + +async function checkJob() { + const jobId = document.getElementById("job-id").value.trim(); + if (!jobId) { + jobOutput.textContent = "Provide a jobId"; + return; + } + + try { + const data = await request(`/jobs/${jobId}`); + jobOutput.textContent = JSON.stringify(data, null, 2); + } catch (error) { + jobOutput.textContent = `Failed to load job: ${error.message}`; + } +} + +document + .getElementById("schedule-form") + .addEventListener("submit", createSchedule); +document + .getElementById("workflow-form") + .addEventListener("submit", createWorkflow); +document + .getElementById("refresh-schedules") + .addEventListener("click", loadSchedules); +document + .getElementById("refresh-workflows") + .addEventListener("click", loadWorkflows); +document.getElementById("check-job").addEventListener("click", checkJob); +datasetSelect.addEventListener("change", (event) => + loadParameterHint(event.target.value), +); + +workflowsBody.addEventListener("click", async (event) => { + const button = event.target.closest("button"); + if (!button) return; + + const action = button.dataset.workflowAction; + const workflowId = button.dataset.workflowId; + + try { + if (action === "run") await runWorkflow(workflowId); + if (action === "delete") await deleteWorkflow(workflowId); + } catch (error) { + write(`Workflow action failed: ${error.message}`); + } +}); + +schedulesBody.addEventListener("click", async (event) => { + const button = event.target.closest("button"); + if (!button) return; + + const action = button.dataset.action; + const scheduleId = button.dataset.id; + + try { + if (action === "run") await runSchedule(scheduleId); + if (action === "callback") await callbackSchedule(scheduleId); + if (action === "toggle") await toggleSchedule(scheduleId); + if (action === "delete") await deleteSchedule(scheduleId); + } catch (error) { + write(`Action failed: ${error.message}`); + } +}); + +(async () => { + try { + await loadCollections(); + await loadWorkflows(); + await loadSchedules(); + } catch (error) { + write(`Initialization failed: ${error.message}`); + } +})(); diff --git a/webapp/index.html b/webapp/index.html new file mode 100644 index 0000000..dd2337d --- /dev/null +++ b/webapp/index.html @@ -0,0 +1,196 @@ + + + + + + EO API Example App + + + +
+

EO API Example App

+

+ Minimal example for scheduled daily temperature/precipitation imports + into DHIS2. +

+ +
+

1) Custom Workflows

+
+
+ +
+ +
+ + +
+
+

+ Workflows are saved in your browser and run steps sequentially via the + API. +

+
+ +
+

2) Workflows

+ + + + + + + + + + +
NameStepsLast JobsActions
+
+ +
+

3) Configure Schedule

+
+
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+ + +
+
+

+
+ +
+

4) Schedules

+ + + + + + + + + + + +
NameCronEnabledLast JobActions
+
+ +
+

5) Job Status

+
+ + +
+

+      
+ +
+

Scheduler Callback (Optional)

+

+ Use this only if callback token protection is enabled in the API + (`EOAPI_SCHEDULER_TOKEN`). +

+ +
+ +
+

Messages

+

+      
+
+ + + + diff --git a/webapp/styles.css b/webapp/styles.css new file mode 100644 index 0000000..a753a7e --- /dev/null +++ b/webapp/styles.css @@ -0,0 +1,114 @@ +:root { + font-family: + -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; +} + +body { + margin: 0; + background: #f5f7fa; + color: #1f2937; +} + +.container { + max-width: 1100px; + margin: 24px auto; + padding: 0 16px 24px; +} + +.subtitle { + margin-top: -8px; + color: #4b5563; +} + +.panel { + background: white; + border: 1px solid #e5e7eb; + border-radius: 8px; + padding: 16px; + margin-top: 16px; +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); + gap: 12px; +} + +label { + display: flex; + flex-direction: column; + gap: 6px; + font-size: 14px; +} + +input, +textarea, +select, +button { + border: 1px solid #d1d5db; + border-radius: 6px; + padding: 8px; + font-size: 14px; +} + +textarea { + width: 100%; + resize: vertical; + font-family: ui-monospace, SFMono-Regular, Menlo, monospace; +} + +button { + cursor: pointer; + background: #111827; + color: white; +} + +button.danger { + background: #b91c1c; +} + +.actions { + margin-top: 12px; + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.checkbox-row { + flex-direction: row; + align-items: center; + margin-top: 24px; +} + +table { + width: 100%; + border-collapse: collapse; +} + +th, +td { + border-bottom: 1px solid #e5e7eb; + text-align: left; + padding: 8px; + font-size: 14px; + vertical-align: top; +} + +td button { + margin-right: 6px; + margin-bottom: 6px; +} + +pre { + margin: 0; + background: #f3f4f6; + border-radius: 6px; + padding: 10px; + white-space: pre-wrap; + word-break: break-word; +} + +.hint { + color: #6b7280; + font-size: 13px; +} From ede167c319b8aaa728f9a3bef72cd5e2695f2e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Tue, 24 Feb 2026 12:21:51 +0100 Subject: [PATCH 12/13] orhestration decision --- .cache/state/jobs.json | 2 +- .cache/state/schedules.json | 2 +- .cache/state/workflows.json | 2 +- ORCHESTRATION_DECISION.md | 80 +++++++++++++++++++++++++++++++++++++ PRESENTATION_EXECUTIVE.md | 21 ++++++++++ README.md | 1 + 6 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 ORCHESTRATION_DECISION.md diff --git a/.cache/state/jobs.json b/.cache/state/jobs.json index e847465..93c96df 100644 --- a/.cache/state/jobs.json +++ b/.cache/state/jobs.json @@ -1 +1 @@ -{"c4e10ad3-03a8-4ccd-b64e-4b36da4ced28": {"jobId": "c4e10ad3-03a8-4ccd-b64e-4b36da4ced28", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:58:59.188643Z", "updated": "2026-02-23T21:58:59.188643Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "7fd59008-4d1c-471c-b3b6-959e14b69edd": {"jobId": "7fd59008-4d1c-471c-b3b6-959e14b69edd", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:58:59.202771Z", "updated": "2026-02-23T21:58:59.202771Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "e3e1dbbc-c230-44e9-8c09-067057cf68d9": {"jobId": "e3e1dbbc-c230-44e9-8c09-067057cf68d9", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.590659Z", "updated": "2026-02-23T21:59:01.590659Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "b6a5a683-f18a-4af5-aeca-4a539e028e67": {"jobId": "b6a5a683-f18a-4af5-aeca-4a539e028e67", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.602127Z", "updated": "2026-02-23T21:59:01.602127Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "c50ec201-9057-44f3-b102-37203efb8682": {"jobId": "c50ec201-9057-44f3-b102-37203efb8682", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.607210Z", "updated": "2026-02-23T21:59:01.607210Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "98e09e8a-fc6c-4f0b-b227-c7bfe30d8675": {"jobId": "98e09e8a-fc6c-4f0b-b227-c7bfe30d8675", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.620520Z", "updated": "2026-02-23T21:59:01.620520Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d": {"jobId": "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.632737Z", "updated": "2026-02-23T21:59:01.632737Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "9ed82292-1c23-4a6f-8077-561c8d431e5a": {"jobId": "9ed82292-1c23-4a6f-8077-561c8d431e5a", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T21:59:01.656924Z", "updated": "2026-02-23T21:59:01.657957Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "865232a5-c544-4120-a2b7-47c8f2a27806": {"jobId": "865232a5-c544-4120-a2b7-47c8f2a27806", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.665259Z", "updated": "2026-02-23T21:59:01.666993Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "8337900a-0fc6-4f53-a13e-89540fb03d2e": {"jobId": "8337900a-0fc6-4f53-a13e-89540fb03d2e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.677649Z", "updated": "2026-02-23T21:59:01.677649Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "2f057f66-9e2f-417a-a416-18a788cc2c4a": {"jobId": "2f057f66-9e2f-417a-a416-18a788cc2c4a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.688591Z", "updated": "2026-02-23T21:59:01.688591Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "75de8c95-32fd-4e9a-91a6-756110b67124": {"jobId": "75de8c95-32fd-4e9a-91a6-756110b67124", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:02.163691Z", "updated": "2026-02-23T21:59:02.163691Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "bdebbf54-ca89-48f2-b2a6-3492d2b7676c": {"jobId": "bdebbf54-ca89-48f2-b2a6-3492d2b7676c", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:02:58.655213Z", "updated": "2026-02-23T22:02:58.655213Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "78c36058-d757-4dad-92fa-f8703a052d41": {"jobId": "78c36058-d757-4dad-92fa-f8703a052d41", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:02:58.669440Z", "updated": "2026-02-23T22:02:58.669440Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "af6c1ed5-0a33-47ae-aef6-9e17653cf0a4": {"jobId": "af6c1ed5-0a33-47ae-aef6-9e17653cf0a4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:00.948460Z", "updated": "2026-02-23T22:03:00.948460Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "c6398375-2a54-47dc-a910-7d6942cc290d": {"jobId": "c6398375-2a54-47dc-a910-7d6942cc290d", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:00.963801Z", "updated": "2026-02-23T22:03:00.963801Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "33118ebd-6849-4b47-b61d-a59b3b9747a3": {"jobId": "33118ebd-6849-4b47-b61d-a59b3b9747a3", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.108286Z", "updated": "2026-02-23T22:03:01.108286Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1a111b92-83f4-44a6-9bcd-c9d7c05b7032": {"jobId": "1a111b92-83f4-44a6-9bcd-c9d7c05b7032", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.242058Z", "updated": "2026-02-23T22:03:01.242058Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8ae1afa0-88d9-493a-89e7-d118c6651e43": {"jobId": "8ae1afa0-88d9-493a-89e7-d118c6651e43", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.347704Z", "updated": "2026-02-23T22:03:01.347704Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fef7a2ef-eda6-42b0-a95d-da21341ab899": {"jobId": "fef7a2ef-eda6-42b0-a95d-da21341ab899", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:03:01.375491Z", "updated": "2026-02-23T22:03:01.377348Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "785832c4-e2a6-43d1-a64a-53d3148f18a9": {"jobId": "785832c4-e2a6-43d1-a64a-53d3148f18a9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.385768Z", "updated": "2026-02-23T22:03:01.388980Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "d42e8fc4-1023-453c-9aae-8c33141ca838": {"jobId": "d42e8fc4-1023-453c-9aae-8c33141ca838", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.501817Z", "updated": "2026-02-23T22:03:01.501817Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "6b0eb5cb-57c9-4945-88b8-029123af9a2d": {"jobId": "6b0eb5cb-57c9-4945-88b8-029123af9a2d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.649712Z", "updated": "2026-02-23T22:03:01.649712Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2187b12b-1dc3-486c-906f-5d5d79a650b4": {"jobId": "2187b12b-1dc3-486c-906f-5d5d79a650b4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.863133Z", "updated": "2026-02-23T22:03:01.863133Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "e7b8935b-cdf0-40e4-a12c-3e0cb94e7fe1": {"jobId": "e7b8935b-cdf0-40e4-a12c-3e0cb94e7fe1", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:32.137243Z", "updated": "2026-02-23T22:03:32.137243Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "589b3193-0684-43bf-83ce-164e22b5866d": {"jobId": "589b3193-0684-43bf-83ce-164e22b5866d", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:32.153159Z", "updated": "2026-02-23T22:03:32.153159Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "1a897341-a4d7-4ed8-827e-a8c70e12743b": {"jobId": "1a897341-a4d7-4ed8-827e-a8c70e12743b", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.420141Z", "updated": "2026-02-23T22:03:34.420141Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "0a34d07d-f3e2-4ce4-9ed1-2e068d448d65": {"jobId": "0a34d07d-f3e2-4ce4-9ed1-2e068d448d65", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.435985Z", "updated": "2026-02-23T22:03:34.435985Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "ba464088-1fa7-46b4-839e-8a6daceae41e": {"jobId": "ba464088-1fa7-46b4-839e-8a6daceae41e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.570403Z", "updated": "2026-02-23T22:03:34.570403Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "6b2d03e9-9e31-42f4-80f4-8d1b27442c78": {"jobId": "6b2d03e9-9e31-42f4-80f4-8d1b27442c78", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.695656Z", "updated": "2026-02-23T22:03:34.695656Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5d45d9ce-795c-4615-b973-33cc358c1327": {"jobId": "5d45d9ce-795c-4615-b973-33cc358c1327", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.805109Z", "updated": "2026-02-23T22:03:34.805109Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4c2dae6b-dbff-4591-91ca-5a679a4cd52f": {"jobId": "4c2dae6b-dbff-4591-91ca-5a679a4cd52f", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:03:34.833666Z", "updated": "2026-02-23T22:03:34.836522Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "c2c62770-2bef-4f4f-9118-84b217b504f0": {"jobId": "c2c62770-2bef-4f4f-9118-84b217b504f0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.846117Z", "updated": "2026-02-23T22:03:34.849465Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "d6098fe4-5916-4d3b-b540-de1076f51c8d": {"jobId": "d6098fe4-5916-4d3b-b540-de1076f51c8d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.960970Z", "updated": "2026-02-23T22:03:34.960970Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2462ff1e-4093-490c-bef6-eacb3b094e1f": {"jobId": "2462ff1e-4093-490c-bef6-eacb3b094e1f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:35.106651Z", "updated": "2026-02-23T22:03:35.106651Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b7920d20-1954-44e2-81d2-e76bf4f03e90": {"jobId": "b7920d20-1954-44e2-81d2-e76bf4f03e90", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:35.319641Z", "updated": "2026-02-23T22:03:35.319641Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "446976dc-2fba-4de9-b94d-9d066fdc0c4e": {"jobId": "446976dc-2fba-4de9-b94d-9d066fdc0c4e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:06.462908Z", "updated": "2026-02-23T22:04:06.462908Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "0ed8ec84-c466-41e3-9591-0553c77975a9": {"jobId": "0ed8ec84-c466-41e3-9591-0553c77975a9", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:06.479128Z", "updated": "2026-02-23T22:04:06.479128Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "b78441e3-a9f1-437c-a279-15518692ac62": {"jobId": "b78441e3-a9f1-437c-a279-15518692ac62", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.742026Z", "updated": "2026-02-23T22:04:08.742026Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "69a12038-bcd5-4e8b-a545-0c6f6d3d2a52": {"jobId": "69a12038-bcd5-4e8b-a545-0c6f6d3d2a52", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.756654Z", "updated": "2026-02-23T22:04:08.756654Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "41bac021-d432-437f-85dc-bba5cb0757a6": {"jobId": "41bac021-d432-437f-85dc-bba5cb0757a6", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.885064Z", "updated": "2026-02-23T22:04:08.885064Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5442f975-e3e8-4627-9737-b0ed509543c8": {"jobId": "5442f975-e3e8-4627-9737-b0ed509543c8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.010488Z", "updated": "2026-02-23T22:04:09.010488Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5f68bea6-8dd8-421e-98d7-0cc70d496462": {"jobId": "5f68bea6-8dd8-421e-98d7-0cc70d496462", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.122398Z", "updated": "2026-02-23T22:04:09.122398Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4": {"jobId": "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:04:09.153630Z", "updated": "2026-02-23T22:04:09.157440Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "67480820-6c57-4fd5-a991-1f7ddfd0ee56": {"jobId": "67480820-6c57-4fd5-a991-1f7ddfd0ee56", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.167290Z", "updated": "2026-02-23T22:04:09.171405Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "fb84e869-28c5-4187-b963-62a0f0ddb0d0": {"jobId": "fb84e869-28c5-4187-b963-62a0f0ddb0d0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.286819Z", "updated": "2026-02-23T22:04:09.286819Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5d9f7eba-2303-4efa-aa2c-30f93fc6971a": {"jobId": "5d9f7eba-2303-4efa-aa2c-30f93fc6971a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.471642Z", "updated": "2026-02-23T22:04:09.471642Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "697f0d2d-d86a-4bfe-8dac-aa80a6b5df7f": {"jobId": "697f0d2d-d86a-4bfe-8dac-aa80a6b5df7f", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.691847Z", "updated": "2026-02-23T22:04:09.691847Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "bab696ee-5483-4c82-bf44-e457c5f0ea69": {"jobId": "bab696ee-5483-4c82-bf44-e457c5f0ea69", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:23.547932Z", "updated": "2026-02-23T22:05:23.547932Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "370b5752-bb53-44e5-b373-96d014ead43f": {"jobId": "370b5752-bb53-44e5-b373-96d014ead43f", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:23.564772Z", "updated": "2026-02-23T22:05:23.564772Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "d9d78be7-a46e-4236-a815-f65e42cab9fe": {"jobId": "d9d78be7-a46e-4236-a815-f65e42cab9fe", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.819681Z", "updated": "2026-02-23T22:05:25.819681Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "d9248c76-d0b1-4107-8739-d26e01dd859c": {"jobId": "d9248c76-d0b1-4107-8739-d26e01dd859c", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.835593Z", "updated": "2026-02-23T22:05:25.835593Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "23ee0b0c-c1f0-4be4-83d3-c82e8fe98ae7": {"jobId": "23ee0b0c-c1f0-4be4-83d3-c82e8fe98ae7", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.939376Z", "updated": "2026-02-23T22:05:25.939376Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "48b4c768-bbaf-47a8-aeb7-44e697067cb9": {"jobId": "48b4c768-bbaf-47a8-aeb7-44e697067cb9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.102926Z", "updated": "2026-02-23T22:05:26.102926Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "052828cb-fe04-4107-8168-bf626dc3d2d4": {"jobId": "052828cb-fe04-4107-8168-bf626dc3d2d4", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.213041Z", "updated": "2026-02-23T22:05:26.213041Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "057a6900-c6e4-4ee7-b392-16cc852a7beb": {"jobId": "057a6900-c6e4-4ee7-b392-16cc852a7beb", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:05:26.244912Z", "updated": "2026-02-23T22:05:26.249375Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "f07f0036-8f43-4d12-8811-7a3e6603228b": {"jobId": "f07f0036-8f43-4d12-8811-7a3e6603228b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.260482Z", "updated": "2026-02-23T22:05:26.265682Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff": {"jobId": "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.380473Z", "updated": "2026-02-23T22:05:26.380473Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b232896b-2721-46b8-abc8-9761a40f9d22": {"jobId": "b232896b-2721-46b8-abc8-9761a40f9d22", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.527434Z", "updated": "2026-02-23T22:05:26.527434Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1f2bf79d-8181-490d-a45e-9438e38b45c6": {"jobId": "1f2bf79d-8181-490d-a45e-9438e38b45c6", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.742199Z", "updated": "2026-02-23T22:05:26.742199Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "6df02f8b-df42-41dd-b987-a06dbeaf5539": {"jobId": "6df02f8b-df42-41dd-b987-a06dbeaf5539", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:17.263363Z", "updated": "2026-02-23T22:06:17.263363Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8ea3e465-f7a8-4b71-8375-38f65fcf63ca": {"jobId": "8ea3e465-f7a8-4b71-8375-38f65fcf63ca", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:17.295123Z", "updated": "2026-02-23T22:06:17.295123Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "444c5c43-cbdd-409f-b180-e8b339f8ef11": {"jobId": "444c5c43-cbdd-409f-b180-e8b339f8ef11", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.520179Z", "updated": "2026-02-23T22:06:19.520179Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "ebc38efc-530c-444c-bb0f-a9b22912944c": {"jobId": "ebc38efc-530c-444c-bb0f-a9b22912944c", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.536100Z", "updated": "2026-02-23T22:06:19.536100Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "973f8a9e-f220-436f-91b2-6507e96b615a": {"jobId": "973f8a9e-f220-436f-91b2-6507e96b615a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.666645Z", "updated": "2026-02-23T22:06:19.666645Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ab19876c-d13d-4c37-82f5-af575b863ae9": {"jobId": "ab19876c-d13d-4c37-82f5-af575b863ae9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.795408Z", "updated": "2026-02-23T22:06:19.795408Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bb27b64c-2cda-41ab-8e2b-b23ff462de71": {"jobId": "bb27b64c-2cda-41ab-8e2b-b23ff462de71", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.907708Z", "updated": "2026-02-23T22:06:19.907708Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d0cd71f3-2aff-4345-8804-6451bd9d78bd": {"jobId": "d0cd71f3-2aff-4345-8804-6451bd9d78bd", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:06:19.940310Z", "updated": "2026-02-23T22:06:19.945539Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "4c120e2c-3b8e-471c-a944-d4fe46e6544d": {"jobId": "4c120e2c-3b8e-471c-a944-d4fe46e6544d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.965760Z", "updated": "2026-02-23T22:06:19.972003Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "a0138e99-87f4-4213-b003-53e4435d2191": {"jobId": "a0138e99-87f4-4213-b003-53e4435d2191", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.085244Z", "updated": "2026-02-23T22:06:20.085244Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "67ffa0a9-35fe-4780-b5e7-17cebd8321c3": {"jobId": "67ffa0a9-35fe-4780-b5e7-17cebd8321c3", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.234581Z", "updated": "2026-02-23T22:06:20.234581Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1640da1c-e8fe-4aaf-b8d6-5f4441a05f4d": {"jobId": "1640da1c-e8fe-4aaf-b8d6-5f4441a05f4d", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.456531Z", "updated": "2026-02-23T22:06:20.456531Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "1bea47ea-b78c-4c37-ad4a-4bc4731dc493": {"jobId": "1bea47ea-b78c-4c37-ad4a-4bc4731dc493", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:07.539027Z", "updated": "2026-02-23T22:07:07.539027Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1277fe9e-4a99-4014-8c55-66804e616440": {"jobId": "1277fe9e-4a99-4014-8c55-66804e616440", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:07.558215Z", "updated": "2026-02-23T22:07:07.558215Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "267b8300-765d-40e3-9ec2-5d6478f47892": {"jobId": "267b8300-765d-40e3-9ec2-5d6478f47892", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.804460Z", "updated": "2026-02-23T22:07:09.804460Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "cdefce12-bd1d-4828-a27d-0960d104c6fa": {"jobId": "cdefce12-bd1d-4828-a27d-0960d104c6fa", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.821632Z", "updated": "2026-02-23T22:07:09.821632Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "092d45de-2992-4688-9eea-5e47bef48651": {"jobId": "092d45de-2992-4688-9eea-5e47bef48651", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.928469Z", "updated": "2026-02-23T22:07:09.928469Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "55481550-c20d-404f-888b-972569e1a21d": {"jobId": "55481550-c20d-404f-888b-972569e1a21d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.096984Z", "updated": "2026-02-23T22:07:10.096984Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "db8c46c0-4252-4091-89b6-7bcac3da7ab2": {"jobId": "db8c46c0-4252-4091-89b6-7bcac3da7ab2", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.207616Z", "updated": "2026-02-23T22:07:10.207616Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "36ad61d8-3b1a-4fa3-bc58-b801c12e6980": {"jobId": "36ad61d8-3b1a-4fa3-bc58-b801c12e6980", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:07:10.241678Z", "updated": "2026-02-23T22:07:10.247863Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "7c89eaf6-cad3-42bf-82b7-0159b289ab4d": {"jobId": "7c89eaf6-cad3-42bf-82b7-0159b289ab4d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.260512Z", "updated": "2026-02-23T22:07:10.267134Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "07711cbe-a49b-43ec-b9f5-a47ff809a637": {"jobId": "07711cbe-a49b-43ec-b9f5-a47ff809a637", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.381958Z", "updated": "2026-02-23T22:07:10.381958Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b60ed6da-a124-49f0-a4ac-d52c8d79cb70": {"jobId": "b60ed6da-a124-49f0-a4ac-d52c8d79cb70", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.534954Z", "updated": "2026-02-23T22:07:10.534954Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b7198527-3cd1-4105-ad05-e96e3eb2dc0b": {"jobId": "b7198527-3cd1-4105-ad05-e96e3eb2dc0b", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.756754Z", "updated": "2026-02-23T22:07:10.756754Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "8c44185b-b5d3-48be-9786-fd8949a4eec0": {"jobId": "8c44185b-b5d3-48be-9786-fd8949a4eec0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:23.056931Z", "updated": "2026-02-23T22:08:23.056931Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "159d008c-2cbe-43dc-9da0-d476df8f8912": {"jobId": "159d008c-2cbe-43dc-9da0-d476df8f8912", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:23.078203Z", "updated": "2026-02-23T22:08:23.078203Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "4fefa042-d0f2-40d5-878e-65410620d408": {"jobId": "4fefa042-d0f2-40d5-878e-65410620d408", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.348486Z", "updated": "2026-02-23T22:08:25.348486Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "a47f73c7-ce37-48c9-af73-11760b35e296": {"jobId": "a47f73c7-ce37-48c9-af73-11760b35e296", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.366760Z", "updated": "2026-02-23T22:08:25.366760Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "9be31308-883e-4f46-927f-8faf8a43795d": {"jobId": "9be31308-883e-4f46-927f-8faf8a43795d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.476319Z", "updated": "2026-02-23T22:08:25.476319Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b10443b2-5b5c-4a8a-9d3d-7fba142e87c8": {"jobId": "b10443b2-5b5c-4a8a-9d3d-7fba142e87c8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.648456Z", "updated": "2026-02-23T22:08:25.648456Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1df779b8-aa1c-439f-a5d7-3525fb54dc77": {"jobId": "1df779b8-aa1c-439f-a5d7-3525fb54dc77", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.758845Z", "updated": "2026-02-23T22:08:25.758845Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33": {"jobId": "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:08:25.793139Z", "updated": "2026-02-23T22:08:25.800459Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "2da98086-c89d-49cb-bac4-5a2f63c02d3b": {"jobId": "2da98086-c89d-49cb-bac4-5a2f63c02d3b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.814740Z", "updated": "2026-02-23T22:08:25.822762Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "e3f2a3ef-efb8-4a71-a892-437463f84e13": {"jobId": "e3f2a3ef-efb8-4a71-a892-437463f84e13", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.940926Z", "updated": "2026-02-23T22:08:25.940926Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c8e8832f-a05e-4ae1-89bc-418391552a31": {"jobId": "c8e8832f-a05e-4ae1-89bc-418391552a31", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:26.094254Z", "updated": "2026-02-23T22:08:26.094254Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "3491be0a-69f9-4f9a-924c-79fbcb7404a5": {"jobId": "3491be0a-69f9-4f9a-924c-79fbcb7404a5", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:26.312951Z", "updated": "2026-02-23T22:08:26.312951Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "b78a5896-d88d-4592-bc98-36dd20426679": {"jobId": "b78a5896-d88d-4592-bc98-36dd20426679", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:08.677668Z", "updated": "2026-02-23T22:10:08.677668Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c842962b-c87d-4787-bbed-499da0a0e659": {"jobId": "c842962b-c87d-4787-bbed-499da0a0e659", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:08.698047Z", "updated": "2026-02-23T22:10:08.698047Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "9ffc08f6-24de-4744-9f55-5416c269c284": {"jobId": "9ffc08f6-24de-4744-9f55-5416c269c284", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:10.975367Z", "updated": "2026-02-23T22:10:10.975367Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "33140241-39cf-4963-9a9f-c4068665dbdb": {"jobId": "33140241-39cf-4963-9a9f-c4068665dbdb", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:10.995315Z", "updated": "2026-02-23T22:10:10.995315Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "51621767-7943-48df-a074-9f29f6c2374d": {"jobId": "51621767-7943-48df-a074-9f29f6c2374d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.106175Z", "updated": "2026-02-23T22:10:11.106175Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d3119749-3e84-489c-b36c-de752ff0f44f": {"jobId": "d3119749-3e84-489c-b36c-de752ff0f44f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.269887Z", "updated": "2026-02-23T22:10:11.269887Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "48cc3a56-6df8-42b6-a1cd-ab380a687d17": {"jobId": "48cc3a56-6df8-42b6-a1cd-ab380a687d17", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.379628Z", "updated": "2026-02-23T22:10:11.379628Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "672705fa-17df-48d3-9dfe-89edd3033977": {"jobId": "672705fa-17df-48d3-9dfe-89edd3033977", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:10:11.415532Z", "updated": "2026-02-23T22:10:11.423246Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "62523329-5a27-4557-ae52-b3a3668cf8b9": {"jobId": "62523329-5a27-4557-ae52-b3a3668cf8b9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.438093Z", "updated": "2026-02-23T22:10:11.447351Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "3bc40154-66d2-44b8-bf8a-3c931d7ce92a": {"jobId": "3bc40154-66d2-44b8-bf8a-3c931d7ce92a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.565043Z", "updated": "2026-02-23T22:10:11.565043Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "aa3f467e-d50a-4120-b9b0-0e2d121f169e": {"jobId": "aa3f467e-d50a-4120-b9b0-0e2d121f169e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.717150Z", "updated": "2026-02-23T22:10:11.717150Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d59d5ce4-e5a1-4087-91df-f5f957b056ef": {"jobId": "d59d5ce4-e5a1-4087-91df-f5f957b056ef", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.933145Z", "updated": "2026-02-23T22:10:11.933145Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "277592bc-6939-4806-af05-87c7bf533d5f": {"jobId": "277592bc-6939-4806-af05-87c7bf533d5f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:24.503021Z", "updated": "2026-02-23T22:12:24.503021Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7006c679-b227-4022-9c35-3e2cfc85b0f4": {"jobId": "7006c679-b227-4022-9c35-3e2cfc85b0f4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:24.525639Z", "updated": "2026-02-23T22:12:24.525639Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "8b551dab-da4c-49ad-99ad-beafe80eebb1": {"jobId": "8b551dab-da4c-49ad-99ad-beafe80eebb1", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:26.896434Z", "updated": "2026-02-23T22:12:26.896434Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "a771c412-cd8d-481f-86c5-60973c502cf2": {"jobId": "a771c412-cd8d-481f-86c5-60973c502cf2", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:26.917174Z", "updated": "2026-02-23T22:12:26.917174Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "895fa56d-a56a-45a0-bcac-1ba7cb072f9d": {"jobId": "895fa56d-a56a-45a0-bcac-1ba7cb072f9d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.031192Z", "updated": "2026-02-23T22:12:27.031192Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b878b07e-4d0c-4452-8ad0-b7d2e014b415": {"jobId": "b878b07e-4d0c-4452-8ad0-b7d2e014b415", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.214706Z", "updated": "2026-02-23T22:12:27.214706Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4c59c2e2-a55c-475e-8f49-8060b0070c15": {"jobId": "4c59c2e2-a55c-475e-8f49-8060b0070c15", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.331969Z", "updated": "2026-02-23T22:12:27.331969Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "743ddcec-4c43-49cf-a3d7-a79fd07d203c": {"jobId": "743ddcec-4c43-49cf-a3d7-a79fd07d203c", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:12:27.370127Z", "updated": "2026-02-23T22:12:27.378919Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "048b97d2-321b-412b-8add-8bfc73947d10": {"jobId": "048b97d2-321b-412b-8add-8bfc73947d10", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.395188Z", "updated": "2026-02-23T22:12:27.405120Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "faaa0822-0996-42aa-9b4a-09db3b38b253": {"jobId": "faaa0822-0996-42aa-9b4a-09db3b38b253", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.528860Z", "updated": "2026-02-23T22:12:27.528860Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2f62167a-3bab-496e-b408-f1078f023253": {"jobId": "2f62167a-3bab-496e-b408-f1078f023253", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.680510Z", "updated": "2026-02-23T22:12:27.680510Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c60578bb-1943-4a06-ba54-ef1f73aa7a31": {"jobId": "c60578bb-1943-4a06-ba54-ef1f73aa7a31", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.896422Z", "updated": "2026-02-23T22:12:27.896422Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "ddd7182d-c5e7-4708-9d27-6c44c59101e6": {"jobId": "ddd7182d-c5e7-4708-9d27-6c44c59101e6", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:52.476895Z", "updated": "2026-02-23T22:13:52.476895Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "dce96d73-0dd2-433a-ab9f-50708fd76735": {"jobId": "dce96d73-0dd2-433a-ab9f-50708fd76735", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:52.499440Z", "updated": "2026-02-23T22:13:52.499440Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "efadd460-9f5d-40e6-b6d2-7f962b324388": {"jobId": "efadd460-9f5d-40e6-b6d2-7f962b324388", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.763632Z", "updated": "2026-02-23T22:13:54.763632Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "9cf3a3f0-f611-41c1-9deb-94268951ce28": {"jobId": "9cf3a3f0-f611-41c1-9deb-94268951ce28", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.785857Z", "updated": "2026-02-23T22:13:54.785857Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "245ec5ef-e750-45ae-8a6e-4b05fd695da7": {"jobId": "245ec5ef-e750-45ae-8a6e-4b05fd695da7", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.893765Z", "updated": "2026-02-23T22:13:54.893765Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "dc3129a8-db7b-4354-bcb5-3beb9df098af": {"jobId": "dc3129a8-db7b-4354-bcb5-3beb9df098af", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.067514Z", "updated": "2026-02-23T22:13:55.067514Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "421d8036-8bb8-4d19-8ab2-16b12114c03f": {"jobId": "421d8036-8bb8-4d19-8ab2-16b12114c03f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.183339Z", "updated": "2026-02-23T22:13:55.183339Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1f0946fe-d7cf-4ff5-ae38-ea332be556f8": {"jobId": "1f0946fe-d7cf-4ff5-ae38-ea332be556f8", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:13:55.221492Z", "updated": "2026-02-23T22:13:55.231516Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "d407d400-5ed4-4dee-9d95-749ef70bfa2d": {"jobId": "d407d400-5ed4-4dee-9d95-749ef70bfa2d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.247933Z", "updated": "2026-02-23T22:13:55.258441Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "89f1748d-a2ff-4fb4-bad4-034af929932e": {"jobId": "89f1748d-a2ff-4fb4-bad4-034af929932e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.373387Z", "updated": "2026-02-23T22:13:55.373387Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fef322d8-8a06-4091-b962-2f6f616cbb71": {"jobId": "fef322d8-8a06-4091-b962-2f6f616cbb71", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.536523Z", "updated": "2026-02-23T22:13:55.536523Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "200b0ab7-b566-4c98-9639-9c019adc4af5": {"jobId": "200b0ab7-b566-4c98-9639-9c019adc4af5", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.767251Z", "updated": "2026-02-23T22:13:55.767251Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "9de477f4-e0ab-44c3-8b0d-a785df5ace6b": {"jobId": "9de477f4-e0ab-44c3-8b0d-a785df5ace6b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:37.450246Z", "updated": "2026-02-23T22:15:37.450246Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2716eab1-7e96-4ecc-a47b-b12890300ed0": {"jobId": "2716eab1-7e96-4ecc-a47b-b12890300ed0", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:37.473495Z", "updated": "2026-02-23T22:15:37.473495Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "affe6d5d-97ce-4762-b4dc-18a8c62bd933": {"jobId": "affe6d5d-97ce-4762-b4dc-18a8c62bd933", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.721512Z", "updated": "2026-02-23T22:15:39.721512Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "5d6a4802-d6fc-4e15-be23-cb55cd6d43fa": {"jobId": "5d6a4802-d6fc-4e15-be23-cb55cd6d43fa", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.743320Z", "updated": "2026-02-23T22:15:39.743320Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "881249ed-7649-49a0-a8d2-ea5d453387b2": {"jobId": "881249ed-7649-49a0-a8d2-ea5d453387b2", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.852155Z", "updated": "2026-02-23T22:15:39.852155Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "09078395-6734-4aa0-804d-342d533f5a08": {"jobId": "09078395-6734-4aa0-804d-342d533f5a08", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.016212Z", "updated": "2026-02-23T22:15:40.016212Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ac76a665-136a-4730-9228-dceb0a828f85": {"jobId": "ac76a665-136a-4730-9228-dceb0a828f85", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.130039Z", "updated": "2026-02-23T22:15:40.130039Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "101a1fa5-3a6b-4923-8b3d-08497fc2cde3": {"jobId": "101a1fa5-3a6b-4923-8b3d-08497fc2cde3", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:15:40.171547Z", "updated": "2026-02-23T22:15:40.182169Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "90649d63-8edc-4d9e-aac5-1b3a6fd2f954": {"jobId": "90649d63-8edc-4d9e-aac5-1b3a6fd2f954", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.200090Z", "updated": "2026-02-23T22:15:40.211787Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b": {"jobId": "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.332893Z", "updated": "2026-02-23T22:15:40.332893Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "e3dee3c1-f3d9-4340-a412-48964442a29b": {"jobId": "e3dee3c1-f3d9-4340-a412-48964442a29b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.497073Z", "updated": "2026-02-23T22:15:40.497073Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "a44b6fc3-3b43-4b6c-ac09-4c2bbd973e37": {"jobId": "a44b6fc3-3b43-4b6c-ac09-4c2bbd973e37", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.733179Z", "updated": "2026-02-23T22:15:40.733179Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "c102da24-1bac-4567-af7f-39a0eff270f4": {"jobId": "c102da24-1bac-4567-af7f-39a0eff270f4", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:53.998689Z", "updated": "2026-02-23T22:16:53.998689Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7b2b7e4b-b1c1-45d7-a382-78b3f72cb077": {"jobId": "7b2b7e4b-b1c1-45d7-a382-78b3f72cb077", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:54.024575Z", "updated": "2026-02-23T22:16:54.024575Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "1a8a2412-5b27-40da-a8f0-94f680e026b4": {"jobId": "1a8a2412-5b27-40da-a8f0-94f680e026b4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.296999Z", "updated": "2026-02-23T22:16:56.296999Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "ec28d8a2-6234-471f-b96f-7c1731d18a0f": {"jobId": "ec28d8a2-6234-471f-b96f-7c1731d18a0f", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.320203Z", "updated": "2026-02-23T22:16:56.320203Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "0dc16554-7eaf-497c-9a1e-4efc286ba872": {"jobId": "0dc16554-7eaf-497c-9a1e-4efc286ba872", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.432278Z", "updated": "2026-02-23T22:16:56.432278Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8e276ac9-189f-432d-adec-b7ab74ea6590": {"jobId": "8e276ac9-189f-432d-adec-b7ab74ea6590", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.602095Z", "updated": "2026-02-23T22:16:56.602095Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9": {"jobId": "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.720377Z", "updated": "2026-02-23T22:16:56.720377Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4e30a788-c134-463a-bdbb-f88b4b5615c9": {"jobId": "4e30a788-c134-463a-bdbb-f88b4b5615c9", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:16:56.760958Z", "updated": "2026-02-23T22:16:56.772441Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "336d659f-b4f7-4a49-a7d0-a5ec78dc25d8": {"jobId": "336d659f-b4f7-4a49-a7d0-a5ec78dc25d8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.791195Z", "updated": "2026-02-23T22:16:56.803752Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "9a34fb59-d815-4107-9c6b-d3207704d83a": {"jobId": "9a34fb59-d815-4107-9c6b-d3207704d83a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.926163Z", "updated": "2026-02-23T22:16:56.926163Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "56c4347f-b16f-40db-9f64-b0239711faac": {"jobId": "56c4347f-b16f-40db-9f64-b0239711faac", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:57.053777Z", "updated": "2026-02-23T22:16:57.053777Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fbe518c3-121e-4097-8a28-322ddee317e7": {"jobId": "fbe518c3-121e-4097-8a28-322ddee317e7", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:57.304091Z", "updated": "2026-02-23T22:16:57.304091Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "cba3a8e8-2dd3-48c3-ad24-822320428aef": {"jobId": "cba3a8e8-2dd3-48c3-ad24-822320428aef", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:06.883459Z", "updated": "2026-02-23T22:18:06.883459Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "40e9fb81-f7f8-48c9-a83c-bf1ce068c960": {"jobId": "40e9fb81-f7f8-48c9-a83c-bf1ce068c960", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:06.910504Z", "updated": "2026-02-23T22:18:06.910504Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "33ff2a20-5a20-4bf0-a70c-dda4f52753e3": {"jobId": "33ff2a20-5a20-4bf0-a70c-dda4f52753e3", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.164136Z", "updated": "2026-02-23T22:18:09.164136Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "798f2a1a-3d44-4778-9552-5eef336a799e": {"jobId": "798f2a1a-3d44-4778-9552-5eef336a799e", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.186896Z", "updated": "2026-02-23T22:18:09.186896Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "426ebad3-da3e-4748-93c0-f7286de43ce8": {"jobId": "426ebad3-da3e-4748-93c0-f7286de43ce8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.295646Z", "updated": "2026-02-23T22:18:09.295646Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4eb5c271-dee4-4f16-9740-141f3ac0e5fa": {"jobId": "4eb5c271-dee4-4f16-9740-141f3ac0e5fa", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.470972Z", "updated": "2026-02-23T22:18:09.470972Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bef54659-7bfc-4c67-b172-1722edcea9cb": {"jobId": "bef54659-7bfc-4c67-b172-1722edcea9cb", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.590918Z", "updated": "2026-02-23T22:18:09.590918Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2ad476b8-a2a6-4783-948e-42087f50a7e4": {"jobId": "2ad476b8-a2a6-4783-948e-42087f50a7e4", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:18:09.635442Z", "updated": "2026-02-23T22:18:09.647649Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "81cfc65f-344c-43da-a0ac-d002ec25c0ed": {"jobId": "81cfc65f-344c-43da-a0ac-d002ec25c0ed", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.667508Z", "updated": "2026-02-23T22:18:09.680422Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "50f69ac8-ca39-4892-bf3c-2921221183b8": {"jobId": "50f69ac8-ca39-4892-bf3c-2921221183b8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.799866Z", "updated": "2026-02-23T22:18:09.799866Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "503e7d84-be48-4fa8-a809-ce44b23325ab": {"jobId": "503e7d84-be48-4fa8-a809-ce44b23325ab", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.925723Z", "updated": "2026-02-23T22:18:09.925723Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c0e21843-e0a2-42a1-806f-faf8b325ab93": {"jobId": "c0e21843-e0a2-42a1-806f-faf8b325ab93", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:10.182289Z", "updated": "2026-02-23T22:18:10.182289Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}} \ No newline at end of file +{"c4e10ad3-03a8-4ccd-b64e-4b36da4ced28": {"jobId": "c4e10ad3-03a8-4ccd-b64e-4b36da4ced28", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:58:59.188643Z", "updated": "2026-02-23T21:58:59.188643Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "7fd59008-4d1c-471c-b3b6-959e14b69edd": {"jobId": "7fd59008-4d1c-471c-b3b6-959e14b69edd", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:58:59.202771Z", "updated": "2026-02-23T21:58:59.202771Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "e3e1dbbc-c230-44e9-8c09-067057cf68d9": {"jobId": "e3e1dbbc-c230-44e9-8c09-067057cf68d9", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.590659Z", "updated": "2026-02-23T21:59:01.590659Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "b6a5a683-f18a-4af5-aeca-4a539e028e67": {"jobId": "b6a5a683-f18a-4af5-aeca-4a539e028e67", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.602127Z", "updated": "2026-02-23T21:59:01.602127Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "c50ec201-9057-44f3-b102-37203efb8682": {"jobId": "c50ec201-9057-44f3-b102-37203efb8682", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.607210Z", "updated": "2026-02-23T21:59:01.607210Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "98e09e8a-fc6c-4f0b-b227-c7bfe30d8675": {"jobId": "98e09e8a-fc6c-4f0b-b227-c7bfe30d8675", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.620520Z", "updated": "2026-02-23T21:59:01.620520Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d": {"jobId": "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.632737Z", "updated": "2026-02-23T21:59:01.632737Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "9ed82292-1c23-4a6f-8077-561c8d431e5a": {"jobId": "9ed82292-1c23-4a6f-8077-561c8d431e5a", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T21:59:01.656924Z", "updated": "2026-02-23T21:59:01.657957Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "865232a5-c544-4120-a2b7-47c8f2a27806": {"jobId": "865232a5-c544-4120-a2b7-47c8f2a27806", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.665259Z", "updated": "2026-02-23T21:59:01.666993Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "8337900a-0fc6-4f53-a13e-89540fb03d2e": {"jobId": "8337900a-0fc6-4f53-a13e-89540fb03d2e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.677649Z", "updated": "2026-02-23T21:59:01.677649Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "2f057f66-9e2f-417a-a416-18a788cc2c4a": {"jobId": "2f057f66-9e2f-417a-a416-18a788cc2c4a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:01.688591Z", "updated": "2026-02-23T21:59:01.688591Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 7.0}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 14.0}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "values": {"precip": 21.0}}}]}}, "75de8c95-32fd-4e9a-91a6-756110b67124": {"jobId": "75de8c95-32fd-4e9a-91a6-756110b67124", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T21:59:02.163691Z", "updated": "2026-02-23T21:59:02.163691Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "bdebbf54-ca89-48f2-b2a6-3492d2b7676c": {"jobId": "bdebbf54-ca89-48f2-b2a6-3492d2b7676c", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:02:58.655213Z", "updated": "2026-02-23T22:02:58.655213Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "78c36058-d757-4dad-92fa-f8703a052d41": {"jobId": "78c36058-d757-4dad-92fa-f8703a052d41", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:02:58.669440Z", "updated": "2026-02-23T22:02:58.669440Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "af6c1ed5-0a33-47ae-aef6-9e17653cf0a4": {"jobId": "af6c1ed5-0a33-47ae-aef6-9e17653cf0a4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:00.948460Z", "updated": "2026-02-23T22:03:00.948460Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "c6398375-2a54-47dc-a910-7d6942cc290d": {"jobId": "c6398375-2a54-47dc-a910-7d6942cc290d", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:00.963801Z", "updated": "2026-02-23T22:03:00.963801Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "33118ebd-6849-4b47-b61d-a59b3b9747a3": {"jobId": "33118ebd-6849-4b47-b61d-a59b3b9747a3", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.108286Z", "updated": "2026-02-23T22:03:01.108286Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1a111b92-83f4-44a6-9bcd-c9d7c05b7032": {"jobId": "1a111b92-83f4-44a6-9bcd-c9d7c05b7032", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.242058Z", "updated": "2026-02-23T22:03:01.242058Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8ae1afa0-88d9-493a-89e7-d118c6651e43": {"jobId": "8ae1afa0-88d9-493a-89e7-d118c6651e43", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.347704Z", "updated": "2026-02-23T22:03:01.347704Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fef7a2ef-eda6-42b0-a95d-da21341ab899": {"jobId": "fef7a2ef-eda6-42b0-a95d-da21341ab899", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:03:01.375491Z", "updated": "2026-02-23T22:03:01.377348Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "785832c4-e2a6-43d1-a64a-53d3148f18a9": {"jobId": "785832c4-e2a6-43d1-a64a-53d3148f18a9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.385768Z", "updated": "2026-02-23T22:03:01.388980Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "d42e8fc4-1023-453c-9aae-8c33141ca838": {"jobId": "d42e8fc4-1023-453c-9aae-8c33141ca838", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.501817Z", "updated": "2026-02-23T22:03:01.501817Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "6b0eb5cb-57c9-4945-88b8-029123af9a2d": {"jobId": "6b0eb5cb-57c9-4945-88b8-029123af9a2d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.649712Z", "updated": "2026-02-23T22:03:01.649712Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2187b12b-1dc3-486c-906f-5d5d79a650b4": {"jobId": "2187b12b-1dc3-486c-906f-5d5d79a650b4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:01.863133Z", "updated": "2026-02-23T22:03:01.863133Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "e7b8935b-cdf0-40e4-a12c-3e0cb94e7fe1": {"jobId": "e7b8935b-cdf0-40e4-a12c-3e0cb94e7fe1", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:32.137243Z", "updated": "2026-02-23T22:03:32.137243Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "589b3193-0684-43bf-83ce-164e22b5866d": {"jobId": "589b3193-0684-43bf-83ce-164e22b5866d", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:32.153159Z", "updated": "2026-02-23T22:03:32.153159Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "1a897341-a4d7-4ed8-827e-a8c70e12743b": {"jobId": "1a897341-a4d7-4ed8-827e-a8c70e12743b", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.420141Z", "updated": "2026-02-23T22:03:34.420141Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "0a34d07d-f3e2-4ce4-9ed1-2e068d448d65": {"jobId": "0a34d07d-f3e2-4ce4-9ed1-2e068d448d65", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.435985Z", "updated": "2026-02-23T22:03:34.435985Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "ba464088-1fa7-46b4-839e-8a6daceae41e": {"jobId": "ba464088-1fa7-46b4-839e-8a6daceae41e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.570403Z", "updated": "2026-02-23T22:03:34.570403Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "6b2d03e9-9e31-42f4-80f4-8d1b27442c78": {"jobId": "6b2d03e9-9e31-42f4-80f4-8d1b27442c78", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.695656Z", "updated": "2026-02-23T22:03:34.695656Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5d45d9ce-795c-4615-b973-33cc358c1327": {"jobId": "5d45d9ce-795c-4615-b973-33cc358c1327", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.805109Z", "updated": "2026-02-23T22:03:34.805109Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4c2dae6b-dbff-4591-91ca-5a679a4cd52f": {"jobId": "4c2dae6b-dbff-4591-91ca-5a679a4cd52f", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:03:34.833666Z", "updated": "2026-02-23T22:03:34.836522Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "c2c62770-2bef-4f4f-9118-84b217b504f0": {"jobId": "c2c62770-2bef-4f4f-9118-84b217b504f0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.846117Z", "updated": "2026-02-23T22:03:34.849465Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "d6098fe4-5916-4d3b-b540-de1076f51c8d": {"jobId": "d6098fe4-5916-4d3b-b540-de1076f51c8d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:34.960970Z", "updated": "2026-02-23T22:03:34.960970Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2462ff1e-4093-490c-bef6-eacb3b094e1f": {"jobId": "2462ff1e-4093-490c-bef6-eacb3b094e1f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:35.106651Z", "updated": "2026-02-23T22:03:35.106651Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b7920d20-1954-44e2-81d2-e76bf4f03e90": {"jobId": "b7920d20-1954-44e2-81d2-e76bf4f03e90", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:03:35.319641Z", "updated": "2026-02-23T22:03:35.319641Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "446976dc-2fba-4de9-b94d-9d066fdc0c4e": {"jobId": "446976dc-2fba-4de9-b94d-9d066fdc0c4e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:06.462908Z", "updated": "2026-02-23T22:04:06.462908Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "0ed8ec84-c466-41e3-9591-0553c77975a9": {"jobId": "0ed8ec84-c466-41e3-9591-0553c77975a9", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:06.479128Z", "updated": "2026-02-23T22:04:06.479128Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "b78441e3-a9f1-437c-a279-15518692ac62": {"jobId": "b78441e3-a9f1-437c-a279-15518692ac62", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.742026Z", "updated": "2026-02-23T22:04:08.742026Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "69a12038-bcd5-4e8b-a545-0c6f6d3d2a52": {"jobId": "69a12038-bcd5-4e8b-a545-0c6f6d3d2a52", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.756654Z", "updated": "2026-02-23T22:04:08.756654Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "41bac021-d432-437f-85dc-bba5cb0757a6": {"jobId": "41bac021-d432-437f-85dc-bba5cb0757a6", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:08.885064Z", "updated": "2026-02-23T22:04:08.885064Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5442f975-e3e8-4627-9737-b0ed509543c8": {"jobId": "5442f975-e3e8-4627-9737-b0ed509543c8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.010488Z", "updated": "2026-02-23T22:04:09.010488Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5f68bea6-8dd8-421e-98d7-0cc70d496462": {"jobId": "5f68bea6-8dd8-421e-98d7-0cc70d496462", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.122398Z", "updated": "2026-02-23T22:04:09.122398Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4": {"jobId": "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:04:09.153630Z", "updated": "2026-02-23T22:04:09.157440Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "67480820-6c57-4fd5-a991-1f7ddfd0ee56": {"jobId": "67480820-6c57-4fd5-a991-1f7ddfd0ee56", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.167290Z", "updated": "2026-02-23T22:04:09.171405Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "fb84e869-28c5-4187-b963-62a0f0ddb0d0": {"jobId": "fb84e869-28c5-4187-b963-62a0f0ddb0d0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.286819Z", "updated": "2026-02-23T22:04:09.286819Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "5d9f7eba-2303-4efa-aa2c-30f93fc6971a": {"jobId": "5d9f7eba-2303-4efa-aa2c-30f93fc6971a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.471642Z", "updated": "2026-02-23T22:04:09.471642Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "697f0d2d-d86a-4bfe-8dac-aa80a6b5df7f": {"jobId": "697f0d2d-d86a-4bfe-8dac-aa80a6b5df7f", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:04:09.691847Z", "updated": "2026-02-23T22:04:09.691847Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "bab696ee-5483-4c82-bf44-e457c5f0ea69": {"jobId": "bab696ee-5483-4c82-bf44-e457c5f0ea69", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:23.547932Z", "updated": "2026-02-23T22:05:23.547932Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "370b5752-bb53-44e5-b373-96d014ead43f": {"jobId": "370b5752-bb53-44e5-b373-96d014ead43f", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:23.564772Z", "updated": "2026-02-23T22:05:23.564772Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "d9d78be7-a46e-4236-a815-f65e42cab9fe": {"jobId": "d9d78be7-a46e-4236-a815-f65e42cab9fe", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.819681Z", "updated": "2026-02-23T22:05:25.819681Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "d9248c76-d0b1-4107-8739-d26e01dd859c": {"jobId": "d9248c76-d0b1-4107-8739-d26e01dd859c", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.835593Z", "updated": "2026-02-23T22:05:25.835593Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "23ee0b0c-c1f0-4be4-83d3-c82e8fe98ae7": {"jobId": "23ee0b0c-c1f0-4be4-83d3-c82e8fe98ae7", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:25.939376Z", "updated": "2026-02-23T22:05:25.939376Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "48b4c768-bbaf-47a8-aeb7-44e697067cb9": {"jobId": "48b4c768-bbaf-47a8-aeb7-44e697067cb9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.102926Z", "updated": "2026-02-23T22:05:26.102926Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "052828cb-fe04-4107-8168-bf626dc3d2d4": {"jobId": "052828cb-fe04-4107-8168-bf626dc3d2d4", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.213041Z", "updated": "2026-02-23T22:05:26.213041Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "057a6900-c6e4-4ee7-b392-16cc852a7beb": {"jobId": "057a6900-c6e4-4ee7-b392-16cc852a7beb", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:05:26.244912Z", "updated": "2026-02-23T22:05:26.249375Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "f07f0036-8f43-4d12-8811-7a3e6603228b": {"jobId": "f07f0036-8f43-4d12-8811-7a3e6603228b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.260482Z", "updated": "2026-02-23T22:05:26.265682Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff": {"jobId": "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.380473Z", "updated": "2026-02-23T22:05:26.380473Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b232896b-2721-46b8-abc8-9761a40f9d22": {"jobId": "b232896b-2721-46b8-abc8-9761a40f9d22", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.527434Z", "updated": "2026-02-23T22:05:26.527434Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1f2bf79d-8181-490d-a45e-9438e38b45c6": {"jobId": "1f2bf79d-8181-490d-a45e-9438e38b45c6", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:05:26.742199Z", "updated": "2026-02-23T22:05:26.742199Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "6df02f8b-df42-41dd-b987-a06dbeaf5539": {"jobId": "6df02f8b-df42-41dd-b987-a06dbeaf5539", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:17.263363Z", "updated": "2026-02-23T22:06:17.263363Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8ea3e465-f7a8-4b71-8375-38f65fcf63ca": {"jobId": "8ea3e465-f7a8-4b71-8375-38f65fcf63ca", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:17.295123Z", "updated": "2026-02-23T22:06:17.295123Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "444c5c43-cbdd-409f-b180-e8b339f8ef11": {"jobId": "444c5c43-cbdd-409f-b180-e8b339f8ef11", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.520179Z", "updated": "2026-02-23T22:06:19.520179Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "ebc38efc-530c-444c-bb0f-a9b22912944c": {"jobId": "ebc38efc-530c-444c-bb0f-a9b22912944c", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.536100Z", "updated": "2026-02-23T22:06:19.536100Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "973f8a9e-f220-436f-91b2-6507e96b615a": {"jobId": "973f8a9e-f220-436f-91b2-6507e96b615a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.666645Z", "updated": "2026-02-23T22:06:19.666645Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ab19876c-d13d-4c37-82f5-af575b863ae9": {"jobId": "ab19876c-d13d-4c37-82f5-af575b863ae9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.795408Z", "updated": "2026-02-23T22:06:19.795408Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bb27b64c-2cda-41ab-8e2b-b23ff462de71": {"jobId": "bb27b64c-2cda-41ab-8e2b-b23ff462de71", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.907708Z", "updated": "2026-02-23T22:06:19.907708Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d0cd71f3-2aff-4345-8804-6451bd9d78bd": {"jobId": "d0cd71f3-2aff-4345-8804-6451bd9d78bd", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:06:19.940310Z", "updated": "2026-02-23T22:06:19.945539Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "4c120e2c-3b8e-471c-a944-d4fe46e6544d": {"jobId": "4c120e2c-3b8e-471c-a944-d4fe46e6544d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:19.965760Z", "updated": "2026-02-23T22:06:19.972003Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "a0138e99-87f4-4213-b003-53e4435d2191": {"jobId": "a0138e99-87f4-4213-b003-53e4435d2191", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.085244Z", "updated": "2026-02-23T22:06:20.085244Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "67ffa0a9-35fe-4780-b5e7-17cebd8321c3": {"jobId": "67ffa0a9-35fe-4780-b5e7-17cebd8321c3", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.234581Z", "updated": "2026-02-23T22:06:20.234581Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1640da1c-e8fe-4aaf-b8d6-5f4441a05f4d": {"jobId": "1640da1c-e8fe-4aaf-b8d6-5f4441a05f4d", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:06:20.456531Z", "updated": "2026-02-23T22:06:20.456531Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "1bea47ea-b78c-4c37-ad4a-4bc4731dc493": {"jobId": "1bea47ea-b78c-4c37-ad4a-4bc4731dc493", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:07.539027Z", "updated": "2026-02-23T22:07:07.539027Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1277fe9e-4a99-4014-8c55-66804e616440": {"jobId": "1277fe9e-4a99-4014-8c55-66804e616440", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:07.558215Z", "updated": "2026-02-23T22:07:07.558215Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "267b8300-765d-40e3-9ec2-5d6478f47892": {"jobId": "267b8300-765d-40e3-9ec2-5d6478f47892", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.804460Z", "updated": "2026-02-23T22:07:09.804460Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "cdefce12-bd1d-4828-a27d-0960d104c6fa": {"jobId": "cdefce12-bd1d-4828-a27d-0960d104c6fa", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.821632Z", "updated": "2026-02-23T22:07:09.821632Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "092d45de-2992-4688-9eea-5e47bef48651": {"jobId": "092d45de-2992-4688-9eea-5e47bef48651", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:09.928469Z", "updated": "2026-02-23T22:07:09.928469Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "55481550-c20d-404f-888b-972569e1a21d": {"jobId": "55481550-c20d-404f-888b-972569e1a21d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.096984Z", "updated": "2026-02-23T22:07:10.096984Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "db8c46c0-4252-4091-89b6-7bcac3da7ab2": {"jobId": "db8c46c0-4252-4091-89b6-7bcac3da7ab2", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.207616Z", "updated": "2026-02-23T22:07:10.207616Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "36ad61d8-3b1a-4fa3-bc58-b801c12e6980": {"jobId": "36ad61d8-3b1a-4fa3-bc58-b801c12e6980", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:07:10.241678Z", "updated": "2026-02-23T22:07:10.247863Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "7c89eaf6-cad3-42bf-82b7-0159b289ab4d": {"jobId": "7c89eaf6-cad3-42bf-82b7-0159b289ab4d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.260512Z", "updated": "2026-02-23T22:07:10.267134Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "07711cbe-a49b-43ec-b9f5-a47ff809a637": {"jobId": "07711cbe-a49b-43ec-b9f5-a47ff809a637", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.381958Z", "updated": "2026-02-23T22:07:10.381958Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b60ed6da-a124-49f0-a4ac-d52c8d79cb70": {"jobId": "b60ed6da-a124-49f0-a4ac-d52c8d79cb70", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.534954Z", "updated": "2026-02-23T22:07:10.534954Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b7198527-3cd1-4105-ad05-e96e3eb2dc0b": {"jobId": "b7198527-3cd1-4105-ad05-e96e3eb2dc0b", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:07:10.756754Z", "updated": "2026-02-23T22:07:10.756754Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "8c44185b-b5d3-48be-9786-fd8949a4eec0": {"jobId": "8c44185b-b5d3-48be-9786-fd8949a4eec0", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:23.056931Z", "updated": "2026-02-23T22:08:23.056931Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "159d008c-2cbe-43dc-9da0-d476df8f8912": {"jobId": "159d008c-2cbe-43dc-9da0-d476df8f8912", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:23.078203Z", "updated": "2026-02-23T22:08:23.078203Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "4fefa042-d0f2-40d5-878e-65410620d408": {"jobId": "4fefa042-d0f2-40d5-878e-65410620d408", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.348486Z", "updated": "2026-02-23T22:08:25.348486Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "a47f73c7-ce37-48c9-af73-11760b35e296": {"jobId": "a47f73c7-ce37-48c9-af73-11760b35e296", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.366760Z", "updated": "2026-02-23T22:08:25.366760Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "9be31308-883e-4f46-927f-8faf8a43795d": {"jobId": "9be31308-883e-4f46-927f-8faf8a43795d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.476319Z", "updated": "2026-02-23T22:08:25.476319Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b10443b2-5b5c-4a8a-9d3d-7fba142e87c8": {"jobId": "b10443b2-5b5c-4a8a-9d3d-7fba142e87c8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.648456Z", "updated": "2026-02-23T22:08:25.648456Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1df779b8-aa1c-439f-a5d7-3525fb54dc77": {"jobId": "1df779b8-aa1c-439f-a5d7-3525fb54dc77", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.758845Z", "updated": "2026-02-23T22:08:25.758845Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33": {"jobId": "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:08:25.793139Z", "updated": "2026-02-23T22:08:25.800459Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "2da98086-c89d-49cb-bac4-5a2f63c02d3b": {"jobId": "2da98086-c89d-49cb-bac4-5a2f63c02d3b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.814740Z", "updated": "2026-02-23T22:08:25.822762Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "e3f2a3ef-efb8-4a71-a892-437463f84e13": {"jobId": "e3f2a3ef-efb8-4a71-a892-437463f84e13", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:25.940926Z", "updated": "2026-02-23T22:08:25.940926Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c8e8832f-a05e-4ae1-89bc-418391552a31": {"jobId": "c8e8832f-a05e-4ae1-89bc-418391552a31", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:26.094254Z", "updated": "2026-02-23T22:08:26.094254Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "3491be0a-69f9-4f9a-924c-79fbcb7404a5": {"jobId": "3491be0a-69f9-4f9a-924c-79fbcb7404a5", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:08:26.312951Z", "updated": "2026-02-23T22:08:26.312951Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "b78a5896-d88d-4592-bc98-36dd20426679": {"jobId": "b78a5896-d88d-4592-bc98-36dd20426679", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:08.677668Z", "updated": "2026-02-23T22:10:08.677668Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c842962b-c87d-4787-bbed-499da0a0e659": {"jobId": "c842962b-c87d-4787-bbed-499da0a0e659", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:08.698047Z", "updated": "2026-02-23T22:10:08.698047Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "9ffc08f6-24de-4744-9f55-5416c269c284": {"jobId": "9ffc08f6-24de-4744-9f55-5416c269c284", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:10.975367Z", "updated": "2026-02-23T22:10:10.975367Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "33140241-39cf-4963-9a9f-c4068665dbdb": {"jobId": "33140241-39cf-4963-9a9f-c4068665dbdb", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:10.995315Z", "updated": "2026-02-23T22:10:10.995315Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "51621767-7943-48df-a074-9f29f6c2374d": {"jobId": "51621767-7943-48df-a074-9f29f6c2374d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.106175Z", "updated": "2026-02-23T22:10:11.106175Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d3119749-3e84-489c-b36c-de752ff0f44f": {"jobId": "d3119749-3e84-489c-b36c-de752ff0f44f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.269887Z", "updated": "2026-02-23T22:10:11.269887Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "48cc3a56-6df8-42b6-a1cd-ab380a687d17": {"jobId": "48cc3a56-6df8-42b6-a1cd-ab380a687d17", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.379628Z", "updated": "2026-02-23T22:10:11.379628Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "672705fa-17df-48d3-9dfe-89edd3033977": {"jobId": "672705fa-17df-48d3-9dfe-89edd3033977", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:10:11.415532Z", "updated": "2026-02-23T22:10:11.423246Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "62523329-5a27-4557-ae52-b3a3668cf8b9": {"jobId": "62523329-5a27-4557-ae52-b3a3668cf8b9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.438093Z", "updated": "2026-02-23T22:10:11.447351Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "3bc40154-66d2-44b8-bf8a-3c931d7ce92a": {"jobId": "3bc40154-66d2-44b8-bf8a-3c931d7ce92a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.565043Z", "updated": "2026-02-23T22:10:11.565043Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "aa3f467e-d50a-4120-b9b0-0e2d121f169e": {"jobId": "aa3f467e-d50a-4120-b9b0-0e2d121f169e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.717150Z", "updated": "2026-02-23T22:10:11.717150Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "d59d5ce4-e5a1-4087-91df-f5f957b056ef": {"jobId": "d59d5ce4-e5a1-4087-91df-f5f957b056ef", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:10:11.933145Z", "updated": "2026-02-23T22:10:11.933145Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "277592bc-6939-4806-af05-87c7bf533d5f": {"jobId": "277592bc-6939-4806-af05-87c7bf533d5f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:24.503021Z", "updated": "2026-02-23T22:12:24.503021Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7006c679-b227-4022-9c35-3e2cfc85b0f4": {"jobId": "7006c679-b227-4022-9c35-3e2cfc85b0f4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:24.525639Z", "updated": "2026-02-23T22:12:24.525639Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "8b551dab-da4c-49ad-99ad-beafe80eebb1": {"jobId": "8b551dab-da4c-49ad-99ad-beafe80eebb1", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:26.896434Z", "updated": "2026-02-23T22:12:26.896434Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "a771c412-cd8d-481f-86c5-60973c502cf2": {"jobId": "a771c412-cd8d-481f-86c5-60973c502cf2", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:26.917174Z", "updated": "2026-02-23T22:12:26.917174Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "895fa56d-a56a-45a0-bcac-1ba7cb072f9d": {"jobId": "895fa56d-a56a-45a0-bcac-1ba7cb072f9d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.031192Z", "updated": "2026-02-23T22:12:27.031192Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "b878b07e-4d0c-4452-8ad0-b7d2e014b415": {"jobId": "b878b07e-4d0c-4452-8ad0-b7d2e014b415", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.214706Z", "updated": "2026-02-23T22:12:27.214706Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4c59c2e2-a55c-475e-8f49-8060b0070c15": {"jobId": "4c59c2e2-a55c-475e-8f49-8060b0070c15", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.331969Z", "updated": "2026-02-23T22:12:27.331969Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "743ddcec-4c43-49cf-a3d7-a79fd07d203c": {"jobId": "743ddcec-4c43-49cf-a3d7-a79fd07d203c", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:12:27.370127Z", "updated": "2026-02-23T22:12:27.378919Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "048b97d2-321b-412b-8add-8bfc73947d10": {"jobId": "048b97d2-321b-412b-8add-8bfc73947d10", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.395188Z", "updated": "2026-02-23T22:12:27.405120Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "faaa0822-0996-42aa-9b4a-09db3b38b253": {"jobId": "faaa0822-0996-42aa-9b4a-09db3b38b253", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.528860Z", "updated": "2026-02-23T22:12:27.528860Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2f62167a-3bab-496e-b408-f1078f023253": {"jobId": "2f62167a-3bab-496e-b408-f1078f023253", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.680510Z", "updated": "2026-02-23T22:12:27.680510Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c60578bb-1943-4a06-ba54-ef1f73aa7a31": {"jobId": "c60578bb-1943-4a06-ba54-ef1f73aa7a31", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:12:27.896422Z", "updated": "2026-02-23T22:12:27.896422Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "ddd7182d-c5e7-4708-9d27-6c44c59101e6": {"jobId": "ddd7182d-c5e7-4708-9d27-6c44c59101e6", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:52.476895Z", "updated": "2026-02-23T22:13:52.476895Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "dce96d73-0dd2-433a-ab9f-50708fd76735": {"jobId": "dce96d73-0dd2-433a-ab9f-50708fd76735", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:52.499440Z", "updated": "2026-02-23T22:13:52.499440Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "efadd460-9f5d-40e6-b6d2-7f962b324388": {"jobId": "efadd460-9f5d-40e6-b6d2-7f962b324388", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.763632Z", "updated": "2026-02-23T22:13:54.763632Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "9cf3a3f0-f611-41c1-9deb-94268951ce28": {"jobId": "9cf3a3f0-f611-41c1-9deb-94268951ce28", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.785857Z", "updated": "2026-02-23T22:13:54.785857Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "245ec5ef-e750-45ae-8a6e-4b05fd695da7": {"jobId": "245ec5ef-e750-45ae-8a6e-4b05fd695da7", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:54.893765Z", "updated": "2026-02-23T22:13:54.893765Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "dc3129a8-db7b-4354-bcb5-3beb9df098af": {"jobId": "dc3129a8-db7b-4354-bcb5-3beb9df098af", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.067514Z", "updated": "2026-02-23T22:13:55.067514Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "421d8036-8bb8-4d19-8ab2-16b12114c03f": {"jobId": "421d8036-8bb8-4d19-8ab2-16b12114c03f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.183339Z", "updated": "2026-02-23T22:13:55.183339Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "1f0946fe-d7cf-4ff5-ae38-ea332be556f8": {"jobId": "1f0946fe-d7cf-4ff5-ae38-ea332be556f8", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:13:55.221492Z", "updated": "2026-02-23T22:13:55.231516Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "d407d400-5ed4-4dee-9d95-749ef70bfa2d": {"jobId": "d407d400-5ed4-4dee-9d95-749ef70bfa2d", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.247933Z", "updated": "2026-02-23T22:13:55.258441Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "89f1748d-a2ff-4fb4-bad4-034af929932e": {"jobId": "89f1748d-a2ff-4fb4-bad4-034af929932e", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.373387Z", "updated": "2026-02-23T22:13:55.373387Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fef322d8-8a06-4091-b962-2f6f616cbb71": {"jobId": "fef322d8-8a06-4091-b962-2f6f616cbb71", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.536523Z", "updated": "2026-02-23T22:13:55.536523Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "200b0ab7-b566-4c98-9639-9c019adc4af5": {"jobId": "200b0ab7-b566-4c98-9639-9c019adc4af5", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:13:55.767251Z", "updated": "2026-02-23T22:13:55.767251Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "9de477f4-e0ab-44c3-8b0d-a785df5ace6b": {"jobId": "9de477f4-e0ab-44c3-8b0d-a785df5ace6b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:37.450246Z", "updated": "2026-02-23T22:15:37.450246Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2716eab1-7e96-4ecc-a47b-b12890300ed0": {"jobId": "2716eab1-7e96-4ecc-a47b-b12890300ed0", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:37.473495Z", "updated": "2026-02-23T22:15:37.473495Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "affe6d5d-97ce-4762-b4dc-18a8c62bd933": {"jobId": "affe6d5d-97ce-4762-b4dc-18a8c62bd933", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.721512Z", "updated": "2026-02-23T22:15:39.721512Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "5d6a4802-d6fc-4e15-be23-cb55cd6d43fa": {"jobId": "5d6a4802-d6fc-4e15-be23-cb55cd6d43fa", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.743320Z", "updated": "2026-02-23T22:15:39.743320Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "881249ed-7649-49a0-a8d2-ea5d453387b2": {"jobId": "881249ed-7649-49a0-a8d2-ea5d453387b2", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:39.852155Z", "updated": "2026-02-23T22:15:39.852155Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "09078395-6734-4aa0-804d-342d533f5a08": {"jobId": "09078395-6734-4aa0-804d-342d533f5a08", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.016212Z", "updated": "2026-02-23T22:15:40.016212Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "ac76a665-136a-4730-9228-dceb0a828f85": {"jobId": "ac76a665-136a-4730-9228-dceb0a828f85", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.130039Z", "updated": "2026-02-23T22:15:40.130039Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "101a1fa5-3a6b-4923-8b3d-08497fc2cde3": {"jobId": "101a1fa5-3a6b-4923-8b3d-08497fc2cde3", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:15:40.171547Z", "updated": "2026-02-23T22:15:40.182169Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "90649d63-8edc-4d9e-aac5-1b3a6fd2f954": {"jobId": "90649d63-8edc-4d9e-aac5-1b3a6fd2f954", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.200090Z", "updated": "2026-02-23T22:15:40.211787Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b": {"jobId": "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.332893Z", "updated": "2026-02-23T22:15:40.332893Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "e3dee3c1-f3d9-4340-a412-48964442a29b": {"jobId": "e3dee3c1-f3d9-4340-a412-48964442a29b", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.497073Z", "updated": "2026-02-23T22:15:40.497073Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "a44b6fc3-3b43-4b6c-ac09-4c2bbd973e37": {"jobId": "a44b6fc3-3b43-4b6c-ac09-4c2bbd973e37", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:15:40.733179Z", "updated": "2026-02-23T22:15:40.733179Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "c102da24-1bac-4567-af7f-39a0eff270f4": {"jobId": "c102da24-1bac-4567-af7f-39a0eff270f4", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:53.998689Z", "updated": "2026-02-23T22:16:53.998689Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "7b2b7e4b-b1c1-45d7-a382-78b3f72cb077": {"jobId": "7b2b7e4b-b1c1-45d7-a382-78b3f72cb077", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:54.024575Z", "updated": "2026-02-23T22:16:54.024575Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "1a8a2412-5b27-40da-a8f0-94f680e026b4": {"jobId": "1a8a2412-5b27-40da-a8f0-94f680e026b4", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.296999Z", "updated": "2026-02-23T22:16:56.296999Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "ec28d8a2-6234-471f-b96f-7c1731d18a0f": {"jobId": "ec28d8a2-6234-471f-b96f-7c1731d18a0f", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.320203Z", "updated": "2026-02-23T22:16:56.320203Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "0dc16554-7eaf-497c-9a1e-4efc286ba872": {"jobId": "0dc16554-7eaf-497c-9a1e-4efc286ba872", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.432278Z", "updated": "2026-02-23T22:16:56.432278Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8e276ac9-189f-432d-adec-b7ab74ea6590": {"jobId": "8e276ac9-189f-432d-adec-b7ab74ea6590", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.602095Z", "updated": "2026-02-23T22:16:56.602095Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9": {"jobId": "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.720377Z", "updated": "2026-02-23T22:16:56.720377Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4e30a788-c134-463a-bdbb-f88b4b5615c9": {"jobId": "4e30a788-c134-463a-bdbb-f88b4b5615c9", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:16:56.760958Z", "updated": "2026-02-23T22:16:56.772441Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "336d659f-b4f7-4a49-a7d0-a5ec78dc25d8": {"jobId": "336d659f-b4f7-4a49-a7d0-a5ec78dc25d8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.791195Z", "updated": "2026-02-23T22:16:56.803752Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "9a34fb59-d815-4107-9c6b-d3207704d83a": {"jobId": "9a34fb59-d815-4107-9c6b-d3207704d83a", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:56.926163Z", "updated": "2026-02-23T22:16:56.926163Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "56c4347f-b16f-40db-9f64-b0239711faac": {"jobId": "56c4347f-b16f-40db-9f64-b0239711faac", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:57.053777Z", "updated": "2026-02-23T22:16:57.053777Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "fbe518c3-121e-4097-8a28-322ddee317e7": {"jobId": "fbe518c3-121e-4097-8a28-322ddee317e7", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:16:57.304091Z", "updated": "2026-02-23T22:16:57.304091Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "cba3a8e8-2dd3-48c3-ad24-822320428aef": {"jobId": "cba3a8e8-2dd3-48c3-ad24-822320428aef", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:06.883459Z", "updated": "2026-02-23T22:18:06.883459Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "40e9fb81-f7f8-48c9-a83c-bf1ce068c960": {"jobId": "40e9fb81-f7f8-48c9-a83c-bf1ce068c960", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:06.910504Z", "updated": "2026-02-23T22:18:06.910504Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "33ff2a20-5a20-4bf0-a70c-dda4f52753e3": {"jobId": "33ff2a20-5a20-4bf0-a70c-dda4f52753e3", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.164136Z", "updated": "2026-02-23T22:18:09.164136Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "798f2a1a-3d44-4778-9552-5eef336a799e": {"jobId": "798f2a1a-3d44-4778-9552-5eef336a799e", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.186896Z", "updated": "2026-02-23T22:18:09.186896Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "426ebad3-da3e-4748-93c0-f7286de43ce8": {"jobId": "426ebad3-da3e-4748-93c0-f7286de43ce8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.295646Z", "updated": "2026-02-23T22:18:09.295646Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "4eb5c271-dee4-4f16-9740-141f3ac0e5fa": {"jobId": "4eb5c271-dee4-4f16-9740-141f3ac0e5fa", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.470972Z", "updated": "2026-02-23T22:18:09.470972Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "bef54659-7bfc-4c67-b172-1722edcea9cb": {"jobId": "bef54659-7bfc-4c67-b172-1722edcea9cb", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.590918Z", "updated": "2026-02-23T22:18:09.590918Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "2ad476b8-a2a6-4783-948e-42087f50a7e4": {"jobId": "2ad476b8-a2a6-4783-948e-42087f50a7e4", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-23T22:18:09.635442Z", "updated": "2026-02-23T22:18:09.647649Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "81cfc65f-344c-43da-a0ac-d002ec25c0ed": {"jobId": "81cfc65f-344c-43da-a0ac-d002ec25c0ed", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.667508Z", "updated": "2026-02-23T22:18:09.680422Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "50f69ac8-ca39-4892-bf3c-2921221183b8": {"jobId": "50f69ac8-ca39-4892-bf3c-2921221183b8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.799866Z", "updated": "2026-02-23T22:18:09.799866Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "503e7d84-be48-4fa8-a809-ce44b23325ab": {"jobId": "503e7d84-be48-4fa8-a809-ce44b23325ab", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:09.925723Z", "updated": "2026-02-23T22:18:09.925723Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "c0e21843-e0a2-42a1-806f-faf8b325ab93": {"jobId": "c0e21843-e0a2-42a1-806f-faf8b325ab93", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-23T22:18:10.182289Z", "updated": "2026-02-23T22:18:10.182289Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}, "7f5e71ec-f2ef-48f4-96ee-8fbc321e746c": {"jobId": "7f5e71ec-f2ef-48f4-96ee-8fbc321e746c", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:13.899162Z", "updated": "2026-02-24T11:01:13.899162Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "744622fe-029a-40f3-8da0-72ca67a1b965": {"jobId": "744622fe-029a-40f3-8da0-72ca67a1b965", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:13.927623Z", "updated": "2026-02-24T11:01:13.927623Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 1, "deleted": 0, "dryRun": true}, "features": [{"type": "Feature", "id": "org-demo", "geometry": {"type": "Point", "coordinates": [0.0, 0.0]}, "properties": {"orgUnit": "org-demo", "value": 4.0}}]}}, "cbcb748c-e2d3-41c8-802c-7fbe6f071ffe": {"jobId": "cbcb748c-e2d3-41c8-802c-7fbe6f071ffe", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:16.564177Z", "updated": "2026-02-24T11:01:16.564177Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 31.0}}]}}, "53534dbe-524f-4057-b501-7aeff92d944e": {"jobId": "53534dbe-524f-4057-b501-7aeff92d944e", "processId": "xclim-warm-days", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:16.587969Z", "updated": "2026-02-24T11:01:16.587969Z", "inputs": {"datasetId": "era5-land-daily", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 35.0, "unit": "degC"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 0.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "era5-land-daily", "indicator": "xclim-warm-days", "parameter": "2m_temperature", "start": "2026-01-01", "end": "2026-01-31", "source": "synthetic-fallback", "threshold": {"value": 35.0, "unit": "degC"}, "value": 3.0}}]}}, "71c380af-7721-47fe-93fc-34a941e09c7f": {"jobId": "71c380af-7721-47fe-93fc-34a941e09c7f", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:16.697073Z", "updated": "2026-02-24T11:01:16.697073Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": false}}, "outputs": {"importSummary": {"imported": 3, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": false, "source": "dhis2"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "91cbfa60-81bf-4151-b6bd-41cfaf45dde1": {"jobId": "91cbfa60-81bf-4151-b6bd-41cfaf45dde1", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:16.873542Z", "updated": "2026-02-24T11:01:16.873542Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8da9f4b3-3858-43ff-a0f4-c9e4c16cc4c6": {"jobId": "8da9f4b3-3858-43ff-a0f4-c9e4c16cc4c6", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:16.997135Z", "updated": "2026-02-24T11:01:16.997135Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "8e3f5696-b9e8-4f4b-ad89-8db4d6e5831e": {"jobId": "8e3f5696-b9e8-4f4b-ad89-8db4d6e5831e", "processId": "eo-aggregate-import", "status": "queued", "progress": 0, "created": "2026-02-24T11:01:17.043907Z", "updated": "2026-02-24T11:01:17.057770Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-1"}}, "df874e3d-9622-4597-9bb4-fd450c7a18a8": {"jobId": "df874e3d-9622-4597-9bb4-fd450c7a18a8", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:17.079347Z", "updated": "2026-02-24T11:01:17.093680Z", "inputs": {"dhis2": {"dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 0, "deleted": 0, "dryRun": true}, "features": []}, "execution": {"source": "prefect", "flowRunId": "flow-run-2", "state": {"type": "COMPLETED", "name": "Completed"}}}, "30fe9414-3c22-4ec1-bad6-19a2890bfaf2": {"jobId": "30fe9414-3c22-4ec1-bad6-19a2890bfaf2", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:17.214544Z", "updated": "2026-02-24T11:01:17.214544Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "855c697c-e377-44d9-b1d2-889a26d0b345": {"jobId": "855c697c-e377-44d9-b1d2-889a26d0b345", "processId": "eo-aggregate-import", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:17.339216Z", "updated": "2026-02-24T11:01:17.339216Z", "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2086}}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.1105}}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "datetime": "2026-01-31T00:00:00Z", "aggregation": "mean", "source": "dhis2eo", "values": {"precip": 0.2383}}}]}}, "59d70a5a-1a33-47e4-9ef6-1abfe715be46": {"jobId": "59d70a5a-1a33-47e4-9ef6-1abfe715be46", "processId": "xclim-cdd", "status": "succeeded", "progress": 100, "created": "2026-02-24T11:01:17.604881Z", "updated": "2026-02-24T11:01:17.604881Z", "inputs": {"datasetId": "chirps-daily", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "orgUnitLevel": 2, "threshold": {"value": 1.0, "unit": "mm/day"}, "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "outputs": {"importSummary": {"imported": 0, "updated": 0, "ignored": 3, "deleted": 0, "dryRun": true, "source": "dry-run"}, "features": [{"type": "Feature", "id": "O6uvpzGd5pu", "geometry": {"type": "Polygon", "coordinates": [[[-11.64, 8.42], [-11.5, 8.42], [-11.5, 8.55], [-11.64, 8.55], [-11.64, 8.42]]]}, "properties": {"orgUnit": "O6uvpzGd5pu", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}, {"type": "Feature", "id": "fdc6uOvgoji", "geometry": {"type": "Polygon", "coordinates": [[[-13.3, 8.8], [-13.1, 8.8], [-13.1, 9.0], [-13.3, 9.0], [-13.3, 8.8]]]}, "properties": {"orgUnit": "fdc6uOvgoji", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 13.0}}, {"type": "Feature", "id": "lc3eMKXaEfw", "geometry": {"type": "Polygon", "coordinates": [[[-12.4, 7.0], [-12.1, 7.0], [-12.1, 7.25], [-12.4, 7.25], [-12.4, 7.0]]]}, "properties": {"orgUnit": "lc3eMKXaEfw", "datasetId": "chirps-daily", "indicator": "xclim-cdd", "parameter": "precip", "start": "2026-01-01", "end": "2026-01-31", "source": "dhis2eo", "threshold": {"value": 1.0, "unit": "mm/day"}, "value": 26.0}}]}}} \ No newline at end of file diff --git a/.cache/state/schedules.json b/.cache/state/schedules.json index 2e2e561..e984f0a 100644 --- a/.cache/state/schedules.json +++ b/.cache/state/schedules.json @@ -1 +1 @@ -{"5cfbf7d5-2c31-493e-aa81-ceb20d13db0e": {"scheduleId": "5cfbf7d5-2c31-493e-aa81-ceb20d13db0e", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.631345Z", "updated": "2026-02-23T21:59:01.633759Z", "lastRunAt": "2026-02-23T21:59:01.633759Z", "lastRunJobId": "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d"}, "b19d087c-73de-4421-88d5-9bc6c29d166b": {"scheduleId": "b19d087c-73de-4421-88d5-9bc6c29d166b", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.640858Z", "updated": "2026-02-23T21:59:01.640858Z", "lastRunAt": null, "lastRunJobId": null}, "195d2328-245f-4573-8e5c-a0d18bb6e027": {"scheduleId": "195d2328-245f-4573-8e5c-a0d18bb6e027", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.648433Z", "updated": "2026-02-23T21:59:01.648433Z", "lastRunAt": null, "lastRunJobId": null}, "0c2f0ab1-d72f-4a85-b0bb-1806c151de48": {"scheduleId": "0c2f0ab1-d72f-4a85-b0bb-1806c151de48", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.655548Z", "updated": "2026-02-23T21:59:01.658990Z", "lastRunAt": "2026-02-23T21:59:01.658990Z", "lastRunJobId": "9ed82292-1c23-4a6f-8077-561c8d431e5a"}, "4daf8538-91de-43c1-ab4f-717d5390230a": {"scheduleId": "4daf8538-91de-43c1-ab4f-717d5390230a", "processId": "workflow", "workflowId": "70a148c9-4c30-4ff4-bdc1-d793853cca5b", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T21:59:01.676128Z", "updated": "2026-02-23T21:59:01.679007Z", "lastRunAt": "2026-02-23T21:59:01.679007Z", "lastRunJobId": "8337900a-0fc6-4f53-a13e-89540fb03d2e"}, "287ad6fc-135a-427b-8c6e-68bedf3a0434": {"scheduleId": "287ad6fc-135a-427b-8c6e-68bedf3a0434", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.254541Z", "updated": "2026-02-23T22:03:01.349695Z", "lastRunAt": "2026-02-23T22:03:01.349695Z", "lastRunJobId": "8ae1afa0-88d9-493a-89e7-d118c6651e43"}, "85e67015-5094-4cee-9ff7-5b25276d71d4": {"scheduleId": "85e67015-5094-4cee-9ff7-5b25276d71d4", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.357868Z", "updated": "2026-02-23T22:03:01.357868Z", "lastRunAt": null, "lastRunJobId": null}, "522c7ff1-709f-487a-b6e7-8e3c258f8b3e": {"scheduleId": "522c7ff1-709f-487a-b6e7-8e3c258f8b3e", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.366100Z", "updated": "2026-02-23T22:03:01.366100Z", "lastRunAt": null, "lastRunJobId": null}, "ccad9e3e-cfd3-4ca2-8d82-9ab18dc746d2": {"scheduleId": "ccad9e3e-cfd3-4ca2-8d82-9ab18dc746d2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.373832Z", "updated": "2026-02-23T22:03:01.379077Z", "lastRunAt": "2026-02-23T22:03:01.379077Z", "lastRunJobId": "fef7a2ef-eda6-42b0-a95d-da21341ab899"}, "26a09350-cc9a-4070-b44c-35a9290d3382": {"scheduleId": "26a09350-cc9a-4070-b44c-35a9290d3382", "processId": "workflow", "workflowId": "5919d4fa-644f-4ffc-8541-d258e987b379", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:03:01.400343Z", "updated": "2026-02-23T22:03:01.504385Z", "lastRunAt": "2026-02-23T22:03:01.504385Z", "lastRunJobId": "d42e8fc4-1023-453c-9aae-8c33141ca838"}, "e002f589-33e2-4689-ab75-55ad752772aa": {"scheduleId": "e002f589-33e2-4689-ab75-55ad752772aa", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.709891Z", "updated": "2026-02-23T22:03:34.808021Z", "lastRunAt": "2026-02-23T22:03:34.808021Z", "lastRunJobId": "5d45d9ce-795c-4615-b973-33cc358c1327"}, "4d02c489-5f53-4ee8-a340-f287e39e8dda": {"scheduleId": "4d02c489-5f53-4ee8-a340-f287e39e8dda", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.816852Z", "updated": "2026-02-23T22:03:34.816852Z", "lastRunAt": null, "lastRunJobId": null}, "b307747d-4327-4a51-9d58-f8b54b25fe38": {"scheduleId": "b307747d-4327-4a51-9d58-f8b54b25fe38", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.824292Z", "updated": "2026-02-23T22:03:34.824292Z", "lastRunAt": null, "lastRunJobId": null}, "2ee41b9f-753d-449b-ae0c-cb6dc0c4a4bd": {"scheduleId": "2ee41b9f-753d-449b-ae0c-cb6dc0c4a4bd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.831948Z", "updated": "2026-02-23T22:03:34.839113Z", "lastRunAt": "2026-02-23T22:03:34.839113Z", "lastRunJobId": "4c2dae6b-dbff-4591-91ca-5a679a4cd52f"}, "8f76daef-6165-483f-8254-a4b61c506d8c": {"scheduleId": "8f76daef-6165-483f-8254-a4b61c506d8c", "processId": "workflow", "workflowId": "90ee914e-925d-4775-bbdb-8489f79e6b2d", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:03:34.860159Z", "updated": "2026-02-23T22:03:34.964368Z", "lastRunAt": "2026-02-23T22:03:34.964368Z", "lastRunJobId": "d6098fe4-5916-4d3b-b540-de1076f51c8d"}, "2adddf18-8041-4049-91ca-e82706bb4bd5": {"scheduleId": "2adddf18-8041-4049-91ca-e82706bb4bd5", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.025807Z", "updated": "2026-02-23T22:04:09.126220Z", "lastRunAt": "2026-02-23T22:04:09.126220Z", "lastRunJobId": "5f68bea6-8dd8-421e-98d7-0cc70d496462"}, "4ced4308-4f5c-4c9d-8ee0-7bf0fdbebe7d": {"scheduleId": "4ced4308-4f5c-4c9d-8ee0-7bf0fdbebe7d", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.135097Z", "updated": "2026-02-23T22:04:09.135097Z", "lastRunAt": null, "lastRunJobId": null}, "c0109e78-5124-4a5c-9ebd-f715c0d63e10": {"scheduleId": "c0109e78-5124-4a5c-9ebd-f715c0d63e10", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.143459Z", "updated": "2026-02-23T22:04:09.143459Z", "lastRunAt": null, "lastRunJobId": null}, "e9be5417-17c2-4335-8e16-696ef8554757": {"scheduleId": "e9be5417-17c2-4335-8e16-696ef8554757", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.151811Z", "updated": "2026-02-23T22:04:09.160932Z", "lastRunAt": "2026-02-23T22:04:09.160932Z", "lastRunJobId": "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4"}, "d1f00049-3f7b-4f65-bab9-4af6b547f867": {"scheduleId": "d1f00049-3f7b-4f65-bab9-4af6b547f867", "processId": "workflow", "workflowId": "364063da-5825-4303-9736-51baf8692530", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:04:09.183145Z", "updated": "2026-02-23T22:04:09.291053Z", "lastRunAt": "2026-02-23T22:04:09.291053Z", "lastRunJobId": "fb84e869-28c5-4187-b963-62a0f0ddb0d0"}, "687d73de-f481-4b7a-8f23-454efb712e04": {"scheduleId": "687d73de-f481-4b7a-8f23-454efb712e04", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.119079Z", "updated": "2026-02-23T22:05:26.217653Z", "lastRunAt": "2026-02-23T22:05:26.217653Z", "lastRunJobId": "052828cb-fe04-4107-8168-bf626dc3d2d4"}, "fb1bc1c1-fb12-4c5c-a973-4bfdbf6fe5cb": {"scheduleId": "fb1bc1c1-fb12-4c5c-a973-4bfdbf6fe5cb", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.226313Z", "updated": "2026-02-23T22:05:26.226313Z", "lastRunAt": null, "lastRunJobId": null}, "02d9f727-8c86-4c7a-961c-2c4bb8608736": {"scheduleId": "02d9f727-8c86-4c7a-961c-2c4bb8608736", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.234478Z", "updated": "2026-02-23T22:05:26.234478Z", "lastRunAt": null, "lastRunJobId": null}, "dff69560-5acc-47cf-a051-8eeb011f2db7": {"scheduleId": "dff69560-5acc-47cf-a051-8eeb011f2db7", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.242902Z", "updated": "2026-02-23T22:05:26.253967Z", "lastRunAt": "2026-02-23T22:05:26.253967Z", "lastRunJobId": "057a6900-c6e4-4ee7-b392-16cc852a7beb"}, "51f94cf2-b5b6-49a7-bf0c-a537a6aa1b56": {"scheduleId": "51f94cf2-b5b6-49a7-bf0c-a537a6aa1b56", "processId": "workflow", "workflowId": "9be46657-dc95-4197-b520-034877ad53fd", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:05:26.278557Z", "updated": "2026-02-23T22:05:26.385589Z", "lastRunAt": "2026-02-23T22:05:26.385589Z", "lastRunJobId": "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff"}, "af06959e-30ef-49e3-93c8-25e9f3d50313": {"scheduleId": "af06959e-30ef-49e3-93c8-25e9f3d50313", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.812584Z", "updated": "2026-02-23T22:06:19.913115Z", "lastRunAt": "2026-02-23T22:06:19.913115Z", "lastRunJobId": "bb27b64c-2cda-41ab-8e2b-b23ff462de71"}, "bd946b5d-305a-45c4-8869-d4d1d25e6a31": {"scheduleId": "bd946b5d-305a-45c4-8869-d4d1d25e6a31", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.921791Z", "updated": "2026-02-23T22:06:19.921791Z", "lastRunAt": null, "lastRunJobId": null}, "4fcde89a-32f2-445e-84f0-dfa7255070d9": {"scheduleId": "4fcde89a-32f2-445e-84f0-dfa7255070d9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.929875Z", "updated": "2026-02-23T22:06:19.929875Z", "lastRunAt": null, "lastRunJobId": null}, "90677ea1-0ed0-4fda-9b94-8b2fcad101d2": {"scheduleId": "90677ea1-0ed0-4fda-9b94-8b2fcad101d2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.938256Z", "updated": "2026-02-23T22:06:19.950940Z", "lastRunAt": "2026-02-23T22:06:19.950940Z", "lastRunJobId": "d0cd71f3-2aff-4345-8804-6451bd9d78bd"}, "19b99ee9-39ff-48d6-ba66-fc4ab92863ae": {"scheduleId": "19b99ee9-39ff-48d6-ba66-fc4ab92863ae", "processId": "workflow", "workflowId": "5b2d0e9f-a83b-46a1-bac0-93d7693df940", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:06:19.985953Z", "updated": "2026-02-23T22:06:20.091324Z", "lastRunAt": "2026-02-23T22:06:20.091324Z", "lastRunJobId": "a0138e99-87f4-4213-b003-53e4435d2191"}, "82e3bc02-1c6a-4b9b-b2d4-4b8e101fe724": {"scheduleId": "82e3bc02-1c6a-4b9b-b2d4-4b8e101fe724", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.115363Z", "updated": "2026-02-23T22:07:10.213898Z", "lastRunAt": "2026-02-23T22:07:10.213898Z", "lastRunJobId": "db8c46c0-4252-4091-89b6-7bcac3da7ab2"}, "ee39e6f6-db58-4b73-bdf0-2489b8bd875d": {"scheduleId": "ee39e6f6-db58-4b73-bdf0-2489b8bd875d", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.222341Z", "updated": "2026-02-23T22:07:10.222341Z", "lastRunAt": null, "lastRunJobId": null}, "4fe2da51-f1e5-4fb9-af57-60b7aef990b3": {"scheduleId": "4fe2da51-f1e5-4fb9-af57-60b7aef990b3", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.231146Z", "updated": "2026-02-23T22:07:10.231146Z", "lastRunAt": null, "lastRunJobId": null}, "675b3b23-e03f-424d-b9e8-0a1fdcb0cf21": {"scheduleId": "675b3b23-e03f-424d-b9e8-0a1fdcb0cf21", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.239832Z", "updated": "2026-02-23T22:07:10.253859Z", "lastRunAt": "2026-02-23T22:07:10.253859Z", "lastRunJobId": "36ad61d8-3b1a-4fa3-bc58-b801c12e6980"}, "91b646d5-d79d-47fe-899b-8267ad579745": {"scheduleId": "91b646d5-d79d-47fe-899b-8267ad579745", "processId": "workflow", "workflowId": "99f60372-418b-4205-b3e1-0f95b8c47ec3", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:07:10.281216Z", "updated": "2026-02-23T22:07:10.388949Z", "lastRunAt": "2026-02-23T22:07:10.388949Z", "lastRunJobId": "07711cbe-a49b-43ec-b9f5-a47ff809a637"}, "d8aef236-4b7d-40db-b379-b24e9b78b458": {"scheduleId": "d8aef236-4b7d-40db-b379-b24e9b78b458", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.668009Z", "updated": "2026-02-23T22:08:25.765997Z", "lastRunAt": "2026-02-23T22:08:25.765997Z", "lastRunJobId": "1df779b8-aa1c-439f-a5d7-3525fb54dc77"}, "c563a474-3ee3-4622-bb9e-2b0216a1bc6a": {"scheduleId": "c563a474-3ee3-4622-bb9e-2b0216a1bc6a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.774336Z", "updated": "2026-02-23T22:08:25.774336Z", "lastRunAt": null, "lastRunJobId": null}, "c33608bb-5677-4e2b-8cd4-1953c538d4ba": {"scheduleId": "c33608bb-5677-4e2b-8cd4-1953c538d4ba", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.782572Z", "updated": "2026-02-23T22:08:25.782572Z", "lastRunAt": null, "lastRunJobId": null}, "f7b1e808-e37d-4524-95da-bcd725fee8f2": {"scheduleId": "f7b1e808-e37d-4524-95da-bcd725fee8f2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.791049Z", "updated": "2026-02-23T22:08:25.807702Z", "lastRunAt": "2026-02-23T22:08:25.807702Z", "lastRunJobId": "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33"}, "730b4b89-b173-454b-8266-3e926815ac8b": {"scheduleId": "730b4b89-b173-454b-8266-3e926815ac8b", "processId": "workflow", "workflowId": "d122ebc8-c984-41dc-a867-25507acedb91", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:08:25.838704Z", "updated": "2026-02-23T22:08:25.949015Z", "lastRunAt": "2026-02-23T22:08:25.949015Z", "lastRunJobId": "e3f2a3ef-efb8-4a71-a892-437463f84e13"}, "610d77ed-461b-4e3e-b435-a6f66758894b": {"scheduleId": "610d77ed-461b-4e3e-b435-a6f66758894b", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.289695Z", "updated": "2026-02-23T22:10:11.387875Z", "lastRunAt": "2026-02-23T22:10:11.387875Z", "lastRunJobId": "48cc3a56-6df8-42b6-a1cd-ab380a687d17"}, "8dc5d3d9-29bb-49bc-b6f8-d59852317d84": {"scheduleId": "8dc5d3d9-29bb-49bc-b6f8-d59852317d84", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.396699Z", "updated": "2026-02-23T22:10:11.396699Z", "lastRunAt": null, "lastRunJobId": null}, "beddb641-b328-4b72-b140-311e8191bf8a": {"scheduleId": "beddb641-b328-4b72-b140-311e8191bf8a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.405166Z", "updated": "2026-02-23T22:10:11.405166Z", "lastRunAt": null, "lastRunJobId": null}, "a6b28e0a-a35e-4a34-b71f-a90d035603bc": {"scheduleId": "a6b28e0a-a35e-4a34-b71f-a90d035603bc", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.413250Z", "updated": "2026-02-23T22:10:11.431385Z", "lastRunAt": "2026-02-23T22:10:11.431385Z", "lastRunJobId": "672705fa-17df-48d3-9dfe-89edd3033977"}, "623057f2-056c-45c2-8f76-103c68bb1184": {"scheduleId": "623057f2-056c-45c2-8f76-103c68bb1184", "processId": "workflow", "workflowId": "8615178b-17c8-434f-842b-e9f13b745301", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:10:11.463710Z", "updated": "2026-02-23T22:10:11.573987Z", "lastRunAt": "2026-02-23T22:10:11.573987Z", "lastRunJobId": "3bc40154-66d2-44b8-bf8a-3c931d7ce92a"}, "622341b1-38a3-4af0-858a-2300012d59a7": {"scheduleId": "622341b1-38a3-4af0-858a-2300012d59a7", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.237291Z", "updated": "2026-02-23T22:12:27.340850Z", "lastRunAt": "2026-02-23T22:12:27.340850Z", "lastRunJobId": "4c59c2e2-a55c-475e-8f49-8060b0070c15"}, "99925ea5-18a8-424a-b7da-d73bd335dc75": {"scheduleId": "99925ea5-18a8-424a-b7da-d73bd335dc75", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.350371Z", "updated": "2026-02-23T22:12:27.350371Z", "lastRunAt": null, "lastRunJobId": null}, "c67b9ab1-0dc1-48a5-aec1-20489807497a": {"scheduleId": "c67b9ab1-0dc1-48a5-aec1-20489807497a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.359375Z", "updated": "2026-02-23T22:12:27.359375Z", "lastRunAt": null, "lastRunJobId": null}, "3cb199b7-50a0-4b65-8b2e-426a1d50fcc9": {"scheduleId": "3cb199b7-50a0-4b65-8b2e-426a1d50fcc9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.367947Z", "updated": "2026-02-23T22:12:27.387899Z", "lastRunAt": "2026-02-23T22:12:27.387899Z", "lastRunJobId": "743ddcec-4c43-49cf-a3d7-a79fd07d203c"}, "ccec39ce-7b47-4fba-b991-a03f2a76fa91": {"scheduleId": "ccec39ce-7b47-4fba-b991-a03f2a76fa91", "processId": "workflow", "workflowId": "696e988e-0e0d-4e2a-8bd2-9e6109ae798d", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:12:27.422585Z", "updated": "2026-02-23T22:12:27.538547Z", "lastRunAt": "2026-02-23T22:12:27.538547Z", "lastRunJobId": "faaa0822-0996-42aa-9b4a-09db3b38b253"}, "8c5aa333-1fbe-4def-871c-67846973a0cd": {"scheduleId": "8c5aa333-1fbe-4def-871c-67846973a0cd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.089768Z", "updated": "2026-02-23T22:13:55.193088Z", "lastRunAt": "2026-02-23T22:13:55.193088Z", "lastRunJobId": "421d8036-8bb8-4d19-8ab2-16b12114c03f"}, "4b60855e-b4f1-47a4-8212-757bede1eae9": {"scheduleId": "4b60855e-b4f1-47a4-8212-757bede1eae9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.201948Z", "updated": "2026-02-23T22:13:55.201948Z", "lastRunAt": null, "lastRunJobId": null}, "56c7219c-2f65-4ecf-9c3b-2637a3721373": {"scheduleId": "56c7219c-2f65-4ecf-9c3b-2637a3721373", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.210517Z", "updated": "2026-02-23T22:13:55.210517Z", "lastRunAt": null, "lastRunJobId": null}, "f097970d-3aea-499b-8378-11f1a649efe6": {"scheduleId": "f097970d-3aea-499b-8378-11f1a649efe6", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.219281Z", "updated": "2026-02-23T22:13:55.241108Z", "lastRunAt": "2026-02-23T22:13:55.241108Z", "lastRunJobId": "1f0946fe-d7cf-4ff5-ae38-ea332be556f8"}, "73ed1631-fa29-4acd-a093-d6f844acda2c": {"scheduleId": "73ed1631-fa29-4acd-a093-d6f844acda2c", "processId": "workflow", "workflowId": "76b22e29-d03d-41cc-8afd-1f6d98c904b8", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:13:55.276114Z", "updated": "2026-02-23T22:13:55.383703Z", "lastRunAt": "2026-02-23T22:13:55.383703Z", "lastRunJobId": "89f1748d-a2ff-4fb4-bad4-034af929932e"}, "719443e3-b9b8-4c98-8513-4eb9f398a68f": {"scheduleId": "719443e3-b9b8-4c98-8513-4eb9f398a68f", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.039255Z", "updated": "2026-02-23T22:15:40.141384Z", "lastRunAt": "2026-02-23T22:15:40.141384Z", "lastRunJobId": "ac76a665-136a-4730-9228-dceb0a828f85"}, "ac016e84-b71a-4570-b097-66e7f56601fd": {"scheduleId": "ac016e84-b71a-4570-b097-66e7f56601fd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.150909Z", "updated": "2026-02-23T22:15:40.150909Z", "lastRunAt": null, "lastRunJobId": null}, "9fef80ef-ee87-4a54-84da-1e49be0823d5": {"scheduleId": "9fef80ef-ee87-4a54-84da-1e49be0823d5", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.160032Z", "updated": "2026-02-23T22:15:40.160032Z", "lastRunAt": null, "lastRunJobId": null}, "bb9b0350-2f4a-4cc3-8d80-2728f5d5f790": {"scheduleId": "bb9b0350-2f4a-4cc3-8d80-2728f5d5f790", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.169187Z", "updated": "2026-02-23T22:15:40.192890Z", "lastRunAt": "2026-02-23T22:15:40.192890Z", "lastRunJobId": "101a1fa5-3a6b-4923-8b3d-08497fc2cde3"}, "c80ba67b-279a-4402-93a1-4f338959a04e": {"scheduleId": "c80ba67b-279a-4402-93a1-4f338959a04e", "processId": "workflow", "workflowId": "f94af166-6944-45d6-b972-4500feec0eec", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:15:40.230848Z", "updated": "2026-02-23T22:15:40.344231Z", "lastRunAt": "2026-02-23T22:15:40.344231Z", "lastRunJobId": "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b"}, "58efaf46-a456-42c4-b649-ea1108f15ea9": {"scheduleId": "58efaf46-a456-42c4-b649-ea1108f15ea9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.626648Z", "updated": "2026-02-23T22:16:56.732055Z", "lastRunAt": "2026-02-23T22:16:56.732055Z", "lastRunJobId": "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9"}, "b7e47eb8-a5c3-4b5f-995d-d11c80819ecb": {"scheduleId": "b7e47eb8-a5c3-4b5f-995d-d11c80819ecb", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.741260Z", "updated": "2026-02-23T22:16:56.741260Z", "lastRunAt": null, "lastRunJobId": null}, "b6886dd9-7b18-403b-ab39-f08b82630146": {"scheduleId": "b6886dd9-7b18-403b-ab39-f08b82630146", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.750007Z", "updated": "2026-02-23T22:16:56.750007Z", "lastRunAt": null, "lastRunJobId": null}, "387c67e0-fadf-4c98-80af-68be8fb71cd1": {"scheduleId": "387c67e0-fadf-4c98-80af-68be8fb71cd1", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.758467Z", "updated": "2026-02-23T22:16:56.783858Z", "lastRunAt": "2026-02-23T22:16:56.783858Z", "lastRunJobId": "4e30a788-c134-463a-bdbb-f88b4b5615c9"}, "ec048ce8-ccdf-4414-8f1e-900235643423": {"scheduleId": "ec048ce8-ccdf-4414-8f1e-900235643423", "processId": "workflow", "workflowId": "ba8a6537-d7a7-4062-b169-bc65113cbb8c", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:16:56.823648Z", "updated": "2026-02-23T22:16:56.938637Z", "lastRunAt": "2026-02-23T22:16:56.938637Z", "lastRunJobId": "9a34fb59-d815-4107-9c6b-d3207704d83a"}, "456d431a-5464-40fd-886c-85a6638ae141": {"scheduleId": "456d431a-5464-40fd-886c-85a6638ae141", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.497375Z", "updated": "2026-02-23T22:18:09.603709Z", "lastRunAt": "2026-02-23T22:18:09.603709Z", "lastRunJobId": "bef54659-7bfc-4c67-b172-1722edcea9cb"}, "6f27c166-ad26-4103-b4fd-0c04d4937464": {"scheduleId": "6f27c166-ad26-4103-b4fd-0c04d4937464", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.614239Z", "updated": "2026-02-23T22:18:09.614239Z", "lastRunAt": null, "lastRunJobId": null}, "86fb93ec-4d8e-496c-8359-ddb8ac1bccb3": {"scheduleId": "86fb93ec-4d8e-496c-8359-ddb8ac1bccb3", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.623851Z", "updated": "2026-02-23T22:18:09.623851Z", "lastRunAt": null, "lastRunJobId": null}, "75f754a7-5bbe-40d9-b05e-26f4b53dac7f": {"scheduleId": "75f754a7-5bbe-40d9-b05e-26f4b53dac7f", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.632760Z", "updated": "2026-02-23T22:18:09.660081Z", "lastRunAt": "2026-02-23T22:18:09.660081Z", "lastRunJobId": "2ad476b8-a2a6-4783-948e-42087f50a7e4"}, "c87d04b7-479a-4038-aa91-5a3806e7ba95": {"scheduleId": "c87d04b7-479a-4038-aa91-5a3806e7ba95", "processId": "workflow", "workflowId": "5a390470-b37d-45b2-9633-8435c0167424", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:18:09.701252Z", "updated": "2026-02-23T22:18:09.813071Z", "lastRunAt": "2026-02-23T22:18:09.813071Z", "lastRunJobId": "50f69ac8-ca39-4892-bf3c-2921221183b8"}} \ No newline at end of file +{"5cfbf7d5-2c31-493e-aa81-ceb20d13db0e": {"scheduleId": "5cfbf7d5-2c31-493e-aa81-ceb20d13db0e", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.631345Z", "updated": "2026-02-23T21:59:01.633759Z", "lastRunAt": "2026-02-23T21:59:01.633759Z", "lastRunJobId": "fd1d2a89-519d-4ead-afb4-a76ef18cdf6d"}, "b19d087c-73de-4421-88d5-9bc6c29d166b": {"scheduleId": "b19d087c-73de-4421-88d5-9bc6c29d166b", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.640858Z", "updated": "2026-02-23T21:59:01.640858Z", "lastRunAt": null, "lastRunJobId": null}, "195d2328-245f-4573-8e5c-a0d18bb6e027": {"scheduleId": "195d2328-245f-4573-8e5c-a0d18bb6e027", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.648433Z", "updated": "2026-02-23T21:59:01.648433Z", "lastRunAt": null, "lastRunJobId": null}, "0c2f0ab1-d72f-4a85-b0bb-1806c151de48": {"scheduleId": "0c2f0ab1-d72f-4a85-b0bb-1806c151de48", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T21:59:01.655548Z", "updated": "2026-02-23T21:59:01.658990Z", "lastRunAt": "2026-02-23T21:59:01.658990Z", "lastRunJobId": "9ed82292-1c23-4a6f-8077-561c8d431e5a"}, "4daf8538-91de-43c1-ab4f-717d5390230a": {"scheduleId": "4daf8538-91de-43c1-ab4f-717d5390230a", "processId": "workflow", "workflowId": "70a148c9-4c30-4ff4-bdc1-d793853cca5b", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T21:59:01.676128Z", "updated": "2026-02-23T21:59:01.679007Z", "lastRunAt": "2026-02-23T21:59:01.679007Z", "lastRunJobId": "8337900a-0fc6-4f53-a13e-89540fb03d2e"}, "287ad6fc-135a-427b-8c6e-68bedf3a0434": {"scheduleId": "287ad6fc-135a-427b-8c6e-68bedf3a0434", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.254541Z", "updated": "2026-02-23T22:03:01.349695Z", "lastRunAt": "2026-02-23T22:03:01.349695Z", "lastRunJobId": "8ae1afa0-88d9-493a-89e7-d118c6651e43"}, "85e67015-5094-4cee-9ff7-5b25276d71d4": {"scheduleId": "85e67015-5094-4cee-9ff7-5b25276d71d4", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.357868Z", "updated": "2026-02-23T22:03:01.357868Z", "lastRunAt": null, "lastRunJobId": null}, "522c7ff1-709f-487a-b6e7-8e3c258f8b3e": {"scheduleId": "522c7ff1-709f-487a-b6e7-8e3c258f8b3e", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.366100Z", "updated": "2026-02-23T22:03:01.366100Z", "lastRunAt": null, "lastRunJobId": null}, "ccad9e3e-cfd3-4ca2-8d82-9ab18dc746d2": {"scheduleId": "ccad9e3e-cfd3-4ca2-8d82-9ab18dc746d2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:01.373832Z", "updated": "2026-02-23T22:03:01.379077Z", "lastRunAt": "2026-02-23T22:03:01.379077Z", "lastRunJobId": "fef7a2ef-eda6-42b0-a95d-da21341ab899"}, "26a09350-cc9a-4070-b44c-35a9290d3382": {"scheduleId": "26a09350-cc9a-4070-b44c-35a9290d3382", "processId": "workflow", "workflowId": "5919d4fa-644f-4ffc-8541-d258e987b379", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:03:01.400343Z", "updated": "2026-02-23T22:03:01.504385Z", "lastRunAt": "2026-02-23T22:03:01.504385Z", "lastRunJobId": "d42e8fc4-1023-453c-9aae-8c33141ca838"}, "e002f589-33e2-4689-ab75-55ad752772aa": {"scheduleId": "e002f589-33e2-4689-ab75-55ad752772aa", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.709891Z", "updated": "2026-02-23T22:03:34.808021Z", "lastRunAt": "2026-02-23T22:03:34.808021Z", "lastRunJobId": "5d45d9ce-795c-4615-b973-33cc358c1327"}, "4d02c489-5f53-4ee8-a340-f287e39e8dda": {"scheduleId": "4d02c489-5f53-4ee8-a340-f287e39e8dda", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.816852Z", "updated": "2026-02-23T22:03:34.816852Z", "lastRunAt": null, "lastRunJobId": null}, "b307747d-4327-4a51-9d58-f8b54b25fe38": {"scheduleId": "b307747d-4327-4a51-9d58-f8b54b25fe38", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.824292Z", "updated": "2026-02-23T22:03:34.824292Z", "lastRunAt": null, "lastRunJobId": null}, "2ee41b9f-753d-449b-ae0c-cb6dc0c4a4bd": {"scheduleId": "2ee41b9f-753d-449b-ae0c-cb6dc0c4a4bd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:03:34.831948Z", "updated": "2026-02-23T22:03:34.839113Z", "lastRunAt": "2026-02-23T22:03:34.839113Z", "lastRunJobId": "4c2dae6b-dbff-4591-91ca-5a679a4cd52f"}, "8f76daef-6165-483f-8254-a4b61c506d8c": {"scheduleId": "8f76daef-6165-483f-8254-a4b61c506d8c", "processId": "workflow", "workflowId": "90ee914e-925d-4775-bbdb-8489f79e6b2d", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:03:34.860159Z", "updated": "2026-02-23T22:03:34.964368Z", "lastRunAt": "2026-02-23T22:03:34.964368Z", "lastRunJobId": "d6098fe4-5916-4d3b-b540-de1076f51c8d"}, "2adddf18-8041-4049-91ca-e82706bb4bd5": {"scheduleId": "2adddf18-8041-4049-91ca-e82706bb4bd5", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.025807Z", "updated": "2026-02-23T22:04:09.126220Z", "lastRunAt": "2026-02-23T22:04:09.126220Z", "lastRunJobId": "5f68bea6-8dd8-421e-98d7-0cc70d496462"}, "4ced4308-4f5c-4c9d-8ee0-7bf0fdbebe7d": {"scheduleId": "4ced4308-4f5c-4c9d-8ee0-7bf0fdbebe7d", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.135097Z", "updated": "2026-02-23T22:04:09.135097Z", "lastRunAt": null, "lastRunJobId": null}, "c0109e78-5124-4a5c-9ebd-f715c0d63e10": {"scheduleId": "c0109e78-5124-4a5c-9ebd-f715c0d63e10", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.143459Z", "updated": "2026-02-23T22:04:09.143459Z", "lastRunAt": null, "lastRunJobId": null}, "e9be5417-17c2-4335-8e16-696ef8554757": {"scheduleId": "e9be5417-17c2-4335-8e16-696ef8554757", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:04:09.151811Z", "updated": "2026-02-23T22:04:09.160932Z", "lastRunAt": "2026-02-23T22:04:09.160932Z", "lastRunJobId": "ebf4ee34-fb19-4872-9701-6ecafe5f1fd4"}, "d1f00049-3f7b-4f65-bab9-4af6b547f867": {"scheduleId": "d1f00049-3f7b-4f65-bab9-4af6b547f867", "processId": "workflow", "workflowId": "364063da-5825-4303-9736-51baf8692530", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:04:09.183145Z", "updated": "2026-02-23T22:04:09.291053Z", "lastRunAt": "2026-02-23T22:04:09.291053Z", "lastRunJobId": "fb84e869-28c5-4187-b963-62a0f0ddb0d0"}, "687d73de-f481-4b7a-8f23-454efb712e04": {"scheduleId": "687d73de-f481-4b7a-8f23-454efb712e04", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.119079Z", "updated": "2026-02-23T22:05:26.217653Z", "lastRunAt": "2026-02-23T22:05:26.217653Z", "lastRunJobId": "052828cb-fe04-4107-8168-bf626dc3d2d4"}, "fb1bc1c1-fb12-4c5c-a973-4bfdbf6fe5cb": {"scheduleId": "fb1bc1c1-fb12-4c5c-a973-4bfdbf6fe5cb", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.226313Z", "updated": "2026-02-23T22:05:26.226313Z", "lastRunAt": null, "lastRunJobId": null}, "02d9f727-8c86-4c7a-961c-2c4bb8608736": {"scheduleId": "02d9f727-8c86-4c7a-961c-2c4bb8608736", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.234478Z", "updated": "2026-02-23T22:05:26.234478Z", "lastRunAt": null, "lastRunJobId": null}, "dff69560-5acc-47cf-a051-8eeb011f2db7": {"scheduleId": "dff69560-5acc-47cf-a051-8eeb011f2db7", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:05:26.242902Z", "updated": "2026-02-23T22:05:26.253967Z", "lastRunAt": "2026-02-23T22:05:26.253967Z", "lastRunJobId": "057a6900-c6e4-4ee7-b392-16cc852a7beb"}, "51f94cf2-b5b6-49a7-bf0c-a537a6aa1b56": {"scheduleId": "51f94cf2-b5b6-49a7-bf0c-a537a6aa1b56", "processId": "workflow", "workflowId": "9be46657-dc95-4197-b520-034877ad53fd", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:05:26.278557Z", "updated": "2026-02-23T22:05:26.385589Z", "lastRunAt": "2026-02-23T22:05:26.385589Z", "lastRunJobId": "8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff"}, "af06959e-30ef-49e3-93c8-25e9f3d50313": {"scheduleId": "af06959e-30ef-49e3-93c8-25e9f3d50313", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.812584Z", "updated": "2026-02-23T22:06:19.913115Z", "lastRunAt": "2026-02-23T22:06:19.913115Z", "lastRunJobId": "bb27b64c-2cda-41ab-8e2b-b23ff462de71"}, "bd946b5d-305a-45c4-8869-d4d1d25e6a31": {"scheduleId": "bd946b5d-305a-45c4-8869-d4d1d25e6a31", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.921791Z", "updated": "2026-02-23T22:06:19.921791Z", "lastRunAt": null, "lastRunJobId": null}, "4fcde89a-32f2-445e-84f0-dfa7255070d9": {"scheduleId": "4fcde89a-32f2-445e-84f0-dfa7255070d9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.929875Z", "updated": "2026-02-23T22:06:19.929875Z", "lastRunAt": null, "lastRunJobId": null}, "90677ea1-0ed0-4fda-9b94-8b2fcad101d2": {"scheduleId": "90677ea1-0ed0-4fda-9b94-8b2fcad101d2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:06:19.938256Z", "updated": "2026-02-23T22:06:19.950940Z", "lastRunAt": "2026-02-23T22:06:19.950940Z", "lastRunJobId": "d0cd71f3-2aff-4345-8804-6451bd9d78bd"}, "19b99ee9-39ff-48d6-ba66-fc4ab92863ae": {"scheduleId": "19b99ee9-39ff-48d6-ba66-fc4ab92863ae", "processId": "workflow", "workflowId": "5b2d0e9f-a83b-46a1-bac0-93d7693df940", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:06:19.985953Z", "updated": "2026-02-23T22:06:20.091324Z", "lastRunAt": "2026-02-23T22:06:20.091324Z", "lastRunJobId": "a0138e99-87f4-4213-b003-53e4435d2191"}, "82e3bc02-1c6a-4b9b-b2d4-4b8e101fe724": {"scheduleId": "82e3bc02-1c6a-4b9b-b2d4-4b8e101fe724", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.115363Z", "updated": "2026-02-23T22:07:10.213898Z", "lastRunAt": "2026-02-23T22:07:10.213898Z", "lastRunJobId": "db8c46c0-4252-4091-89b6-7bcac3da7ab2"}, "ee39e6f6-db58-4b73-bdf0-2489b8bd875d": {"scheduleId": "ee39e6f6-db58-4b73-bdf0-2489b8bd875d", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.222341Z", "updated": "2026-02-23T22:07:10.222341Z", "lastRunAt": null, "lastRunJobId": null}, "4fe2da51-f1e5-4fb9-af57-60b7aef990b3": {"scheduleId": "4fe2da51-f1e5-4fb9-af57-60b7aef990b3", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.231146Z", "updated": "2026-02-23T22:07:10.231146Z", "lastRunAt": null, "lastRunJobId": null}, "675b3b23-e03f-424d-b9e8-0a1fdcb0cf21": {"scheduleId": "675b3b23-e03f-424d-b9e8-0a1fdcb0cf21", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:07:10.239832Z", "updated": "2026-02-23T22:07:10.253859Z", "lastRunAt": "2026-02-23T22:07:10.253859Z", "lastRunJobId": "36ad61d8-3b1a-4fa3-bc58-b801c12e6980"}, "91b646d5-d79d-47fe-899b-8267ad579745": {"scheduleId": "91b646d5-d79d-47fe-899b-8267ad579745", "processId": "workflow", "workflowId": "99f60372-418b-4205-b3e1-0f95b8c47ec3", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:07:10.281216Z", "updated": "2026-02-23T22:07:10.388949Z", "lastRunAt": "2026-02-23T22:07:10.388949Z", "lastRunJobId": "07711cbe-a49b-43ec-b9f5-a47ff809a637"}, "d8aef236-4b7d-40db-b379-b24e9b78b458": {"scheduleId": "d8aef236-4b7d-40db-b379-b24e9b78b458", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.668009Z", "updated": "2026-02-23T22:08:25.765997Z", "lastRunAt": "2026-02-23T22:08:25.765997Z", "lastRunJobId": "1df779b8-aa1c-439f-a5d7-3525fb54dc77"}, "c563a474-3ee3-4622-bb9e-2b0216a1bc6a": {"scheduleId": "c563a474-3ee3-4622-bb9e-2b0216a1bc6a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.774336Z", "updated": "2026-02-23T22:08:25.774336Z", "lastRunAt": null, "lastRunJobId": null}, "c33608bb-5677-4e2b-8cd4-1953c538d4ba": {"scheduleId": "c33608bb-5677-4e2b-8cd4-1953c538d4ba", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.782572Z", "updated": "2026-02-23T22:08:25.782572Z", "lastRunAt": null, "lastRunJobId": null}, "f7b1e808-e37d-4524-95da-bcd725fee8f2": {"scheduleId": "f7b1e808-e37d-4524-95da-bcd725fee8f2", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:08:25.791049Z", "updated": "2026-02-23T22:08:25.807702Z", "lastRunAt": "2026-02-23T22:08:25.807702Z", "lastRunJobId": "7dd93d56-a789-4e5e-9f4b-b34bdc9edc33"}, "730b4b89-b173-454b-8266-3e926815ac8b": {"scheduleId": "730b4b89-b173-454b-8266-3e926815ac8b", "processId": "workflow", "workflowId": "d122ebc8-c984-41dc-a867-25507acedb91", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:08:25.838704Z", "updated": "2026-02-23T22:08:25.949015Z", "lastRunAt": "2026-02-23T22:08:25.949015Z", "lastRunJobId": "e3f2a3ef-efb8-4a71-a892-437463f84e13"}, "610d77ed-461b-4e3e-b435-a6f66758894b": {"scheduleId": "610d77ed-461b-4e3e-b435-a6f66758894b", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.289695Z", "updated": "2026-02-23T22:10:11.387875Z", "lastRunAt": "2026-02-23T22:10:11.387875Z", "lastRunJobId": "48cc3a56-6df8-42b6-a1cd-ab380a687d17"}, "8dc5d3d9-29bb-49bc-b6f8-d59852317d84": {"scheduleId": "8dc5d3d9-29bb-49bc-b6f8-d59852317d84", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.396699Z", "updated": "2026-02-23T22:10:11.396699Z", "lastRunAt": null, "lastRunJobId": null}, "beddb641-b328-4b72-b140-311e8191bf8a": {"scheduleId": "beddb641-b328-4b72-b140-311e8191bf8a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.405166Z", "updated": "2026-02-23T22:10:11.405166Z", "lastRunAt": null, "lastRunJobId": null}, "a6b28e0a-a35e-4a34-b71f-a90d035603bc": {"scheduleId": "a6b28e0a-a35e-4a34-b71f-a90d035603bc", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:10:11.413250Z", "updated": "2026-02-23T22:10:11.431385Z", "lastRunAt": "2026-02-23T22:10:11.431385Z", "lastRunJobId": "672705fa-17df-48d3-9dfe-89edd3033977"}, "623057f2-056c-45c2-8f76-103c68bb1184": {"scheduleId": "623057f2-056c-45c2-8f76-103c68bb1184", "processId": "workflow", "workflowId": "8615178b-17c8-434f-842b-e9f13b745301", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:10:11.463710Z", "updated": "2026-02-23T22:10:11.573987Z", "lastRunAt": "2026-02-23T22:10:11.573987Z", "lastRunJobId": "3bc40154-66d2-44b8-bf8a-3c931d7ce92a"}, "622341b1-38a3-4af0-858a-2300012d59a7": {"scheduleId": "622341b1-38a3-4af0-858a-2300012d59a7", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.237291Z", "updated": "2026-02-23T22:12:27.340850Z", "lastRunAt": "2026-02-23T22:12:27.340850Z", "lastRunJobId": "4c59c2e2-a55c-475e-8f49-8060b0070c15"}, "99925ea5-18a8-424a-b7da-d73bd335dc75": {"scheduleId": "99925ea5-18a8-424a-b7da-d73bd335dc75", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.350371Z", "updated": "2026-02-23T22:12:27.350371Z", "lastRunAt": null, "lastRunJobId": null}, "c67b9ab1-0dc1-48a5-aec1-20489807497a": {"scheduleId": "c67b9ab1-0dc1-48a5-aec1-20489807497a", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.359375Z", "updated": "2026-02-23T22:12:27.359375Z", "lastRunAt": null, "lastRunJobId": null}, "3cb199b7-50a0-4b65-8b2e-426a1d50fcc9": {"scheduleId": "3cb199b7-50a0-4b65-8b2e-426a1d50fcc9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:12:27.367947Z", "updated": "2026-02-23T22:12:27.387899Z", "lastRunAt": "2026-02-23T22:12:27.387899Z", "lastRunJobId": "743ddcec-4c43-49cf-a3d7-a79fd07d203c"}, "ccec39ce-7b47-4fba-b991-a03f2a76fa91": {"scheduleId": "ccec39ce-7b47-4fba-b991-a03f2a76fa91", "processId": "workflow", "workflowId": "696e988e-0e0d-4e2a-8bd2-9e6109ae798d", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:12:27.422585Z", "updated": "2026-02-23T22:12:27.538547Z", "lastRunAt": "2026-02-23T22:12:27.538547Z", "lastRunJobId": "faaa0822-0996-42aa-9b4a-09db3b38b253"}, "8c5aa333-1fbe-4def-871c-67846973a0cd": {"scheduleId": "8c5aa333-1fbe-4def-871c-67846973a0cd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.089768Z", "updated": "2026-02-23T22:13:55.193088Z", "lastRunAt": "2026-02-23T22:13:55.193088Z", "lastRunJobId": "421d8036-8bb8-4d19-8ab2-16b12114c03f"}, "4b60855e-b4f1-47a4-8212-757bede1eae9": {"scheduleId": "4b60855e-b4f1-47a4-8212-757bede1eae9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.201948Z", "updated": "2026-02-23T22:13:55.201948Z", "lastRunAt": null, "lastRunJobId": null}, "56c7219c-2f65-4ecf-9c3b-2637a3721373": {"scheduleId": "56c7219c-2f65-4ecf-9c3b-2637a3721373", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.210517Z", "updated": "2026-02-23T22:13:55.210517Z", "lastRunAt": null, "lastRunJobId": null}, "f097970d-3aea-499b-8378-11f1a649efe6": {"scheduleId": "f097970d-3aea-499b-8378-11f1a649efe6", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:13:55.219281Z", "updated": "2026-02-23T22:13:55.241108Z", "lastRunAt": "2026-02-23T22:13:55.241108Z", "lastRunJobId": "1f0946fe-d7cf-4ff5-ae38-ea332be556f8"}, "73ed1631-fa29-4acd-a093-d6f844acda2c": {"scheduleId": "73ed1631-fa29-4acd-a093-d6f844acda2c", "processId": "workflow", "workflowId": "76b22e29-d03d-41cc-8afd-1f6d98c904b8", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:13:55.276114Z", "updated": "2026-02-23T22:13:55.383703Z", "lastRunAt": "2026-02-23T22:13:55.383703Z", "lastRunJobId": "89f1748d-a2ff-4fb4-bad4-034af929932e"}, "719443e3-b9b8-4c98-8513-4eb9f398a68f": {"scheduleId": "719443e3-b9b8-4c98-8513-4eb9f398a68f", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.039255Z", "updated": "2026-02-23T22:15:40.141384Z", "lastRunAt": "2026-02-23T22:15:40.141384Z", "lastRunJobId": "ac76a665-136a-4730-9228-dceb0a828f85"}, "ac016e84-b71a-4570-b097-66e7f56601fd": {"scheduleId": "ac016e84-b71a-4570-b097-66e7f56601fd", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.150909Z", "updated": "2026-02-23T22:15:40.150909Z", "lastRunAt": null, "lastRunJobId": null}, "9fef80ef-ee87-4a54-84da-1e49be0823d5": {"scheduleId": "9fef80ef-ee87-4a54-84da-1e49be0823d5", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.160032Z", "updated": "2026-02-23T22:15:40.160032Z", "lastRunAt": null, "lastRunJobId": null}, "bb9b0350-2f4a-4cc3-8d80-2728f5d5f790": {"scheduleId": "bb9b0350-2f4a-4cc3-8d80-2728f5d5f790", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:15:40.169187Z", "updated": "2026-02-23T22:15:40.192890Z", "lastRunAt": "2026-02-23T22:15:40.192890Z", "lastRunJobId": "101a1fa5-3a6b-4923-8b3d-08497fc2cde3"}, "c80ba67b-279a-4402-93a1-4f338959a04e": {"scheduleId": "c80ba67b-279a-4402-93a1-4f338959a04e", "processId": "workflow", "workflowId": "f94af166-6944-45d6-b972-4500feec0eec", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:15:40.230848Z", "updated": "2026-02-23T22:15:40.344231Z", "lastRunAt": "2026-02-23T22:15:40.344231Z", "lastRunJobId": "a0aa8517-0ec2-4b4a-86c0-5645c4077a6b"}, "58efaf46-a456-42c4-b649-ea1108f15ea9": {"scheduleId": "58efaf46-a456-42c4-b649-ea1108f15ea9", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.626648Z", "updated": "2026-02-23T22:16:56.732055Z", "lastRunAt": "2026-02-23T22:16:56.732055Z", "lastRunJobId": "bc4505e6-8dbf-4d87-ae54-43e5b714a4e9"}, "b7e47eb8-a5c3-4b5f-995d-d11c80819ecb": {"scheduleId": "b7e47eb8-a5c3-4b5f-995d-d11c80819ecb", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.741260Z", "updated": "2026-02-23T22:16:56.741260Z", "lastRunAt": null, "lastRunJobId": null}, "b6886dd9-7b18-403b-ab39-f08b82630146": {"scheduleId": "b6886dd9-7b18-403b-ab39-f08b82630146", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.750007Z", "updated": "2026-02-23T22:16:56.750007Z", "lastRunAt": null, "lastRunJobId": null}, "387c67e0-fadf-4c98-80af-68be8fb71cd1": {"scheduleId": "387c67e0-fadf-4c98-80af-68be8fb71cd1", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:16:56.758467Z", "updated": "2026-02-23T22:16:56.783858Z", "lastRunAt": "2026-02-23T22:16:56.783858Z", "lastRunJobId": "4e30a788-c134-463a-bdbb-f88b4b5615c9"}, "ec048ce8-ccdf-4414-8f1e-900235643423": {"scheduleId": "ec048ce8-ccdf-4414-8f1e-900235643423", "processId": "workflow", "workflowId": "ba8a6537-d7a7-4062-b169-bc65113cbb8c", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:16:56.823648Z", "updated": "2026-02-23T22:16:56.938637Z", "lastRunAt": "2026-02-23T22:16:56.938637Z", "lastRunJobId": "9a34fb59-d815-4107-9c6b-d3207704d83a"}, "456d431a-5464-40fd-886c-85a6638ae141": {"scheduleId": "456d431a-5464-40fd-886c-85a6638ae141", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.497375Z", "updated": "2026-02-23T22:18:09.603709Z", "lastRunAt": "2026-02-23T22:18:09.603709Z", "lastRunJobId": "bef54659-7bfc-4c67-b172-1722edcea9cb"}, "6f27c166-ad26-4103-b4fd-0c04d4937464": {"scheduleId": "6f27c166-ad26-4103-b4fd-0c04d4937464", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.614239Z", "updated": "2026-02-23T22:18:09.614239Z", "lastRunAt": null, "lastRunJobId": null}, "86fb93ec-4d8e-496c-8359-ddb8ac1bccb3": {"scheduleId": "86fb93ec-4d8e-496c-8359-ddb8ac1bccb3", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.623851Z", "updated": "2026-02-23T22:18:09.623851Z", "lastRunAt": null, "lastRunJobId": null}, "75f754a7-5bbe-40d9-b05e-26f4b53dac7f": {"scheduleId": "75f754a7-5bbe-40d9-b05e-26f4b53dac7f", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-23T22:18:09.632760Z", "updated": "2026-02-23T22:18:09.660081Z", "lastRunAt": "2026-02-23T22:18:09.660081Z", "lastRunJobId": "2ad476b8-a2a6-4783-948e-42087f50a7e4"}, "c87d04b7-479a-4038-aa91-5a3806e7ba95": {"scheduleId": "c87d04b7-479a-4038-aa91-5a3806e7ba95", "processId": "workflow", "workflowId": "5a390470-b37d-45b2-9633-8435c0167424", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-23T22:18:09.701252Z", "updated": "2026-02-23T22:18:09.813071Z", "lastRunAt": "2026-02-23T22:18:09.813071Z", "lastRunJobId": "50f69ac8-ca39-4892-bf3c-2921221183b8"}, "78df810b-b129-4660-9186-e2a6ba77293f": {"scheduleId": "78df810b-b129-4660-9186-e2a6ba77293f", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-24T11:01:16.901478Z", "updated": "2026-02-24T11:01:17.011463Z", "lastRunAt": "2026-02-24T11:01:17.011463Z", "lastRunJobId": "8da9f4b3-3858-43ff-a0f4-c9e4c16cc4c6"}, "8beadc46-40a6-4a61-be68-bc5388857bcf": {"scheduleId": "8beadc46-40a6-4a61-be68-bc5388857bcf", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-24T11:01:17.020819Z", "updated": "2026-02-24T11:01:17.020819Z", "lastRunAt": null, "lastRunJobId": null}, "f6fdab58-6f13-449b-b44e-a5034e6400ea": {"scheduleId": "f6fdab58-6f13-449b-b44e-a5034e6400ea", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-24T11:01:17.031472Z", "updated": "2026-02-24T11:01:17.031472Z", "lastRunAt": null, "lastRunJobId": null}, "8ab6d636-1289-431f-9338-637ca91ede80": {"scheduleId": "8ab6d636-1289-431f-9338-637ca91ede80", "processId": "eo-aggregate-import", "workflowId": null, "name": "nightly-precip-import", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "start": null, "end": null, "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dataElementMap": null, "dryRun": true}}, "created": "2026-02-24T11:01:17.041326Z", "updated": "2026-02-24T11:01:17.071524Z", "lastRunAt": "2026-02-24T11:01:17.071524Z", "lastRunJobId": "8e3f5696-b9e8-4f4b-ad89-8db4d6e5831e"}, "77c9d9f5-ddf6-4771-8100-94bed3ae0c20": {"scheduleId": "77c9d9f5-ddf6-4771-8100-94bed3ae0c20", "processId": "workflow", "workflowId": "a1ef8b41-460c-40ba-a219-aef155d1e67e", "name": "nightly-workflow", "cron": "0 0 * * *", "timezone": "UTC", "enabled": true, "inputs": null, "created": "2026-02-24T11:01:17.115211Z", "updated": "2026-02-24T11:01:17.229533Z", "lastRunAt": "2026-02-24T11:01:17.229533Z", "lastRunJobId": "30fe9414-3c22-4ec1-bad6-19a2890bfaf2"}} \ No newline at end of file diff --git a/.cache/state/workflows.json b/.cache/state/workflows.json index 79cddb1..29ae554 100644 --- a/.cache/state/workflows.json +++ b/.cache/state/workflows.json @@ -1 +1 @@ -{"70a148c9-4c30-4ff4-bdc1-d793853cca5b": {"workflowId": "70a148c9-4c30-4ff4-bdc1-d793853cca5b", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T21:59:01.674872Z", "updated": "2026-02-23T21:59:01.678721Z", "lastRunAt": "2026-02-23T21:59:01.678721Z", "lastRunJobIds": ["8337900a-0fc6-4f53-a13e-89540fb03d2e"]}, "5919d4fa-644f-4ffc-8541-d258e987b379": {"workflowId": "5919d4fa-644f-4ffc-8541-d258e987b379", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:03:01.398456Z", "updated": "2026-02-23T22:03:01.503931Z", "lastRunAt": "2026-02-23T22:03:01.503931Z", "lastRunJobIds": ["d42e8fc4-1023-453c-9aae-8c33141ca838"]}, "90ee914e-925d-4775-bbdb-8489f79e6b2d": {"workflowId": "90ee914e-925d-4775-bbdb-8489f79e6b2d", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:03:34.858713Z", "updated": "2026-02-23T22:03:34.964026Z", "lastRunAt": "2026-02-23T22:03:34.964026Z", "lastRunJobIds": ["d6098fe4-5916-4d3b-b540-de1076f51c8d"]}, "364063da-5825-4303-9736-51baf8692530": {"workflowId": "364063da-5825-4303-9736-51baf8692530", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:04:09.181686Z", "updated": "2026-02-23T22:04:09.290683Z", "lastRunAt": "2026-02-23T22:04:09.290683Z", "lastRunJobIds": ["fb84e869-28c5-4187-b963-62a0f0ddb0d0"]}, "9be46657-dc95-4197-b520-034877ad53fd": {"workflowId": "9be46657-dc95-4197-b520-034877ad53fd", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:05:26.277030Z", "updated": "2026-02-23T22:05:26.385208Z", "lastRunAt": "2026-02-23T22:05:26.385208Z", "lastRunJobIds": ["8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff"]}, "5b2d0e9f-a83b-46a1-bac0-93d7693df940": {"workflowId": "5b2d0e9f-a83b-46a1-bac0-93d7693df940", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:06:19.984497Z", "updated": "2026-02-23T22:06:20.090912Z", "lastRunAt": "2026-02-23T22:06:20.090912Z", "lastRunJobIds": ["a0138e99-87f4-4213-b003-53e4435d2191"]}, "99f60372-418b-4205-b3e1-0f95b8c47ec3": {"workflowId": "99f60372-418b-4205-b3e1-0f95b8c47ec3", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:07:10.279699Z", "updated": "2026-02-23T22:07:10.388391Z", "lastRunAt": "2026-02-23T22:07:10.388391Z", "lastRunJobIds": ["07711cbe-a49b-43ec-b9f5-a47ff809a637"]}, "d122ebc8-c984-41dc-a867-25507acedb91": {"workflowId": "d122ebc8-c984-41dc-a867-25507acedb91", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:08:25.837044Z", "updated": "2026-02-23T22:08:25.948539Z", "lastRunAt": "2026-02-23T22:08:25.948539Z", "lastRunJobIds": ["e3f2a3ef-efb8-4a71-a892-437463f84e13"]}, "8615178b-17c8-434f-842b-e9f13b745301": {"workflowId": "8615178b-17c8-434f-842b-e9f13b745301", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:10:11.462031Z", "updated": "2026-02-23T22:10:11.573452Z", "lastRunAt": "2026-02-23T22:10:11.573452Z", "lastRunJobIds": ["3bc40154-66d2-44b8-bf8a-3c931d7ce92a"]}, "696e988e-0e0d-4e2a-8bd2-9e6109ae798d": {"workflowId": "696e988e-0e0d-4e2a-8bd2-9e6109ae798d", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:12:27.421003Z", "updated": "2026-02-23T22:12:27.537998Z", "lastRunAt": "2026-02-23T22:12:27.537998Z", "lastRunJobIds": ["faaa0822-0996-42aa-9b4a-09db3b38b253"]}, "76b22e29-d03d-41cc-8afd-1f6d98c904b8": {"workflowId": "76b22e29-d03d-41cc-8afd-1f6d98c904b8", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:13:55.274478Z", "updated": "2026-02-23T22:13:55.383149Z", "lastRunAt": "2026-02-23T22:13:55.383149Z", "lastRunJobIds": ["89f1748d-a2ff-4fb4-bad4-034af929932e"]}, "f94af166-6944-45d6-b972-4500feec0eec": {"workflowId": "f94af166-6944-45d6-b972-4500feec0eec", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:15:40.229164Z", "updated": "2026-02-23T22:15:40.343668Z", "lastRunAt": "2026-02-23T22:15:40.343668Z", "lastRunJobIds": ["a0aa8517-0ec2-4b4a-86c0-5645c4077a6b"]}, "ba8a6537-d7a7-4062-b169-bc65113cbb8c": {"workflowId": "ba8a6537-d7a7-4062-b169-bc65113cbb8c", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:16:56.821962Z", "updated": "2026-02-23T22:16:56.938046Z", "lastRunAt": "2026-02-23T22:16:56.938046Z", "lastRunJobIds": ["9a34fb59-d815-4107-9c6b-d3207704d83a"]}, "5a390470-b37d-45b2-9633-8435c0167424": {"workflowId": "5a390470-b37d-45b2-9633-8435c0167424", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:18:09.699497Z", "updated": "2026-02-23T22:18:09.812445Z", "lastRunAt": "2026-02-23T22:18:09.812445Z", "lastRunJobIds": ["50f69ac8-ca39-4892-bf3c-2921221183b8"]}} \ No newline at end of file +{"70a148c9-4c30-4ff4-bdc1-d793853cca5b": {"workflowId": "70a148c9-4c30-4ff4-bdc1-d793853cca5b", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T21:59:01.674872Z", "updated": "2026-02-23T21:59:01.678721Z", "lastRunAt": "2026-02-23T21:59:01.678721Z", "lastRunJobIds": ["8337900a-0fc6-4f53-a13e-89540fb03d2e"]}, "5919d4fa-644f-4ffc-8541-d258e987b379": {"workflowId": "5919d4fa-644f-4ffc-8541-d258e987b379", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:03:01.398456Z", "updated": "2026-02-23T22:03:01.503931Z", "lastRunAt": "2026-02-23T22:03:01.503931Z", "lastRunJobIds": ["d42e8fc4-1023-453c-9aae-8c33141ca838"]}, "90ee914e-925d-4775-bbdb-8489f79e6b2d": {"workflowId": "90ee914e-925d-4775-bbdb-8489f79e6b2d", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:03:34.858713Z", "updated": "2026-02-23T22:03:34.964026Z", "lastRunAt": "2026-02-23T22:03:34.964026Z", "lastRunJobIds": ["d6098fe4-5916-4d3b-b540-de1076f51c8d"]}, "364063da-5825-4303-9736-51baf8692530": {"workflowId": "364063da-5825-4303-9736-51baf8692530", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:04:09.181686Z", "updated": "2026-02-23T22:04:09.290683Z", "lastRunAt": "2026-02-23T22:04:09.290683Z", "lastRunJobIds": ["fb84e869-28c5-4187-b963-62a0f0ddb0d0"]}, "9be46657-dc95-4197-b520-034877ad53fd": {"workflowId": "9be46657-dc95-4197-b520-034877ad53fd", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:05:26.277030Z", "updated": "2026-02-23T22:05:26.385208Z", "lastRunAt": "2026-02-23T22:05:26.385208Z", "lastRunJobIds": ["8eee9f98-bab7-43d9-a8ea-6d7d0f8c5bff"]}, "5b2d0e9f-a83b-46a1-bac0-93d7693df940": {"workflowId": "5b2d0e9f-a83b-46a1-bac0-93d7693df940", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:06:19.984497Z", "updated": "2026-02-23T22:06:20.090912Z", "lastRunAt": "2026-02-23T22:06:20.090912Z", "lastRunJobIds": ["a0138e99-87f4-4213-b003-53e4435d2191"]}, "99f60372-418b-4205-b3e1-0f95b8c47ec3": {"workflowId": "99f60372-418b-4205-b3e1-0f95b8c47ec3", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:07:10.279699Z", "updated": "2026-02-23T22:07:10.388391Z", "lastRunAt": "2026-02-23T22:07:10.388391Z", "lastRunJobIds": ["07711cbe-a49b-43ec-b9f5-a47ff809a637"]}, "d122ebc8-c984-41dc-a867-25507acedb91": {"workflowId": "d122ebc8-c984-41dc-a867-25507acedb91", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:08:25.837044Z", "updated": "2026-02-23T22:08:25.948539Z", "lastRunAt": "2026-02-23T22:08:25.948539Z", "lastRunJobIds": ["e3f2a3ef-efb8-4a71-a892-437463f84e13"]}, "8615178b-17c8-434f-842b-e9f13b745301": {"workflowId": "8615178b-17c8-434f-842b-e9f13b745301", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:10:11.462031Z", "updated": "2026-02-23T22:10:11.573452Z", "lastRunAt": "2026-02-23T22:10:11.573452Z", "lastRunJobIds": ["3bc40154-66d2-44b8-bf8a-3c931d7ce92a"]}, "696e988e-0e0d-4e2a-8bd2-9e6109ae798d": {"workflowId": "696e988e-0e0d-4e2a-8bd2-9e6109ae798d", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:12:27.421003Z", "updated": "2026-02-23T22:12:27.537998Z", "lastRunAt": "2026-02-23T22:12:27.537998Z", "lastRunJobIds": ["faaa0822-0996-42aa-9b4a-09db3b38b253"]}, "76b22e29-d03d-41cc-8afd-1f6d98c904b8": {"workflowId": "76b22e29-d03d-41cc-8afd-1f6d98c904b8", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:13:55.274478Z", "updated": "2026-02-23T22:13:55.383149Z", "lastRunAt": "2026-02-23T22:13:55.383149Z", "lastRunJobIds": ["89f1748d-a2ff-4fb4-bad4-034af929932e"]}, "f94af166-6944-45d6-b972-4500feec0eec": {"workflowId": "f94af166-6944-45d6-b972-4500feec0eec", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:15:40.229164Z", "updated": "2026-02-23T22:15:40.343668Z", "lastRunAt": "2026-02-23T22:15:40.343668Z", "lastRunJobIds": ["a0aa8517-0ec2-4b4a-86c0-5645c4077a6b"]}, "ba8a6537-d7a7-4062-b169-bc65113cbb8c": {"workflowId": "ba8a6537-d7a7-4062-b169-bc65113cbb8c", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:16:56.821962Z", "updated": "2026-02-23T22:16:56.938046Z", "lastRunAt": "2026-02-23T22:16:56.938046Z", "lastRunJobIds": ["9a34fb59-d815-4107-9c6b-d3207704d83a"]}, "5a390470-b37d-45b2-9633-8435c0167424": {"workflowId": "5a390470-b37d-45b2-9633-8435c0167424", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-23T22:18:09.699497Z", "updated": "2026-02-23T22:18:09.812445Z", "lastRunAt": "2026-02-23T22:18:09.812445Z", "lastRunJobIds": ["50f69ac8-ca39-4892-bf3c-2921221183b8"]}, "a1ef8b41-460c-40ba-a219-aef155d1e67e": {"workflowId": "a1ef8b41-460c-40ba-a219-aef155d1e67e", "name": "scheduled-workflow", "steps": [{"name": "aggregate", "processId": "eo-aggregate-import", "payload": {"inputs": {"datasetId": "chirps-daily", "parameters": ["precip"], "datetime": "2026-01-31T00:00:00Z", "orgUnitLevel": 2, "aggregation": "mean", "dhis2": {"dataElementId": "abc123", "dryRun": true}}}}], "created": "2026-02-24T11:01:17.113543Z", "updated": "2026-02-24T11:01:17.228929Z", "lastRunAt": "2026-02-24T11:01:17.228929Z", "lastRunJobIds": ["30fe9414-3c22-4ec1-bad6-19a2890bfaf2"]}} \ No newline at end of file diff --git a/ORCHESTRATION_DECISION.md b/ORCHESTRATION_DECISION.md new file mode 100644 index 0000000..ff40004 --- /dev/null +++ b/ORCHESTRATION_DECISION.md @@ -0,0 +1,80 @@ +# Orchestration Decision Scorecard + +## Purpose + +Select the primary orchestrator for eo-api scheduled and long-running execution. + +Options compared: + +- Prefect +- Airflow +- Dagster +- Temporal +- Argo Workflows +- Internal scheduler only + +## Scoring model + +- Scale: 1 (weak) to 5 (strong) +- Weighted score = score × weight +- Weights reflect current eo-api phase (MVP to near-production) + +| Criterion | Weight | +|---|---:| +| API-triggered integration fit | 20 | +| Time to production | 15 | +| Operations overhead | 15 | +| Reliability and retries | 15 | +| Governance and auditability | 10 | +| Developer productivity | 10 | +| Scalability and parallelism | 10 | +| Cost predictability | 5 | +| **Total** | **100** | + +## Results + +| Option | API fit (20) | Time (15) | Ops (15) | Reliability (15) | Governance (10) | Dev speed (10) | Scale (10) | Cost (5) | **Weighted total / 100** | +|---|---:|---:|---:|---:|---:|---:|---:|---:|---:| +| **Prefect** | 5 | 5 | 4 | 4 | 3 | 5 | 4 | 4 | **87** | +| **Dagster** | 3 | 3 | 3 | 4 | 4 | 4 | 4 | 3 | **68** | +| **Airflow** | 3 | 3 | 2 | 4 | 5 | 3 | 5 | 3 | **67** | +| **Temporal** | 4 | 2 | 3 | 5 | 3 | 2 | 5 | 3 | **66** | +| **Argo Workflows** | 3 | 2 | 3 | 4 | 3 | 2 | 5 | 3 | **61** | +| **Internal scheduler only** | 2 | 5 | 5 | 2 | 1 | 4 | 2 | 5 | **59** | + +## Recommendation + +### Primary now + +- **Use Prefect as the primary orchestrator** for eo-api. +- Keep the internal scheduler enabled as fallback for simple local/dev operation. + +### Why + +- Strongest fit with current API-driven execution design. +- Lowest implementation friction in this repository today. +- Good reliability and operational controls without Airflow-level overhead. + +## Re-evaluation triggers + +Re-run this decision if one or more of these become true: + +- Organization mandates a central Airflow platform for all production data pipelines. +- Multi-team governance, strict lineage, or compliance reporting dominates requirements. +- Workflow complexity shifts to very long-lived, stateful business processes. +- eo-api run volume and fan-out exceed current orchestration/operator capacity. + +## Practical adoption plan + +1. Keep Prefect as default orchestration backend. +2. Preserve adapter-style boundary in eo-api so alternate orchestrators can be added. +3. Review quarterly using real metrics: + - schedule success rate + - mean time to recovery + - operator effort per week + - backfill effort and failure rate + +## Notes + +- Scores are tuned for current project context, not universal. +- If enterprise governance is weighted higher than implementation speed, Airflow can become the preferred option. diff --git a/PRESENTATION_EXECUTIVE.md b/PRESENTATION_EXECUTIVE.md index 169a362..3a8cccf 100644 --- a/PRESENTATION_EXECUTIVE.md +++ b/PRESENTATION_EXECUTIVE.md @@ -109,6 +109,27 @@ Outputs include: --- +# 6b) Orchestrator scorecard (weighted) + +Scoring basis: +- 1–5 score scale across API fit, time to production, ops overhead, reliability, governance, dev speed, scale, and cost. + +| Option | Weighted total (/100) | +|---|---:| +| Prefect | **87** | +| Dagster | 68 | +| Airflow | 67 | +| Temporal | 66 | +| Argo Workflows | 61 | +| Internal scheduler only | 59 | + +Decision for current phase: +- Choose **Prefect** as primary orchestrator. +- Keep internal scheduler as fallback. +- Re-evaluate if enterprise governance constraints become dominant. + +--- + # 7) Operational resilience - Durable local persistence for jobs/schedules/workflows diff --git a/README.md b/README.md index 20e0fd1..816c3c2 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ This app demonstrates creating and running scheduled imports (for example nightl - Runtime summary example for `GET /`: [`API_EXAMPLES.md#landing-page-runtime-summary`](API_EXAMPLES.md#landing-page-runtime-summary) - Project presentation deck: [`PRESENTATION.md`](PRESENTATION.md) - Executive presentation deck (10 slides): [`PRESENTATION_EXECUTIVE.md`](PRESENTATION_EXECUTIVE.md) +- Orchestration tool decision scorecard: [`ORCHESTRATION_DECISION.md`](ORCHESTRATION_DECISION.md) - Dataset schema and resolver conventions: [`eoapi/datasets/README.md`](eoapi/datasets/README.md) - Product requirements and scope: [`PRD.md`](PRD.md) - Prefect orchestration design: [`PREFECT_INTEGRATION.md`](PREFECT_INTEGRATION.md) From f15bc10363b122dde5640f95bd5d1cbe5e924f80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Sandvik?= Date: Tue, 24 Feb 2026 13:10:00 +0100 Subject: [PATCH 13/13] Orchestration desition --- API_EXAMPLES.md | 34 +++++++++++++++++----------------- ORCHESTRATION_DECISION.md | 38 +++++++++++++++++++------------------- PRESENTATION.md | 13 +++++++++++++ PRESENTATION_EXECUTIVE.md | 23 +++++++++++++++-------- 4 files changed, 64 insertions(+), 44 deletions(-) diff --git a/API_EXAMPLES.md b/API_EXAMPLES.md index 6f2103f..c25d58e 100644 --- a/API_EXAMPLES.md +++ b/API_EXAMPLES.md @@ -24,23 +24,23 @@ Example runtime payload: ```json { - "cors": { - "mode": "wildcard", - "origins": 1 - }, - "apiKeyRequired": false, - "dhis2": { - "configured": false, - "host": "unset", - "authMode": "none" - }, - "state": { - "persistenceEnabled": true, - "directory": ".cache/state" - }, - "internalScheduler": { - "enabled": true - } + "cors": { + "mode": "wildcard", + "origins": 1 + }, + "apiKeyRequired": false, + "dhis2": { + "configured": false, + "host": "unset", + "authMode": "none" + }, + "state": { + "persistenceEnabled": true, + "directory": ".cache/state" + }, + "internalScheduler": { + "enabled": true + } } ``` diff --git a/ORCHESTRATION_DECISION.md b/ORCHESTRATION_DECISION.md index ff40004..9b2e6c4 100644 --- a/ORCHESTRATION_DECISION.md +++ b/ORCHESTRATION_DECISION.md @@ -19,28 +19,28 @@ Options compared: - Weighted score = score × weight - Weights reflect current eo-api phase (MVP to near-production) -| Criterion | Weight | -|---|---:| -| API-triggered integration fit | 20 | -| Time to production | 15 | -| Operations overhead | 15 | -| Reliability and retries | 15 | -| Governance and auditability | 10 | -| Developer productivity | 10 | -| Scalability and parallelism | 10 | -| Cost predictability | 5 | -| **Total** | **100** | +| Criterion | Weight | +| ----------------------------- | ------: | +| API-triggered integration fit | 20 | +| Time to production | 15 | +| Operations overhead | 15 | +| Reliability and retries | 15 | +| Governance and auditability | 10 | +| Developer productivity | 10 | +| Scalability and parallelism | 10 | +| Cost predictability | 5 | +| **Total** | **100** | ## Results -| Option | API fit (20) | Time (15) | Ops (15) | Reliability (15) | Governance (10) | Dev speed (10) | Scale (10) | Cost (5) | **Weighted total / 100** | -|---|---:|---:|---:|---:|---:|---:|---:|---:|---:| -| **Prefect** | 5 | 5 | 4 | 4 | 3 | 5 | 4 | 4 | **87** | -| **Dagster** | 3 | 3 | 3 | 4 | 4 | 4 | 4 | 3 | **68** | -| **Airflow** | 3 | 3 | 2 | 4 | 5 | 3 | 5 | 3 | **67** | -| **Temporal** | 4 | 2 | 3 | 5 | 3 | 2 | 5 | 3 | **66** | -| **Argo Workflows** | 3 | 2 | 3 | 4 | 3 | 2 | 5 | 3 | **61** | -| **Internal scheduler only** | 2 | 5 | 5 | 2 | 1 | 4 | 2 | 5 | **59** | +| Option | API fit (20) | Time (15) | Ops (15) | Reliability (15) | Governance (10) | Dev speed (10) | Scale (10) | Cost (5) | **Weighted total / 100** | +| --------------------------- | -----------: | --------: | -------: | ---------------: | --------------: | -------------: | ---------: | -------: | -----------------------: | +| **Prefect** | 5 | 5 | 4 | 4 | 3 | 5 | 4 | 4 | **87** | +| **Dagster** | 3 | 3 | 3 | 4 | 4 | 4 | 4 | 3 | **68** | +| **Airflow** | 3 | 3 | 2 | 4 | 5 | 3 | 5 | 3 | **67** | +| **Temporal** | 4 | 2 | 3 | 5 | 3 | 2 | 5 | 3 | **66** | +| **Argo Workflows** | 3 | 2 | 3 | 4 | 3 | 2 | 5 | 3 | **61** | +| **Internal scheduler only** | 2 | 5 | 5 | 2 | 1 | 4 | 2 | 5 | **59** | ## Recommendation diff --git a/PRESENTATION.md b/PRESENTATION.md index 0a92193..913acdd 100644 --- a/PRESENTATION.md +++ b/PRESENTATION.md @@ -6,6 +6,7 @@ title: DHIS2 EO API --- # DHIS2 EO API + ## Unified Earth Observation processing for DHIS2 and CHAP - Standards-aligned geospatial API for discovery, processing, and ingestion @@ -17,10 +18,12 @@ title: DHIS2 EO API # Why this API exists ## Problem + - EO and climate workflows are often fragmented across scripts and tools - Hard to repeat, schedule, validate, and operationalize at scale ## Goal + - One API surface for: - Dataset discovery - EO processing @@ -80,6 +83,7 @@ flowchart LR # OGC APIs used: what, how, why Used in this API: + - **OGC API - Common**: landing page + collection discovery (`/`, `/collections`) - **OGC API - Coverages**: gridded raster access (`/collections/{id}/coverage`) - **OGC API - EDR**: direct query patterns for point/area extraction (`/position`, `/area`) @@ -87,12 +91,14 @@ Used in this API: - **OGC API - Processes (style)**: process catalog + execution (`/processes/*`) How they relate: + - `Common` provides dataset identities and link relations - `Coverages` + `EDR` are complementary views over the same collections - `Processes` consume collection-based inputs and emit job/output links - `Features` carries both input geometries and process outputs Why this mix: + - Interoperability with geospatial tools and ecosystem clients - Predictable contracts for DHIS2 Maps/Climate integration - Composable workflow model (discover → query → process → import) @@ -130,12 +136,14 @@ flowchart TB # Endpoint map ## Discovery and standards + - GET / - GET /conformance - GET /collections - GET /collections/{collectionId} ## Data access + - GET /collections/{collectionId}/coverage - GET /collections/{collectionId}/position - GET /collections/{collectionId}/area @@ -143,12 +151,14 @@ flowchart TB - GET /features/{collectionId}/items ## Execution + - GET /processes - GET /processes/{processId} - POST /processes/{processId}/execution - GET /jobs/{jobId} ## Orchestration + - CRUD /workflows + POST /workflows/{workflowId}/run - CRUD /schedules + POST /schedules/{scheduleId}/run @@ -173,6 +183,7 @@ flowchart TB - xclim-warm-days Each process produces: + - Import summary - Feature outputs - Traceable job status @@ -203,10 +214,12 @@ Each process produces: # Scheduling options ## Internal scheduler + - Poll-based cron worker built into API process - Runs enabled schedules at due times ## Prefect integration + - Optional offloading of schedule runs to Prefect deployments - Job status can sync from Prefect flow states diff --git a/PRESENTATION_EXECUTIVE.md b/PRESENTATION_EXECUTIVE.md index 3a8cccf..d9c13ff 100644 --- a/PRESENTATION_EXECUTIVE.md +++ b/PRESENTATION_EXECUTIVE.md @@ -6,6 +6,7 @@ title: DHIS2 EO API — Executive Brief --- # DHIS2 EO API + ## Executive Brief (10 slides) - Unified API for Earth Observation data into DHIS2 and CHAP @@ -49,6 +50,7 @@ flowchart LR # 4) OGC APIs used: what, how, why Used in this API: + - **OGC API - Common**: landing page + collection discovery (`/`, `/collections`) - **OGC API - Coverages**: gridded raster access (`/collections/{id}/coverage`) - **OGC API - EDR**: direct query patterns for point/area extraction (`/position`, `/area`) @@ -56,12 +58,14 @@ Used in this API: - **OGC API - Processes (style)**: process catalog + execution (`/processes/*`) How they relate: + - `Common` provides dataset identities and links - `Coverages` + `EDR` are complementary views over the same collections - `Processes` consume collection-driven inputs and publish job/output links - `Features` carries both input geometries (org units) and process outputs Why this mix: + - Interoperability with geospatial tools and clients - Predictable contracts for DHIS2 Maps/Climate integration - Composable architecture (discover → query → process → import) @@ -94,6 +98,7 @@ flowchart TB - `xclim-warm-days` Outputs include: + - Import summary - Feature-level results - Traceable job state @@ -112,18 +117,20 @@ Outputs include: # 6b) Orchestrator scorecard (weighted) Scoring basis: + - 1–5 score scale across API fit, time to production, ops overhead, reliability, governance, dev speed, scale, and cost. -| Option | Weighted total (/100) | -|---|---:| -| Prefect | **87** | -| Dagster | 68 | -| Airflow | 67 | -| Temporal | 66 | -| Argo Workflows | 61 | -| Internal scheduler only | 59 | +| Option | Weighted total (/100) | +| ----------------------- | --------------------: | +| Prefect | **87** | +| Dagster | 68 | +| Airflow | 67 | +| Temporal | 66 | +| Argo Workflows | 61 | +| Internal scheduler only | 59 | Decision for current phase: + - Choose **Prefect** as primary orchestrator. - Keep internal scheduler as fallback. - Re-evaluate if enterprise governance constraints become dominant.