Align GoChat with Chatwoot frontend contracts

This commit is contained in:
2026-06-13 22:13:32 +08:00
parent 71abf58636
commit d884fdda0a
162 changed files with 9825 additions and 528 deletions
@@ -4,20 +4,32 @@
CREATE TABLE IF NOT EXISTS dashboard_apps (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
user_id INTEGER, -- optional: per-user dashboard
title VARCHAR(255) NOT NULL, -- dashboard display name
description TEXT DEFAULT '', -- dashboard description
icon VARCHAR(255) DEFAULT '', -- icon URL or icon name
url VARCHAR(512) DEFAULT '', -- primary iframe URL
kind VARCHAR(100) DEFAULT 'frame', -- app kind: frame, link
content JSONB DEFAULT '[]', -- iframe config array: [{"type":"frame","url":"..."}]
active BOOLEAN DEFAULT TRUE NOT NULL, -- whether the app is active
title VARCHAR(255) NOT NULL,
description TEXT DEFAULT '',
icon VARCHAR(255) DEFAULT '',
url VARCHAR(512) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE -- soft-delete support
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX idx_dashboard_apps_account_id ON dashboard_apps(account_id) WHERE deleted_at IS NULL;
CREATE INDEX idx_dashboard_apps_user_id ON dashboard_apps(user_id) WHERE deleted_at IS NULL AND user_id IS NOT NULL;
CREATE INDEX idx_dashboard_apps_deleted_at ON dashboard_apps(deleted_at);
ALTER TABLE dashboard_apps ADD COLUMN IF NOT EXISTS account_id INTEGER;
ALTER TABLE dashboard_apps ADD COLUMN IF NOT EXISTS user_id INTEGER;
ALTER TABLE dashboard_apps ADD COLUMN IF NOT EXISTS kind VARCHAR(100) DEFAULT 'frame';
ALTER TABLE dashboard_apps ADD COLUMN IF NOT EXISTS content JSONB DEFAULT '[]';
ALTER TABLE dashboard_apps ADD COLUMN IF NOT EXISTS active BOOLEAN DEFAULT TRUE;
UPDATE dashboard_apps SET account_id = 0 WHERE account_id IS NULL;
ALTER TABLE dashboard_apps ALTER COLUMN account_id SET NOT NULL;
ALTER TABLE dashboard_apps ALTER COLUMN description SET DEFAULT '';
ALTER TABLE dashboard_apps ALTER COLUMN icon SET DEFAULT '';
ALTER TABLE dashboard_apps ALTER COLUMN url TYPE VARCHAR(512);
ALTER TABLE dashboard_apps ALTER COLUMN url SET DEFAULT '';
ALTER TABLE dashboard_apps ALTER COLUMN kind SET DEFAULT 'frame';
ALTER TABLE dashboard_apps ALTER COLUMN content SET DEFAULT '[]';
ALTER TABLE dashboard_apps ALTER COLUMN active SET DEFAULT TRUE;
ALTER TABLE dashboard_apps ALTER COLUMN active SET NOT NULL;
CREATE INDEX IF NOT EXISTS idx_dashboard_apps_account_id ON dashboard_apps(account_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_dashboard_apps_user_id ON dashboard_apps(user_id) WHERE deleted_at IS NULL AND user_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_dashboard_apps_deleted_at ON dashboard_apps(deleted_at);
@@ -5,6 +5,7 @@ DROP INDEX IF EXISTS idx_contacts_blocked;
ALTER TABLE contacts DROP COLUMN IF EXISTS company_id;
ALTER TABLE contacts DROP COLUMN IF EXISTS source_id;
ALTER TABLE contact_inboxes DROP COLUMN IF EXISTS hmac_verified;
ALTER TABLE contacts DROP COLUMN IF EXISTS location;
ALTER TABLE contacts DROP COLUMN IF EXISTS country_code;
ALTER TABLE contacts DROP COLUMN IF EXISTS last_name;
@@ -12,4 +13,4 @@ ALTER TABLE contacts DROP COLUMN IF EXISTS middle_name;
ALTER TABLE contacts DROP COLUMN IF EXISTS contact_type;
ALTER TABLE contacts DROP COLUMN IF EXISTS blocked;
ALTER TABLE contacts DROP COLUMN IF EXISTS custom_attributes;
ALTER TABLE contacts DROP COLUMN IF EXISTS additional_attributes;
ALTER TABLE contacts DROP COLUMN IF EXISTS additional_attributes;
@@ -15,5 +15,7 @@ ALTER TABLE contacts ADD COLUMN IF NOT EXISTS location VARCHAR(255) DEFAULT '';
ALTER TABLE contacts ADD COLUMN IF NOT EXISTS source_id VARCHAR(255);
ALTER TABLE contacts ADD COLUMN IF NOT EXISTS company_id INTEGER;
ALTER TABLE contact_inboxes ADD COLUMN IF NOT EXISTS hmac_verified BOOLEAN DEFAULT FALSE;
CREATE INDEX IF NOT EXISTS idx_contacts_blocked ON contacts(blocked) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_contacts_contact_type ON contacts(contact_type) WHERE deleted_at IS NULL AND contact_type != '';
CREATE INDEX IF NOT EXISTS idx_contacts_contact_type ON contacts(contact_type) WHERE deleted_at IS NULL AND contact_type != '';
+16 -3
View File
@@ -16,8 +16,21 @@ CREATE INDEX IF NOT EXISTS idx_messages_account_content_type ON messages (accoun
CREATE INDEX IF NOT EXISTS idx_messages_account_private ON messages (account_id, private);
CREATE INDEX IF NOT EXISTS idx_messages_conversation_id ON messages (conversation_id);
-- Contacts: text search on name, email, phone; filter by source
CREATE INDEX IF NOT EXISTS idx_contacts_account_source ON contacts (account_id, source);
-- Contacts: text search on name, email, phone; filter by source/source_id.
DO $$
BEGIN
IF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'contacts' AND column_name = 'source'
) THEN
CREATE INDEX IF NOT EXISTS idx_contacts_account_source ON contacts (account_id, source);
ELSIF EXISTS (
SELECT 1 FROM information_schema.columns
WHERE table_name = 'contacts' AND column_name = 'source_id'
) THEN
CREATE INDEX IF NOT EXISTS idx_contacts_account_source_id ON contacts (account_id, source_id);
END IF;
END $$;
CREATE INDEX IF NOT EXISTS idx_contacts_name ON contacts (account_id, name);
CREATE INDEX IF NOT EXISTS idx_contacts_email ON contacts (account_id, email);
CREATE INDEX IF NOT EXISTS idx_contacts_phone ON contacts (account_id, phone_number);
CREATE INDEX IF NOT EXISTS idx_contacts_phone ON contacts (account_id, phone_number);
@@ -7,5 +7,6 @@ ALTER TABLE users DROP COLUMN IF EXISTS custom_attributes;
ALTER TABLE users DROP COLUMN IF EXISTS ui_settings;
ALTER TABLE users DROP COLUMN IF EXISTS pubsub_token;
ALTER TABLE users DROP COLUMN IF EXISTS message_signature;
ALTER TABLE users DROP COLUMN IF EXISTS password;
ALTER TABLE accounts DROP COLUMN IF EXISTS onboarding_step;
@@ -2,6 +2,8 @@
ALTER TABLE accounts ADD COLUMN IF NOT EXISTS onboarding_step VARCHAR(100);
ALTER TABLE users ADD COLUMN IF NOT EXISTS password VARCHAR(255);
ALTER TABLE users ALTER COLUMN password_hash DROP NOT NULL;
ALTER TABLE users ADD COLUMN IF NOT EXISTS message_signature TEXT;
ALTER TABLE users ADD COLUMN IF NOT EXISTS pubsub_token VARCHAR(255);
ALTER TABLE users ADD COLUMN IF NOT EXISTS ui_settings JSONB NOT NULL DEFAULT '{}';
@@ -11,6 +11,7 @@ ALTER TABLE conversations DROP COLUMN IF EXISTS resumed_at;
ALTER TABLE conversations DROP COLUMN IF EXISTS resolved_at;
ALTER TABLE conversations DROP COLUMN IF EXISTS muted;
ALTER TABLE conversations DROP COLUMN IF EXISTS first_reply_created_at;
ALTER TABLE conversations DROP COLUMN IF EXISTS last_non_sys_msg_at;
ALTER TABLE conversations DROP COLUMN IF EXISTS last_activity_at;
ALTER TABLE conversations DROP COLUMN IF EXISTS waiting_since;
ALTER TABLE conversations DROP COLUMN IF EXISTS contact_last_seen_at;
@@ -22,5 +23,6 @@ ALTER TABLE conversations DROP COLUMN IF EXISTS snoozed_until;
ALTER TABLE conversations DROP COLUMN IF EXISTS sla_policy_id;
ALTER TABLE conversations DROP COLUMN IF EXISTS campaign_id;
ALTER TABLE conversations DROP COLUMN IF EXISTS team_id;
ALTER TABLE conversations DROP COLUMN IF EXISTS assignee_agent_bot_id;
ALTER TABLE conversations DROP COLUMN IF EXISTS contact_inbox_id;
ALTER TABLE conversations DROP COLUMN IF EXISTS display_id;
@@ -1,5 +1,6 @@
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS display_id INTEGER;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS contact_inbox_id INTEGER;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS assignee_agent_bot_id INTEGER;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS team_id INTEGER;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS campaign_id INTEGER;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS sla_policy_id INTEGER;
@@ -12,6 +13,7 @@ ALTER TABLE conversations ADD COLUMN IF NOT EXISTS contact_last_seen_at BIGINT;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS waiting_since BIGINT;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS last_activity_at BIGINT;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS first_reply_created_at BIGINT;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS last_non_sys_msg_at BIGINT;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS muted BOOLEAN DEFAULT FALSE;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS resolved_at TIMESTAMP WITH TIME ZONE;
ALTER TABLE conversations ADD COLUMN IF NOT EXISTS resumed_at TIMESTAMP WITH TIME ZONE;
@@ -1,3 +1,24 @@
ALTER TABLE accounts
DROP COLUMN IF EXISTS inbox_limit;
ALTER TABLE accounts
DROP COLUMN IF EXISTS agent_limit;
DROP INDEX IF EXISTS idx_inboxes_portal_id;
ALTER TABLE inboxes DROP COLUMN IF EXISTS secret;
ALTER TABLE inboxes DROP COLUMN IF EXISTS webhook_url;
ALTER TABLE inboxes DROP COLUMN IF EXISTS portal_id;
ALTER TABLE inboxes DROP COLUMN IF EXISTS avatar_url;
ALTER TABLE inboxes DROP COLUMN IF EXISTS csat_config;
ALTER TABLE inboxes DROP COLUMN IF EXISTS business_name;
ALTER TABLE inboxes DROP COLUMN IF EXISTS sender_name_type;
ALTER TABLE inboxes DROP COLUMN IF EXISTS lock_to_single_conversation;
ALTER TABLE inboxes DROP COLUMN IF EXISTS allow_messages_after_resolved;
ALTER TABLE inboxes DROP COLUMN IF EXISTS timezone;
ALTER TABLE inboxes DROP COLUMN IF EXISTS out_of_office_message;
ALTER TABLE inboxes DROP COLUMN IF EXISTS working_hours_enabled;
ALTER TABLE inboxes DROP COLUMN IF EXISTS csat_survey_enabled;
ALTER TABLE inboxes DROP COLUMN IF EXISTS enable_email_collect;
ALTER TABLE inboxes DROP COLUMN IF EXISTS greeting_message;
ALTER TABLE inboxes DROP COLUMN IF EXISTS greeting_enabled;
@@ -1,3 +1,24 @@
ALTER TABLE accounts
ADD COLUMN IF NOT EXISTS inbox_limit INTEGER DEFAULT 0;
ALTER TABLE accounts
ADD COLUMN IF NOT EXISTS agent_limit INTEGER DEFAULT 0;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS greeting_enabled BOOLEAN DEFAULT FALSE;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS greeting_message TEXT;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS enable_email_collect BOOLEAN DEFAULT TRUE;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS csat_survey_enabled BOOLEAN DEFAULT FALSE;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS working_hours_enabled BOOLEAN DEFAULT FALSE;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS out_of_office_message TEXT;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS timezone VARCHAR(100);
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS allow_messages_after_resolved BOOLEAN DEFAULT TRUE;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS lock_to_single_conversation BOOLEAN DEFAULT FALSE;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS sender_name_type VARCHAR(50) DEFAULT 'friendly';
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS business_name VARCHAR(255);
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS csat_config TEXT;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS avatar_url VARCHAR(1024);
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS portal_id INTEGER;
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS webhook_url VARCHAR(1024);
ALTER TABLE inboxes ADD COLUMN IF NOT EXISTS secret VARCHAR(255);
CREATE INDEX IF NOT EXISTS idx_inboxes_portal_id ON inboxes(portal_id) WHERE deleted_at IS NULL;
@@ -1,3 +1,4 @@
ALTER TABLE accounts
DROP COLUMN IF EXISTS keep_pending_on_bot_failure,
DROP COLUMN IF EXISTS captain_features,
DROP COLUMN IF EXISTS captain_models;
@@ -2,4 +2,5 @@
ALTER TABLE accounts
ADD COLUMN IF NOT EXISTS captain_models JSONB NOT NULL DEFAULT '{}',
ADD COLUMN IF NOT EXISTS captain_features JSONB NOT NULL DEFAULT '{}';
ADD COLUMN IF NOT EXISTS captain_features JSONB NOT NULL DEFAULT '{}',
ADD COLUMN IF NOT EXISTS keep_pending_on_bot_failure BOOLEAN NOT NULL DEFAULT FALSE;
@@ -1,2 +1,35 @@
CREATE TABLE IF NOT EXISTS calls (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
inbox_id INTEGER,
conversation_id INTEGER NOT NULL,
contact_id INTEGER,
message_id INTEGER,
accepted_by_agent_id INTEGER,
provider VARCHAR(50) DEFAULT 'twilio',
direction VARCHAR(50),
provider_call_id VARCHAR(255),
conference_sid VARCHAR(255),
caller_type VARCHAR(100) NOT NULL DEFAULT '',
caller_id INTEGER NOT NULL DEFAULT 0,
status VARCHAR(50) NOT NULL DEFAULT 'ringing',
duration INTEGER DEFAULT 0,
call_direction VARCHAR(50) NOT NULL DEFAULT '',
recording_url VARCHAR(512),
additional_attributes JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_calls_deleted_at ON calls(deleted_at);
CREATE INDEX IF NOT EXISTS idx_calls_account_id ON calls(account_id);
CREATE INDEX IF NOT EXISTS idx_calls_inbox_id ON calls(inbox_id);
CREATE INDEX IF NOT EXISTS idx_calls_conversation_id ON calls(conversation_id);
CREATE INDEX IF NOT EXISTS idx_calls_contact_id ON calls(contact_id);
CREATE INDEX IF NOT EXISTS idx_calls_message_id ON calls(message_id);
CREATE INDEX IF NOT EXISTS idx_calls_accepted_by_agent_id ON calls(accepted_by_agent_id);
CREATE INDEX IF NOT EXISTS idx_calls_provider_call_id ON calls(provider, provider_call_id);
ALTER TABLE calls ADD COLUMN IF NOT EXISTS started_at TIMESTAMPTZ;
ALTER TABLE calls ADD COLUMN IF NOT EXISTS end_reason VARCHAR(255);
@@ -1,2 +1,7 @@
ALTER TABLE channel_twitters ADD COLUMN IF NOT EXISTS tweets_enabled BOOLEAN DEFAULT TRUE;
ALTER TABLE channel_twitter_profiles ADD COLUMN IF NOT EXISTS tweets_enabled BOOLEAN DEFAULT TRUE;
DO $$
BEGIN
IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'channel_twitter_profiles') THEN
ALTER TABLE channel_twitter_profiles ADD COLUMN IF NOT EXISTS tweets_enabled BOOLEAN DEFAULT TRUE;
END IF;
END $$;
@@ -0,0 +1,2 @@
DROP TABLE IF EXISTS company_contacts;
DROP TABLE IF EXISTS companies;
@@ -0,0 +1,27 @@
CREATE TABLE IF NOT EXISTS companies (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT DEFAULT '',
website_url VARCHAR(512),
favicon_url VARCHAR(512),
domain VARCHAR(255),
last_activity_at TIMESTAMPTZ,
additional_attributes JSONB DEFAULT '{}',
custom_attributes JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_companies_account_id ON companies(account_id);
CREATE INDEX IF NOT EXISTS idx_companies_name ON companies(account_id, name);
CREATE INDEX IF NOT EXISTS idx_companies_domain ON companies(account_id, domain);
CREATE TABLE IF NOT EXISTS company_contacts (
company_id INTEGER NOT NULL,
contact_id INTEGER NOT NULL,
PRIMARY KEY (company_id, contact_id)
);
CREATE INDEX IF NOT EXISTS idx_company_contacts_company_id ON company_contacts(company_id);
CREATE INDEX IF NOT EXISTS idx_company_contacts_contact_id ON company_contacts(contact_id);
@@ -0,0 +1,4 @@
DROP TABLE IF EXISTS sla_events;
DROP TABLE IF EXISTS applied_slas;
DROP TABLE IF EXISTS sla_policy_inboxes;
DROP TABLE IF EXISTS sla_policies;
+75
View File
@@ -0,0 +1,75 @@
CREATE TABLE IF NOT EXISTS sla_policies (
id SERIAL PRIMARY KEY,
account_id INTEGER NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
first_response_time_threshold INTEGER DEFAULT 0,
next_response_time_threshold INTEGER DEFAULT 0,
resolution_time_threshold INTEGER DEFAULT 0,
only_during_business_hours BOOLEAN DEFAULT FALSE,
paused_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_sla_policies_account_id ON sla_policies(account_id);
CREATE INDEX IF NOT EXISTS idx_sla_policies_paused_at ON sla_policies(paused_at);
CREATE INDEX IF NOT EXISTS idx_sla_policies_deleted_at ON sla_policies(deleted_at);
CREATE TABLE IF NOT EXISTS sla_policy_inboxes (
id SERIAL PRIMARY KEY,
sla_policy_id INTEGER NOT NULL,
inbox_id INTEGER NOT NULL,
account_id INTEGER NOT NULL,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_sla_inbox_unique ON sla_policy_inboxes(inbox_id) WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_sla_policy_inboxes_sla_policy_id ON sla_policy_inboxes(sla_policy_id);
CREATE INDEX IF NOT EXISTS idx_sla_policy_inboxes_account_id ON sla_policy_inboxes(account_id);
CREATE INDEX IF NOT EXISTS idx_sla_policy_inboxes_deleted_at ON sla_policy_inboxes(deleted_at);
CREATE TABLE IF NOT EXISTS applied_slas (
id SERIAL PRIMARY KEY,
sla_policy_id INTEGER NOT NULL,
conversation_id INTEGER NOT NULL,
account_id INTEGER NOT NULL,
sla_status VARCHAR(50) NOT NULL DEFAULT 'active',
frt_target_at TIMESTAMPTZ,
nrt_target_at TIMESTAMPTZ,
rt_target_at TIMESTAMPTZ,
frt_actual_at TIMESTAMPTZ,
nrt_actual_at TIMESTAMPTZ,
rt_actual_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_applied_slas_sla_policy_id ON applied_slas(sla_policy_id);
CREATE INDEX IF NOT EXISTS idx_applied_slas_conversation_id ON applied_slas(conversation_id);
CREATE INDEX IF NOT EXISTS idx_applied_slas_account_id ON applied_slas(account_id);
CREATE INDEX IF NOT EXISTS idx_applied_slas_frt_target_at ON applied_slas(frt_target_at);
CREATE INDEX IF NOT EXISTS idx_applied_slas_nrt_target_at ON applied_slas(nrt_target_at);
CREATE INDEX IF NOT EXISTS idx_applied_slas_rt_target_at ON applied_slas(rt_target_at);
CREATE INDEX IF NOT EXISTS idx_applied_slas_deleted_at ON applied_slas(deleted_at);
CREATE TABLE IF NOT EXISTS sla_events (
id SERIAL PRIMARY KEY,
applied_sla_id INTEGER NOT NULL,
account_id INTEGER NOT NULL,
conversation_id INTEGER NOT NULL,
inbox_id INTEGER NOT NULL,
sla_policy_id INTEGER NOT NULL,
event_type VARCHAR(50) NOT NULL,
meta JSONB DEFAULT '{}',
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
deleted_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_sla_events_applied_sla_id ON sla_events(applied_sla_id);
CREATE INDEX IF NOT EXISTS idx_sla_events_account_id ON sla_events(account_id);
CREATE INDEX IF NOT EXISTS idx_sla_events_conversation_id ON sla_events(conversation_id);
CREATE INDEX IF NOT EXISTS idx_sla_events_inbox_id ON sla_events(inbox_id);
CREATE INDEX IF NOT EXISTS idx_sla_events_sla_policy_id ON sla_events(sla_policy_id);
CREATE INDEX IF NOT EXISTS idx_sla_events_deleted_at ON sla_events(deleted_at);
@@ -0,0 +1 @@
DROP TABLE IF EXISTS installation_configs;
@@ -0,0 +1,15 @@
CREATE TABLE IF NOT EXISTS installation_configs (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
name VARCHAR(100) NOT NULL,
value TEXT NOT NULL
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_installation_configs_name
ON installation_configs (name)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_installation_configs_deleted_at
ON installation_configs (deleted_at);
@@ -0,0 +1,3 @@
DROP TABLE IF EXISTS bot_trigger_configs;
DROP TABLE IF EXISTS bot_rules;
DROP TABLE IF EXISTS csat_survey_responses;
@@ -0,0 +1,66 @@
CREATE TABLE IF NOT EXISTS csat_survey_responses (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
account_id BIGINT NOT NULL,
conversation_id BIGINT NOT NULL,
contact_id BIGINT,
message_id BIGINT,
assigned_agent_id BIGINT,
rating INTEGER NOT NULL,
feedback_message TEXT,
csat_review_notes TEXT,
review_notes_updated_by_id BIGINT,
review_notes_updated_at TIMESTAMPTZ
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_csat_survey_responses_message_id
ON csat_survey_responses (message_id)
WHERE message_id IS NOT NULL AND deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_csat_survey_responses_account_id ON csat_survey_responses (account_id);
CREATE INDEX IF NOT EXISTS idx_csat_survey_responses_conversation_id ON csat_survey_responses (conversation_id);
CREATE INDEX IF NOT EXISTS idx_csat_survey_responses_contact_id ON csat_survey_responses (contact_id);
CREATE INDEX IF NOT EXISTS idx_csat_survey_responses_assigned_agent_id ON csat_survey_responses (assigned_agent_id);
CREATE INDEX IF NOT EXISTS idx_csat_survey_responses_review_notes_updated_by_id ON csat_survey_responses (review_notes_updated_by_id);
CREATE INDEX IF NOT EXISTS idx_csat_survey_responses_deleted_at ON csat_survey_responses (deleted_at);
CREATE TABLE IF NOT EXISTS bot_rules (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
agent_bot_id BIGINT NOT NULL,
account_id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
event_name VARCHAR(100) NOT NULL,
conditions JSONB DEFAULT '[]'::jsonb,
actions JSONB DEFAULT '[]'::jsonb,
status VARCHAR(20) DEFAULT 'active'
);
CREATE INDEX IF NOT EXISTS idx_bot_rules_agent_bot_id ON bot_rules (agent_bot_id);
CREATE INDEX IF NOT EXISTS idx_bot_rules_account_id ON bot_rules (account_id);
CREATE INDEX IF NOT EXISTS idx_bot_rules_event_name ON bot_rules (event_name);
CREATE INDEX IF NOT EXISTS idx_bot_rules_deleted_at ON bot_rules (deleted_at);
CREATE TABLE IF NOT EXISTS bot_trigger_configs (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
agent_bot_id BIGINT NOT NULL,
account_id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
event_name VARCHAR(100) NOT NULL,
conditions JSONB DEFAULT '[]'::jsonb,
query_operator VARCHAR(10) DEFAULT 'and',
active BOOLEAN DEFAULT true
);
CREATE INDEX IF NOT EXISTS idx_bot_trigger_configs_agent_bot_id ON bot_trigger_configs (agent_bot_id);
CREATE INDEX IF NOT EXISTS idx_bot_trigger_configs_account_id ON bot_trigger_configs (account_id);
CREATE INDEX IF NOT EXISTS idx_bot_trigger_configs_event_name ON bot_trigger_configs (event_name);
CREATE INDEX IF NOT EXISTS idx_bot_trigger_configs_deleted_at ON bot_trigger_configs (deleted_at);
@@ -0,0 +1,3 @@
DROP TABLE IF EXISTS macro_executions;
DROP TABLE IF EXISTS macros;
DROP TABLE IF EXISTS automation_rules;
@@ -0,0 +1,51 @@
CREATE TABLE IF NOT EXISTS automation_rules (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
account_id BIGINT NOT NULL,
event_name VARCHAR(100) NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
active BOOLEAN DEFAULT true,
active_at TIMESTAMPTZ,
inactive_at TIMESTAMPTZ,
conditions JSONB DEFAULT '[]'::jsonb,
actions JSONB DEFAULT '[]'::jsonb
);
CREATE INDEX IF NOT EXISTS idx_automation_rules_account_id ON automation_rules (account_id);
CREATE INDEX IF NOT EXISTS idx_automation_rules_event_name ON automation_rules (event_name);
CREATE INDEX IF NOT EXISTS idx_automation_rules_active_at ON automation_rules (active_at);
CREATE INDEX IF NOT EXISTS idx_automation_rules_inactive_at ON automation_rules (inactive_at);
CREATE INDEX IF NOT EXISTS idx_automation_rules_deleted_at ON automation_rules (deleted_at);
CREATE TABLE IF NOT EXISTS macros (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
account_id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
actions JSONB DEFAULT '[]'::jsonb,
visibility INTEGER DEFAULT 0,
active BOOLEAN NOT NULL DEFAULT true,
created_by_id BIGINT NOT NULL,
updated_by_id BIGINT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_macros_account_id ON macros (account_id);
CREATE INDEX IF NOT EXISTS idx_macros_created_by_id ON macros (created_by_id);
CREATE INDEX IF NOT EXISTS idx_macros_updated_by_id ON macros (updated_by_id);
CREATE INDEX IF NOT EXISTS idx_macros_deleted_at ON macros (deleted_at);
CREATE TABLE IF NOT EXISTS macro_executions (
id BIGSERIAL PRIMARY KEY,
macro_id BIGINT NOT NULL,
conversation_id BIGINT NOT NULL,
executed_by_id BIGINT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_macro_executions_macro_id ON macro_executions (macro_id);
CREATE INDEX IF NOT EXISTS idx_macro_executions_conversation_id ON macro_executions (conversation_id);
CREATE INDEX IF NOT EXISTS idx_macro_executions_executed_by_id ON macro_executions (executed_by_id);
@@ -0,0 +1 @@
DROP TABLE IF EXISTS audits;
+25
View File
@@ -0,0 +1,25 @@
CREATE TABLE IF NOT EXISTS audits (
id BIGSERIAL PRIMARY KEY,
account_id BIGINT NOT NULL,
user_id BIGINT,
auditable_type VARCHAR(100) NOT NULL,
auditable_id BIGINT NOT NULL,
action VARCHAR(50) NOT NULL,
audited_changes JSONB DEFAULT '{}'::jsonb,
associated_type VARCHAR(100),
associated_id BIGINT,
username VARCHAR(255),
remote_address VARCHAR(100),
request_uuid VARCHAR(100),
version BIGINT,
comment TEXT,
user_type VARCHAR(50),
created_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_audits_account_id ON audits (account_id);
CREATE INDEX IF NOT EXISTS idx_audits_user_id ON audits (user_id);
CREATE INDEX IF NOT EXISTS idx_audits_action ON audits (action);
CREATE INDEX IF NOT EXISTS idx_audits_auditable ON audits (auditable_type, auditable_id);
CREATE INDEX IF NOT EXISTS idx_audits_associated ON audits (associated_type, associated_id);
CREATE INDEX IF NOT EXISTS idx_audits_created_at ON audits (created_at);
@@ -0,0 +1,3 @@
DROP TABLE IF EXISTS campaigns;
DROP TABLE IF EXISTS team_members;
DROP TABLE IF EXISTS teams;
@@ -0,0 +1,58 @@
CREATE TABLE IF NOT EXISTS teams (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
account_id BIGINT NOT NULL,
name VARCHAR(255) NOT NULL,
description TEXT,
allow_auto_assignment BOOLEAN DEFAULT true
);
CREATE INDEX IF NOT EXISTS idx_teams_account_id ON teams (account_id);
CREATE INDEX IF NOT EXISTS idx_teams_deleted_at ON teams (deleted_at);
CREATE TABLE IF NOT EXISTS team_members (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
team_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
availability_status VARCHAR(50) DEFAULT 'offline'
);
CREATE INDEX IF NOT EXISTS idx_team_members_team_id ON team_members (team_id);
CREATE INDEX IF NOT EXISTS idx_team_members_user_id ON team_members (user_id);
CREATE INDEX IF NOT EXISTS idx_team_members_deleted_at ON team_members (deleted_at);
CREATE UNIQUE INDEX IF NOT EXISTS idx_team_members_team_user ON team_members (team_id, user_id) WHERE deleted_at IS NULL;
CREATE TABLE IF NOT EXISTS campaigns (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMPTZ,
updated_at TIMESTAMPTZ,
deleted_at TIMESTAMPTZ,
account_id BIGINT NOT NULL,
inbox_id BIGINT NOT NULL,
sender_id BIGINT,
display_id BIGINT NOT NULL,
title VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
description TEXT,
campaign_status VARCHAR(50) DEFAULT 'active',
campaign_type VARCHAR(50) NOT NULL,
audience JSONB DEFAULT '{}'::jsonb,
trigger_rules JSONB DEFAULT '{}'::jsonb,
template_params JSONB DEFAULT '{}'::jsonb,
scheduled_at TIMESTAMPTZ,
enabled BOOLEAN DEFAULT true,
trigger_only_during_business_hours BOOLEAN DEFAULT false
);
CREATE UNIQUE INDEX IF NOT EXISTS idx_campaign_display ON campaigns (display_id);
CREATE INDEX IF NOT EXISTS idx_campaigns_account_id ON campaigns (account_id);
CREATE INDEX IF NOT EXISTS idx_campaigns_inbox_id ON campaigns (inbox_id);
CREATE INDEX IF NOT EXISTS idx_campaigns_sender_id ON campaigns (sender_id);
CREATE INDEX IF NOT EXISTS idx_campaigns_campaign_status ON campaigns (campaign_status);
CREATE INDEX IF NOT EXISTS idx_campaigns_scheduled_at ON campaigns (scheduled_at);
CREATE INDEX IF NOT EXISTS idx_campaigns_deleted_at ON campaigns (deleted_at);
@@ -0,0 +1,4 @@
DROP INDEX IF EXISTS idx_portals_channel_web_widget_id;
ALTER TABLE portals
DROP COLUMN IF EXISTS channel_web_widget_id;
@@ -0,0 +1,8 @@
-- Add Chatwoot portal web-widget association used by the help-center/widget frontend contract.
ALTER TABLE portals
ADD COLUMN IF NOT EXISTS channel_web_widget_id INTEGER;
CREATE INDEX IF NOT EXISTS idx_portals_channel_web_widget_id
ON portals(channel_web_widget_id)
WHERE deleted_at IS NULL;
@@ -0,0 +1,19 @@
DROP INDEX IF EXISTS idx_folders_parent_id;
DROP INDEX IF EXISTS idx_folders_category_id;
DROP INDEX IF EXISTS idx_folders_account_id;
ALTER TABLE folders
DROP COLUMN IF EXISTS custom_attributes,
DROP COLUMN IF EXISTS parent_id,
DROP COLUMN IF EXISTS category_id,
DROP COLUMN IF EXISTS account_id;
DROP INDEX IF EXISTS idx_categories_associated_category_id;
DROP INDEX IF EXISTS idx_categories_parent_id;
DROP INDEX IF EXISTS idx_categories_account_id;
ALTER TABLE categories
DROP COLUMN IF EXISTS custom_attributes,
DROP COLUMN IF EXISTS associated_category_id,
DROP COLUMN IF EXISTS parent_id,
DROP COLUMN IF EXISTS account_id;
@@ -0,0 +1,49 @@
-- Align help-center tables with current GoChat/Chatwoot frontend model fields.
ALTER TABLE categories
ADD COLUMN IF NOT EXISTS account_id INTEGER,
ADD COLUMN IF NOT EXISTS parent_id INTEGER,
ADD COLUMN IF NOT EXISTS associated_category_id INTEGER,
ADD COLUMN IF NOT EXISTS custom_attributes JSONB DEFAULT '{}';
UPDATE categories c
SET account_id = p.account_id
FROM portals p
WHERE c.portal_id = p.id AND c.account_id IS NULL;
ALTER TABLE categories
ALTER COLUMN account_id SET NOT NULL;
CREATE INDEX IF NOT EXISTS idx_categories_account_id
ON categories(account_id)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_categories_parent_id
ON categories(parent_id)
WHERE deleted_at IS NULL AND parent_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_categories_associated_category_id
ON categories(associated_category_id)
WHERE deleted_at IS NULL AND associated_category_id IS NOT NULL;
ALTER TABLE folders
ADD COLUMN IF NOT EXISTS account_id INTEGER,
ADD COLUMN IF NOT EXISTS category_id INTEGER,
ADD COLUMN IF NOT EXISTS parent_id INTEGER,
ADD COLUMN IF NOT EXISTS custom_attributes JSONB DEFAULT '{}';
UPDATE folders f
SET account_id = p.account_id
FROM portals p
WHERE f.portal_id = p.id AND f.account_id IS NULL;
ALTER TABLE folders
ALTER COLUMN account_id SET NOT NULL;
CREATE INDEX IF NOT EXISTS idx_folders_account_id
ON folders(account_id)
WHERE deleted_at IS NULL;
CREATE INDEX IF NOT EXISTS idx_folders_category_id
ON folders(category_id)
WHERE deleted_at IS NULL AND category_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_folders_parent_id
ON folders(parent_id)
WHERE deleted_at IS NULL AND parent_id IS NOT NULL;