Files
smoothschedule/smoothschedule/SETUP_GUIDE.md
poduck 156cc2676d refactor: Reorganize Django apps into domain-based structure
Restructured 13 Django apps from flat/mixed organization into 5 logical
domain packages following cookiecutter-django conventions:

- identity/: core (tenant/domain models, middleware, mixins), users
- scheduling/: schedule, contracts, analytics
- communication/: notifications, credits, mobile, messaging
- commerce/: payments, tickets
- platform/: admin, api

Key changes:
- Moved all apps to smoothschedule/smoothschedule/{domain}/{app}/
- Updated all import paths across the codebase
- Updated settings (base.py, multitenancy.py, test.py)
- Updated URL configuration in config/urls.py
- Updated middleware and permission paths
- Preserved app_label in AppConfig for migration compatibility
- Updated CLAUDE.md documentation with new structure

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-07 18:24:50 -05:00

9.6 KiB

Smooth Schedule - Installation & Setup Guide

🎉 Project Structure Created Successfully!

Your Smooth Schedule multi-tenant SaaS platform has been initialized with:

  • Cookiecutter-Django base structure
  • Multi-tenancy with django-tenants 3.9.0
  • Masquerading security with django-hijack 3.7.4
  • Custom 8-tier role hierarchy
  • Audit logging middleware
  • PostgreSQL schema-per-tenant architecture

📁 Project Location

/home/poduck/Desktop/smoothschedule2/smoothschedule/

🚀 Next Steps to Get Running

1. Navigate to Project Directory

cd /home/poduck/Desktop/smoothschedule2/smoothschedule

2. Configure Environment Variables

Create .envs/.local/.django file:

mkdir -p .envs/.local
cat > .envs/.local/.django << 'EOF'
# General
# ------------------------------------------------------------------------------
DJANGO_SETTINGS_MODULE=config.settings.local
DJANGO_SECRET_KEY=your-secret-key-here-change-in-production
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1,.localhost,.127.0.0.1
USE_DOCKER=yes

# Database
# ------------------------------------------------------------------------------
DATABASE_URL=postgres://postgres:changeme@postgres:5432/smoothschedule

# Redis
# ------------------------------------------------------------------------------
REDIS_URL=redis://redis:6379/0

#AWS  
# ------------------------------------------------------------------------------
DJANGO_AWS_ACCESS_KEY_ID=
DJANGO_AWS_SECRET_ACCESS_KEY=
DJANGO_AWS_STORAGE_BUCKET_NAME=smoothschedule-media
DJANGO_AWS_S3_REGION_NAME=us-east-1
EOF

Create .envs/.local/.postgres file:

cat > .envs/.local/.postgres << 'EOF'
# PostgreSQL
# ------------------------------------------------------------------------------
POSTGRES_HOST=postgres
POSTGRES_PORT=5432
POSTGRES_DB=smoothschedule
POSTGRES_USER=postgres
POSTGRES_PASSWORD=changeme
EOF

3. Build and Start Docker Containers

# Build the Docker images
docker-compose -f docker-compose.local.yml build

# Start all services (Django, PostgreSQL, Redis, Celery)
docker-compose -f docker-compose.local.yml up -d

# Check logs
docker-compose -f docker-compose.local.yml logs -f

4. Run Database Migrations

IMPORTANT: With django-tenants, you must run migrations in a specific order:

# 1. Create the shared schema (public) FIRST
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas --shared

# 2. Create a superuser (in the public schema)
docker-compose -f docker-compose.local.yml run --rm django python manage.py createsuperuser

5. Create Your First Tenant

Open Django shell:

docker-compose -f docker-compose.local.yml run --rm django python manage.py shell

In the shell, create a tenant:

from core.models import Tenant, Domain

# Create the tenant
tenant = Tenant.objects.create(
    name="Demo Company",
    schema_name="demo",  # This will be the PostgreSQL schema name
    subscription_tier="PROFESSIONAL",
    max_users=50,
    max_resources=100,
)

# Create a domain for the tenant
domain = Domain.objects.create(
    domain="demo.localhost",  # For local development
    tenant=tenant,
    is_primary=True,
)

print(f"Created tenant: {tenant.name} with schema: {tenant.schema_name}")
print(f"Domain: {domain.domain}")

Exit the shell (exit() or Ctrl+D).

6. Run Tenant Migrations

Now migrate all tenant schemas:

docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas

7. Access the Application

🔐 Creating Users with Roles

In Django shell or admin, create users with different roles:

from smoothschedule.identity.users.models import User
from core.models import Tenant

# Get the tenant
tenant = Tenant.objects.get(schema_name="demo")

# Create a Tenant Owner
owner = User.objects.create_user(
    email="owner@demo.com",
    password="secure-password",
    role=User.Role.TENANT_OWNER,
    tenant=tenant,
    first_name="John",
    last_name="Owner",
)

# Create a Tenant Staff member
staff = User.objects.create_user(
    email="staff@demo.com",
    password="secure-password",
    role=User.Role.TENANT_STAFF,
    tenant=tenant,
    first_name="Jane",
    last_name="Staff",
)

# Create a demo account (for sales)
demo_user = User.objects.create_user(
    email="demo@demo.com",
    password="demo-password",
    role=User.Role.TENANT_OWNER,
    tenant=tenant,
    is_temporary=True,  # Sales can masquerade as this user
    first_name="Demo",
    last_name="Account",
)

# Create a Platform Support user
support = User.objects.create_user(
    email="support@smoothschedule.com",
    password="support-password",
    role=User.Role.PLATFORM_SUPPORT,
    tenant=None,  # Platform users have no tenant
    is_staff=True,  # Needed for admin access
    first_name="Support",
    last_name="Team",
)

🎭 Testing Masquerading

  1. Login to admin as a superuser or support user
  2. Go to Users section
  3. Click the "Hijack" button next to a user you can masquerade as
  4. You'll now see the interface as that user
  5. Check logs/masquerade.log for audit trail:
docker-compose -f docker-compose.local.yml exec django cat logs/masquerade.log

📊 Understanding the Architecture

Multi-Tenancy

Each tenant gets their own PostgreSQL schema:

PostgreSQL Database: smoothschedule
├── public (shared schema)
│   ├── core_tenant
│   ├── core_domain  
│   ├── users_user
│   └── core_permissiongrant
├── demo (tenant schema for "Demo Company")
│   └── (your tenant-scoped apps go here)
└── acme (tenant schema for "Acme Corp")
    └── (completely isolated data)

Role Hierarchy

Role Level Can Hijack
SUPERUSER Platform Everyone
PLATFORM_SUPPORT Platform Tenant users
PLATFORM_SALES Platform Demo accounts only
TENANT_OWNER Tenant Staff in same tenant
TENANT_MANAGER Tenant -
TENANT_STAFF Tenant -
CUSTOMER Tenant -

🛠️ Development Workflow

Adding Tenant-Scoped Apps

  1. Create your app:

    docker-compose -f docker-compose.local.yml run --rm django python manage.py startapp myapp
    
  2. Add to TENANT_APPS in config/settings/multitenancy.py:

    TENANT_APPS = [
        'django.contrib.contenttypes',
        'myapp',  # Your new app
    ]
    
  3. Run migrations:

    docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas
    

Useful Commands

# View logs
docker-compose -f docker-compose.local.yml logs -f django

# Shell access
docker-compose -f docker-compose.local.yml run --rm django python manage.py shell

# Create migrations
docker-compose -f docker-compose.local.yml run --rm django python manage.py makemigrations

# Migrate all tenants
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas

# Collect static files
docker-compose -f docker-compose.local.yml run --rm django python manage.py collectstatic --noinput

📝 Key Files Reference

File Purpose
config/settings/multitenancy.py Multi-tenancy configuration
config/settings/local.py Local development settings
smoothschedule/core/ Tenant, Domain, PermissionGrant models
smoothschedule/users/models.py Custom User with 8 roles
core/permissions.py Masquerading permission matrix
core/middleware.py Audit logging middleware

🐛 Troubleshooting

Problem: "django_tenants not found"

Solution: Rebuild the Docker image:

docker-compose -f docker-compose.local.yml build --no-cache django

Problem: "relation does not exist"

Solution: Run migrations in correct order:

# 1. Shared schema first
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas --shared

# 2. Then tenant schemas
docker-compose -f docker-compose.local.yml run --rm django python manage.py migrate_schemas

Problem: Cannot access tenant URL

Solution: Add to /etc/hosts:

echo "127.0.0.1   demo.localhost" | sudo tee -a /etc/hosts

Problem: Hijack button doesn't appear

Solution:

  1. Ensure user has appropriate role (see permission matrix)
  2. Check that HijackUserAdminMixin is in users/admin.py
  3. Verify middleware order in settings

🎯 Production Deployment

Before deploying to production:

  1. Update SECRET_KEY: Use environment variable
  2. Set DEBUG=False: In production settings
  3. Configure ALLOWED_HOSTS: Add your domain
  4. Update Database Credentials: Use secure passwords
  5. Configure AWS: Set real S3 and Route53 credentials
  6. Enable HTTPS: Set SECURE_SSL_REDIRECT = True
  7. Review Security Settings: Check config/settings/production.py

📚 Additional Resources


Your multi-tenant SaaS platform is ready! 🚀