Files
gochat/backend/migrations/000001_init_schema.up.sql
T
rogee aeddedf2a3 Reorganize repo: backend/, deploy/, docs/ layout + AGENTS.md
Restructure the monorepo into clear top-level directories:
- backend/: Go module root (cmd, internal, pkg, configs, migrations,
  docs/swagger, scripts, tests, go.mod, Makefile, .air.toml)
- deploy/: Docker (Dockerfile, docker-compose*), quickstart, fluentd
- docs/: project documentation + reports/ (moved from repo root)
- AGENTS.md: new AI coding-agent guide at repo root

Update all references to the new layout:
- Dockerfile: COPY backend/go.mod, COPY backend/ (context = repo root)
- docker-compose files: context ../.., dockerfile deploy/docker/Dockerfile,
  env_file ../../.env, volume mounts ../../backend:/app
- deploy/quickstart/compose.yaml: dockerfile deploy/docker/Dockerfile
- CI: working-directory: backend for go commands, file deploy/docker/Dockerfile,
  coverage path backend/coverage.out, health_check backend/scripts/
- backend/Makefile: docker target uses -f ../deploy/docker/Dockerfile ../
- README: architecture tree, quickstart, config paths updated

Move root stray scripts (rename_models.*, run_m11_tests.sh, verify_build.sh,
gorm_bool_main.go) to backend/scripts/legacy/. All moves via git mv to
preserve history. Build, vet, SQLite tests, and docker compose config verified.
2026-07-07 14:44:12 +08:00

450 lines
18 KiB
SQL

