Retail — demand & replenishment
The problem. A retail chain spans regions, each with stores, each tracking sales and stock per SKU. Regional teams must see their numbers and only their numbers, while head office rolls everything up. The data is one big stream; the requirement is clean separation by region — for access, for ownership, for reporting.
This scenario centres on datasets as the unit of segmentation: give each region its own, tag everything with it, and the partitioning falls out for free.
Set up demo data
New workspace? Run this once (Python) to create the region's dataset and a store's SKU sales series with a month of daily units. Safe to re-run.
import datahub_sdk, numpy as np, pandas as pd
client = datahub_sdk.DataHubClient.from_env()
region_id = client.datasets.create([datahub_sdk.Dataset(external_id="region_nordics", name="Nordics region")])[0].id
client.timeseries.create([datahub_sdk.TimeSeries(external_id="store_oslo_01_sku_4471_sales",
name="Oslo-01 SKU 4471 units sold", unit="units", value_type="float", data_set_id=region_id)])
idx = pd.date_range(end=pd.Timestamp.now(tz="UTC"), periods=30, freq="1d")
client.timeseries.insert_from_lists(timestamps=idx, values=np.random.poisson(40, 30).astype(float),
ts="store_oslo_01_sku_4471_sales")
1. A dataset per region
Create a dataset for each region; every series the region owns carries its
data_set_id.
- Java
- Python
- Rust
DataSetModel region = new DataSetModel();
region.setExternalId("region_nordics");
region.setName("Nordics region");
long regionId = client.datasets().create(List.of(region))
.getItems().iterator().next().getId();
var salesSeries = Timeseries.of("store_oslo_01_sku_4471_sales")
.name("Oslo 01 — SKU 4471 units sold")
.setDataSetId(regionId);
salesSeries.setUnit("units");
client.timeseries().create(salesSeries);
import datahub_sdk
region_id = client.datasets.create([
datahub_sdk.Dataset(external_id="region_nordics", name="Nordics region")])[0].id
client.timeseries.create([datahub_sdk.TimeSeries(
external_id="store_oslo_01_sku_4471_sales",
name="Oslo 01 — SKU 4471 units sold", unit="units", value_type="float", data_set_id=region_id)])
use dataplatform_rust_sdk::datasets::Dataset;
use dataplatform_rust_sdk::timeseries::TimeSeries;
// Dataset::new derives external_id as snake_case → set it explicitly to match
let mut ds = Dataset::new("Nordics region".into());
ds.external_id = "region_nordics".into();
let created = api.datasets.create(&vec![ds]).await?;
let region_id = created.get_items()[0].id;
let mut ts = TimeSeries::new("store_oslo_01_sku_4471_sales", "Oslo 01 — SKU 4471 units sold");
ts.unit = Some("units".into());
ts.data_set_id = region_id;
api.time_series.create_one(&ts).await?;
2. Roll up demand per region
Each region lists or filters by its own dataset, then aggregates daily sales to feed replenishment. See Datasets reference and Query & aggregate.
- Java
- Python
- Rust
DataSetRetreiver retriever = new DataSetRetreiver();
retriever.getFilter().setExternalIdPrefix("region_nordics"); // scope to the region's dataset
DataWrapper<DataSetModel> regional = client.datasets().list(retriever);
regional = client.datasets.by_ids(["region_nordics"])
use dataplatform_rust_sdk::generic::IdAndExtId;
let regional = api.datasets.by_ids(&vec![IdAndExtId::from_external_id("region_nordics")]).await?;
3. Trigger replenishment
When a store's on-hand for a SKU falls below its reorder point, raise a reorder
event carrying the store, SKU and suggested quantity — the
replenishment system acts on it, scoped to the region's dataset.
See the result
Chart the SKU's daily sales — the demand signal replenishment runs on:
import matplotlib.pyplot as plt
rf = datahub_sdk.RetrieveFilter(ts="store_oslo_01_sku_4471_sales",
start=pd.Timestamp.now(tz="UTC") - pd.Timedelta(days=30), end=pd.Timestamp.now(tz="UTC"),
aggregates=["sum"], granularity="1d")
sales = [dp.sum for dp in client.timeseries.retrieve_datapoints(rf)[0].get_datapoints()]
plt.bar(range(len(sales)), sales); plt.title("Oslo-01 SKU 4471 daily units sold"); plt.show()
See also
- Datasets reference — segmentation and access by region.
- Query & aggregate — demand roll-ups.
- Turn readings into events — the reorder rule.
- Demand forecasting (advanced) — forecast demand to drive replenishment ahead of the shelf going empty.