# Orion Multi-Tenant E-Commerce Platform Makefile # Cross-platform compatible (Windows & Linux) .PHONY: install install-dev install-docs install-all dev test test-coverage lint format check docker-build docker-up docker-down clean help tailwind-install tailwind-dev tailwind-build tailwind-watch arch-check arch-check-file arch-check-object test-db-up test-db-down test-db-reset test-db-status celery-worker celery-beat celery-dev flower celery-status celery-purge urls # Detect OS ifeq ($(OS),Windows_NT) DETECTED_OS := Windows else DETECTED_OS := $(shell uname -s) endif # Set Python based on OS PYTHON := python3 PIP := pip3 # Set PYTHONPATH for scripts export PYTHONPATH := $(shell pwd) # ============================================================================= # INSTALLATION & SETUP # ============================================================================= install: $(PIP) install -r requirements.txt install-dev: install $(PIP) install -r requirements-dev.txt install-test: $(PIP) install -r requirements-test.txt install-docs: $(PIP) install -r requirements-docs.txt install-all: install install-dev install-test install-docs setup: install-all migrate-up init-prod @echo "✅ Development environment setup complete!" @echo "Run 'make dev' to start development server" # ============================================================================= # DEVELOPMENT SERVERS # ============================================================================= dev: $(PYTHON) -m uvicorn main:app --reload --host 0.0.0.0 --port 9999 # ============================================================================= # DATABASE MIGRATIONS # ============================================================================= migrate-create: ifeq ($(DETECTED_OS),Windows) @if "$(message)"=="" (echo Error: Please provide a message. Usage: make migrate-create message="your_description") else ($(PYTHON) -m alembic revision --autogenerate -m "$(message)") else @if [ -z "$(message)" ]; then \ echo "Error: Please provide a message. Usage: make migrate-create message=\"your_description\""; \ else \ $(PYTHON) -m alembic revision --autogenerate -m "$(message)"; \ fi endif migrate-create-manual: ifeq ($(DETECTED_OS),Windows) @if "$(message)"=="" (echo Error: Please provide a message. Usage: make migrate-create-manual message="your_description") else ($(PYTHON) -m alembic revision -m "$(message)") else @if [ -z "$(message)" ]; then \ echo "Error: Please provide a message. Usage: make migrate-create-manual message=\"your_description\""; \ else \ $(PYTHON) -m alembic revision -m "$(message)"; \ fi endif migrate-up: @echo "Running database migrations..." $(PYTHON) -m alembic upgrade head @echo "✅ Migrations completed successfully" migrate-down: @echo "Rolling back last migration..." $(PYTHON) -m alembic downgrade -1 @echo "✅ Rollback completed" migrate-status: @echo "Current migration status:" $(PYTHON) -m alembic current @echo "" @echo "Migration history:" $(PYTHON) -m alembic history --verbose migrate-squash: @echo "Squashing all migrations into a single initial migration..." $(PYTHON) scripts/squash_migrations.py # ============================================================================= # DATABASE INITIALIZATION & SEEDING # ============================================================================= # Production initialization - Run on first setup (production OR development) init-prod: @echo "🔧 Initializing production database..." @echo "" @echo "Step 0/6: Ensuring database exists (running migrations)..." @$(PYTHON) -m alembic upgrade heads @echo "" @echo "Step 1/5: Creating admin user and platform settings..." $(PYTHON) scripts/seed/init_production.py @echo "" @echo "Step 2/5: Initializing log settings..." $(PYTHON) scripts/seed/init_log_settings.py @echo "" @echo "Step 3/5: Creating default CMS content pages..." $(PYTHON) scripts/seed/create_default_content_pages.py @echo "" @echo "Step 4/5: Seeding email templates..." $(PYTHON) scripts/seed/seed_email_templates.py @echo "" @echo "Step 5/5: Seeding subscription tiers..." @echo " (Handled by init_production.py Step 6)" @echo "" @echo "✅ Production initialization completed" @echo "✨ Platform is ready for production OR development" seed-tiers: @echo "🏷️ Seeding subscription tiers..." $(PYTHON) -c "from scripts.seed.init_production import *; from app.core.database import SessionLocal; from sqlalchemy import select; db = SessionLocal(); oms = db.execute(select(Platform).where(Platform.code == 'oms')).scalar_one_or_none(); create_subscription_tiers(db, oms) if oms else print('OMS platform not found'); db.commit(); db.close()" @echo "✅ Subscription tiers seeded" # First-time installation - Complete setup with configuration validation platform-install: @echo "🚀 ORION PLATFORM INSTALLATION" @echo "==================================" $(PYTHON) scripts/seed/install.py # Demo data seeding - Cross-platform using Python to set environment seed-demo: @echo "🎪 Seeding demo data (normal mode)..." ifeq ($(DETECTED_OS),Windows) @set SEED_MODE=normal&& $(PYTHON) scripts/seed/seed_demo.py else SEED_MODE=normal $(PYTHON) scripts/seed/seed_demo.py endif @echo "✅ Demo seeding completed" seed-demo-minimal: @echo "🎪 Seeding demo data (minimal mode - 1 store only)..." ifeq ($(DETECTED_OS),Windows) @set SEED_MODE=minimal&& $(PYTHON) scripts/seed/seed_demo.py else SEED_MODE=minimal $(PYTHON) scripts/seed/seed_demo.py endif @echo "✅ Minimal demo seeding completed" seed-demo-reset: @echo "⚠️ WARNING: This will DELETE ALL existing data!" ifeq ($(DETECTED_OS),Windows) @set SEED_MODE=reset&& $(PYTHON) scripts/seed/seed_demo.py else SEED_MODE=reset $(PYTHON) scripts/seed/seed_demo.py endif db-setup: migrate-up init-prod seed-demo @echo "" @echo "✅ Database setup complete!" @echo "✨ Run 'make dev' to start development server" db-reset: @echo "⚠️ WARNING: This will DELETE ALL existing data!" @echo "Dropping and recreating public schema..." $(PYTHON) -c "from app.core.config import settings; from sqlalchemy import create_engine, text; e=create_engine(settings.database_url); c=e.connect(); c.execute(text('DROP SCHEMA public CASCADE')); c.execute(text('CREATE SCHEMA public')); c.commit(); c.close()" @echo "Applying all migrations..." $(PYTHON) -m alembic upgrade head @echo "Initializing production data..." $(PYTHON) scripts/seed/init_production.py @echo "Seeding demo data..." ifeq ($(DETECTED_OS),Windows) @set SEED_MODE=reset&& set FORCE_RESET=true&& $(PYTHON) scripts/seed/seed_demo.py else SEED_MODE=reset FORCE_RESET=true $(PYTHON) scripts/seed/seed_demo.py endif @echo "" @echo "✅ Database completely reset!" backup-db: @echo "Creating database backup..." @$(PYTHON) scripts/seed/backup_database.py # Utility commands (usually not needed - init-prod handles these) create-cms-defaults: @echo "📄 Creating default CMS content pages..." $(PYTHON) scripts/seed/create_default_content_pages.py @echo "✅ CMS defaults created" init-logging: @echo "📝 Initializing log settings..." $(PYTHON) scripts/seed/init_log_settings.py @echo "✅ Log settings initialized" # ============================================================================= # TEST DATABASE (PostgreSQL in Docker) # ============================================================================= test-db-up: @echo "Starting test database (PostgreSQL on port 5433)..." docker compose -f docker-compose.test.yml up -d @sleep 3 @echo "✅ Test database ready" test-db-down: @echo "Stopping test database..." docker compose -f docker-compose.test.yml down @echo "✅ Test database stopped" test-db-reset: @echo "Resetting test database..." docker compose -f docker-compose.test.yml down -v docker compose -f docker-compose.test.yml up -d @sleep 3 @echo "✅ Test database reset" test-db-status: @docker compose -f docker-compose.test.yml ps # ============================================================================= # TESTING # ============================================================================= # Test database URL TEST_DB_URL := postgresql://test_user:test_password@localhost:5433/orion_test # Build pytest marker expression from module= and frontend= params MARKER_EXPR := ifdef module MARKER_EXPR := -m "$(module)" endif ifdef frontend ifdef module MARKER_EXPR := -m "$(module) and $(frontend)" else MARKER_EXPR := -m "$(frontend)" endif endif # All testpaths (central + module tests) TEST_PATHS := tests/ app/modules/tenancy/tests/ app/modules/catalog/tests/ app/modules/billing/tests/ app/modules/messaging/tests/ app/modules/orders/tests/ app/modules/customers/tests/ app/modules/marketplace/tests/ app/modules/inventory/tests/ app/modules/loyalty/tests/ test: @docker compose -f docker-compose.test.yml up -d 2>/dev/null || true @sleep 2 TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) -v $(MARKER_EXPR) test-unit: @docker compose -f docker-compose.test.yml up -d 2>/dev/null || true @sleep 2 ifdef module TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) -v -m "unit and $(module)" else TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) -v -m unit endif test-integration: @docker compose -f docker-compose.test.yml up -d 2>/dev/null || true @sleep 2 ifdef module TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) -v -m "integration and $(module)" else TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) -v -m integration endif test-coverage: @docker compose -f docker-compose.test.yml up -d 2>/dev/null || true @sleep 2 TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) --cov=app --cov=models --cov=utils --cov=middleware --cov-report=html --cov-report=term-missing $(MARKER_EXPR) test-fast: @docker compose -f docker-compose.test.yml up -d 2>/dev/null || true @sleep 2 TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) -v -m "not slow" $(MARKER_EXPR) test-slow: @docker compose -f docker-compose.test.yml up -d 2>/dev/null || true @sleep 2 TEST_DATABASE_URL="$(TEST_DB_URL)" \ $(PYTHON) -m pytest $(TEST_PATHS) -v -m slow # ============================================================================= # CODE QUALITY # ============================================================================= format: @echo "Formatting code with ruff..." $(PYTHON) -m ruff format . lint: @echo "Linting code with ruff..." $(PYTHON) -m ruff check . --fix @echo "Type checking with mypy..." $(PYTHON) -m mypy . lint-strict: @echo "Linting (no auto-fix)..." $(PYTHON) -m ruff check . @echo "Type checking with mypy..." $(PYTHON) -m mypy . check: format lint verify-imports ci: lint-strict verify-imports test-coverage verify-imports: @echo "Verifying critical imports..." $(PYTHON) scripts/validate/verify_critical_imports.py arch-check: @echo "Running architecture validation..." $(PYTHON) scripts/validate/validate_architecture.py arch-check-file: ifeq ($(DETECTED_OS),Windows) @if "$(file)"=="" (echo Error: Please provide a file. Usage: make arch-check-file file="path/to/file.py") else ($(PYTHON) scripts/validate/validate_architecture.py -f "$(file)") else @if [ -z "$(file)" ]; then \ echo "Error: Please provide a file. Usage: make arch-check-file file=\"path/to/file.py\""; \ else \ $(PYTHON) scripts/validate/validate_architecture.py -f "$(file)"; \ fi endif arch-check-object: ifeq ($(DETECTED_OS),Windows) @if "$(name)"=="" (echo Error: Please provide an object name. Usage: make arch-check-object name="merchant") else ($(PYTHON) scripts/validate/validate_architecture.py -o "$(name)") else @if [ -z "$(name)" ]; then \ echo "Error: Please provide an object name. Usage: make arch-check-object name=\"merchant\""; \ else \ $(PYTHON) scripts/validate/validate_architecture.py -o "$(name)"; \ fi endif qa: format lint arch-check test-coverage docs-check @echo "Quality assurance checks completed!" # ============================================================================= # DOCUMENTATION # ============================================================================= docs-serve: @echo "Starting documentation server..." $(PYTHON) -m mkdocs serve --dev-addr=0.0.0.0:9991 docs-build: @echo "Building documentation..." $(PYTHON) -m mkdocs build --clean --strict docs-deploy: @echo "Deploying documentation..." $(PYTHON) -m mkdocs gh-deploy --clean docs-clean: ifeq ($(DETECTED_OS),Windows) @if exist site rmdir /s /q site else @rm -rf site endif @echo "Documentation build files cleaned!" docs-check: @echo "Checking documentation for issues..." $(PYTHON) -m mkdocs build --strict --verbose # ============================================================================= # FRONTEND / TAILWIND CSS (Standalone CLI - No Node.js Required) # ============================================================================= # Tailwind CLI binary location TAILWIND_CLI := $(HOME)/.local/bin/tailwindcss tailwind-install: @echo "Installing Tailwind CSS standalone CLI..." @mkdir -p $(HOME)/.local/bin @curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-linux-x64 @chmod +x tailwindcss-linux-x64 @mv tailwindcss-linux-x64 $(TAILWIND_CLI) @echo "Tailwind CLI installed: $$($(TAILWIND_CLI) --help | head -1)" # All frontends that have a Tailwind build (static//css/tailwind.css) TAILWIND_FRONTENDS := admin store storefront platform merchant tailwind-dev: @echo "Building Tailwind CSS (development)..." @$(foreach fe,$(TAILWIND_FRONTENDS),$(TAILWIND_CLI) -i static/$(fe)/css/tailwind.css -o static/$(fe)/css/tailwind.output.css &&) true @echo "Tailwind CSS built ($(TAILWIND_FRONTENDS))" tailwind-build: @echo "Building Tailwind CSS (production - minified)..." @$(foreach fe,$(TAILWIND_FRONTENDS),$(TAILWIND_CLI) -i static/$(fe)/css/tailwind.css -o static/$(fe)/css/tailwind.output.css --minify &&) true @echo "Tailwind CSS built and minified for production" tailwind-watch: @echo "Watching Tailwind CSS for changes ($(fe))..." $(TAILWIND_CLI) -i static/$(fe)/css/tailwind.css -o static/$(fe)/css/tailwind.output.css --watch # ============================================================================= # CELERY / TASK QUEUE # ============================================================================= celery-worker: @echo "Starting Celery worker..." celery -A app.core.celery_config worker --loglevel=info -Q default,long_running,scheduled celery-beat: @echo "Starting Celery beat scheduler..." celery -A app.core.celery_config beat --loglevel=info celery-dev: @echo "Starting Celery worker + beat (development mode)..." celery -A app.core.celery_config worker --loglevel=info -B -Q default,long_running,scheduled flower: @echo "Starting Flower monitoring dashboard on http://localhost:5555..." celery -A app.core.celery_config flower --port=5555 --basic-auth=admin:admin celery-status: @echo "Celery worker status:" celery -A app.core.celery_config inspect active celery-purge: @echo "Purging all pending tasks..." celery -A app.core.celery_config purge -f # ============================================================================= # DOCKER # ============================================================================= docker-build: docker compose build docker-up: docker compose up -d docker-down: docker compose down docker-restart: docker-down docker-up # ============================================================================= # DEPLOYMENT # ============================================================================= deploy-staging: migrate-up docker compose -f docker-compose.staging.yml up -d deploy-prod: migrate-up docker compose -f docker-compose.prod.yml up -d # ============================================================================= # UTILITIES # ============================================================================= clean: ifeq ($(DETECTED_OS),Windows) @if exist htmlcov rmdir /s /q htmlcov @if exist .pytest_cache rmdir /s /q .pytest_cache @if exist .coverage del .coverage @if exist .mypy_cache rmdir /s /q .mypy_cache @for /d /r . %%d in (__pycache__) do @if exist "%%d" rmdir /s /q "%%d" @del /s /q *.pyc 2>nul || echo No .pyc files found else @find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true @find . -type f -name "*.pyc" -delete 2>/dev/null || true @rm -rf htmlcov .pytest_cache .coverage .mypy_cache 2>/dev/null || true endif @echo "Cleaned up build artifacts" verify-setup: @echo "Running setup verification..." @$(PYTHON) scripts/verify_setup.py urls: @$(PYTHON) scripts/show_urls.py urls-dev: @$(PYTHON) scripts/show_urls.py --dev urls-prod: @$(PYTHON) scripts/show_urls.py --prod urls-check: @$(PYTHON) scripts/show_urls.py --check check-env: @echo "Checking Python environment..." @echo "Detected OS: $(DETECTED_OS)" @echo "" @echo "Python version:" @$(PYTHON) --version @echo "" ifeq ($(DETECTED_OS),Windows) @echo "Python location:" @where $(PYTHON) else @echo "Python location:" @which $(PYTHON) endif @echo "" @echo "Virtual environment active:" @$(PYTHON) -c "import sys; print('YES' if hasattr(sys, 'real_prefix') or (hasattr(sys, 'base_prefix') and sys.base_prefix != sys.prefix) else 'NO')" @echo "" @echo "Python executable:" @$(PYTHON) -c "import sys; print(sys.executable)" # ============================================================================= # HELP # ============================================================================= help: @echo "Orion Platform Development Commands" @echo "" @echo "=== SETUP ===" @echo " install - Install production dependencies" @echo " install-test - Install test dependencies only" @echo " install-dev - Install development dependencies" @echo " install-all - Install all dependencies" @echo " setup - Complete development setup" @echo "" @echo "=== DEVELOPMENT ===" @echo " dev - Start API development server" @echo "" @echo "=== DATABASE ===" @echo " migrate-create message=\"msg\" - Create new migration" @echo " migrate-up - Apply pending migrations" @echo " migrate-down - Rollback last migration" @echo " migrate-status - Show migration status" @echo " platform-install - First-time setup (validates config + migrate + init)" @echo " init-prod - Initialize platform (admin, CMS, pages, emails, tiers)" @echo " seed-tiers - Seed subscription tiers only" @echo " seed-demo - Seed demo data (3 merchants + stores)" @echo " seed-demo-minimal - Seed minimal demo (1 merchant + store)" @echo " seed-demo-reset - DELETE ALL demo data and reseed" @echo " db-setup - Full dev setup (migrate + init-prod + seed-demo)" @echo " backup-db - Backup database" @echo "" @echo "=== TESTING (PostgreSQL) ===" @echo " test-db-up - Start test PostgreSQL database" @echo " test-db-down - Stop test database" @echo " test-db-reset - Reset test database" @echo " test - Run all tests (auto-starts DB)" @echo " test module=loyalty - Run tests for a specific module" @echo " test-unit - Run unit tests only" @echo " test-unit module=X - Run unit tests for module X" @echo " test-integration - Run integration tests only" @echo " test-coverage - Run tests with coverage" @echo " test-fast - Run fast tests only" @echo " test frontend=storefront - Run storefront tests" @echo "" @echo "=== CODE QUALITY ===" @echo " format - Format code with ruff" @echo " lint - Lint and auto-fix with ruff + mypy" @echo " lint-strict - Lint without auto-fix + mypy" @echo " verify-imports - Verify critical imports haven't been removed" @echo " arch-check - Validate architecture patterns" @echo " arch-check-file file=\"path\" - Check a single file" @echo " arch-check-object name=\"merchant\" - Check all files for an entity" @echo " check - Format + lint + verify imports" @echo " ci - Full CI pipeline (strict)" @echo " qa - Quality assurance (includes arch-check)" @echo "" @echo "=== DOCUMENTATION ===" @echo " docs-serve - Start documentation server" @echo " docs-build - Build documentation" @echo "" @echo "=== FRONTEND / TAILWIND (No Node.js Required) ===" @echo " tailwind-install - Install Tailwind standalone CLI" @echo " tailwind-dev - Build Tailwind CSS (development)" @echo " tailwind-build - Build Tailwind CSS (production, minified)" @echo " tailwind-watch fe=X - Watch and rebuild on changes (specify frontend)" @echo "" @echo "=== CELERY / TASK QUEUE ===" @echo " celery-worker - Start Celery worker" @echo " celery-beat - Start Celery beat scheduler" @echo " celery-dev - Start worker + beat together (dev)" @echo " flower - Start Flower monitoring (localhost:5555)" @echo " celery-status - Show active worker tasks" @echo " celery-purge - Purge all pending tasks" @echo "" @echo "=== DOCKER ===" @echo " docker-build - Build Docker containers" @echo " docker-up - Start Docker containers" @echo " docker-down - Stop Docker containers" @echo "" @echo "=== UTILITIES ===" @echo " urls - Show all platform/store/storefront URLs" @echo " urls-dev - Show development URLs only" @echo " urls-prod - Show production URLs only" @echo " urls-check - Check dev URLs with curl (server must be running)" @echo " clean - Clean build artifacts" @echo " check-env - Check Python environment and OS" @echo "" @echo "=== DAILY WORKFLOW ===" @echo " make setup # Initial setup" @echo " make dev # Start development" @echo " make migrate-create message=\"feature\" # Create migration" @echo " make migrate-up # Apply migration" @echo " make test # Run tests" help-db: @echo "=== DATABASE COMMANDS ===" @echo "" @echo "MIGRATIONS:" @echo " migrate-create message=\"description\" - Create auto-generated migration" @echo " migrate-create-manual message=\"desc\" - Create empty migration template" @echo " migrate-up - Apply all pending migrations" @echo " migrate-down - Rollback last migration" @echo " migrate-status - Show current status and history" @echo "" @echo "FIRST-TIME INSTALLATION:" @echo "──────────────────────────────────────────────────────────" @echo " platform-install - Complete installation wizard:" @echo " - Validates .env configuration" @echo " - Checks Stripe, Email, Security settings" @echo " - Runs database migrations" @echo " - Initializes all platform data" @echo " - Provides configuration report" @echo "" @echo "PLATFORM INITIALIZATION (Production + Development):" @echo "──────────────────────────────────────────────────────────" @echo " init-prod - Complete platform setup (6 steps):" @echo " 1. Create admin user + settings" @echo " 2. Initialize log settings" @echo " 3. Create CMS defaults" @echo " 4. Create platform pages" @echo " 5. Seed email templates" @echo " 6. Seed subscription tiers" @echo "" @echo "DEMO DATA (Development Only - NEVER in production):" @echo "──────────────────────────────────────────────────────────" @echo " seed-demo - Create 3 demo merchants + stores + data" @echo " seed-demo-minimal - Create 1 demo merchant + store only" @echo " seed-demo-reset - DELETE ALL demo data and reseed (DANGEROUS!)" @echo "" @echo "UTILITY COMMANDS (Advanced - usually not needed):" @echo "──────────────────────────────────────────────────────────" @echo " create-cms-defaults - Re-create CMS pages only" @echo " create-platform-pages - Re-create platform pages only" @echo " init-logging - Re-initialize logging only" @echo "" @echo "QUICK WORKFLOWS:" @echo "──────────────────────────────────────────────────────────" @echo " db-setup - Full dev setup (migrate + init-prod + seed-demo)" @echo " db-reset - Nuclear reset (rollback + init-prod + reseed)" @echo "" @echo "TYPICAL FIRST-TIME SETUP (Development):" @echo "──────────────────────────────────────────────────────────" @echo " 1. cp .env.example .env # Configure environment" @echo " 2. make platform-install # Validates config + initializes platform" @echo " 3. make seed-demo # Add demo data (optional)" @echo " 4. make dev # Start development server" @echo "" @echo "PRODUCTION SETUP:" @echo "──────────────────────────────────────────────────────────" @echo " 1. Configure .env with production values:" @echo " - DATABASE_URL (PostgreSQL recommended)" @echo " - JWT_SECRET_KEY (use: openssl rand -hex 32)" @echo " - STRIPE_SECRET_KEY, STRIPE_PUBLISHABLE_KEY" @echo " - Email provider settings (SMTP/SendGrid/Mailgun/SES)" @echo " - ADMIN_PASSWORD (strong password)" @echo " 2. make platform-install # Validates + initializes" @echo " 3. DO NOT run seed-demo in production!"