-- GoChat Initial Schema
-- Reference: Chatwoot db/migrate/ initial schema migration
-- Creates core tables matching Chatwoot's data model
-- Accounts (ref: Chatwoot accounts table)
CREATE TABLE IF NOT EXISTS accounts (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
locale VARCHAR(10) DEFAULT 'en',
timezone VARCHAR(50) DEFAULT 'UTC',
domain VARCHAR(255),
feature_flags TEXT DEFAULT '{}',
limits JSONB NOT NULL DEFAULT '{}',
status VARCHAR(50) DEFAULT 'active',
active BOOLEAN DEFAULT TRUE,
auto_resolve_duration INTEGER DEFAULT 0,
inbox_limit INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_accounts_deleted_at ON accounts(deleted_at);
CREATE INDEX idx_accounts_status ON accounts(status) WHERE deleted_at IS NULL;
-- Users (ref: Chatwoot users table)
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
password_digest VARCHAR(255),
provider VARCHAR(50) DEFAULT 'email',
uid VARCHAR(255),
avatar_url VARCHAR(512),
display_name VARCHAR(255),
role VARCHAR(50) DEFAULT 'agent',
type VARCHAR(50) DEFAULT 'user',
active BOOLEAN DEFAULT TRUE,
available BOOLEAN DEFAULT FALSE,
availability_status VARCHAR(50) DEFAULT 'offline',
confirmed BOOLEAN DEFAULT FALSE,
totp_secret VARCHAR(255),
totp_enabled BOOLEAN DEFAULT FALSE,
custom_role_id INTEGER,
sign_in_count INTEGER DEFAULT 0,
confirmed_at TIMESTAMP WITH TIME ZONE,
last_sign_in_at TIMESTAMP WITH TIME ZONE,
current_sign_in_at TIMESTAMP WITH TIME ZONE,
locale VARCHAR(10) DEFAULT 'en',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_users_deleted_at ON users(deleted_at);
CREATE INDEX idx_users_email ON users(email) WHERE deleted_at IS NULL;
CREATE INDEX idx_users_account_id ON users(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_users_availability ON users(availability_status) WHERE deleted_at IS NULL;
CREATE INDEX idx_users_custom_role_id ON users(custom_role_id) WHERE deleted_at IS NULL;
-- Account Users (ref: Chatwoot account_users join table)
CREATE TABLE IF NOT EXISTS account_users (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
account_id INTEGER NOT NULL,
role VARCHAR(50) NOT NULL DEFAULT 'agent',
custom_role_id INTEGER DEFAULT 0,
availability VARCHAR(50) DEFAULT 'offline',
invited_by INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE,
UNIQUE(user_id, account_id)
);
CREATE INDEX idx_account_users_deleted_at ON account_users(deleted_at);
CREATE INDEX idx_account_users_user_id ON account_users(user_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_account_users_account_id ON account_users(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_account_users_role ON account_users(role) WHERE deleted_at IS NULL;
-- Custom Roles (ref: Chatwoot enterprise/app/models/custom_role.rb)
CREATE TABLE IF NOT EXISTS custom_roles (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
permissions JSONB NOT NULL DEFAULT '[]',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_custom_roles_deleted_at ON custom_roles(deleted_at);
CREATE INDEX idx_custom_roles_account_id ON custom_roles(account_id) WHERE deleted_at IS NULL;
-- Contacts (ref: Chatwoot contacts table)
CREATE TABLE IF NOT EXISTS contacts (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
name VARCHAR(255),
email VARCHAR(255),
phone_number VARCHAR(50),
avatar_url VARCHAR(512),
identifier VARCHAR(255),
last_activity_at BIGINT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_contacts_deleted_at ON contacts(deleted_at);
CREATE INDEX idx_contacts_account_id ON contacts(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_contacts_email ON contacts(email) WHERE deleted_at IS NULL;
CREATE INDEX idx_contacts_phone_number ON contacts(phone_number) WHERE deleted_at IS NULL;
CREATE INDEX idx_contacts_identifier ON contacts(identifier) WHERE deleted_at IS NULL;
CREATE INDEX idx_contacts_last_activity_at ON contacts(last_activity_at) WHERE deleted_at IS NULL;
-- Inboxes (ref: Chatwoot inboxes table)
CREATE TABLE IF NOT EXISTS inboxes (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
name VARCHAR(255) NOT NULL,
channel_type VARCHAR(50) NOT NULL,
channel_id INTEGER NOT NULL,
enable_auto_assignment BOOLEAN DEFAULT FALSE,
auto_assignment_limit INTEGER DEFAULT 0,
enabled BOOLEAN DEFAULT TRUE,
channel_config TEXT,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_inboxes_deleted_at ON inboxes(deleted_at);
CREATE INDEX idx_inboxes_account_id ON inboxes(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_inboxes_channel_type ON inboxes(channel_type) WHERE deleted_at IS NULL;
CREATE INDEX idx_inboxes_channel_id ON inboxes(channel_id) WHERE deleted_at IS NULL;
-- Contact Inboxes (ref: Chatwoot contact_inboxes)
CREATE TABLE IF NOT EXISTS contact_inboxes (
id SERIAL PRIMARY KEY,
contact_id INTEGER NOT NULL,
inbox_id INTEGER NOT NULL,
source_id VARCHAR(255),
hmac_token VARCHAR(255),
pubsub_token VARCHAR(255),
has_around_flag BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_contact_inboxes_deleted_at ON contact_inboxes(deleted_at);
CREATE INDEX idx_contact_inboxes_contact_id ON contact_inboxes(contact_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_contact_inboxes_inbox_id ON contact_inboxes(inbox_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_contact_inboxes_source_id ON contact_inboxes(source_id) WHERE deleted_at IS NULL;
-- Inbox Members (ref: Chatwoot inbox_members)
CREATE TABLE IF NOT EXISTS inbox_members (
id SERIAL PRIMARY KEY,
inbox_id INTEGER NOT NULL,
user_id INTEGER NOT NULL,
role VARCHAR(50) DEFAULT 'agent',
availability_status VARCHAR(50) DEFAULT 'offline',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_inbox_members_deleted_at ON inbox_members(deleted_at);
CREATE INDEX idx_inbox_members_inbox_id ON inbox_members(inbox_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_inbox_members_user_id ON inbox_members(user_id) WHERE deleted_at IS NULL;
-- Conversations (ref: Chatwoot conversations table)
CREATE TABLE IF NOT EXISTS conversations (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
inbox_id INTEGER NOT NULL,
contact_id INTEGER NOT NULL,
assignee_id INTEGER,
status VARCHAR(50) DEFAULT 'open',
priority VARCHAR(50) DEFAULT 'none',
channel_type VARCHAR(50) NOT NULL,
channel VARCHAR(50) NOT NULL,
labels TEXT,
last_message_at BIGINT,
last_non_system_message_at BIGINT,
uuid VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_conversations_deleted_at ON conversations(deleted_at);
CREATE INDEX idx_conversations_account ON conversations(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_conversations_inbox ON conversations(inbox_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_conversations_contact ON conversations(contact_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_conversations_status ON conversations(status) WHERE deleted_at IS NULL;
CREATE INDEX idx_conversations_assignee ON conversations(assignee_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_conversations_last_message ON conversations(last_message_at) WHERE deleted_at IS NULL;
-- Messages (ref: Chatwoot messages table)
CREATE TABLE IF NOT EXISTS messages (
id SERIAL PRIMARY KEY,
conversation_id INTEGER NOT NULL REFERENCES conversations(id),
account_id INTEGER NOT NULL REFERENCES accounts(id),
inbox_id INTEGER NOT NULL REFERENCES inboxes(id),
sender_id INTEGER,
sender_type VARCHAR(50) NOT NULL,
content TEXT NOT NULL,
content_type VARCHAR(50) DEFAULT 'text',
message_type VARCHAR(50) NOT NULL DEFAULT 'incoming',
private BOOLEAN DEFAULT FALSE,
external BOOLEAN DEFAULT FALSE,
source_id VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_messages_deleted_at ON messages(deleted_at);
CREATE INDEX idx_messages_conversation ON messages(conversation_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_messages_account ON messages(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_messages_inbox ON messages(inbox_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_messages_sender ON messages(sender_id, sender_type) WHERE deleted_at IS NULL;
CREATE INDEX idx_messages_message_type ON messages(message_type) WHERE deleted_at IS NULL;
-- Attachments (ref: Chatwoot attachments)
CREATE TABLE IF NOT EXISTS attachments (
id SERIAL PRIMARY KEY,
message_id INTEGER NOT NULL,
account_id INTEGER NOT NULL,
file_type VARCHAR(50) NOT NULL,
external_url VARCHAR(512),
file_url VARCHAR(512),
thumb_url VARCHAR(512),
file_size INTEGER,
file_name VARCHAR(255),
width INTEGER DEFAULT 0,
height INTEGER DEFAULT 0,
alt_text VARCHAR(255),
metadata JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_attachments_deleted_at ON attachments(deleted_at);
CREATE INDEX idx_attachments_message_id ON attachments(message_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_attachments_account_id ON attachments(account_id) WHERE deleted_at IS NULL;
-- Notifications (ref: Chatwoot notifications)
CREATE TABLE IF NOT EXISTS notifications (
id SERIAL PRIMARY KEY,
account_id INTEGER,
user_id INTEGER NOT NULL,
notification_type VARCHAR(100) NOT NULL,
primary_actor_type VARCHAR(100),
primary_actor_id INTEGER,
secondary_actor_type VARCHAR(100),
secondary_actor_id INTEGER,
read_at TIMESTAMP WITH TIME ZONE,
push_enabled BOOLEAN DEFAULT FALSE,
email_enabled BOOLEAN DEFAULT FALSE,
additional_attributes JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_notifications_deleted_at ON notifications(deleted_at);
CREATE INDEX idx_notifications_user_id ON notifications(user_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_notifications_account_id ON notifications(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_notifications_type ON notifications(notification_type) WHERE deleted_at IS NULL;
CREATE INDEX idx_notifications_created_at ON notifications(created_at) WHERE deleted_at IS NULL;
-- Notification Preferences (ref: Chatwoot notification_preferences)
CREATE TABLE IF NOT EXISTS notification_preferences (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
account_id INTEGER,
channel VARCHAR(100) NOT NULL,
event_type VARCHAR(100) NOT NULL,
enabled BOOLEAN DEFAULT TRUE,
preferences JSONB,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, account_id, channel, event_type)
);
CREATE INDEX idx_notification_preferences_user_id ON notification_preferences(user_id);
-- Platform Apps (ref: Chatwoot platform_apps / agent_bots)
CREATE TABLE IF NOT EXISTS platform_apps (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
api_key VARCHAR(255) NOT NULL UNIQUE,
account_id INTEGER,
description VARCHAR(500),
type VARCHAR(50) DEFAULT 'api',
status VARCHAR(50) DEFAULT 'active',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_platform_apps_deleted_at ON platform_apps(deleted_at);
CREATE INDEX idx_platform_apps_api_key ON platform_apps(api_key) WHERE deleted_at IS NULL;
CREATE INDEX idx_platform_apps_account_id ON platform_apps(account_id) WHERE deleted_at IS NULL;
-- Reporting Events (ref: Chatwoot reporting_events)
CREATE TABLE IF NOT EXISTS reporting_events (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
inbox_id INTEGER,
user_id INTEGER,
conversation_id INTEGER,
name VARCHAR(50) NOT NULL,
value DOUBLE PRECISION NOT NULL,
value_in_business_hours DOUBLE PRECISION DEFAULT 0,
event_start_time TIMESTAMP WITH TIME ZONE,
event_end_time TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_reporting_events_deleted_at ON reporting_events(deleted_at);
CREATE INDEX idx_reporting_events_account_id ON reporting_events(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_reporting_events_inbox_id ON reporting_events(inbox_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_reporting_events_user_id ON reporting_events(user_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_reporting_events_conversation_id ON reporting_events(conversation_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_reporting_events_name ON reporting_events(name) WHERE deleted_at IS NULL;
-- Reporting Events Rollups (ref: Chatwoot reporting_events_rollups)
CREATE TABLE IF NOT EXISTS reporting_events_rollups (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
dimension VARCHAR(50) NOT NULL,
dimension_value VARCHAR(255) NOT NULL,
metric_name VARCHAR(50) NOT NULL,
value DOUBLE PRECISION NOT NULL,
value_in_business_hours DOUBLE PRECISION DEFAULT 0,
period VARCHAR(50) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE,
UNIQUE(account_id, dimension, dimension_value, metric_name, period)
);
CREATE INDEX idx_reporting_events_rollups_deleted_at ON reporting_events_rollups(deleted_at);
-- Dashboard Apps (ref: Chatwoot dashboard_apps)
CREATE TABLE IF NOT EXISTS dashboard_apps (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL,
description TEXT,
icon VARCHAR(255),
url TEXT NOT NULL,
type VARCHAR(50) DEFAULT 'internal',
enabled BOOLEAN DEFAULT TRUE,
position INTEGER DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_dashboard_apps_deleted_at ON dashboard_apps(deleted_at);
-- Channels base table (ref: Chatwoot channelable pattern)
CREATE TABLE IF NOT EXISTS channels (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
inbox_id INTEGER NOT NULL,
channel_type VARCHAR(50) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_channels_deleted_at ON channels(deleted_at);
CREATE INDEX idx_channels_account_id ON channels(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_channels_inbox_id ON channels(inbox_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_channels_channel_type ON channels(channel_type) WHERE deleted_at IS NULL;
-- Channel: Telegram
CREATE TABLE IF NOT EXISTS channel_telegrams (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
inbox_id INTEGER,
bot_token VARCHAR(255) NOT NULL UNIQUE,
bot_name VARCHAR(255),
welcome_message TEXT,
reauthorization_required BOOLEAN DEFAULT FALSE,
webhook_url VARCHAR(512),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_channel_telegrams_deleted_at ON channel_telegrams(deleted_at);
CREATE INDEX idx_channel_telegrams_account_id ON channel_telegrams(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_channel_telegrams_inbox_id ON channel_telegrams(inbox_id) WHERE deleted_at IS NULL;
-- Channel: Web Widget
CREATE TABLE IF NOT EXISTS channel_web_widgets (
inbox_id INTEGER NOT NULL UNIQUE,
website_url VARCHAR(1024) NOT NULL,
welcome_title VARCHAR(255),
welcome_tagline VARCHAR(255),
widget_color VARCHAR(20) DEFAULT '#1f93ff',
reply_time VARCHAR(50) DEFAULT 'in_a_few_minutes',
hmac_token VARCHAR(255),
pre_chat_form_enabled BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_channel_web_widgets_inbox_id ON channel_web_widgets(inbox_id) WHERE deleted_at IS NULL;
-- Channel: Facebook Pages
CREATE TABLE IF NOT EXISTS channel_facebook_pages (
inbox_id INTEGER NOT NULL UNIQUE,
page_id VARCHAR(255) NOT NULL,
page_access_token VARCHAR(512) NOT NULL,
page_name VARCHAR(255),
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_channel_facebook_pages_inbox_id ON channel_facebook_pages(inbox_id) WHERE deleted_at IS NULL;
-- Channel: WhatsApp
CREATE TABLE IF NOT EXISTS channel_whatsapps (
inbox_id INTEGER NOT NULL UNIQUE,
phone_number_id VARCHAR(255) NOT NULL,
business_id VARCHAR(255),
whatsapp_account_name VARCHAR(255),
access_token VARCHAR(512) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_channel_whatsapps_inbox_id ON channel_whatsapps(inbox_id) WHERE deleted_at IS NULL;