Files
whatsappNucleo/server/database/init/001_schema.sql
josedario87 faedec47d7
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 6m46s
feat: WhatsApp Nucleo con Nuxt 4 + Baileys v7
Reemplazo completo de Evolution API por implementación directa con Baileys.

Características:
- Dashboard completo con Nuxt UI v4
- Soporte para múltiples instancias de WhatsApp
- Conexión via QR code o pairing code
- Persistencia de mensajes en PostgreSQL
- API REST para integraciones externas
- Webhooks con firma HMAC
- SSE para actualizaciones en tiempo real
- Autenticación con Authentik
2025-12-02 17:54:31 -06:00

209 lines
7.3 KiB
PL/PgSQL

-- =====================================================
-- WhatsApp Nucleo - Database Schema
-- =====================================================
-- Extension for UUID generation
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
-- =====================================================
-- INSTANCES: WhatsApp connection instances
-- =====================================================
CREATE TABLE instances (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL,
phone_number VARCHAR(20),
status VARCHAR(20) DEFAULT 'disconnected'
CHECK (status IN ('disconnected', 'connecting', 'connected', 'qr_ready', 'pairing')),
qr_code TEXT,
pairing_code VARCHAR(10),
last_connected_at TIMESTAMPTZ,
created_by VARCHAR(100) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_phone UNIQUE (phone_number)
);
-- =====================================================
-- AUTH_KEYS: Baileys credentials per instance
-- =====================================================
CREATE TABLE auth_keys (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
key_type VARCHAR(50) NOT NULL,
key_id VARCHAR(100),
key_data JSONB NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_key UNIQUE (instance_id, key_type, key_id)
);
-- =====================================================
-- CONTACTS: WhatsApp contacts
-- =====================================================
CREATE TABLE contacts (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
jid VARCHAR(100) NOT NULL,
name VARCHAR(255),
push_name VARCHAR(255),
phone_number VARCHAR(20),
profile_picture_url TEXT,
is_group BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_contact UNIQUE (instance_id, jid)
);
-- =====================================================
-- CHATS: Conversations
-- =====================================================
CREATE TABLE chats (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
jid VARCHAR(100) NOT NULL,
name VARCHAR(255),
is_group BOOLEAN DEFAULT FALSE,
is_archived BOOLEAN DEFAULT FALSE,
is_pinned BOOLEAN DEFAULT FALSE,
unread_count INTEGER DEFAULT 0,
last_message_id UUID,
last_message_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_chat UNIQUE (instance_id, jid)
);
-- =====================================================
-- MESSAGES: All messages
-- =====================================================
CREATE TABLE messages (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
instance_id UUID NOT NULL REFERENCES instances(id) ON DELETE CASCADE,
chat_id UUID NOT NULL REFERENCES chats(id) ON DELETE CASCADE,
message_id VARCHAR(100) NOT NULL,
from_jid VARCHAR(100) NOT NULL,
to_jid VARCHAR(100),
from_me BOOLEAN DEFAULT FALSE,
message_type VARCHAR(50) NOT NULL,
content TEXT,
caption TEXT,
media_url TEXT,
media_mimetype VARCHAR(100),
media_filename VARCHAR(255),
quoted_message_id VARCHAR(100),
timestamp TIMESTAMPTZ NOT NULL,
status VARCHAR(20) DEFAULT 'sent'
CHECK (status IN ('pending', 'sent', 'delivered', 'read', 'failed')),
raw_message JSONB,
created_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_message UNIQUE (instance_id, message_id)
);
-- =====================================================
-- WEBHOOKS: Webhook configurations
-- =====================================================
CREATE TABLE webhooks (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
instance_id UUID REFERENCES instances(id) ON DELETE CASCADE,
name VARCHAR(100) NOT NULL,
url TEXT NOT NULL,
secret VARCHAR(255),
events TEXT[] NOT NULL DEFAULT '{}',
is_active BOOLEAN DEFAULT TRUE,
headers JSONB DEFAULT '{}',
retry_count INTEGER DEFAULT 3,
timeout_ms INTEGER DEFAULT 5000,
created_by VARCHAR(100) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
-- =====================================================
-- WEBHOOK_LOGS: Delivery logs
-- =====================================================
CREATE TABLE webhook_logs (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
webhook_id UUID NOT NULL REFERENCES webhooks(id) ON DELETE CASCADE,
event_type VARCHAR(50) NOT NULL,
payload JSONB NOT NULL,
response_status INTEGER,
response_body TEXT,
error_message TEXT,
attempt INTEGER DEFAULT 1,
delivered_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- =====================================================
-- API_KEYS: External API access keys
-- =====================================================
CREATE TABLE api_keys (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(100) NOT NULL,
key_hash VARCHAR(255) NOT NULL,
key_prefix VARCHAR(10) NOT NULL,
instance_id UUID REFERENCES instances(id) ON DELETE CASCADE,
permissions TEXT[] NOT NULL DEFAULT '{}',
is_active BOOLEAN DEFAULT TRUE,
last_used_at TIMESTAMPTZ,
expires_at TIMESTAMPTZ,
created_by VARCHAR(100) NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- =====================================================
-- INDEXES for performance
-- =====================================================
CREATE INDEX idx_auth_keys_instance ON auth_keys(instance_id);
CREATE INDEX idx_contacts_instance ON contacts(instance_id);
CREATE INDEX idx_chats_instance ON chats(instance_id);
CREATE INDEX idx_chats_last_message ON chats(instance_id, last_message_at DESC);
CREATE INDEX idx_messages_instance_chat ON messages(instance_id, chat_id);
CREATE INDEX idx_messages_timestamp ON messages(timestamp DESC);
CREATE INDEX idx_messages_chat_timestamp ON messages(chat_id, timestamp DESC);
CREATE INDEX idx_webhooks_instance ON webhooks(instance_id);
CREATE INDEX idx_webhooks_active ON webhooks(is_active) WHERE is_active = TRUE;
CREATE INDEX idx_webhook_logs_webhook ON webhook_logs(webhook_id, created_at DESC);
CREATE INDEX idx_api_keys_prefix ON api_keys(key_prefix) WHERE is_active = TRUE;
-- =====================================================
-- TRIGGERS for updated_at
-- =====================================================
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ language 'plpgsql';
CREATE TRIGGER update_instances_updated_at
BEFORE UPDATE ON instances
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_auth_keys_updated_at
BEFORE UPDATE ON auth_keys
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_contacts_updated_at
BEFORE UPDATE ON contacts
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_chats_updated_at
BEFORE UPDATE ON chats
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_webhooks_updated_at
BEFORE UPDATE ON webhooks
FOR EACH ROW
EXECUTE FUNCTION update_updated_at_column();