23 KiB
Multi-Tenant Ecommerce Platform
A production-ready, multi-tenant ecommerce platform that enables vendors to operate independent webshops while integrating with external marketplaces. Built with complete vendor isolation, comprehensive business features, and modern reactive frontend.
🚀 Features
Core Business Features
- Multi-Vendor Marketplace: Complete vendor isolation with independent webshops
- Marketplace Integration: Import and curate products from external marketplaces (Letzshop CSV)
- Product Catalog Management: Vendor-scoped product publishing from marketplace imports
- Inventory Management: Real-time stock tracking with location-based inventory
- Order Management: Complete order lifecycle with status tracking and fulfillment
- Customer Management: Vendor-scoped customer accounts with order history
- Team Management: Role-based access control with granular permissions
- Shopping Cart: Session-based cart with real-time updates
Technical Features
- Modern Frontend Stack: Alpine.js for reactive UI with zero build step
- RESTful API Architecture: FastAPI with comprehensive OpenAPI documentation
- Service Layer Pattern: Clean separation of business logic and data access
- Exception-First Error Handling: Frontend-friendly error responses with consistent error codes
- Multi-tenant Security: Complete data isolation with vendor context detection
- Background Job Processing: Async marketplace imports with status tracking
- Comprehensive API: Admin, Vendor, and Public (Customer) endpoints
Security & Compliance
- Complete Data Isolation: Chinese wall between vendor data
- JWT Authentication: Secure token-based authentication for all user types
- Role-Based Access Control: Granular permissions (Owner, Manager, Editor, Viewer)
- Vendor Context Detection: Subdomain and path-based tenant isolation
- Input Validation: Pydantic models for all API requests
- Exception Handling: Structured error responses with proper HTTP status codes
🏗️ Architecture
Technology Stack
- Backend: Python 3.13+ with FastAPI
- Database: PostgreSQL with SQLAlchemy ORM
- Frontend: Vanilla HTML, CSS, JavaScript with Alpine.js (CDN-based, no build step)
- Authentication: JWT tokens with role-based permissions
- Background Jobs: Async CSV import processing
- API Documentation: Auto-generated OpenAPI/Swagger
Multi-Tenancy Model
Platform
├── Admin Portal (admin.platform.com or /admin)
│ ├── Vendor management
│ ├── User administration
│ ├── Platform statistics
│ └── Import job monitoring
├── Vendor A (vendor-a.platform.com or /vendor/{code})
│ ├── Marketplace product imports
│ ├── Product catalog publishing
│ ├── Order management
│ ├── Customer management
│ ├── Team management
│ └── Inventory tracking
├── Vendor B (vendor-b.platform.com or /vendor/{code})
│ └── Completely isolated from Vendor A
└── Customer Shop (/shop or subdomain)
├── Product browsing
├── Shopping cart
├── Order placement
└── Order history
Data Flow
Marketplace CSV → Import Job → MarketplaceProduct (Staging) → Product (Catalog) → Order → Customer
↓ ↓ ↓
Job Status Product Selection Inventory Tracking
📁 Project Structure
├── main.py # FastAPI application entry point
├── app/
│ ├── api/
│ │ ├── main.py # API router aggregation
│ │ ├── deps.py # Dependency injection (auth, context)
│ │ └── v1/ # API version 1
│ │ ├── admin/ # Admin endpoints
│ │ │ ├── __init__.py
│ │ │ ├── auth.py
│ │ │ ├── vendors.py
│ │ │ ├── users.py
│ │ │ ├── marketplace.py
│ │ │ └── dashboard.py
│ │ ├── vendor/ # Vendor endpoints
│ │ │ ├── __init__.py
│ │ │ ├── auth.py
│ │ │ ├── dashboard.py
│ │ │ ├── products.py
│ │ │ ├── orders.py
│ │ │ ├── marketplace.py
│ │ │ ├── inventory.py
│ │ │ └── vendor.py
│ │ └── public/ # Customer endpoints
│ │ ├── __init__.py
│ │ └── vendors/
│ │ ├── auth.py
│ │ ├── products.py
│ │ ├── cart.py
│ │ └── orders.py
│ ├── core/
│ │ ├── database.py # Database configuration
│ │ ├── security.py # JWT and password utilities
│ │ └── config.py # Application settings
│ ├── exceptions/ # Custom exceptions
│ │ ├── __init__.py
│ │ ├── base.py
│ │ ├── auth.py
│ │ ├── vendor.py
│ │ ├── customer.py
│ │ ├── product.py
│ │ ├── order.py
│ │ ├── inventory.py
│ │ ├── team.py
│ │ ├── marketplace_product.py
│ │ ├── marketplace_import_job.py
│ │ └── admin.py
│ └── services/ # Business logic layer
│ ├── auth_service.py
│ ├── admin_service.py
│ ├── vendor_service.py
│ ├── customer_service.py
│ ├── product_service.py
│ ├── order_service.py
│ ├── cart_service.py
│ ├── inventory_service.py
│ ├── team_service.py
│ ├── marketplace_service.py
│ └── stats_service.py
├── models/
│ ├── database/ # SQLAlchemy ORM models
│ │ ├── base.py
│ │ ├── user.py
│ │ ├── vendor.py
│ │ ├── customer.py
│ │ ├── product.py
│ │ ├── order.py
│ │ ├── inventory.py
│ │ ├── marketplace_product.py
│ │ └── marketplace_import_job.py
│ └── schemas/ # Pydantic validation models
│ ├── auth.py
│ ├── vendor.py
│ ├── customer.py
│ ├── product.py
│ ├── order.py
│ ├── inventory.py
│ ├── marketplace_product.py
│ ├── marketplace_import_job.py
│ └── stats.py
├── middleware/
│ ├── auth.py # JWT authentication
│ ├── vendor_context.py # Multi-tenant context detection
│ ├── rate_limiter.py # API rate limiting
│ └── decorators.py # Utility decorators
├── static/ # Frontend assets (no build step required)
│ ├── admin/ # Admin interface
│ │ ├── login.html
│ │ ├── dashboard.html
│ │ └── vendors.html
│ ├── vendor/ # Vendor management UI
│ │ ├── login.html
│ │ ├── dashboard.html
│ │ └── admin/
│ │ ├── products.html
│ │ ├── orders.html
│ │ └── marketplace.html
│ ├── shop/ # Customer shop interface
│ │ ├── products.html
│ │ ├── product.html # Alpine.js product detail
│ │ ├── cart.html
│ │ └── account/
│ │ ├── register.html
│ │ ├── login.html
│ │ └── orders.html
│ ├── css/
│ │ ├── shared/
│ │ │ ├── base.css # CSS variables, utility classes
│ │ │ └── auth.css
│ │ ├── admin/
│ │ │ └── admin.css
│ │ ├── vendor/
│ │ │ └── vendor.css
│ │ └── shop/
│ │ └── shop.css
│ └── js/
│ └── shared/
│ ├── api-client.js
│ ├── vendor-context.js
│ └── utils.js
├── scripts/
│ ├── init_db.py # Database initialization
│ └── create_admin.py # Admin user creation
└── tests/
├── unit/
├── integration/
└── e2e/
🚀 Quick Start
Prerequisites
- Python 3.13+
- PostgreSQL 14+ (SQLite for development)
- Node.js (optional, only for development tools)
Development Setup
1. Clone and Setup Environment
git clone <repository-url>
cd multi-tenant-ecommerce
python -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
pip install -r requirements.txt
2. Database Setup
# Create database
createdb ecommerce_db
# Run migrations
python scripts/init_db.py
# Create initial admin user
python scripts/create_admin.py
3. Environment Configuration
cp .env.example .env
# Edit .env with your configuration
Minimal .env:
DATABASE_URL=postgresql://user:pass@localhost:5432/ecommerce_db
SECRET_KEY=your-secret-key-here-generate-with-openssl
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
DEVELOPMENT_MODE=true
4. Start Application
# Start FastAPI application
uvicorn main:app --reload --port 8000
5. Access the Platform
- Admin Panel: http://localhost:8000/admin/
- Vendor Login: http://localhost:8000/vendor/login
- Customer Shop: http://localhost:8000/shop/
- API Documentation: http://localhost:8000/docs
- Health Check: http://localhost:8000/health
First Steps
-
Login to Admin Panel
- URL: http://localhost:8000/admin/
- Credentials: Created via
create_admin.py
-
Create First Vendor
- Navigate to Admin → Vendors
- Click "Create Vendor"
- Fill in vendor details (name, code, subdomain)
- System creates vendor + owner user account
- Note the temporary password
-
Login as Vendor Owner
- URL: http://localhost:8000/vendor/login (or subdomain)
- Use vendor owner credentials
-
Import Products from Marketplace
- Navigate to Vendor → Marketplace Import
- Configure Letzshop CSV URL
- Trigger import job
- Monitor import status
-
Publish Products to Catalog
- Review imported products in staging
- Select products to publish
- Configure pricing and inventory
- Publish to customer-facing catalog
📋 API Structure
Admin APIs (/api/v1/admin)
Authentication:
POST /auth/login # Admin login
Vendor Management:
GET /vendors # List all vendors
POST /vendors # Create vendor with owner
GET /vendors/{id} # Get vendor details
PUT /vendors/{id}/verify # Verify/unverify vendor
PUT /vendors/{id}/status # Toggle active status
DELETE /vendors/{id} # Delete vendor
User Management:
GET /users # List all users
PUT /users/{id}/status # Toggle user status
Marketplace Monitoring:
GET /marketplace-import-jobs # Monitor all import jobs
Dashboard & Statistics:
GET /dashboard # Admin dashboard
GET /dashboard/stats # Comprehensive statistics
GET /dashboard/stats/marketplace # Marketplace breakdown
GET /dashboard/stats/platform # Platform-wide metrics
Vendor APIs (/api/v1/vendor)
Authentication:
POST /auth/login # Vendor team login
POST /auth/logout # Logout
Dashboard:
GET /dashboard/stats # Vendor-specific statistics
Product Management:
GET /products # List catalog products
POST /products # Add product to catalog
GET /products/{id} # Get product details
PUT /products/{id} # Update product
DELETE /products/{id} # Remove from catalog
POST /products/from-import/{id} # Publish from marketplace
PUT /products/{id}/toggle-active # Toggle product active
PUT /products/{id}/toggle-featured # Toggle featured status
Order Management:
GET /orders # List vendor orders
GET /orders/{id} # Get order details
PUT /orders/{id}/status # Update order status
Marketplace Integration:
POST /marketplace/import # Trigger import job
GET /marketplace/jobs # List import jobs
GET /marketplace/jobs/{id} # Get job status
GET /marketplace/products # List staged products
POST /marketplace/products/publish # Bulk publish to catalog
Inventory Management:
GET /inventory # List inventory items
POST /inventory # Add inventory
PUT /inventory/{id} # Update inventory
GET /inventory/movements # Inventory movement history
Public/Customer APIs (/api/v1/public/vendors)
Authentication:
POST /{vendor_id}/auth/register # Customer registration
POST /{vendor_id}/auth/login # Customer login
POST /{vendor_id}/auth/logout # Customer logout
Product Browsing:
GET /{vendor_id}/products # Browse product catalog
GET /{vendor_id}/products/{id} # Product details
GET /{vendor_id}/products/search # Search products
Shopping Cart:
GET /{vendor_id}/cart/{session} # Get cart
POST /{vendor_id}/cart/{session}/items # Add to cart
PUT /{vendor_id}/cart/{session}/items/{id} # Update quantity
DELETE /{vendor_id}/cart/{session}/items/{id} # Remove item
DELETE /{vendor_id}/cart/{session} # Clear cart
Order Placement:
POST /{vendor_id}/orders # Place order
GET /{vendor_id}/customers/{id}/orders # Order history
GET /{vendor_id}/customers/{id}/orders/{id} # Order details
🎨 Frontend Architecture
Alpine.js Integration
Why Alpine.js?
- ✅ Lightweight (15KB) - perfect for multi-tenant platform
- ✅ No build step required - works directly in HTML
- ✅ Reactive state management - modern UX without complexity
- ✅ Perfect Jinja2 integration - server + client harmony
- ✅ Scoped components - natural vendor isolation
Example: Product Detail Page
<div x-data="productDetail()" x-init="loadProduct()">
<!-- Reactive product display -->
<h1 x-text="product?.title"></h1>
<p class="price">€<span x-text="product?.price"></span></p>
<!-- Quantity selector with validation -->
<input
type="number"
x-model.number="quantity"
:min="product?.min_quantity"
:max="product?.available_inventory"
>
<!-- Add to cart with loading state -->
<button
@click="addToCart()"
:disabled="!canAddToCart || addingToCart"
>
<span x-show="!addingToCart">Add to Cart</span>
<span x-show="addingToCart">Adding...</span>
</button>
</div>
CSS Architecture
CSS Variables for Multi-Tenant Theming
/* Base variables in base.css */
:root {
--primary-color: #3b82f6;
--primary-dark: #2563eb;
--success-color: #10b981;
--danger-color: #ef4444;
--warning-color: #f59e0b;
/* Typography */
--font-base: 16px;
--font-sm: 0.875rem;
--font-xl: 1.25rem;
/* Spacing */
--spacing-sm: 0.5rem;
--spacing-md: 1rem;
--spacing-lg: 1.5rem;
/* Borders & Shadows */
--radius-md: 0.375rem;
--shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
}
/* Vendor-specific overrides */
[data-vendor-theme="dark"] {
--primary-color: #1f2937;
--background-color: #111827;
}
🔒 Security Implementation
Authentication Flow
Admin Login:
1. POST /api/v1/admin/auth/login
2. Verify credentials + admin role
3. Generate JWT token
4. Store token in localStorage
5. Include in Authorization header for protected routes
Vendor Team Login:
1. POST /api/v1/vendor/auth/login
2. Detect vendor context (subdomain or path)
3. Verify credentials + vendor membership
4. Generate JWT token with vendor context
5. All subsequent requests validated against vendor
Customer Login:
1. POST /api/v1/public/vendors/{id}/auth/login
2. Verify customer credentials for specific vendor
3. Generate JWT token with customer context
4. Customer can only access their own data
Vendor Context Detection
# Automatic vendor detection from:
1. Subdomain: vendor-a.platform.com
2. Path parameter: /vendor/VENDOR_A/
3. JWT token: Embedded vendor_id in claims
# Complete data isolation:
- All queries automatically scoped to vendor_id
- Cross-vendor access prevented at service layer
- Exception raised if vendor mismatch detected
Exception Handling Pattern
# Frontend-friendly error responses
{
"detail": "Human-readable error message",
"error_code": "PRODUCT_NOT_FOUND",
"status_code": 404,
"timestamp": "2025-01-10T12:00:00Z",
"request_id": "abc123"
}
# Consistent error codes across platform
- VENDOR_NOT_FOUND
- PRODUCT_NOT_IN_CATALOG
- INSUFFICIENT_INVENTORY
- INVALID_ORDER_STATUS
- UNAUTHORIZED_VENDOR_ACCESS
📊 Database Schema
Core Tables
Multi-Tenant Foundation:
vendors # Vendor accounts
├── users # Platform/admin users
├── vendor_users # Vendor team members (many-to-many)
└── roles # Role definitions per vendor
customers # Vendor-scoped customers
└── customer_addresses
Product & Inventory:
marketplace_products # Imported from marketplaces (staging)
└── marketplace_import_jobs # Import tracking
products # Published vendor catalog
└── inventory # Stock tracking by location
└── inventory_movements
Orders & Commerce:
orders
├── order_items
├── shipping_address (FK to customer_addresses)
└── billing_address (FK to customer_addresses)
Key Relationships
Vendor (1) ──→ (N) Products
Vendor (1) ──→ (N) Customers
Vendor (1) ──→ (N) Orders
Vendor (1) ──→ (N) MarketplaceProducts
Product (1) ──→ (N) Inventory
Product (1) ──→ (1) MarketplaceProduct
Order (1) ──→ (N) OrderItems
Order (1) ──→ (1) Customer
Order (1) ──→ (1) ShippingAddress
Order (1) ──→ (1) BillingAddress
🧪 Testing
Current Test Coverage
# Run all tests
pytest tests/
# Run with coverage
pytest --cov=app --cov=models --cov=middleware tests/
# Run specific test category
pytest tests/unit/
pytest tests/integration/
pytest tests/e2e/
Test Structure
- Unit Tests: Service layer logic, model validation
- Integration Tests: API endpoints, database operations
- E2E Tests: Complete user workflows (admin creates vendor → vendor imports products → customer places order)
🚦 Development Status
✅ Completed Features
Slice 1: Multi-Tenant Foundation
- ✅ Admin creates vendors through admin interface
- ✅ Vendor owner login with context detection
- ✅ Complete vendor data isolation
- ✅ Role-based access control
- ✅ JWT authentication system
Slice 2: Marketplace Integration
- ✅ CSV import from Letzshop
- ✅ Background job processing
- ✅ Import status tracking
- ✅ Product staging area
- 🚧 Real-time Alpine.js status updates
Slice 3: Product Catalog
- ✅ Product publishing from marketplace staging
- ✅ Vendor product catalog management
- ✅ Product CRUD operations
- ✅ Inventory tracking
- ✅ Product filtering and search
Slice 4: Customer Shopping
- ✅ Customer service implementation
- ✅ Customer registration/login
- ✅ Product browsing interface
- ✅ Shopping cart with Alpine.js
- ✅ Product detail page (Alpine.js)
Slice 5: Order Processing
- ✅ Order creation from cart
- ✅ Order management (vendor)
- ✅ Order history (customer)
- ✅ Order status tracking
- ✅ Inventory reservation
🚧 In Progress (BOOTS)
Current Sprint:
- 🚧 Customer account dashboard (Alpine.js)
- 🚧 Multi-step checkout flow
- 🚧 Payment integration placeholder (Stripe ready)
- 🚧 Order confirmation page
- 🚧 Email notifications (order confirmations)
📋 Roadmap
Phase 1: Core Platform (90% Complete)
- ✅ Multi-tenant architecture
- ✅ Vendor management
- ✅ Product catalog system
- ✅ Order processing
- ✅ Customer management
- 🚧 Payment integration (ready for Stripe)
- 🚧 Email notifications
Phase 2: Advanced Features (Next)
- Persistent cart storage (Redis/Database)
- Order search and filtering
- Advanced inventory management
- Product variants support
- Customer reviews and ratings
- Vendor analytics dashboard
Phase 3: Enterprise Features (Future)
- Multi-language support
- Advanced reporting and exports
- Webhook integrations
- API rate limiting enhancements
- Performance monitoring
- Automated backups
📝 Naming Conventions
The project follows strict naming conventions for consistency:
Files
- API files: Plural (
products.py,orders.py) - Model files: Singular (
product.py,order.py) - Service files: Singular + service (
product_service.py) - Exception files: Singular (
product.py,order.py)
Terminology
- inventory (not stock)
- vendor (not shop)
- customer (not user for end-users)
- team (not staff)
See docs/6.complete_naming_convention.md for full details.
🤝 Contributing
Development Workflow
- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature - Follow existing patterns (service layer, exceptions, Alpine.js)
- Add tests for new features
- Update API documentation
- Submit pull request
Code Quality
# Format code
black app/ models/ middleware/
# Sort imports
isort app/ models/ middleware/
# Lint
flake8 app/ models/ middleware/
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🆘 Support
Documentation
- API Reference: http://localhost:8000/docs
- Development Guides:
/docs/ - Naming Conventions:
/docs/6.complete_naming_convention.md - Vertical Slice Plan:
/docs/3.vertical_slice_roadmap.md
Key Features
- Zero Build Step: Frontend works without compilation
- Alpine.js Reactive UI: Modern UX without framework complexity
- Service Layer Pattern: Clean, testable business logic
- Exception-First: Consistent error handling
- Multi-Tenant by Design: Complete vendor isolation
Built with FastAPI, PostgreSQL, Alpine.js, and modern Python patterns for a scalable, maintainable multi-tenant ecommerce platform. 🚀