Spaces:
Sleeping
Sleeping
File size: 8,328 Bytes
2f9626c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 | -- ProspectIQ Supabase PostgreSQL Database Schema
-- Enable pgvector if not already enabled (for future vector functionality)
CREATE EXTENSION IF NOT EXISTS vector;
-- Drop tables if they exist (for a clean setup, but we'll use IF NOT EXISTS)
-- 1. CRM Schema Tables
CREATE TABLE IF NOT EXISTS tenants (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
brand_color VARCHAR(50),
logo_url TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS permissions (
id SERIAL PRIMARY KEY,
code VARCHAR(255) UNIQUE NOT NULL,
description TEXT
);
CREATE TABLE IF NOT EXISTS roles (
id SERIAL PRIMARY KEY,
tenant_id INTEGER NOT NULL REFERENCES tenants(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(tenant_id, name)
);
CREATE TABLE IF NOT EXISTS role_permissions (
role_id INTEGER NOT NULL REFERENCES roles(id) ON DELETE CASCADE,
permission_id INTEGER NOT NULL REFERENCES permissions(id) ON DELETE CASCADE,
PRIMARY KEY(role_id, permission_id)
);
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
tenant_id INTEGER NOT NULL REFERENCES tenants(id),
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255) NOT NULL,
password_hash TEXT,
role_id INTEGER REFERENCES roles(id),
role VARCHAR(50) NOT NULL CHECK(role IN ('Super Admin', 'Admin', 'BD Rep', 'Viewer')),
is_active INTEGER DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS stages (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
order_index INTEGER NOT NULL UNIQUE,
color_bg VARCHAR(50),
color_text VARCHAR(50),
is_active INTEGER DEFAULT 1
);
CREATE TABLE IF NOT EXISTS import_batches (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id),
filename VARCHAR(255),
status VARCHAR(50),
total_rows INTEGER,
added INTEGER,
updated INTEGER,
skipped INTEGER,
errored INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP
);
CREATE TABLE IF NOT EXISTS companies (
id SERIAL PRIMARY KEY,
tenant_id INTEGER NOT NULL REFERENCES tenants(id),
name VARCHAR(255) NOT NULL,
legal_name VARCHAR(255),
website TEXT,
website_link TEXT,
phone VARCHAR(50),
nic_code VARCHAR(50),
industry VARCHAR(255),
street TEXT,
city VARCHAR(255),
province VARCHAR(255),
postal_code VARCHAR(50),
country VARCHAR(255),
size_staff INTEGER,
revenue_band VARCHAR(255),
business_type VARCHAR(50) CHECK(business_type IN ('OEM', 'distributor', 'other', 'OEM / distributor', 'OEM / Distributor')),
products_made TEXT,
parts_sourced TEXT,
current_supplier_notes TEXT,
maplempss_fit_score REAL DEFAULT 0.0,
stage_id INTEGER NOT NULL REFERENCES stages(id),
assigned_rep_id INTEGER REFERENCES users(id),
created_by INTEGER REFERENCES users(id),
updated_by INTEGER REFERENCES users(id),
import_batch_id INTEGER, -- Not enforced by constraint to prevent cyclic dependencies easily
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS contacts (
id SERIAL PRIMARY KEY,
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
first_name VARCHAR(255) NOT NULL,
last_name VARCHAR(255) NOT NULL,
title VARCHAR(255),
email VARCHAR(255),
phone VARCHAR(50),
linkedin TEXT,
is_primary INTEGER DEFAULT 0 CHECK(is_primary IN (0, 1)),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS activities (
id SERIAL PRIMARY KEY,
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
contact_id INTEGER REFERENCES contacts(id) ON DELETE SET NULL,
user_id INTEGER NOT NULL REFERENCES users(id),
type VARCHAR(50) NOT NULL CHECK(type IN ('Cold Call', 'Email', 'LinkedIn Message', 'Meeting', 'Follow-Up', 'Note')),
outcome VARCHAR(255),
notes TEXT,
next_action TEXT,
next_action_date VARCHAR(50),
occurred_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS notes (
id SERIAL PRIMARY KEY,
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
contact_id INTEGER REFERENCES contacts(id) ON DELETE SET NULL,
user_id INTEGER NOT NULL REFERENCES users(id),
body TEXT NOT NULL,
is_pinned INTEGER DEFAULT 0 CHECK(is_pinned IN (0, 1)),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS stage_changes (
id SERIAL PRIMARY KEY,
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
from_stage_id INTEGER REFERENCES stages(id),
to_stage_id INTEGER NOT NULL REFERENCES stages(id),
changed_by_user_id INTEGER NOT NULL REFERENCES users(id),
source VARCHAR(50) NOT NULL CHECK(source IN ('manual', 'ai_suggested', 'ai_confirmed')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS ai_field_values (
id SERIAL PRIMARY KEY,
company_id INTEGER NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
field_name VARCHAR(255) NOT NULL,
value TEXT,
source_url TEXT,
confidence_score REAL,
enriched_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
confirmed_by_user_id INTEGER REFERENCES users(id),
confirmed_at TIMESTAMP
);
-- Indices for fast searching and filtering
CREATE INDEX IF NOT EXISTS idx_companies_stage ON companies(stage_id);
CREATE INDEX IF NOT EXISTS idx_companies_tenant ON companies(tenant_id);
CREATE INDEX IF NOT EXISTS idx_companies_rep ON companies(assigned_rep_id);
CREATE INDEX IF NOT EXISTS idx_contacts_company ON contacts(company_id);
CREATE INDEX IF NOT EXISTS idx_activities_company ON activities(company_id);
CREATE INDEX IF NOT EXISTS idx_notes_company ON notes(company_id);
-- 2. AI / Agent Interaction History Table
CREATE TABLE IF NOT EXISTS interactions (
id VARCHAR(255) PRIMARY KEY,
kind VARCHAR(50) NOT NULL,
title VARCHAR(255) NOT NULL,
status VARCHAR(50) NOT NULL,
input_json TEXT NOT NULL DEFAULT '{}',
output_json TEXT NOT NULL DEFAULT '{}',
result_text TEXT NOT NULL DEFAULT '',
logs_json TEXT NOT NULL DEFAULT '[]',
error TEXT NOT NULL DEFAULT '',
run_dir TEXT NOT NULL DEFAULT '',
profile_path TEXT NOT NULL DEFAULT '',
command_json TEXT NOT NULL DEFAULT '[]',
returncode INTEGER,
pid INTEGER,
created_at VARCHAR(50) NOT NULL,
started_at VARCHAR(50) NOT NULL DEFAULT '',
finished_at VARCHAR(50) NOT NULL DEFAULT '',
updated_at VARCHAR(50) NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_interactions_created_at ON interactions(created_at DESC);
CREATE INDEX IF NOT EXISTS idx_interactions_kind ON interactions(kind);
CREATE INDEX IF NOT EXISTS idx_interactions_kind_created ON interactions(kind, created_at DESC);
-- 3. Restructured RAG Playbook Tables
CREATE TABLE IF NOT EXISTS rag_collections (
id VARCHAR(255) PRIMARY KEY,
name VARCHAR(255) NOT NULL,
user_id VARCHAR(255),
visibility VARCHAR(50) DEFAULT 'private',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS rag_documents (
id VARCHAR(255) PRIMARY KEY,
collection_id VARCHAR(255) REFERENCES rag_collections(id) ON DELETE CASCADE,
filename VARCHAR(255) NOT NULL,
original_type VARCHAR(50),
pages INTEGER DEFAULT 0,
chunks INTEGER DEFAULT 0,
uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
upload_path TEXT
);
CREATE TABLE IF NOT EXISTS rag_sessions (
id VARCHAR(255) PRIMARY KEY,
collection_id VARCHAR(255) REFERENCES rag_collections(id) ON DELETE CASCADE,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS rag_messages (
id SERIAL PRIMARY KEY,
collection_id VARCHAR(255) REFERENCES rag_collections(id) ON DELETE CASCADE,
session_id VARCHAR(255) REFERENCES rag_sessions(id) ON DELETE CASCADE,
role VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
sources JSONB DEFAULT '[]'::jsonb,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
|