Deploy: 2026-05-21 01:26:06
This commit is contained in:
164
backend/database_schema.sql
Normal file
164
backend/database_schema.sql
Normal file
@@ -0,0 +1,164 @@
|
||||
-- ==============================================================================
|
||||
-- 🗄️ Nabeh Multi-Tenant Database Schema
|
||||
-- UTF-8 Unicode (utf8mb4) is used to support Arabic text and Emojis perfectly.
|
||||
-- ==============================================================================
|
||||
|
||||
-- 1. Companies (Tenants) Table
|
||||
CREATE TABLE IF NOT EXISTS `companies` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`status` ENUM('active', 'inactive', 'suspended') DEFAULT 'active',
|
||||
`max_sessions` INT DEFAULT 1 COMMENT 'Limit the number of WhatsApp numbers allowed',
|
||||
`api_key` VARCHAR(64) UNIQUE NULL COMMENT 'For external integrations (CRM/APIs)',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
INDEX `idx_company_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 2. Users Table (Multi-Tenant Staff/Admins)
|
||||
CREATE TABLE IF NOT EXISTS `users` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`email` VARCHAR(512) NOT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`email_hash` VARCHAR(64) NOT NULL COMMENT 'HMAC-SHA256 Blind Index for secure searching',
|
||||
`password` VARCHAR(255) NOT NULL,
|
||||
`role` ENUM('admin', 'staff') DEFAULT 'staff',
|
||||
`status` ENUM('active', 'inactive') DEFAULT 'active',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY `unique_email_hash` (`email_hash`),
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
INDEX `idx_user_company` (`company_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 3. WhatsApp Sessions Table (Baileys Connections)
|
||||
CREATE TABLE IF NOT EXISTS `whatsapp_sessions` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL COMMENT 'e.g., Customer Support, Sales Team',
|
||||
`session_key` VARCHAR(100) UNIQUE NOT NULL COMMENT 'Unique identifier for Baileys node service',
|
||||
`phone` VARCHAR(512) DEFAULT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`phone_hash` VARCHAR(64) DEFAULT NULL COMMENT 'HMAC-SHA256 Blind Index',
|
||||
`status` ENUM('disconnected', 'waiting_qr', 'connected', 'connecting') DEFAULT 'disconnected',
|
||||
`qr_code` TEXT DEFAULT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
INDEX `idx_session_company` (`company_id`),
|
||||
INDEX `idx_session_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 4. Contacts Table (Customers / Leads)
|
||||
CREATE TABLE IF NOT EXISTS `contacts` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`phone` VARCHAR(512) NOT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`phone_hash` VARCHAR(64) NOT NULL COMMENT 'HMAC-SHA256 Blind Index',
|
||||
`email` VARCHAR(512) DEFAULT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`email_hash` VARCHAR(64) DEFAULT NULL COMMENT 'HMAC-SHA256 Blind Index',
|
||||
`notes` TEXT DEFAULT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
UNIQUE KEY `unique_company_phone_hash` (`company_id`, `phone_hash`),
|
||||
INDEX `idx_contact_company` (`company_id`),
|
||||
INDEX `idx_contact_phone_hash` (`phone_hash`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 5. Contact Groups Table (Lists for Broadcasts)
|
||||
CREATE TABLE IF NOT EXISTS `contact_groups` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
INDEX `idx_group_company` (`company_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 6. Contact Group Relations Table (Pivot Table)
|
||||
CREATE TABLE IF NOT EXISTS `contact_group_relations` (
|
||||
`contact_id` INT NOT NULL,
|
||||
`group_id` INT NOT NULL,
|
||||
PRIMARY KEY (`contact_id`, `group_id`),
|
||||
FOREIGN KEY (`contact_id`) REFERENCES `contacts` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`group_id`) REFERENCES `contact_groups` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 7. Predefined WhatsApp Templates Table
|
||||
CREATE TABLE IF NOT EXISTS `templates` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`body` TEXT NOT NULL COMMENT 'Message body. Supports variables like {{name}}',
|
||||
`type` ENUM('text', 'image', 'video', 'document') DEFAULT 'text',
|
||||
`media_url` TEXT DEFAULT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
INDEX `idx_template_company` (`company_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 8. Broadcast Campaigns Table
|
||||
CREATE TABLE IF NOT EXISTS `campaigns` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`session_id` INT NOT NULL COMMENT 'Which WhatsApp number sends this campaign',
|
||||
`group_id` INT NOT NULL COMMENT 'Target contact group',
|
||||
`template_id` INT DEFAULT NULL,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`status` ENUM('pending', 'running', 'completed', 'paused', 'failed') DEFAULT 'pending',
|
||||
`scheduled_at` TIMESTAMP NULL DEFAULT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`session_id`) REFERENCES `whatsapp_sessions` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`group_id`) REFERENCES `contact_groups` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`template_id`) REFERENCES `templates` (`id`) ON DELETE SET NULL,
|
||||
INDEX `idx_campaign_company` (`company_id`),
|
||||
INDEX `idx_campaign_status` (`status`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 9. Message History Log Table (Inbound & Outbound)
|
||||
CREATE TABLE IF NOT EXISTS `messages_log` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`session_id` INT NOT NULL COMMENT 'WhatsApp number that received or sent the message',
|
||||
`campaign_id` INT DEFAULT NULL COMMENT 'Null if sent individually or received',
|
||||
`contact_phone` VARCHAR(512) NOT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`contact_phone_hash` VARCHAR(64) NOT NULL COMMENT 'HMAC-SHA256 Blind Index',
|
||||
`direction` ENUM('inbound', 'outbound') NOT NULL,
|
||||
`message_type` ENUM('text', 'image', 'video', 'document', 'audio') DEFAULT 'text',
|
||||
`message_body` TEXT DEFAULT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`media_url` TEXT DEFAULT NULL COMMENT 'Encrypted using AES-256-GCM',
|
||||
`whatsapp_message_id` VARCHAR(100) UNIQUE NULL COMMENT 'To prevent duplicates & track receipt status',
|
||||
`status` ENUM('pending', 'sent', 'delivered', 'read', 'failed') DEFAULT 'pending',
|
||||
`error_message` VARCHAR(255) DEFAULT NULL,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`session_id`) REFERENCES `whatsapp_sessions` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`campaign_id`) REFERENCES `campaigns` (`id`) ON DELETE SET NULL,
|
||||
INDEX `idx_msg_company` (`company_id`),
|
||||
INDEX `idx_msg_session` (`session_id`),
|
||||
INDEX `idx_msg_status` (`status`),
|
||||
INDEX `idx_msg_phone_hash` (`contact_phone_hash`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- 10. AI Auto-Reply & Bot Rules
|
||||
CREATE TABLE IF NOT EXISTS `chatbot_rules` (
|
||||
`id` INT AUTO_INCREMENT PRIMARY KEY,
|
||||
`company_id` INT NOT NULL,
|
||||
`session_id` INT DEFAULT NULL COMMENT 'If NULL, applies to all company numbers',
|
||||
`trigger_type` ENUM('keyword', 'gemini_ai') DEFAULT 'keyword',
|
||||
`keyword` VARCHAR(255) DEFAULT NULL COMMENT 'Comma separated trigger words for keyword-match',
|
||||
`ai_prompt` TEXT DEFAULT NULL COMMENT 'Prompt instructions for Gemini AI responder',
|
||||
`is_active` TINYINT(1) DEFAULT 1,
|
||||
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`session_id`) REFERENCES `whatsapp_sessions` (`id`) ON DELETE CASCADE,
|
||||
INDEX `idx_bot_company` (`company_id`),
|
||||
INDEX `idx_bot_active` (`is_active`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
Reference in New Issue
Block a user