Skip to content

About

Multi-page Plotly Dash BI dashboard analyzing e-commerce price war data (Lazada vs Zalora Malaysia) — PostgreSQL-backed, Docker-deployable with auto-seeding, interactive filters, and category drill-down.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

📊 ecommerce-bi-dashboard — Lazada vs Zalora Price War Analytics

Python Dash PostgreSQL Docker Tests


❓ Problem

Raw scraped e-commerce data is only useful if someone can actually explore it. A one-off notebook analysis answers today's question — but the moment a business user (or a recruiter reviewing the work) wants to slice the data differently, filter by category, or drill into a specific segment, it means going back to the code. There's no self-serve way to ask a new question of the data.


💡 Solution

A multi-page BI dashboard, backed by a real PostgreSQL database, that lets anyone explore the Lazada vs Zalora price war dataset interactively — no code required:

  • Live KPIs — total products, average discount, platform breakdown, at a glance
  • Interactive comparison — filter by category and price range, charts update instantly
  • Category drill-down — pick a category to see every product in it, sortable, with summary stats
  • One-command deployment — docker compose up --build seeds the database and serves the dashboard, zero manual steps

✨ Features

  • 📈 KPI Overview — total products, avg discount %, products on discount, per-platform breakdown (count, avg discount, avg rating)
  • 🔍 Interactive Filters — category dropdown + price range slider, shared across pages, charts update live via Dash callbacks
  • 📊 Price Comparison Charts — avg discount by platform, price distribution (log-scale box plot), product count by category
  • 🗂️ Category Drill-Down — cross-category discount comparison, or a sortable product table for any selected category
  • 🐘 PostgreSQL Backend — real relational database, not a static CSV — schema includes indexes and a discount-filtered view
  • 🐳 Docker-First — Compose stack with a health-checked Postgres service and automatic, idempotent data seeding on first boot
  • ♿ Accessible Color Palette — platform colors validated for colorblind-safe separation and contrast on light/dark surfaces
  • ✅ Integration Tested — 14 tests running against the real database, auto-skipping cleanly if Postgres isn't reachable

🛠️ Tech Stack

Layer Tool Purpose
Dashboard Framework Plotly Dash Multi-page app, callbacks, interactive components
Charts Plotly Graph Objects Bar charts, box plots, all built as pure functions
Database PostgreSQL 16 Relational store for the product dataset
ORM / Connection SQLAlchemy Query execution, connection pooling
Data Processing Pandas Query result shaping, numeric coercion
Deployment Docker Compose App + database, healthcheck-gated startup
Config python-dotenv DB credentials from .env, never hardcoded
Testing pytest 14 integration tests against real migrated data

📡 Pages

Page URL What it shows
Overview / KPI cards: total products, avg discount %, products on discount, per-platform breakdown
Price Comparison /comparison Lazada vs Zalora charts with category + price-range filters, updating live
Categories /categories Category-level discount comparison, or a sortable detail table for a selected category

⚡ Quick Start

Docker (recommended)

git clone https://github.com/rizalcodes/ecommerce-bi-dashboard.git
cd ecommerce-bi-dashboard

docker compose up --build

That's it — Postgres starts, waits to be healthy, the app seeds the database automatically from data/raw/, and the dashboard is live at http://localhost:8050.

Port note: the database maps to host port 5433 (not 5432), since a native PostgreSQL install often already occupies 5432. This only affects host-side tools (psql, tests, local dev) — the app itself connects internally on the standard port.

Local development

python -m venv .venv
.venv\Scripts\activate        # Windows (source .venv/bin/activate on macOS/Linux)
pip install -r requirements-dev.txt
copy .env.example .env         # fill in; for the compose db use DB_PORT=5433
docker compose up -d db
python data/migrate.py         # one-time seed (idempotent, safe to re-run)
python app.py

Tests

docker compose up -d db
pytest

📁 Project Structure

ecommerce-bi-dashboard/
├── app.py                  # Dash entry point, page registration
├── pages/
│   ├── overview.py          # KPI summary
│   ├── comparison.py         # Filtered charts
│   └── categories.py           # Category drill-down
├── data/
│   ├── db.py                    # SQLAlchemy engine, credentials from .env
│   ├── queries.py                 # All SQL lives here
│   ├── migrate.py                   # Idempotent seed script
│   ├── schema.sql                     # Table + index + view definitions
│   └── raw/                             # Source CSVs (Lazada + Zalora)
├── components/                            # Reusable filters, KPI cards, charts
├── tests/                                   # 14 integration tests
├── docker-compose.yml
└── Dockerfile

👤 Author

Rizal

Portfolio GitHub Twitter/X


Built with Plotly Dash, PostgreSQL, and the belief that a chart you can't filter is just a screenshot.

About

Multi-page Plotly Dash BI dashboard analyzing e-commerce price war data (Lazada vs Zalora Malaysia) — PostgreSQL-backed, Docker-deployable with auto-seeding, interactive filters, and category drill-down.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages