-- ============================================================ -- FreightDesk — Migration 005: SaaS Marketplace Foundation -- Adds shipper/driver self-registration, load marketplace, bidding -- ============================================================ -- ============================================================ -- 1. ENHANCE SHIPPERS TABLE (self-registration support) -- ============================================================ ALTER TABLE shippers ADD COLUMN IF NOT EXISTS user_id UUID REFERENCES auth.users(id); ALTER TABLE shipppers ADD COLUMN IF NOT EXISTS is_verified BOOLEAN DEFAULT false; ALTER TABLE shipppers ADD COLUMN IF NOT EXISTS verification_token TEXT; ALTER TABLE shipppers ADD COLUMN IF NOT EXISTS company_name TEXT; ALTER TABLE shipppers ADD COLUMN IF NOT EXISTS gst_number TEXT; ALTER TABLE shipppers ADD COLUMN IF NOT EXISTS pan_number TEXT; ALTER TABLE shipppers ADD COLUMN IF NOT EXISTS address TEXT; ALTER TABLE shippers ADD COLUMN IF NOT EXISTS pincode TEXT; ALTER TABLE shippers ADD COLUMN IF NOT EXISTS rating DECIMAL(3,2) DEFAULT 0; ALTER TABLE shippers ADD COLUMN IF NOT EXISTS total_shipments INTEGER DEFAULT 0; -- ============================================================ -- 2. ENHANCE VEHICLES/DRIVERS TABLE (self-registration support) -- ============================================================ ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS user_id UUID REFERENCES auth.users(id); ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS driver_name TEXT; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS driver_phone TEXT; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS driver_license TEXT; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS is_verified BOOLEAN DEFAULT false; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS verification_token TEXT; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS vehicle_type TEXT; -- 'mini_truck', 'truck', 'trailer', 'container' ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS capacity_tons DECIMAL(6,2); ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS body_type TEXT; -- 'open', 'closed', 'container', 'tanker' ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS current_lat DECIMAL(10,8); ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS current_lng DECIMAL(11,8); ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS current_city TEXT; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS is_available BOOLEAN DEFAULT true; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS rating DECIMAL(3,2) DEFAULT 0; ALTER TABLE vehicles ADD COLUMN IF NOT EXISTS total_trips INTEGER DEFAULT 0; -- ============================================================ -- 3. ENHANCE LOADS TABLE (marketplace support) -- ============================================================ ALTER TABLE loads ADD COLUMN IF NOT EXISTS posted_by UUID REFERENCES auth.users(id); ALTER TABLE loads ADD COLUMN IF NOT EXISTS load_type TEXT; -- 'ftl', 'ptl', 'parcel' ALTER TABLE loads ADD COLUMN IF NOT EXISTS weight_kg INTEGER; ALTER TABLE loads ADD COLUMN IF NOT EXISTS material_type TEXT; ALTER TABLE loads ADD COLUMN IF NOT EXISTS packaging_type TEXT; ALTER TABLE loads ADD COLUMN IF NOT EXISTS pickup_address TEXT; ALTER TABLE loads ADD COLUMN IF NOT EXISTS pickup_pincode TEXT; ALTER TABLE loads ADD COLUMN IF NOT EXISTS pickup_lat DECIMAL(10,8); ALTER TABLE loads ADD COLUMN IF NOT EXISTS pickup_lng DECIMAL(11,8); ALTER TABLE loads ADD COLUMN IF NOT EXISTS delivery_address TEXT; ALTER TABLE loads ADD COLUMN IF NOT EXISTS delivery_pincode TEXT; ALTER TABLE loads ADD COLUMN IF NOT EXISTS delivery_lat DECIMAL(10,8); ALTER TABLE loads ADD COLUMN IF NOT EXISTS delivery_lng DECIMAL(11,8); ALTER TABLE loads ADD COLUMN IF NOT EXISTS pickup_date DATE; ALTER TABLE loads ADD COLUMN IF NOT EXISTS delivery_date DATE; ALTER TABLE loads ADD COLUMN IF NOT EXISTS budget_min INTEGER; ALTER TABLE loads ADD COLUMN IF NOT EXISTS budget_max INTEGER; ALTER TABLE loads ADD COLUMN IF NOT EXISTS is_open BOOLEAN DEFAULT true; -- open for bidding ALTER TABLE loads ADD COLUMN IF NOT EXISTS expires_at TIMESTAMP WITH TIME ZONE; ALTER TABLE loads ADD COLUMN IF NOT EXISTS accepted_bid_id UUID; ALTER TABLE loads ADD COLUMN IF NOT EXISTS views INTEGER DEFAULT 0; -- ============================================================ -- 4. BIDS TABLE -- ============================================================ CREATE TABLE IF NOT EXISTS bids ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), load_id UUID NOT NULL REFERENCES loads(id) ON DELETE CASCADE, driver_id UUID NOT NULL REFERENCES vehicles(id), shipper_id UUID REFERENCES shippers(id), amount INTEGER NOT NULL, message TEXT, status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'rejected', 'withdrawn', 'expired')), valid_until TIMESTAMP WITH TIME ZONE, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE(load_id, driver_id) -- one bid per driver per load ); CREATE INDEX IF NOT EXISTS idx_bids_load ON bids(load_id); CREATE INDEX IF NOT EXISTS idx_bids_driver ON bids(driver_id); CREATE INDEX IF NOT EXISTS idx_bids_status ON bids(status); -- ============================================================ -- 5. NEGOTIATION / COUNTER-OFFERS TABLE -- ============================================================ CREATE TABLE IF NOT EXISTS negotiations ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), bid_id UUID NOT NULL REFERENCES bids(id) ON DELETE CASCADE, proposed_by UUID NOT NULL, -- user_id who proposed proposed_amount INTEGER NOT NULL, message TEXT, status TEXT DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'rejected', 'countered')), created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_negotiations_bid ON negotiations(bid_id); -- ============================================================ -- 6. RATINGS & REVIEWS TABLE -- ============================================================ CREATE TABLE IF NOT EXISTS ratings ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), from_user_id UUID NOT NULL, to_user_id UUID NOT NULL, load_id UUID REFERENCES loads(id), driver_id UUID REFERENCES vehicles(id), shipper_id UUID REFERENCES shippers(id), rating INTEGER NOT NULL CHECK (rating >= 1 AND rating <= 5), review TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_ratings_to_user ON ratings(to_user_id); CREATE INDEX IF NOT EXISTS idx_ratings_driver ON ratings(driver_id); CREATE INDEX IF NOT EXISTS idx_ratings_shipper ON ratings(shipper_id); -- ============================================================ -- 7. NOTIFICATIONS TABLE -- ============================================================ CREATE TABLE IF NOT EXISTS notifications ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL, type TEXT NOT NULL CHECK (type IN ('bid_received', 'bid_accepted', 'bid_rejected', 'negotiation', 'load_assigned', 'delivery_update', 'payment', 'system')), title TEXT NOT NULL, message TEXT, data JSONB DEFAULT '{}', is_read BOOLEAN DEFAULT false, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id); CREATE INDEX IF NOT EXISTS idx_notifications_unread ON notifications(user_id, is_read) WHERE is_read = false; -- ============================================================ -- 8. LOAD VIEWS TABLE (analytics) -- ============================================================ CREATE TABLE IF NOT EXISTS load_views ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), load_id UUID NOT NULL REFERENCES loads(id) ON DELETE CASCADE, viewer_id UUID, viewed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); CREATE INDEX IF NOT EXISTS idx_load_views_load ON load_views(load_id);