Skip to content

Database Schema

Core Tables

users

Column Type Constraints
id UUID PRIMARY KEY
email VARCHAR(255) UNIQUE, NOT NULL
hashed_password VARCHAR(255) NOT NULL
name VARCHAR(255) NOT NULL
role VARCHAR(50) NOT NULL DEFAULT 'user'
is_active BOOLEAN NOT NULL DEFAULT true
tenant_id UUID FK → tenants(id), NOT NULL
verification_code VARCHAR(10)
verification_code_expires TIMESTAMP
reset_code VARCHAR(10)
reset_code_expires TIMESTAMP
created_at TIMESTAMP NOT NULL
updated_at TIMESTAMP

tenants

Column Type Constraints
id UUID PRIMARY KEY
name VARCHAR(255) UNIQUE, NOT NULL
domain VARCHAR(255) UNIQUE
pricing_tier VARCHAR(50) NOT NULL DEFAULT 'STARTER'
custom_tracking_url VARCHAR(255)
created_at TIMESTAMP NOT NULL
updated_at TIMESTAMP

sessions

Column Type Constraints
id UUID PRIMARY KEY
user_id UUID FK → users(id), NOT NULL
refresh_token_hash VARCHAR(255) NOT NULL
expires_at TIMESTAMP NOT NULL
created_at TIMESTAMP NOT NULL

Shipments Tables

shipments

Column Type Constraints
id UUID PRIMARY KEY
tenant_id UUID FK → tenants(id), NOT NULL
tracking_id VARCHAR(20) UNIQUE, NOT NULL
sender_name VARCHAR(255) NOT NULL
sender_phone VARCHAR(50) NOT NULL
recipient_name VARCHAR(255) NOT NULL
recipient_phone VARCHAR(50) NOT NULL
origin VARCHAR(255) NOT NULL
destination VARCHAR(255) NOT NULL
description TEXT
weight DECIMAL(10,2)
price DECIMAL(10,2)
status VARCHAR(50) NOT NULL DEFAULT 'RECEIVED'
payment_status VARCHAR(50) NOT NULL DEFAULT 'PENDING'
eta TIMESTAMP
bag_id UUID FK → bags(id)
notification_whatsapp BOOLEAN DEFAULT true
notification_email BOOLEAN DEFAULT true
notification_push BOOLEAN DEFAULT true
recipient_email VARCHAR(255)
device_token TEXT
last_notification_sent TIMESTAMP
created_at TIMESTAMP NOT NULL
updated_at TIMESTAMP

bags

Column Type Constraints
id UUID PRIMARY KEY
tenant_id UUID FK → tenants(id), NOT NULL
label VARCHAR(100) NOT NULL
status VARCHAR(50) NOT NULL DEFAULT 'PACKAGED'
flight_id UUID FK → flights(id)
created_at TIMESTAMP NOT NULL
updated_at TIMESTAMP

flights

Column Type Constraints
id UUID PRIMARY KEY
tenant_id UUID FK → tenants(id), NOT NULL
flight_number VARCHAR(20) NOT NULL
airline_name VARCHAR(255)
departure_airport VARCHAR(10) NOT NULL
arrival_airport VARCHAR(10) NOT NULL
scheduled_departure TIMESTAMP
scheduled_arrival TIMESTAMP
actual_departure TIMESTAMP
actual_arrival TIMESTAMP
flight_status VARCHAR(50) DEFAULT 'scheduled'
delay_minutes INTEGER DEFAULT 0
departure_terminal VARCHAR(50)
arrival_terminal VARCHAR(50)
created_at TIMESTAMP NOT NULL
updated_at TIMESTAMP

flight_alert_subscriptions

Column Type Constraints
id UUID PRIMARY KEY
tenant_id UUID FK → tenants(id), NOT NULL
flight_id UUID FK → flights(id), NOT NULL
subscription_id VARCHAR(255)
webhook_url VARCHAR(500)
expires_at TIMESTAMP
created_at TIMESTAMP NOT NULL

Row Level Security (RLS)

All tenant-scoped tables have RLS enabled:

ENABLE ROW LEVEL SECURITY;
FORCE ROW LEVEL SECURITY;

POLICY mandatory_tenant_policy ON table_name
USING (tenant_id = current_setting('app.current_tenant')::uuid)
WITH CHECK (tenant_id = current_setting('app.current_tenant')::uuid);

RLS Context Manager in Python:

class TenantContext:
    async def __aenter__(self):
        await conn.execute("SET LOCAL app.current_tenant = %s", tenant_id)
    async def __aexit__(self, *args):
        await conn.execute("RESET app.current_tenant")

Shipment Status Values

Status Description
RECEIVED Shipment received, awaiting bag assignment
VERIFIED Verified (internal)
PAID Payment confirmed (internal)
PREPARING Assigned to bag, in preparation
PACKAGED Packed in bag
IN_TRANSIT In transit to destination
AT_PICKUP_POINT At pickup point
OUT_FOR_DELIVERY Out for delivery
DELIVERED Delivered to recipient
RETURNED Returned to sender
CANCELLED Cancelled

Payment Status Values

Status Description
PENDING Awaiting payment
PAID Payment received
REFUNDED Payment refunded