ET-Mock / SQL.txt
SakibAhmed's picture
Upload 6 files
21d2ae0 verified
-- ================================================
-- SUPABASE DATABASE SCHEMA FOR SSG WHATSAPP AI
-- ================================================
-- Enable UUID extension
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
-- ================================================
-- TABLE: categories
-- Purpose: Store business categories
-- ================================================
CREATE TABLE categories (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
description TEXT,
icon VARCHAR(50),
display_order INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_categories_name ON categories(name);
CREATE INDEX idx_categories_active ON categories(is_active);
-- ================================================
-- TABLE: locations
-- Purpose: Store geographical locations
-- ================================================
CREATE TABLE locations (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
country VARCHAR(100),
region VARCHAR(100),
latitude DECIMAL(10, 8),
longitude DECIMAL(11, 8),
display_order INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT TRUE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_locations_name ON locations(name);
CREATE INDEX idx_locations_country ON locations(country);
CREATE INDEX idx_locations_active ON locations(is_active);
-- ================================================
-- TABLE: companies
-- Purpose: Store company listings
-- ================================================
CREATE TABLE companies (
id SERIAL PRIMARY KEY,
company_name VARCHAR(255) NOT NULL,
description TEXT,
website_link VARCHAR(500),
advertising_tier VARCHAR(20) DEFAULT 'Free' CHECK (advertising_tier IN ('Premium', 'Enhanced', 'Logo', 'Free')),
category_id INTEGER NOT NULL REFERENCES categories(id) ON DELETE CASCADE,
location_id INTEGER NOT NULL REFERENCES locations(id) ON DELETE CASCADE,
keywords TEXT[],
contact_email VARCHAR(255),
contact_phone VARCHAR(50),
address TEXT,
logo_url VARCHAR(500),
is_active BOOLEAN DEFAULT TRUE,
featured BOOLEAN DEFAULT FALSE,
views_count INTEGER DEFAULT 0,
clicks_count INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_companies_category ON companies(category_id);
CREATE INDEX idx_companies_location ON companies(location_id);
CREATE INDEX idx_companies_tier ON companies(advertising_tier);
CREATE INDEX idx_companies_active ON companies(is_active);
CREATE INDEX idx_companies_keywords ON companies USING GIN(keywords);
-- ================================================
-- TABLE: users
-- Purpose: Store user profiles and subscription info
-- ================================================
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
phone_number VARCHAR(20) UNIQUE NOT NULL,
full_name VARCHAR(255),
email VARCHAR(255),
role VARCHAR(50) DEFAULT 'boat_owner',
vessel_size VARCHAR(50),
vessel_name VARCHAR(255),
subscription_tier VARCHAR(20) DEFAULT 'free' CHECK (subscription_tier IN ('free', 'premium')),
subscription_start_date TIMESTAMP WITH TIME ZONE,
subscription_end_date TIMESTAMP WITH TIME ZONE,
queries_today INTEGER DEFAULT 0,
max_daily_queries INTEGER DEFAULT 10,
total_queries INTEGER DEFAULT 0,
onboarding_completed BOOLEAN DEFAULT FALSE,
preferences JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
last_active_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Index for fast phone number lookups
CREATE INDEX idx_users_phone_number ON users(phone_number);
CREATE INDEX idx_users_subscription_tier ON users(subscription_tier);
CREATE INDEX idx_users_last_active ON users(last_active_at);
-- ================================================
-- TABLE: conversations
-- Purpose: Store message history for context
-- ================================================
CREATE TABLE conversations (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
role VARCHAR(20) NOT NULL CHECK (role IN ('user', 'assistant', 'system')),
content TEXT NOT NULL,
content_type VARCHAR(20) DEFAULT 'text' CHECK (content_type IN ('text', 'image', 'audio', 'video')),
media_url TEXT,
metadata JSONB DEFAULT '{}',
tokens_used INTEGER,
model_used VARCHAR(100),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Indexes for conversation retrieval
CREATE INDEX idx_conversations_user_id ON conversations(user_id);
CREATE INDEX idx_conversations_created_at ON conversations(created_at DESC);
CREATE INDEX idx_conversations_user_created ON conversations(user_id, created_at DESC);
-- ================================================
-- TABLE: search_queries
-- Purpose: Log searches for analytics
-- ================================================
CREATE TABLE search_queries (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
category_id VARCHAR(10),
category_name VARCHAR(255),
location_id VARCHAR(10),
location_name VARCHAR(255),
search_term TEXT,
results_count INTEGER DEFAULT 0,
top_result_company VARCHAR(255),
user_query TEXT,
extracted_intent JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Indexes for analytics queries
CREATE INDEX idx_search_queries_user_id ON search_queries(user_id);
CREATE INDEX idx_search_queries_category ON search_queries(category_name);
CREATE INDEX idx_search_queries_location ON search_queries(location_name);
CREATE INDEX idx_search_queries_created_at ON search_queries(created_at DESC);
-- ================================================
-- TABLE: api_logs
-- Purpose: Track API calls for debugging/monitoring
-- ================================================
CREATE TABLE api_logs (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
endpoint VARCHAR(255) NOT NULL,
method VARCHAR(10) NOT NULL,
request_params JSONB,
response_status INTEGER,
response_time_ms INTEGER,
error_message TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_api_logs_created_at ON api_logs(created_at DESC);
CREATE INDEX idx_api_logs_endpoint ON api_logs(endpoint);
-- ================================================
-- TABLE: user_feedback
-- Purpose: Store user feedback and ratings
-- ================================================
CREATE TABLE user_feedback (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
conversation_id UUID REFERENCES conversations(id) ON DELETE SET NULL,
rating INTEGER CHECK (rating >= 1 AND rating <= 5),
feedback_text TEXT,
feedback_type VARCHAR(50) CHECK (feedback_type IN ('helpful', 'not_helpful', 'incorrect', 'bug', 'feature_request', 'other')),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_user_feedback_user_id ON user_feedback(user_id);
CREATE INDEX idx_user_feedback_rating ON user_feedback(rating);
CREATE INDEX idx_user_feedback_created_at ON user_feedback(created_at DESC);
-- ================================================
-- TABLE: system_metrics
-- Purpose: Track system performance metrics
-- ================================================
CREATE TABLE system_metrics (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
metric_type VARCHAR(100) NOT NULL,
metric_value NUMERIC,
metadata JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_system_metrics_type ON system_metrics(metric_type);
CREATE INDEX idx_system_metrics_created_at ON system_metrics(created_at DESC);
-- ================================================
-- TABLE: subscription_history
-- Purpose: Track subscription changes and payments
-- ================================================
CREATE TABLE subscription_history (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
previous_tier VARCHAR(20),
new_tier VARCHAR(20) NOT NULL,
change_reason VARCHAR(255),
amount_paid NUMERIC(10, 2),
payment_method VARCHAR(50),
payment_status VARCHAR(50),
valid_from TIMESTAMP WITH TIME ZONE NOT NULL,
valid_until TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX idx_subscription_history_user_id ON subscription_history(user_id);
CREATE INDEX idx_subscription_history_created_at ON subscription_history(created_at DESC);
-- ================================================
-- FUNCTIONS & TRIGGERS
-- ================================================
-- Function to update updated_at timestamp
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
-- Trigger for users table
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- Function to reset daily query count
CREATE OR REPLACE FUNCTION reset_daily_queries()
RETURNS void AS $$
BEGIN
UPDATE users SET queries_today = 0;
END;
$$ language 'plpgsql';
-- Function to increment user queries
CREATE OR REPLACE FUNCTION increment_user_query(p_user_id UUID)
RETURNS void AS $$
BEGIN
UPDATE users
SET
queries_today = queries_today + 1,
total_queries = total_queries + 1,
last_active_at = NOW()
WHERE id = p_user_id;
END;
$$ language 'plpgsql';
-- Function to get conversation context (last N messages)
CREATE OR REPLACE FUNCTION get_conversation_context(
p_user_id UUID,
p_limit INTEGER DEFAULT 10
)
RETURNS TABLE (
role VARCHAR(20),
content TEXT,
created_at TIMESTAMP WITH TIME ZONE
) AS $$
BEGIN
RETURN QUERY
SELECT c.role, c.content, c.created_at
FROM conversations c
WHERE c.user_id = p_user_id
ORDER BY c.created_at DESC
LIMIT p_limit;
END;
$$ language 'plpgsql';
-- ================================================
-- ROW LEVEL SECURITY (RLS) POLICIES
-- ================================================
-- Enable RLS on all tables
ALTER TABLE users ENABLE ROW LEVEL SECURITY;
ALTER TABLE conversations ENABLE ROW LEVEL SECURITY;
ALTER TABLE search_queries ENABLE ROW LEVEL SECURITY;
ALTER TABLE user_feedback ENABLE ROW LEVEL SECURITY;
ALTER TABLE subscription_history ENABLE ROW LEVEL SECURITY;
-- Policy: Users can only read their own data
CREATE POLICY "Users can view own data" ON users
FOR SELECT USING (auth.uid()::text = id::text);
-- Policy: Users can update their own profile
CREATE POLICY "Users can update own profile" ON users
FOR UPDATE USING (auth.uid()::text = id::text);
-- Policy: Users can view their own conversations
CREATE POLICY "Users can view own conversations" ON conversations
FOR SELECT USING (auth.uid()::text = user_id::text);
-- Policy: Users can view their own search queries
CREATE POLICY "Users can view own searches" ON search_queries
FOR SELECT USING (auth.uid()::text = user_id::text);
-- ================================================
-- COMMENTS FOR DOCUMENTATION
-- ================================================
COMMENT ON TABLE users IS 'Stores user profiles, subscription status, and usage metrics';
COMMENT ON TABLE conversations IS 'Message history for providing conversation context to AI';
COMMENT ON TABLE search_queries IS 'Logs all search queries for analytics and improvement';
COMMENT ON TABLE api_logs IS 'Tracks API performance and errors for monitoring';
COMMENT ON TABLE user_feedback IS 'Stores user feedback and ratings for quality improvement';
COMMENT ON TABLE system_metrics IS 'System-wide performance and usage metrics';
COMMENT ON TABLE subscription_history IS 'Audit trail of subscription changes and payments';
COMMENT ON COLUMN users.preferences IS 'JSON object storing user preferences like language, notification settings';
COMMENT ON COLUMN conversations.metadata IS 'JSON object storing additional message metadata like processing time, model version';
COMMENT ON COLUMN search_queries.extracted_intent IS 'JSON object containing the extracted category, location, and search term';