72 lines
3.0 KiB
SQL
72 lines
3.0 KiB
SQL
-- +goose Up
|
|||
|
|
-- Internal support center: tickets, threaded messages, in-app notifications.
|
||
|
|
|
||
|
|
CREATE TABLE support_tickets (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
||
|
|
created_by_user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||
|
|
subject TEXT NOT NULL,
|
||
|
|
category TEXT NOT NULL DEFAULT 'other'
|
||
|
|
CHECK (category IN ('billing', 'bug', 'account', 'other')),
|
||
|
|
status TEXT NOT NULL DEFAULT 'open'
|
||
|
|
CHECK (status IN ('open', 'pending', 'resolved', 'closed')),
|
||
|
|
priority TEXT NOT NULL DEFAULT 'normal'
|
||
|
|
CHECK (priority IN ('low', 'normal', 'high')),
|
||
|
|
assignee_admin_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||
|
|
last_message_at TIMESTAMPTZ,
|
||
|
|
last_customer_message_at TIMESTAMPTZ,
|
||
|
|
last_agent_message_at TIMESTAMPTZ,
|
||
|
|
resolved_at TIMESTAMPTZ,
|
||
|
|
closed_at TIMESTAMPTZ,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX support_tickets_admin_queue_idx
|
||
|
|
ON support_tickets (status, last_message_at DESC NULLS LAST);
|
||
|
|
CREATE INDEX support_tickets_company_user_idx
|
||
|
|
ON support_tickets (company_id, created_by_user_id, updated_at DESC);
|
||
|
|
CREATE INDEX support_tickets_company_status_idx
|
||
|
|
ON support_tickets (company_id, status);
|
||
|
|
|
||
|
|
CREATE TABLE support_messages (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
ticket_id UUID NOT NULL REFERENCES support_tickets(id) ON DELETE CASCADE,
|
||
|
|
company_id UUID NOT NULL REFERENCES companies(id) ON DELETE CASCADE,
|
||
|
|
author_user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||
|
|
author_role TEXT NOT NULL
|
||
|
|
CHECK (author_role IN ('user', 'agent', 'system')),
|
||
|
|
body TEXT NOT NULL,
|
||
|
|
is_internal_note BOOLEAN NOT NULL DEFAULT false,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX support_messages_ticket_idx
|
||
|
|
ON support_messages (ticket_id, created_at ASC);
|
||
|
|
|
||
|
|
CREATE TABLE support_notifications (
|
||
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||
|
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||
|
|
ticket_id UUID NOT NULL REFERENCES support_tickets(id) ON DELETE CASCADE,
|
||
|
|
message_id UUID REFERENCES support_messages(id) ON DELETE SET NULL,
|
||
|
|
kind TEXT NOT NULL
|
||
|
|
CHECK (kind IN ('ticket_created', 'agent_reply', 'status_changed', 'user_reply')),
|
||
|
|
read_at TIMESTAMPTZ,
|
||
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX support_notifications_user_unread_idx
|
||
|
|
ON support_notifications (user_id, read_at, created_at DESC);
|
||
|
|
CREATE INDEX support_notifications_user_created_idx
|
||
|
|
ON support_notifications (user_id, created_at DESC);
|
||
|
|
|
||
|
|
-- +goose Down
|
||
|
|
DROP INDEX IF EXISTS support_notifications_user_created_idx;
|
||
|
|
DROP INDEX IF EXISTS support_notifications_user_unread_idx;
|
||
|
|
DROP TABLE IF EXISTS support_notifications;
|
||
|
|
DROP INDEX IF EXISTS support_messages_ticket_idx;
|
||
|
|
DROP TABLE IF EXISTS support_messages;
|
||
|
|
DROP INDEX IF EXISTS support_tickets_company_status_idx;
|
||
|
|
DROP INDEX IF EXISTS support_tickets_company_user_idx;
|
||
|
|
DROP INDEX IF EXISTS support_tickets_admin_queue_idx;
|
||
|
|
DROP TABLE IF EXISTS support_tickets;
|