Most small businesses run on Excel and guesswork. I switched to a live Python dashboard 6 months ago — here's how to build one in an afternoon.
What We're Building
A dashboard that shows:
- Today's revenue vs yesterday (and vs last week same day)
- Pending orders/invoices
- Low stock alerts
- Top 5 customers this month
- Simple profit/expense summary
Runs in terminal, updates every 30 seconds.
The Complete Code
import sqlite3
import time
import os
from datetime import datetime, timedelta
def clear_screen():
os.system("cls" if os.name == "nt" else "clear")
def get_dashboard_data(db_path="business.db"):
conn = sqlite3.connect(db_path)
c = conn.cursor()
today = datetime.now().date()
yesterday = today - timedelta(days=1)
last_week_today = today - timedelta(days=7)
month_start = today.replace(day=1)
# Today's revenue
c.execute("SELECT COALESCE(SUM(amount), 0) FROM orders WHERE date(order_date) = ?", (str(today),))
today_revenue = c.fetchone()[0]
c.execute("SELECT COALESCE(SUM(amount), 0) FROM orders WHERE date(order_date) = ?", (str(yesterday),))
yesterday_revenue = c.fetchone()[0]
c.execute("SELECT COALESCE(SUM(amount), 0) FROM orders WHERE date(order_date) = ?", (str(last_week_today),))
last_week_revenue = c.fetchone()[0]
# Pending invoices
c.execute("SELECT COUNT(*), COALESCE(SUM(amount), 0) FROM invoices WHERE paid = 0")
pending_count, pending_amount = c.fetchone()
# Overdue invoices
c.execute("""
SELECT COUNT(*), COALESCE(SUM(amount), 0) FROM invoices
WHERE paid = 0 AND due_date < ?
""", (str(today),))
overdue_count, overdue_amount = c.fetchone()
# Low stock
c.execute("SELECT name, quantity, reorder_point FROM inventory WHERE quantity <= reorder_point")
low_stock = c.fetchall()
# Top customers this month
c.execute("""
SELECT client_name, SUM(amount) as total FROM orders
WHERE date(order_date) >= ?
GROUP BY client_name ORDER BY total DESC LIMIT 5
""", (str(month_start),))
top_customers = c.fetchall()
# Monthly expenses
c.execute("""
SELECT category, SUM(amount) FROM expenses
WHERE date(expense_date) >= ? GROUP BY category
""", (str(month_start),))
expenses = dict(c.fetchall())
# Monthly revenue
c.execute("""
SELECT COALESCE(SUM(amount), 0) FROM orders WHERE date(order_date) >= ?
""", (str(month_start),))
month_revenue = c.fetchone()[0]
conn.close()
return {
"today_revenue": today_revenue,
"yesterday_revenue": yesterday_revenue,
"last_week_revenue": last_week_revenue,
"pending": (pending_count, pending_amount),
"overdue": (overdue_count, overdue_amount),
"low_stock": low_stock,
"top_customers": top_customers,
"expenses": expenses,
"month_revenue": month_revenue,
}
def render_dashboard(data):
clear_screen()
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Header
print("=" * 60)
print(f" BUSINESS DASHBOARD | {now}")
print("=" * 60)
# Revenue
rev = data["today_revenue"]
yesterday = data["yesterday_revenue"]
lw = data["last_week_revenue"]
vs_yesterday = ((rev - yesterday) / yesterday * 100) if yesterday > 0 else 0
vs_last_week = ((rev - lw) / lw * 100) if lw > 0 else 0
yoy_icon = "↑" if vs_yesterday >= 0 else "↓"
lw_icon = "↑" if vs_last_week >= 0 else "↓"
print(f"\n💰 TODAY'S REVENUE: ${rev:,.2f}")
print(f" vs yesterday: {yoy_icon} {abs(vs_yesterday):.1f}% (${yesterday:,.2f})")
print(f" vs last week: {lw_icon} {abs(vs_last_week):.1f}% (${lw:,.2f})")
# Invoices
pc, pa = data["pending"]
oc, oa = data["overdue"]
print(f"\n📄 INVOICES: {pc} pending (${pa:,.2f})")
if oc > 0:
print(f" ⚠️ {oc} OVERDUE: ${oa:,.2f}")
# Low stock
if data["low_stock"]:
print(f"\n📦 LOW STOCK ALERTS:")
for name, qty, reorder in data["low_stock"]:
print(f" ⚠️ {name}: {qty} left (reorder at {reorder})")
# Top customers
print(f"\n👥 TOP CUSTOMERS THIS MONTH:")
for i, (name, total) in enumerate(data["top_customers"], 1):
print(f" {i}. {name:20} ${total:,.2f}")
# Monthly P&L summary
month_rev = data["month_revenue"]
total_exp = sum(data["expenses"].values())
profit = month_rev - total_exp
print(f"\n📊 MONTH TO DATE:")
print(f" Revenue: ${month_rev:,.2f}")
print(f" Expenses: ${total_exp:,.2f}")
print(f" Profit: ${profit:,.2f}")
print("\n" + "=" * 60)
print("Press Ctrl+C to exit | Refreshes every 30s")
def run_dashboard(db_path="business.db", refresh_interval=30):
print("Starting dashboard... Press Ctrl+C to stop.")
try:
while True:
try:
data = get_dashboard_data(db_path)
render_dashboard(data)
except Exception as e:
clear_screen()
print(f"Dashboard error: {e}")
time.sleep(refresh_interval)
except KeyboardInterrupt:
print("\nDashboard stopped.")
if __name__ == "__main__":
run_dashboard()
Setting Up the Database
You'll need a SQLite database with these tables:
import sqlite3
def setup_database(db_path="business.db"):
conn = sqlite3.connect(db_path)
c = conn.cursor()
c.executescript("""
CREATE TABLE IF NOT EXISTS orders (
id INTEGER PRIMARY KEY,
client_name TEXT,
amount REAL,
order_date TEXT
);
CREATE TABLE IF NOT EXISTS invoices (
id INTEGER PRIMARY KEY,
invoice_num TEXT,
client_name TEXT,
amount REAL,
due_date TEXT,
paid INTEGER DEFAULT 0
);
CREATE TABLE IF NOT EXISTS inventory (
id INTEGER PRIMARY KEY,
name TEXT,
quantity INTEGER,
reorder_point INTEGER
);
CREATE TABLE IF NOT EXISTS expenses (
id INTEGER PRIMARY KEY,
category TEXT,
amount REAL,
description TEXT,
expense_date TEXT
);
""")
conn.commit()
conn.close()
print("Database setup complete")
setup_database()
Import from CSV (If You Use Excel Now)
If your current system is spreadsheets, import your existing data:
import pandas as pd
import sqlite3
def import_orders_from_csv(csv_file, db_path="business.db"):
df = pd.read_csv(csv_file)
# Assumes columns: client_name, amount, order_date
conn = sqlite3.connect(db_path)
df.to_sql("orders", conn, if_exists="append", index=False)
conn.close()
print(f"Imported {len(df)} orders")
import_orders_from_csv("orders.csv")
Run It Automatically at Startup
On Linux/Mac, add to crontab to start the dashboard every morning:
# Run dashboard at 8am, output to log
0 8 * * * python3 /path/to/dashboard.py >> /tmp/dashboard.log 2>&1
Or just run python3 dashboard.py in a terminal and keep it open.
What This Replaced
Before this dashboard, I'd spend 20-30 minutes each morning:
- Opening QuickBooks to check payments
- Checking inventory spreadsheet manually
- Cross-referencing invoices against bank statement
Now I see it all in one place, updated every 30 seconds, with anomaly detection built in.
Want all 12 scripts I use to run my business automatically? The Python Business Automation Toolkit has everything: invoicing, payment reminders, inventory alerts, competitor monitoring, and email automation — $29 one-time download.
What metrics do you wish you could see at a glance? Share in the comments.
Top comments (0)