Core Tables
Essential database tables and their structure
Core Tables
The Smart Shelf database consists of several core table groups that handle different aspects of inventory management.
Authentication & Users
users
Extends Supabase auth.users with application-specific data.
CREATE TABLE users (
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
email VARCHAR(255) UNIQUE NOT NULL,
full_name VARCHAR(255),
role VARCHAR(50) DEFAULT 'viewer' CHECK (role IN ('admin', 'manager', 'employee', 'viewer')),
avatar_url TEXT,
phone VARCHAR(20),
is_active BOOLEAN DEFAULT true,
last_login TIMESTAMPTZ,
preferences JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
Indexes:
CREATE INDEX idx_users_email ON users(email);
CREATE INDEX idx_users_role ON users(role);
CREATE INDEX idx_users_active ON users(is_active);
user_sessions
Track user login sessions.
CREATE TABLE user_sessions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
session_token VARCHAR(255) UNIQUE NOT NULL,
ip_address INET,
user_agent TEXT,
expires_at TIMESTAMPTZ NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
Product Management
categories
Hierarchical product categories.
CREATE TABLE categories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
description TEXT,
parent_id UUID REFERENCES categories(id) ON DELETE SET NULL,
sort_order INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
products
Core product information.
CREATE TABLE products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
sku VARCHAR(100) UNIQUE NOT NULL,
description TEXT,
category_id UUID REFERENCES categories(id) ON DELETE SET NULL,
-- Pricing
cost_price DECIMAL(10,2) DEFAULT 0,
selling_price DECIMAL(10,2) DEFAULT 0,
msrp DECIMAL(10,2),
-- Physical attributes
weight DECIMAL(8,3),
length DECIMAL(8,2),
width DECIMAL(8,2),
height DECIMAL(8,2),
volume DECIMAL(10,3),
-- Inventory settings
reorder_point INTEGER DEFAULT 0,
max_stock_level INTEGER,
min_order_quantity INTEGER DEFAULT 1,
-- Product status
is_active BOOLEAN DEFAULT true,
is_serialized BOOLEAN DEFAULT false,
track_expiry BOOLEAN DEFAULT false,
-- Metadata
tags JSONB DEFAULT '[]',
custom_fields JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
Indexes:
CREATE INDEX idx_products_sku ON products(sku);
CREATE INDEX idx_products_name ON products(name);
CREATE INDEX idx_products_category ON products(category_id);
CREATE INDEX idx_products_active ON products(is_active);
CREATE INDEX idx_products_tags ON products USING GIN(tags);
product_barcodes
Multiple barcodes per product support.
CREATE TABLE product_barcodes (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
barcode VARCHAR(255) NOT NULL,
barcode_type VARCHAR(50) DEFAULT 'UPC-A',
is_primary BOOLEAN DEFAULT false,
created_at TIMESTAMPTZ DEFAULT now()
);
product_variants
Product variations (size, color, etc.).
CREATE TABLE product_variants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
variant_name VARCHAR(255) NOT NULL,
sku VARCHAR(100) UNIQUE NOT NULL,
-- Variant-specific pricing
cost_price DECIMAL(10,2),
selling_price DECIMAL(10,2),
-- Variant attributes
attributes JSONB DEFAULT '{}', -- {"size": "L", "color": "red"}
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
Warehouse Management
warehouses
Warehouse/location information.
CREATE TABLE warehouses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
code VARCHAR(50) UNIQUE NOT NULL,
-- Address information
address_line1 VARCHAR(255),
address_line2 VARCHAR(255),
city VARCHAR(100),
state VARCHAR(100),
postal_code VARCHAR(20),
country VARCHAR(100) DEFAULT 'US',
-- Contact information
phone VARCHAR(20),
email VARCHAR(255),
manager_id UUID REFERENCES users(id) ON DELETE SET NULL,
-- Capacity settings
capacity_limit INTEGER,
capacity_unit VARCHAR(20) DEFAULT 'units',
-- Operational settings
timezone VARCHAR(50) DEFAULT 'UTC',
operating_hours JSONB DEFAULT '{}',
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
warehouse_zones
Storage zones within warehouses.
CREATE TABLE warehouse_zones (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
code VARCHAR(50) NOT NULL,
zone_type VARCHAR(50) DEFAULT 'storage', -- storage, staging, shipping, receiving
capacity INTEGER,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(warehouse_id, code)
);
warehouse_locations
Specific storage locations (bins, shelves).
CREATE TABLE warehouse_locations (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE CASCADE,
zone_id UUID REFERENCES warehouse_zones(id) ON DELETE SET NULL,
location_code VARCHAR(100) NOT NULL,
-- Location hierarchy: Zone-Aisle-Shelf-Bin
aisle VARCHAR(10),
shelf VARCHAR(10),
bin VARCHAR(10),
-- Capacity
max_capacity INTEGER,
current_capacity INTEGER DEFAULT 0,
-- Location attributes
temperature_controlled BOOLEAN DEFAULT false,
hazmat_approved BOOLEAN DEFAULT false,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(warehouse_id, location_code)
);
Inventory Management
inventory
Current inventory levels by product and warehouse.
CREATE TABLE inventory (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE CASCADE,
location_id UUID REFERENCES warehouse_locations(id) ON DELETE SET NULL,
-- Quantity tracking
quantity_on_hand INTEGER DEFAULT 0,
quantity_allocated INTEGER DEFAULT 0,
quantity_available INTEGER GENERATED ALWAYS AS (quantity_on_hand - quantity_allocated) STORED,
-- Cost tracking
average_cost DECIMAL(10,2) DEFAULT 0,
last_cost DECIMAL(10,2) DEFAULT 0,
-- Audit fields
last_counted_at TIMESTAMPTZ,
last_movement_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now(),
UNIQUE(product_id, warehouse_id)
);
Indexes:
CREATE INDEX idx_inventory_product ON inventory(product_id);
CREATE INDEX idx_inventory_warehouse ON inventory(warehouse_id);
CREATE INDEX idx_inventory_available ON inventory(quantity_available);
CREATE INDEX idx_inventory_low_stock ON inventory(quantity_on_hand, quantity_allocated)
WHERE quantity_on_hand <= quantity_allocated;
stock_movements
All inventory movements/transactions.
CREATE TABLE stock_movements (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE CASCADE,
-- Movement details
movement_type VARCHAR(50) NOT NULL CHECK (movement_type IN ('in', 'out', 'adjustment', 'transfer')),
quantity INTEGER NOT NULL,
unit_cost DECIMAL(10,2),
-- Balance tracking
balance_before INTEGER NOT NULL,
balance_after INTEGER NOT NULL,
-- Reference information
reference_type VARCHAR(50), -- purchase_order, sales_order, adjustment, transfer
reference_id UUID,
-- Additional details
notes TEXT,
performed_by UUID REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
Partitioning:
-- Partition by month for performance
CREATE TABLE stock_movements_y2024m01 PARTITION OF stock_movements
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');
inventory_adjustments
Batch inventory adjustments.
CREATE TABLE inventory_adjustments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
adjustment_number VARCHAR(100) UNIQUE NOT NULL,
warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE CASCADE,
-- Adjustment details
adjustment_type VARCHAR(50) NOT NULL, -- physical_count, damage, loss, found
reason TEXT,
-- Status and workflow
status VARCHAR(50) DEFAULT 'draft' CHECK (status IN ('draft', 'approved', 'applied')),
approved_by UUID REFERENCES users(id) ON DELETE SET NULL,
approved_at TIMESTAMPTZ,
-- Audit
created_by UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
inventory_adjustment_items
Individual items in adjustment batches.
CREATE TABLE inventory_adjustment_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
adjustment_id UUID NOT NULL REFERENCES inventory_adjustments(id) ON DELETE CASCADE,
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
-- Quantity differences
expected_quantity INTEGER NOT NULL,
actual_quantity INTEGER NOT NULL,
difference_quantity INTEGER GENERATED ALWAYS AS (actual_quantity - expected_quantity) STORED,
-- Cost impact
unit_cost DECIMAL(10,2),
cost_impact DECIMAL(10,2) GENERATED ALWAYS AS (difference_quantity * unit_cost) STORED,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
Supply Chain Management
suppliers
Supplier/vendor information.
CREATE TABLE suppliers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
code VARCHAR(50) UNIQUE,
-- Contact information
email VARCHAR(255),
phone VARCHAR(20),
website VARCHAR(255),
-- Address
address_line1 VARCHAR(255),
address_line2 VARCHAR(255),
city VARCHAR(100),
state VARCHAR(100),
postal_code VARCHAR(20),
country VARCHAR(100) DEFAULT 'US',
-- Business information
tax_id VARCHAR(50),
payment_terms VARCHAR(50) DEFAULT 'net_30',
credit_limit DECIMAL(12,2),
-- Primary contact
contact_name VARCHAR(255),
contact_email VARCHAR(255),
contact_phone VARCHAR(20),
-- Performance metrics
performance_rating DECIMAL(3,2) DEFAULT 0,
on_time_delivery_rate DECIMAL(5,2) DEFAULT 0,
quality_rating DECIMAL(3,2) DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
purchase_orders
Purchase order header information.
CREATE TABLE purchase_orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
po_number VARCHAR(100) UNIQUE NOT NULL,
supplier_id UUID NOT NULL REFERENCES suppliers(id) ON DELETE CASCADE,
warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE CASCADE,
-- Order details
order_date DATE DEFAULT CURRENT_DATE,
expected_date DATE,
delivery_date DATE,
-- Financial
subtotal DECIMAL(12,2) DEFAULT 0,
tax_rate DECIMAL(5,2) DEFAULT 0,
tax_amount DECIMAL(12,2) DEFAULT 0,
shipping_cost DECIMAL(10,2) DEFAULT 0,
total_amount DECIMAL(12,2) DEFAULT 0,
-- Status workflow
status VARCHAR(50) DEFAULT 'draft'
CHECK (status IN ('draft', 'sent', 'confirmed', 'partial', 'received', 'cancelled')),
-- Additional information
notes TEXT,
terms TEXT,
internal_notes TEXT,
-- Audit
created_by UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
approved_by UUID REFERENCES users(id) ON DELETE SET NULL,
approved_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
purchase_order_items
Individual items in purchase orders.
CREATE TABLE purchase_order_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
purchase_order_id UUID NOT NULL REFERENCES purchase_orders(id) ON DELETE CASCADE,
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
-- Order quantities
quantity_ordered INTEGER NOT NULL,
quantity_received INTEGER DEFAULT 0,
quantity_cancelled INTEGER DEFAULT 0,
quantity_pending INTEGER GENERATED ALWAYS AS (quantity_ordered - quantity_received - quantity_cancelled) STORED,
-- Pricing
unit_cost DECIMAL(10,2) NOT NULL,
total_cost DECIMAL(12,2) GENERATED ALWAYS AS (quantity_ordered * unit_cost) STORED,
-- Delivery
expected_date DATE,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
Sales Management
customers
Customer information.
CREATE TABLE customers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
customer_number VARCHAR(100) UNIQUE,
-- Contact information
email VARCHAR(255),
phone VARCHAR(20),
website VARCHAR(255),
-- Billing address
billing_address_line1 VARCHAR(255),
billing_address_line2 VARCHAR(255),
billing_city VARCHAR(100),
billing_state VARCHAR(100),
billing_postal_code VARCHAR(20),
billing_country VARCHAR(100) DEFAULT 'US',
-- Shipping address (if different)
shipping_address_line1 VARCHAR(255),
shipping_address_line2 VARCHAR(255),
shipping_city VARCHAR(100),
shipping_state VARCHAR(100),
shipping_postal_code VARCHAR(20),
shipping_country VARCHAR(100) DEFAULT 'US',
-- Business information
tax_id VARCHAR(50),
payment_terms VARCHAR(50) DEFAULT 'due_on_receipt',
credit_limit DECIMAL(12,2) DEFAULT 0,
current_balance DECIMAL(12,2) DEFAULT 0,
-- Customer preferences
preferred_shipping_method VARCHAR(100),
discount_rate DECIMAL(5,2) DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
sales_orders
Sales order header information.
CREATE TABLE sales_orders (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
order_number VARCHAR(100) UNIQUE NOT NULL,
customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
warehouse_id UUID NOT NULL REFERENCES warehouses(id) ON DELETE CASCADE,
-- Order details
order_date DATE DEFAULT CURRENT_DATE,
requested_ship_date DATE,
promised_ship_date DATE,
actual_ship_date DATE,
-- Financial
subtotal DECIMAL(12,2) DEFAULT 0,
discount_amount DECIMAL(10,2) DEFAULT 0,
tax_rate DECIMAL(5,2) DEFAULT 0,
tax_amount DECIMAL(12,2) DEFAULT 0,
shipping_cost DECIMAL(10,2) DEFAULT 0,
total_amount DECIMAL(12,2) DEFAULT 0,
-- Status workflow
status VARCHAR(50) DEFAULT 'draft'
CHECK (status IN ('draft', 'confirmed', 'picking', 'packed', 'shipped', 'delivered', 'cancelled')),
-- Shipping information
shipping_method VARCHAR(100),
tracking_number VARCHAR(255),
-- Additional information
notes TEXT,
internal_notes TEXT,
-- Audit
created_by UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
sales_order_items
Individual items in sales orders.
CREATE TABLE sales_order_items (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
sales_order_id UUID NOT NULL REFERENCES sales_orders(id) ON DELETE CASCADE,
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
-- Order quantities
quantity_ordered INTEGER NOT NULL,
quantity_shipped INTEGER DEFAULT 0,
quantity_cancelled INTEGER DEFAULT 0,
quantity_pending INTEGER GENERATED ALWAYS AS (quantity_ordered - quantity_shipped - quantity_cancelled) STORED,
-- Pricing
unit_price DECIMAL(10,2) NOT NULL,
discount_rate DECIMAL(5,2) DEFAULT 0,
discount_amount DECIMAL(10,2) DEFAULT 0,
total_amount DECIMAL(12,2) GENERATED ALWAYS AS ((unit_price * quantity_ordered) - discount_amount) STORED,
notes TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
Financial Management
invoices
Customer invoices.
CREATE TABLE invoices (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
invoice_number VARCHAR(100) UNIQUE NOT NULL,
customer_id UUID NOT NULL REFERENCES customers(id) ON DELETE CASCADE,
sales_order_id UUID REFERENCES sales_orders(id) ON DELETE SET NULL,
-- Invoice details
invoice_date DATE DEFAULT CURRENT_DATE,
due_date DATE NOT NULL,
-- Financial
subtotal DECIMAL(12,2) NOT NULL,
tax_rate DECIMAL(5,2) DEFAULT 0,
tax_amount DECIMAL(12,2) DEFAULT 0,
total_amount DECIMAL(12,2) NOT NULL,
amount_paid DECIMAL(12,2) DEFAULT 0,
balance_due DECIMAL(12,2) GENERATED ALWAYS AS (total_amount - amount_paid) STORED,
-- Status
status VARCHAR(50) DEFAULT 'draft'
CHECK (status IN ('draft', 'sent', 'paid', 'overdue', 'cancelled')),
-- Payment information
payment_terms VARCHAR(100),
payment_method VARCHAR(50),
notes TEXT,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
expenses
Business expenses.
CREATE TABLE expenses (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
supplier_id UUID REFERENCES suppliers(id) ON DELETE SET NULL,
-- Expense details
expense_number VARCHAR(100) UNIQUE,
description TEXT NOT NULL,
amount DECIMAL(10,2) NOT NULL,
expense_date DATE DEFAULT CURRENT_DATE,
-- Classification
category VARCHAR(100),
subcategory VARCHAR(100),
-- Payment
payment_method VARCHAR(50),
status VARCHAR(50) DEFAULT 'pending' CHECK (status IN ('pending', 'paid', 'cancelled')),
-- Supporting documentation
receipt_url TEXT,
receipt_file_name VARCHAR(255),
-- Tax information
tax_amount DECIMAL(10,2) DEFAULT 0,
tax_rate DECIMAL(5,2) DEFAULT 0,
notes TEXT,
created_by UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
created_at TIMESTAMPTZ DEFAULT now(),
updated_at TIMESTAMPTZ DEFAULT now()
);
Audit & Logging
audit_logs
System audit trail.
CREATE TABLE audit_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
table_name VARCHAR(100) NOT NULL,
record_id UUID NOT NULL,
action VARCHAR(50) NOT NULL CHECK (action IN ('INSERT', 'UPDATE', 'DELETE')),
-- Change tracking
old_values JSONB,
new_values JSONB,
changed_fields TEXT[],
-- Context
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
session_id UUID,
ip_address INET,
user_agent TEXT,
created_at TIMESTAMPTZ DEFAULT now()
);
Partitioning:
-- Partition audit logs by month
CREATE TABLE audit_logs_y2024m01 PARTITION OF audit_logs
FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');