Net revenue
$12.55MSource: Commercial KPI summary
Revenue after returns and discounts.
Deterministic query executed by scripts/build_analytics_projects.py.
Data Analytics dashboard
A decision-focused synthetic FMCG commercial analytics dashboard.
Decision: where should a fictional commercial team reallocate next-quarter promotion investment while protecting net revenue and gross margin?
Deterministic synthetic portfolio data · snapshot 30 Jun 2026 · no employer or customer information.
Net revenue
$12.55MSource: Commercial KPI summary
Revenue after returns and discounts.
Deterministic query executed by scripts/build_analytics_projects.py.
Vs budget
-0.9%Source: Commercial KPI summary
Actual net revenue versus the complete-period budget.
Deterministic query executed by scripts/build_analytics_projects.py.
Gross margin
61.5%Source: Commercial KPI summary
Weighted gross profit divided by net revenue.
Deterministic query executed by scripts/build_analytics_projects.py.
Net units
4.16MSource: Commercial KPI summary
Gross units less returned units.
Deterministic query executed by scripts/build_analytics_projects.py.
Forecast WAPE
2.2%Source: Commercial KPI summary
Absolute locked-forecast unit error divided by actual units; lower is better.
Deterministic query executed by scripts/build_analytics_projects.py.
Deterministic query executed by scripts/build_analytics_projects.py.
| Month | Actual Revenue | Budget Revenue |
|---|---|---|
| 2025-01 | $575.79K | $581.95K |
| 2025-02 | $539.3K | $544.21K |
| 2025-03 | $651.74K | $656.77K |
| 2025-04 | $664.03K | $670.14K |
| 2025-05 | $759.24K | $764.11K |
| 2025-06 | $770.1K | $775.86K |
| 2025-07 | $828.45K | $833.53K |
| 2025-08 | $799.63K | $806.81K |
| 2025-09 | $673.83K | $679.47K |
| 2025-10 | $669.53K | $674.28K |
| 2025-11 | $711.18K | $714.43K |
| 2025-12 | $812.8K | $817.48K |
| 2026-01 | $601.76K | $606.45K |
| 2026-02 | $561.46K | $565.62K |
| 2026-03 | $674.52K | $681.26K |
| 2026-04 | $691.32K | $696.45K |
| 2026-05 | $765.59K | $794.43K |
| 2026-06 | $800.77K | $806.12K |
Deterministic query executed by scripts/build_analytics_projects.py.
| Market | Net revenue | Gross margin | Vs budget |
|---|---|---|---|
| Central | $3.7MSource: Market performance | 61.8%Source: Market performance | -0.9%Source: Market performance |
| North | $3.62MSource: Market performance | 63.6%Source: Market performance | -0.8%Source: Market performance |
| South | $2.8MSource: Market performance | 59.3%Source: Market performance | -1%Source: Market performance |
| West | $2.44MSource: Market performance | 60.6%Source: Market performance | -1.1%Source: Market performance |
Recommendation: Run a bounded next-quarter test in the 10%Source: Promotion effectiveness band (modeled weighted ROI 24.5%Source: Promotion effectiveness); keep the modeled baseline and margin guardrail visible before scaling.
Deterministic query executed by scripts/build_analytics_projects.py.
Deterministic query executed by scripts/build_analytics_projects.py.
| Discount Band | Promotion Roi |
|---|---|
| 10% | 24.5% |
| 15% | 7.9% |
| 20% | 1.4% |
| 30% | -41.6% |
Deterministic query executed by scripts/build_analytics_projects.py.
| Discount band | Weighted ROI | Modeled unit uplift | Incremental profit | Investment |
|---|---|---|---|---|
| 10% | 24.5%Source: Promotion effectiveness | 45.4%Source: Promotion effectiveness | $1.78KSource: Promotion effectiveness | $7.28KSource: Promotion effectiveness |
| 15% | 7.9%Source: Promotion effectiveness | 57.8%Source: Promotion effectiveness | $761.42Source: Promotion effectiveness | $9.66KSource: Promotion effectiveness |
| 20% | 1.4%Source: Promotion effectiveness | 71.5%Source: Promotion effectiveness | $185.82Source: Promotion effectiveness | $12.89KSource: Promotion effectiveness |
| 30% | -41.6%Source: Promotion effectiveness | 54.6%Source: Promotion effectiveness | -$7.65KSource: Promotion effectiveness | $18.41KSource: Promotion effectiveness |
Deterministic query executed by scripts/build_analytics_projects.py.
| Product Name | Net Revenue |
|---|---|
| Luma Granola | $982.48K |
| Luma Oats | $885.71K |
| Orbit Bites | $874.86K |
| Vela Mix | $873.26K |
| Aster Crunch | $864.71K |
| Halo Muesli | $857.83K |
| Northstar Porridge | $794.52K |
| Aster Sparkling | $755.2K |
| Orbit Bar | $736.67K |
| Vela Citrus | $735.08K |
| Vela Protein Shake | $726.03K |
| Aster Still | $724.21K |
| Luma Oat Drink | $715.86K |
| Vela Berry | $709.9K |
| Halo Almond Drink | $683.03K |
| Orbit Plant Snack | $631.69K |
Deterministic query executed by scripts/build_analytics_projects.py.
| Product | Category | Net revenue | Gross margin | Vs budget | Net units |
|---|---|---|---|---|---|
| Luma Granola | Breakfast | $982.48KSource: Product decision detail | 59.3%Source: Product decision detail | -0.8%Source: Product decision detail | 215.66KSource: Product decision detail |
| Luma Oats | Breakfast | $885.71KSource: Product decision detail | 61.2%Source: Product decision detail | -0.7%Source: Product decision detail | 235.15KSource: Product decision detail |
| Orbit Bites | Snacks | $874.86KSource: Product decision detail | 64%Source: Product decision detail | -0.2%Source: Product decision detail | 304.65KSource: Product decision detail |
| Vela Mix | Snacks | $873.26KSource: Product decision detail | 61.9%Source: Product decision detail | -0.7%Source: Product decision detail | 244.69KSource: Product decision detail |
| Aster Crunch | Snacks | $864.71KSource: Product decision detail | 62.4%Source: Product decision detail | -0.6%Source: Product decision detail | 264.74KSource: Product decision detail |
| Halo Muesli | Breakfast | $857.83KSource: Product decision detail | 59.5%Source: Product decision detail | -0.9%Source: Product decision detail | 176.73KSource: Product decision detail |
| Northstar Porridge | Breakfast | $794.52KSource: Product decision detail | 60.4%Source: Product decision detail | -3.4%Source: Product decision detail | 191.4KSource: Product decision detail |
| Aster Sparkling | Hydration | $755.2KSource: Product decision detail | 64.6%Source: Product decision detail | -0.6%Source: Product decision detail | 347.39KSource: Product decision detail |
| Orbit Bar | Snacks | $736.67KSource: Product decision detail | 65.1%Source: Product decision detail | -1.3%Source: Product decision detail | 437.15KSource: Product decision detail |
| Vela Citrus | Hydration | $735.08KSource: Product decision detail | 63.5%Source: Product decision detail | -0.6%Source: Product decision detail | 284.97KSource: Product decision detail |
| Vela Protein Shake | Plant-Based | $726.03KSource: Product decision detail | 56.3%Source: Product decision detail | -1.2%Source: Product decision detail | 166.57KSource: Product decision detail |
| Aster Still | Hydration | $724.21KSource: Product decision detail | 64.8%Source: Product decision detail | -1%Source: Product decision detail | 405.7KSource: Product decision detail |
| Luma Oat Drink | Plant-Based | $715.86KSource: Product decision detail | 59.1%Source: Product decision detail | -0.6%Source: Product decision detail | 225.69KSource: Product decision detail |
| Vela Berry | Hydration | $709.9KSource: Product decision detail | 63.2%Source: Product decision detail | -0.5%Source: Product decision detail | 265.41KSource: Product decision detail |
| Halo Almond Drink | Plant-Based | $683.03KSource: Product decision detail | 58.3%Source: Product decision detail | -0.9%Source: Product decision detail | 186.3KSource: Product decision detail |
16 results · Showing first 15
Deterministic query executed by scripts/build_analytics_projects.py.
| Check | Status | Evidence |
|---|---|---|
| All four planned discount bands are represented | PASS | 4 bands |
| Daily sales grain is unique | PASS | 139,776 rows; 0 duplicates |
| Dashboard and SQL totals agree | PASS | Exact to €0.01 |
| Discount depth is not confounded with one execution mechanic | PASS | 4 mechanics represented in every discount band |
| Every sales slice has one budget and locked forecast | PASS | 4,608 matched slices |
| Forecast is locked before each reporting month | PASS | 0 invalid lock dates |
| Net revenue formula reconciles | PASS | 0 rows outside €0.01 tolerance |
| Promotion dates are valid | PASS | 0 invalid windows |
| Returns never exceed gross units | PASS | 0 violations |
Promotion baselines are modeled, so ROI is scenario analysis rather than a causal experiment. Budget and actual cover the same complete period. Exact formulas, SQL, data dictionary, notebook and QA evidence are included beside this dashboard.
Deterministic query executed by scripts/build_analytics_projects.py.
WITH actual_by_slice AS (
SELECT month, sku_id, market, channel,
SUM(net_units) AS actual_units,
SUM(net_revenue_eur) AS net_revenue,
SUM(gross_profit_eur) AS gross_profit
FROM fact_sales GROUP BY month, sku_id, market, channel
), actual AS (
SELECT SUM(net_revenue) AS net_revenue,
SUM(gross_profit) AS gross_profit,
SUM(actual_units) AS net_units,
SUM(ABS(actual_units - forecast_units)) AS absolute_forecast_error,
SUM(actual_units) AS actual_units
FROM actual_by_slice
JOIN fact_budget_forecast USING (month, sku_id, market, channel)
), plan AS (
SELECT SUM(budget_revenue_eur) AS budget_revenue FROM fact_budget_forecast
)
SELECT ROUND(net_revenue, 2) AS net_revenue,
ROUND((net_revenue - budget_revenue) / budget_revenue, 6) AS budget_variance_rate,
ROUND(gross_profit / net_revenue, 6) AS gross_margin_rate,
net_units,
ROUND(absolute_forecast_error * 1.0 / actual_units, 6) AS forecast_wape
FROM actual CROSS JOIN plan;Deterministic query executed by scripts/build_analytics_projects.py.
SELECT s.month,
ROUND(SUM(s.net_revenue_eur), 2) AS actual_revenue,
ROUND(MAX(b.budget_revenue), 2) AS budget_revenue,
ROUND(SUM(s.gross_profit_eur), 2) AS gross_profit
FROM fact_sales s
JOIN (SELECT month, SUM(budget_revenue_eur) AS budget_revenue
FROM fact_budget_forecast GROUP BY month) b ON b.month = s.month
GROUP BY s.month ORDER BY s.month;Deterministic query executed by scripts/build_analytics_projects.py.
WITH budgets AS (
SELECT market, SUM(budget_revenue_eur) AS budget_revenue
FROM fact_budget_forecast GROUP BY market
)
SELECT s.market,
ROUND(SUM(s.net_revenue_eur), 2) AS net_revenue,
ROUND(SUM(s.gross_profit_eur) / SUM(s.net_revenue_eur), 6) AS gross_margin_rate,
ROUND((SUM(s.net_revenue_eur) - MAX(b.budget_revenue)) / MAX(b.budget_revenue), 6) AS budget_variance_rate
FROM fact_sales s JOIN budgets b ON b.market = s.market
GROUP BY s.market ORDER BY net_revenue DESC;Deterministic query executed by scripts/build_analytics_projects.py.
SELECT CASE
WHEN discount_pct < .125 THEN '10%'
WHEN discount_pct < .175 THEN '15%'
WHEN discount_pct < .25 THEN '20%'
ELSE '30%'
END AS discount_band,
ROUND(AVG(discount_pct), 4) AS discount_pct,
ROUND(SUM(incremental_profit_eur), 2) AS incremental_profit_eur,
ROUND(SUM(promotion_investment_eur), 2) AS promotion_investment_eur,
ROUND(SUM(incremental_profit_eur) / SUM(promotion_investment_eur), 6) AS promotion_roi,
ROUND(SUM(actual_units - baseline_units) * 1.0 / SUM(baseline_units), 6) AS unit_uplift_pct
FROM fact_promotion GROUP BY discount_band ORDER BY discount_pct;Deterministic query executed by scripts/build_analytics_projects.py.
WITH budgets AS (
SELECT sku_id, SUM(budget_revenue_eur) AS budget_revenue
FROM fact_budget_forecast GROUP BY sku_id
)
SELECT s.sku_id, MAX(s.product_name) AS product_name, MAX(s.category) AS category,
ROUND(SUM(s.net_revenue_eur), 2) AS net_revenue,
ROUND(SUM(s.gross_profit_eur) / SUM(s.net_revenue_eur), 6) AS gross_margin_rate,
ROUND((SUM(s.net_revenue_eur) - MAX(b.budget_revenue)) / MAX(b.budget_revenue), 6) AS budget_variance_rate,
SUM(s.net_units) AS net_units
FROM fact_sales s JOIN budgets b ON b.sku_id = s.sku_id
GROUP BY s.sku_id ORDER BY net_revenue DESC;Deterministic query executed by scripts/build_analytics_projects.py.
SELECT "check" AS "check", status, result FROM quality_checks ORDER BY "check";