A production-grade inventory management engine built for distribution agencies. Combines ABC analysis, safety stock modelling, reorder point calculation, and ML demand forecasting into a single automated pipeline โ with Tableau-ready outputs.
Distribution agencies face a constant tension between two costly mistakes:
| Problem | Business Impact |
|---|---|
| Stockouts | Lost sales, damaged customer relationships, emergency restocking costs |
| Overstocking | Tied-up working capital, storage costs, spoilage (especially perishables) |
This tool answers three precise questions every week:
- What do we need to reorder? (ABC Analysis)
- When do we place the order? (Reorder Point)
- How much do we order? (EOQ + Safety Stock)
- What will demand look like? (ML Forecasting)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ DATA LAYER (PostgreSQL) โ
โ products โโ sales_transactions โโ current_inventory โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PYTHON PIPELINE (4 steps) โ
โ โ
โ [1] generate_data.py โ Synthetic sales (6 months, 10 SKU)โ
โ [2] optimization.py โ ABC + Safety Stock + ROP + EOQ โ
โ [3] forecasting.py โ Linear Regression (7-day horizon) โ
โ [4] export_insights.py โ Merge โ inventory_insights table โ
โโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ TABLEAU DASHBOARD (5 sheets) โ
โ ABC Revenue โ Reorder Alerts โ Trend โ Forecast โ KPI Cards โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
smart-inventory-tool/
โ
โโโ 01_schema.sql โ PostgreSQL DDL (tables + views)
โโโ 02_generate_data.py โ Synthetic data generator
โโโ 03_optimization_engine.py โ Core inventory algorithms
โโโ 04_forecasting.py โ ML demand forecasting
โโโ 05_export_insights.py โ Final merge + export
โโโ run_all.py โ One-click pipeline runner
โโโ requirements.txt
โโโ README.md
โ
โโโ output/ โ Generated (git-ignored)
โโโ inventory_insights.csv โ PRIMARY Tableau source
โโโ daily_sales_enriched.csv โ Trend chart data
โโโ forecast_daily.csv โ Day-by-day predictions
โโโ forecast_summary.csv โ 7-day totals
โโโ abc_summary.csv โ Class breakdown
โโโ model_metrics.csv โ MAE / MAPE per product
git clone https://github.com/YOUR_USERNAME/smart-inventory-tool.git
cd smart-inventory-tool
pip install -r requirements.txtpsql -U postgres -c "CREATE DATABASE inventory_db;"
psql -U postgres -d inventory_db -f 01_schema.sqlpython run_all.pyOr step by step:
python 02_generate_data.py # ~2s
python 03_optimization_engine.py # ~1s
python 04_forecasting.py # ~5s
python 05_export_insights.py # ~3sFlag: python run_all.py --skip-data to reuse existing sales data on re-runs.
Products are ranked by 6-month revenue contribution:
| Class | Revenue Threshold | Management Policy |
|---|---|---|
| A | Top 70% | Weekly stock count, tight ROP, priority supplier terms |
| B | 70โ90% | Bi-weekly count, standard ROP, moderate buffer |
| C | Bottom 10% | Monthly count, relaxed ROP, bulk ordering |
Protects against demand spikes during the supplier lead time window:
Safety Stock = Z ร ฯ_demand ร โ(lead_time_days)
Where:
- Z = 1.645 โ 95% service level (stockout in only 5% of replenishment cycles)
- ฯ_demand = standard deviation of daily sales (zero-filled, including stockout days)
- โ(lead_time) = volatility scales with the square root of time
ROP = (avg_daily_demand ร lead_time_days) + safety_stock
The system triggers a purchase order the moment effective_stock โค ROP.
effective_stock = stock_on_hand + stock_on_order
Minimises the total of ordering costs + holding costs:
EOQ = โ( 2 ร D ร S / H )
Where:
- D = annual demand (units)
- S = cost per order placed (โฆ500 default)
- H = annual holding cost per unit (20% of unit cost)
Final recommended_order_qty = max(EOQ, supplier_MOQ)
10 engineered features trained on 6 months of daily demand:
| Feature Group | Features |
|---|---|
| Lag | lag_1, lag_7, lag_14 |
| Rolling statistics | rolling_mean_7, rolling_mean_14, rolling_std_7 |
| Calendar | day_of_week, week_of_year, is_weekend |
| Trend | t (linear time index) |
Model is trained on the first ~166 days and evaluated on the final 14 days (MAE / MAPE reported per SKU).
- CSV mode: Data โ Text File โ
output/inventory_insights.csv - Live mode: Data โ PostgreSQL โ
localhost:5432/inventory_db
- Chart type: Horizontal Bar
- Rows:
product_name| Measure:total_revenue_6m - Colour:
abc_class(Red=A, Amber=B, Green=C) - Sort: Descending by revenue
- Chart type: Text / Highlight Table
- Rows:
product_name,stock_status,effective_stock,reorder_point,recommended_order_qty - Filter:
stock_status โ OK - Colour:
stock_status(Red = REORDER NOW, Amber = MONITOR)
- Chart type: Dual-axis Line
- Source:
daily_sales_enriched.csv - X:
date| Y1:units_sold| Y2:rolling_avg_7d - Filter: Product parameter (dropdown)
- Chart type: Bar (grouped)
- Source:
forecast_daily.csv - X:
forecast_date| Y:predicted_units - Colour:
product_name
Create calculated fields:
// Items Needing Action
COUNTD(IF [stock_status] != "OK" THEN [product_id] END)
// Total Immediate Order Value
SUM([estimated_order_cost])
// Avg Days of Supply
AVG([days_of_supply])
// Class A Revenue Share
SUM(IF [abc_class] = "A" THEN [total_revenue_6m] END)
/ SUM([total_revenue_6m]) * 100
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine("postgresql://user:password@localhost:5432/inventory_db")
tables = {
"products": pd.read_csv("output/products.csv"),
"sales_transactions": pd.read_csv("output/sales_transactions.csv"),
"current_inventory": pd.read_csv("output/current_inventory.csv"),
"inventory_insights": pd.read_csv("output/inventory_insights.csv"),
"daily_sales_enriched": pd.read_csv("output/daily_sales_enriched.csv"),
}
for table_name, df in tables.items():
df.to_sql(table_name, engine, if_exists="replace", index=False)
print(f"โ
{table_name} loaded ({len(df):,} rows)")All tunable parameters are at the top of each script:
| Script | Parameter | Default | Description |
|---|---|---|---|
03_optimization_engine.py |
SERVICE_LEVEL |
0.95 |
Target fill rate (0.99 = tighter buffer) |
03_optimization_engine.py |
ORDER_COST |
โฆ500 |
Admin cost per purchase order |
03_optimization_engine.py |
HOLDING_COST_RT |
0.20 |
Annual holding cost as % of unit cost |
04_forecasting.py |
FORECAST_HORIZON |
7 |
Days ahead to forecast |
| Enhancement | Tool | Effort |
|---|---|---|
| Better forecasting | Facebook Prophet | 2h โ replace LinearRegression block |
| Automated alerts | Airflow / cron + SMTP | 4h โ wrap run_all.py in a DAG |
| Live POS integration | Kafka / REST API | 1โ2 days |
| Multi-warehouse | Add warehouse_id FK to schema |
1 day |
| Price elasticity | Add promo flag + regression | 3h |
| Interactive UI | Streamlit app | 4โ6h |
MIT โ free to use, modify, and include in your portfolio.
Built as a portfolio project demonstrating supply chain analytics, statistical inventory modelling, and ML-based demand forecasting.