Deploy: 2026-05-21 01:26:06

This commit is contained in:
Hamza-Ayed
2026-05-21 01:26:06 +03:00
parent 146ebd7200
commit 16d494b4e1
13 changed files with 816 additions and 32 deletions

164
backend/database_schema.sql Normal file
View 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;