-- Idempotent column sync for existing databases -- Adds columns that may be absent if the production DB was bootstrapped from an older schema. -- Safe to run multiple times: all statements use ADD COLUMN IF NOT EXISTS. -- ============================================================ -- forms table: columns added after initial deployment -- ============================================================ ALTER TABLE forms ADD COLUMN IF NOT EXISTS chat_layout varchar(20) DEFAULT 'default'; ALTER TABLE forms ADD COLUMN IF NOT EXISTS chat_enabled boolean DEFAULT true; ALTER TABLE forms ADD COLUMN IF NOT EXISTS system_fields_tab_id integer; ALTER TABLE forms ADD COLUMN IF NOT EXISTS default_tab_id integer; ALTER TABLE forms ADD COLUMN IF NOT EXISTS detail_layout_code text; ALTER TABLE forms ADD COLUMN IF NOT EXISTS title_template text; ALTER TABLE forms ADD COLUMN IF NOT EXISTS hidden_system_fields text[] DEFAULT '{}'::text[]; ALTER TABLE forms ADD COLUMN IF NOT EXISTS ai_summary text; --> statement-breakpoint -- ============================================================ -- organizations table: billing_blocked flag -- ============================================================ ALTER TABLE organizations ADD COLUMN IF NOT EXISTS billing_blocked boolean DEFAULT false; --> statement-breakpoint -- ============================================================ -- tasks table: subtask and completion columns -- ============================================================ ALTER TABLE tasks ADD COLUMN IF NOT EXISTS is_completed boolean DEFAULT false; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS completed_at timestamp; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS due_date timestamp; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS parent_task_id integer; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS depth integer DEFAULT 0; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS position integer DEFAULT 0; ALTER TABLE tasks ADD COLUMN IF NOT EXISTS organization_id integer; --> statement-breakpoint -- ============================================================ -- form_tabs table: type column -- ============================================================ ALTER TABLE form_tabs ADD COLUMN IF NOT EXISTS type varchar(20) DEFAULT 'fields'; ALTER TABLE form_tabs ADD COLUMN IF NOT EXISTS table_columns jsonb; --> statement-breakpoint -- ============================================================ -- form_statuses table: isFinal flag -- ============================================================ ALTER TABLE form_statuses ADD COLUMN IF NOT EXISTS is_final boolean DEFAULT false; --> statement-breakpoint -- ============================================================ -- form_fields table: newer field type columns -- ============================================================ ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS tab_id integer; ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS button_action_type varchar(20); ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS button_url text; ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS button_form_id integer; ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS company_autofill jsonb; ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS task_relation_type varchar(10); ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS max_file_count integer; ALTER TABLE form_fields ADD COLUMN IF NOT EXISTS max_file_size_mb integer; --> statement-breakpoint -- ============================================================ -- task_messages table: bot support columns -- ============================================================ ALTER TABLE task_messages ADD COLUMN IF NOT EXISTS bot_id integer; ALTER TABLE task_messages ADD COLUMN IF NOT EXISTS reply_to_message_id integer; ALTER TABLE task_messages ADD COLUMN IF NOT EXISTS bot_buttons jsonb; ALTER TABLE task_messages ADD COLUMN IF NOT EXISTS attachments jsonb; --> statement-breakpoint -- ============================================================ -- users table: password reset columns -- ============================================================ ALTER TABLE users ADD COLUMN IF NOT EXISTS reset_password_token varchar(255); ALTER TABLE users ADD COLUMN IF NOT EXISTS reset_password_expires timestamp; --> statement-breakpoint -- ============================================================ -- user_notifications table: message_id column -- ============================================================ ALTER TABLE user_notifications ADD COLUMN IF NOT EXISTS message_id integer; --> statement-breakpoint -- ============================================================ -- Indexes that may be missing on existing installations -- ============================================================ CREATE INDEX IF NOT EXISTS "users_org_role_idx" ON "users" USING btree ("organization_id", "role"); CREATE INDEX IF NOT EXISTS "tasks_org_id_form_id_idx" ON "tasks" USING btree ("organization_id", "form_id"); CREATE INDEX IF NOT EXISTS "tasks_org_id_status_idx" ON "tasks" USING btree ("organization_id", "current_status_id"); CREATE INDEX IF NOT EXISTS "tasks_org_id_assigned_idx" ON "tasks" USING btree ("organization_id", "assigned_to"); CREATE INDEX IF NOT EXISTS "task_messages_task_created_idx" ON "task_messages" USING btree ("task_id", "created_at" DESC); CREATE INDEX IF NOT EXISTS "task_field_values_task_field_idx" ON "task_field_values" USING btree ("task_id", "field_id"); CREATE UNIQUE INDEX IF NOT EXISTS "one_initial_status_per_form" ON "form_statuses" ("form_id") WHERE (is_initial = true);