mirror of
https://github.com/abhinavxd/libredesk.git
synced 2026-09-10 14:15:42 +00:00
aa9e4cdae2
- Introduced a new category field for conversation statuses to classify them as 'open', 'waiting', or 'resolved'. Which allows max assignment limits in team to work with custom statuses as well.
858 lines
27 KiB
SQL
858 lines
27 KiB
SQL
-- name: unsnooze-all
|
|
UPDATE conversations
|
|
SET snoozed_until = NULL, status_id = (SELECT id FROM conversation_statuses WHERE name = 'Open')
|
|
WHERE snoozed_until <= NOW();
|
|
|
|
-- name: insert-conversation
|
|
-- $11 = rate limit window start (timestamptz), $12 = max conversations (0 = unlimited)
|
|
WITH
|
|
status_id AS (
|
|
SELECT id FROM conversation_statuses WHERE name = $2
|
|
),
|
|
reference_number AS (
|
|
SELECT generate_reference_number($7) AS reference_number
|
|
)
|
|
INSERT INTO conversations
|
|
(contact_id, status_id, inbox_id, last_message, last_message_at, subject, reference_number, meta, custom_attributes)
|
|
SELECT
|
|
$1,
|
|
(SELECT id FROM status_id),
|
|
$3,
|
|
$4,
|
|
$5,
|
|
CASE
|
|
WHEN $8 = TRUE THEN CONCAT($6::text, ' - #', (SELECT reference_number FROM reference_number), '')
|
|
ELSE $6::text
|
|
END,
|
|
(SELECT reference_number FROM reference_number),
|
|
$9,
|
|
$10
|
|
WHERE $12::int = 0 OR (SELECT COUNT(*) FROM conversations WHERE contact_id = $1 AND created_at >= $11) < $12::int
|
|
RETURNING id, uuid;
|
|
|
|
-- name: get-conversations
|
|
-- $1 = viewing user ID for per-agent unread count
|
|
-- $2 = include mentioned message UUID (true for mentioned inbox, false otherwise)
|
|
SELECT
|
|
COUNT(*) OVER() as total,
|
|
conversations.id,
|
|
conversations.created_at,
|
|
conversations.updated_at,
|
|
conversations.uuid,
|
|
conversations.reference_number,
|
|
conversations.waiting_since,
|
|
users.created_at as "contact.created_at",
|
|
users.updated_at as "contact.updated_at",
|
|
users.first_name as "contact.first_name",
|
|
users.last_name as "contact.last_name",
|
|
users.email as "contact.email",
|
|
users.avatar_url as "contact.avatar_url",
|
|
inboxes.channel as inbox_channel,
|
|
inboxes.name as inbox_name,
|
|
conversations.sla_policy_id,
|
|
conversations.first_reply_at,
|
|
conversations.last_reply_at,
|
|
conversations.resolved_at,
|
|
conversations.subject,
|
|
conversations.last_message,
|
|
conversations.last_message_at,
|
|
conversations.last_message_sender,
|
|
conversations.last_interaction,
|
|
conversations.last_interaction_at,
|
|
conversations.last_interaction_sender,
|
|
conversations.next_sla_deadline_at,
|
|
conversations.priority_id,
|
|
(
|
|
SELECT CASE WHEN COUNT(*) > 9 THEN 10 ELSE COUNT(*) END
|
|
FROM (
|
|
SELECT 1 FROM conversation_messages
|
|
WHERE conversation_id = conversations.id
|
|
AND created_at > COALESCE(
|
|
(SELECT last_seen_at FROM conversation_last_seen
|
|
WHERE conversation_id = conversations.id AND user_id = $1),
|
|
'1970-01-01'::TIMESTAMPTZ
|
|
)
|
|
AND (meta IS NULL OR NOT COALESCE((meta->>'continuity_email')::boolean, false))
|
|
LIMIT 10
|
|
) t
|
|
) as unread_message_count,
|
|
conversation_statuses.name as status,
|
|
conversation_priorities.name as priority,
|
|
as_latest.first_response_deadline_at,
|
|
as_latest.resolution_deadline_at,
|
|
as_latest.id as applied_sla_id,
|
|
nxt_resp_event.deadline_at AS next_response_deadline_at,
|
|
nxt_resp_event.met_at as next_response_met_at,
|
|
CASE WHEN $2 = true THEN (
|
|
SELECT msg.uuid
|
|
FROM conversation_mentions cm2
|
|
JOIN conversation_messages msg ON msg.id = cm2.message_id
|
|
WHERE cm2.conversation_id = conversations.id
|
|
AND (cm2.mentioned_user_id = $1 OR EXISTS(
|
|
SELECT 1 FROM team_members tm2
|
|
WHERE tm2.team_id = cm2.mentioned_team_id AND tm2.user_id = $1
|
|
))
|
|
ORDER BY cm2.created_at DESC
|
|
LIMIT 1
|
|
) ELSE NULL END as mentioned_message_uuid
|
|
FROM conversations
|
|
JOIN users ON contact_id = users.id
|
|
JOIN inboxes ON inbox_id = inboxes.id
|
|
LEFT JOIN conversation_statuses ON status_id = conversation_statuses.id
|
|
LEFT JOIN conversation_priorities ON priority_id = conversation_priorities.id
|
|
LEFT JOIN LATERAL (
|
|
SELECT id, first_response_deadline_at, resolution_deadline_at
|
|
FROM applied_slas
|
|
WHERE conversation_id = conversations.id
|
|
ORDER BY created_at DESC LIMIT 1
|
|
) as_latest ON true
|
|
LEFT JOIN LATERAL (
|
|
SELECT se.deadline_at, se.met_at
|
|
FROM sla_events se
|
|
WHERE se.applied_sla_id = as_latest.id
|
|
AND se.type = 'next_response'
|
|
ORDER BY se.created_at DESC
|
|
LIMIT 1
|
|
) nxt_resp_event ON true
|
|
WHERE 1=1 %s
|
|
|
|
-- name: get-conversation
|
|
SELECT
|
|
c.id,
|
|
c.created_at,
|
|
c.updated_at,
|
|
c.closed_at,
|
|
c.resolved_at,
|
|
c.inbox_id,
|
|
inb.name as inbox_name,
|
|
COALESCE(inb.from, '') as inbox_mail,
|
|
COALESCE(inb.channel::TEXT, '') as inbox_channel,
|
|
c.status_id,
|
|
c.priority_id,
|
|
p.name as priority,
|
|
s.name as status,
|
|
c.uuid,
|
|
c.reference_number,
|
|
c.first_reply_at,
|
|
c.last_reply_at,
|
|
c.waiting_since,
|
|
c.assigned_user_id,
|
|
c.assigned_team_id,
|
|
c.subject,
|
|
c.contact_id,
|
|
c.sla_policy_id,
|
|
c.meta,
|
|
sla.name as sla_policy_name,
|
|
c.last_message_at,
|
|
c.last_message_sender,
|
|
c.last_message,
|
|
c.last_interaction,
|
|
c.last_interaction_at,
|
|
c.last_interaction_sender,
|
|
c.custom_attributes,
|
|
(SELECT COALESCE(
|
|
(SELECT json_agg(t.name)
|
|
FROM tags t
|
|
INNER JOIN conversation_tags ct ON ct.tag_id = t.id
|
|
WHERE ct.conversation_id = c.id),
|
|
'[]'::json
|
|
)) AS tags,
|
|
ct.id as "contact.id",
|
|
ct.created_at as "contact.created_at",
|
|
ct.updated_at as "contact.updated_at",
|
|
ct.first_name as "contact.first_name",
|
|
ct.last_name as "contact.last_name",
|
|
ct.email as "contact.email",
|
|
ct.type as "contact.type",
|
|
ct.availability_status as "contact.availability_status",
|
|
ct.avatar_url as "contact.avatar_url",
|
|
ct.phone_number as "contact.phone_number",
|
|
ct.phone_number_country_code as "contact.phone_number_country_code",
|
|
ct.country as "contact.country",
|
|
ct.custom_attributes as "contact.custom_attributes",
|
|
ct.enabled as "contact.enabled",
|
|
ct.last_active_at as "contact.last_active_at",
|
|
ct.last_login_at as "contact.last_login_at",
|
|
ct.external_user_id as "contact.external_user_id",
|
|
as_latest.first_response_deadline_at,
|
|
as_latest.resolution_deadline_at,
|
|
as_latest.id as applied_sla_id,
|
|
nxt_resp_event.deadline_at AS next_response_deadline_at,
|
|
nxt_resp_event.met_at as next_response_met_at,
|
|
c.last_continuity_email_sent_at
|
|
FROM conversations c
|
|
JOIN users ct ON c.contact_id = ct.id
|
|
JOIN inboxes inb ON c.inbox_id = inb.id
|
|
LEFT JOIN sla_policies sla ON c.sla_policy_id = sla.id
|
|
LEFT JOIN teams at ON at.id = c.assigned_team_id
|
|
LEFT JOIN conversation_statuses s ON c.status_id = s.id
|
|
LEFT JOIN conversation_priorities p ON c.priority_id = p.id
|
|
LEFT JOIN LATERAL (
|
|
SELECT id, first_response_deadline_at, resolution_deadline_at
|
|
FROM applied_slas
|
|
WHERE conversation_id = c.id
|
|
ORDER BY created_at DESC LIMIT 1
|
|
) as_latest ON true
|
|
LEFT JOIN LATERAL (
|
|
SELECT se.deadline_at, se.met_at
|
|
FROM sla_events se
|
|
WHERE se.applied_sla_id = as_latest.id
|
|
AND se.type = 'next_response'
|
|
ORDER BY se.created_at DESC
|
|
LIMIT 1
|
|
) nxt_resp_event ON true
|
|
WHERE
|
|
($1 > 0 AND c.id = $1)
|
|
OR
|
|
($2::uuid IS NOT NULL AND c.uuid = $2::uuid)
|
|
OR
|
|
($3::TEXT != '' AND c.reference_number = $3::TEXT)
|
|
|
|
|
|
-- name: get-conversations-created-after
|
|
SELECT
|
|
c.id,
|
|
c.uuid
|
|
FROM conversations c
|
|
WHERE c.created_at > $1;
|
|
|
|
-- name: get-contact-previous-conversations
|
|
SELECT
|
|
c.id,
|
|
c.created_at,
|
|
c.updated_at,
|
|
c.uuid,
|
|
c.subject,
|
|
u.first_name AS "contact.first_name",
|
|
u.last_name AS "contact.last_name",
|
|
u.avatar_url AS "contact.avatar_url",
|
|
c.last_message as last_message,
|
|
c.last_message_at as last_message_at
|
|
FROM users u
|
|
JOIN conversations c ON c.contact_id = u.id
|
|
WHERE c.contact_id = $1
|
|
ORDER BY c.created_at DESC
|
|
LIMIT $2;
|
|
|
|
-- name: get-chat-conversation
|
|
SELECT
|
|
c.created_at,
|
|
c.uuid,
|
|
cs.name as status,
|
|
COALESCE(c.last_interaction, '') as "last_message.content",
|
|
c.last_interaction_at as "last_message.created_at",
|
|
COALESCE(lis.id, 0) AS "last_message.author.id",
|
|
COALESCE(lis.first_name, '') AS "last_message.author.first_name",
|
|
COALESCE(lis.last_name, '') AS "last_message.author.last_name",
|
|
COALESCE(lis.avatar_url, '') AS "last_message.author.avatar_url",
|
|
COALESCE(c.last_interaction_sender::TEXT, '') AS "last_message.author.type",
|
|
(SELECT CASE WHEN COUNT(*) > 9 THEN 10 ELSE COUNT(*) END
|
|
FROM (
|
|
SELECT 1 FROM conversation_messages unread
|
|
WHERE unread.conversation_id = c.id
|
|
AND unread.created_at > c.contact_last_seen_at
|
|
AND unread.type = 'outgoing'
|
|
AND unread.private = false
|
|
LIMIT 10
|
|
) t) AS unread_message_count,
|
|
COALESCE(au.availability_status::TEXT, '') as "assignee.availability_status",
|
|
au.avatar_url as "assignee.avatar_url",
|
|
COALESCE(au.first_name, '') as "assignee.first_name",
|
|
COALESCE(au.id, 0) as "assignee.id",
|
|
COALESCE(au.last_name, '') as "assignee.last_name",
|
|
COALESCE(au.type::TEXT, '') as "assignee.type"
|
|
FROM conversations c
|
|
INNER JOIN inboxes inb on c.inbox_id = inb.id
|
|
LEFT JOIN conversation_statuses cs ON c.status_id = cs.id
|
|
LEFT JOIN users au ON c.assigned_user_id = au.id
|
|
LEFT JOIN users lis ON c.last_interaction_sender_id = lis.id
|
|
WHERE c.uuid = $1
|
|
AND inb.deleted_at IS NULL;
|
|
|
|
-- name: get-contact-chat-conversations
|
|
SELECT
|
|
c.created_at,
|
|
c.uuid,
|
|
cs.name as status,
|
|
COALESCE(c.last_interaction, '') as "last_message.content",
|
|
c.last_interaction_at as "last_message.created_at",
|
|
COALESCE(lis.id, 0) AS "last_message.author.id",
|
|
COALESCE(lis.first_name, '') AS "last_message.author.first_name",
|
|
COALESCE(lis.last_name, '') AS "last_message.author.last_name",
|
|
COALESCE(lis.avatar_url, '') AS "last_message.author.avatar_url",
|
|
COALESCE(c.last_interaction_sender::TEXT, '') AS "last_message.author.type",
|
|
(SELECT CASE WHEN COUNT(*) > 9 THEN 10 ELSE COUNT(*) END
|
|
FROM (
|
|
SELECT 1 FROM conversation_messages unread
|
|
WHERE unread.conversation_id = c.id
|
|
AND unread.created_at > c.contact_last_seen_at
|
|
AND unread.type = 'outgoing'
|
|
AND unread.private = false
|
|
LIMIT 10
|
|
) t) AS unread_message_count,
|
|
COALESCE(au.availability_status::TEXT, '') as "assignee.availability_status",
|
|
au.avatar_url as "assignee.avatar_url",
|
|
COALESCE(au.first_name, '') as "assignee.first_name",
|
|
COALESCE(au.id, 0) as "assignee.id",
|
|
COALESCE(au.last_name, '') as "assignee.last_name",
|
|
COALESCE(au.type::TEXT, '') as "assignee.type"
|
|
FROM conversations c
|
|
INNER JOIN inboxes inb ON c.inbox_id = inb.id
|
|
INNER JOIN users con ON c.contact_id = con.id
|
|
LEFT JOIN conversation_statuses cs ON c.status_id = cs.id
|
|
LEFT JOIN users au ON c.assigned_user_id = au.id
|
|
LEFT JOIN users lis ON c.last_interaction_sender_id = lis.id
|
|
WHERE c.contact_id = $1 AND c.inbox_id = $2
|
|
AND inb.deleted_at IS NULL
|
|
AND con.deleted_at IS NULL
|
|
ORDER BY c.created_at DESC
|
|
LIMIT 200;
|
|
|
|
-- name: get-conversation-uuid
|
|
SELECT uuid from conversations where id = $1;
|
|
|
|
-- name: update-conversation-assigned-user
|
|
UPDATE conversations
|
|
SET assigned_user_id = $2,
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
-- name: update-conversation-contact-last-seen
|
|
UPDATE conversations
|
|
SET contact_last_seen_at = NOW(),
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
-- name: update-conversation-assigned-team
|
|
UPDATE conversations
|
|
SET assigned_team_id = $2,
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
|
|
-- name: update-conversation-status
|
|
WITH new_status AS (
|
|
SELECT id, category FROM conversation_statuses WHERE name = $2
|
|
)
|
|
UPDATE conversations
|
|
SET status_id = (SELECT id FROM new_status),
|
|
resolved_at = COALESCE(resolved_at, CASE WHEN (SELECT category FROM new_status) = 'resolved' THEN NOW() END),
|
|
closed_at = COALESCE(closed_at, CASE WHEN $2 = 'Closed' THEN NOW() END),
|
|
snoozed_until = CASE WHEN $2 = 'Snoozed' THEN $3::timestamptz ELSE snoozed_until END,
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
-- name: get-user-active-conversations-count
|
|
SELECT COUNT(*) FROM conversations WHERE status_id IN (SELECT id FROM conversation_statuses WHERE category = 'open') AND assigned_user_id = $1;
|
|
|
|
-- name: update-conversation-priority
|
|
UPDATE conversations
|
|
SET priority_id = (SELECT id FROM conversation_priorities WHERE name = $2),
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
-- name: upsert-user-last-seen
|
|
INSERT INTO conversation_last_seen (user_id, conversation_id, last_seen_at)
|
|
VALUES ($1, (SELECT id FROM conversations WHERE uuid = $2), NOW())
|
|
ON CONFLICT (conversation_id, user_id)
|
|
DO UPDATE SET last_seen_at = NOW(), updated_at = NOW();
|
|
|
|
-- name: update-conversation-last-message
|
|
-- $1=id, $2=uuid, $3=content, $4=sender_type, $5=timestamp, $6=message_type, $7=private, $8=sender_id
|
|
UPDATE conversations SET
|
|
last_message = $3,
|
|
last_message_sender = $4,
|
|
last_message_sender_id = $8,
|
|
last_message_at = $5,
|
|
last_interaction = CASE WHEN $6 != 'activity' AND $7 = false THEN $3 ELSE last_interaction END,
|
|
last_interaction_sender = CASE WHEN $6 != 'activity' AND $7 = false THEN $4 ELSE last_interaction_sender END,
|
|
last_interaction_sender_id = CASE WHEN $6 != 'activity' AND $7 = false THEN $8 ELSE last_interaction_sender_id END,
|
|
last_interaction_at = CASE WHEN $6 != 'activity' AND $7 = false THEN $5 ELSE last_interaction_at END,
|
|
updated_at = NOW()
|
|
WHERE CASE
|
|
WHEN $1 > 0 THEN id = $1
|
|
ELSE uuid = $2
|
|
END
|
|
|
|
-- name: get-conversation-participants
|
|
SELECT users.id as id, first_name, last_name, avatar_url
|
|
FROM conversation_participants
|
|
INNER JOIN users ON users.id = conversation_participants.user_id
|
|
WHERE conversation_id =
|
|
(
|
|
SELECT id FROM conversations WHERE uuid = $1
|
|
);
|
|
|
|
-- name: insert-conversation-participant
|
|
INSERT INTO conversation_participants
|
|
(user_id, conversation_id)
|
|
VALUES($1, (SELECT id FROM conversations WHERE uuid = $2));
|
|
|
|
-- name: get-unassigned-conversations
|
|
SELECT
|
|
c.created_at,
|
|
c.updated_at,
|
|
c.uuid,
|
|
c.assigned_team_id,
|
|
inb.channel as inbox_channel,
|
|
inb.name as inbox_name
|
|
FROM conversations c
|
|
JOIN inboxes inb ON c.inbox_id = inb.id
|
|
WHERE assigned_user_id IS NULL AND assigned_team_id IS NOT NULL
|
|
ORDER BY c.created_at ASC;
|
|
|
|
-- name: add-conversation-tags
|
|
-- Insert new tags
|
|
INSERT INTO conversation_tags (conversation_id, tag_id)
|
|
SELECT c.id, t.id
|
|
FROM conversations c, tags t
|
|
WHERE t.name = ANY($2::text[]) AND c.uuid = $1
|
|
ON CONFLICT (conversation_id, tag_id) DO UPDATE SET tag_id = EXCLUDED.tag_id;
|
|
|
|
-- name: set-conversation-tags
|
|
WITH conversation_id AS (
|
|
SELECT id FROM conversations WHERE uuid = $1
|
|
),
|
|
-- Insert new tags
|
|
inserted AS (
|
|
INSERT INTO conversation_tags (conversation_id, tag_id)
|
|
SELECT conversation_id.id, t.id
|
|
FROM conversation_id, tags t
|
|
WHERE t.name = ANY($2::text[])
|
|
ON CONFLICT (conversation_id, tag_id) DO UPDATE SET tag_id = EXCLUDED.tag_id
|
|
)
|
|
-- Delete tags that are not in the new list
|
|
DELETE FROM conversation_tags
|
|
WHERE conversation_id = (SELECT id FROM conversation_id)
|
|
AND tag_id NOT IN (
|
|
SELECT id FROM tags WHERE name = ANY($2::text[])
|
|
);
|
|
|
|
-- name: remove-conversation-tags
|
|
-- Delete tags that are not in the new list
|
|
DELETE FROM conversation_tags
|
|
WHERE conversation_id = (SELECT id FROM conversations WHERE uuid = $1)
|
|
AND tag_id IN (
|
|
SELECT id FROM tags WHERE name = ANY($2::text[])
|
|
);
|
|
|
|
-- name: get-conversation-tags
|
|
SELECT t.name
|
|
FROM conversation_tags ct
|
|
JOIN tags t ON ct.tag_id = t.id
|
|
WHERE ct.conversation_id = (SELECT id FROM conversations WHERE uuid = $1);
|
|
|
|
-- name: get-conversation-uuid-from-message-uuid
|
|
SELECT c.uuid AS conversation_uuid
|
|
FROM conversation_messages m
|
|
JOIN conversations c ON m.conversation_id = c.id
|
|
WHERE m.uuid = $1;
|
|
|
|
-- name: unassign-open-conversations
|
|
UPDATE conversations
|
|
SET assigned_user_id = NULL,
|
|
updated_at = NOW()
|
|
WHERE assigned_user_id = $1 AND status_id IN (SELECT id FROM conversation_statuses WHERE category != 'resolved');
|
|
|
|
-- name: update-conversation-custom-attributes
|
|
UPDATE conversations
|
|
SET custom_attributes = $2,
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
-- name: update-conversation-waiting-since
|
|
UPDATE conversations
|
|
SET waiting_since = $2,
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
-- name: update-conversation-reply-timestamps
|
|
WITH old AS (
|
|
SELECT first_reply_at IS NULL AS is_first FROM conversations WHERE id = $1
|
|
)
|
|
UPDATE conversations SET
|
|
first_reply_at = COALESCE(conversations.first_reply_at, $2),
|
|
last_reply_at = $2,
|
|
waiting_since = NULL,
|
|
updated_at = NOW()
|
|
FROM old WHERE conversations.id = $1
|
|
RETURNING old.is_first AS is_first_reply;
|
|
|
|
-- name: remove-conversation-assignee
|
|
UPDATE conversations
|
|
SET
|
|
assigned_user_id = CASE WHEN $2 = 'user' THEN NULL ELSE assigned_user_id END,
|
|
assigned_team_id = CASE WHEN $2 = 'team' THEN NULL ELSE assigned_team_id END,
|
|
updated_at = NOW()
|
|
WHERE uuid = $1;
|
|
|
|
-- name: re-open-conversation
|
|
-- Open conversation if it is not already open and unset the assigned user if they are away and reassigning.
|
|
UPDATE conversations
|
|
SET
|
|
status_id = (SELECT id FROM conversation_statuses WHERE name = 'Open'),
|
|
snoozed_until = NULL,
|
|
updated_at = NOW(),
|
|
assigned_user_id = CASE
|
|
WHEN EXISTS (
|
|
SELECT 1 FROM users
|
|
WHERE users.id = conversations.assigned_user_id
|
|
AND users.availability_status = 'away_and_reassigning'
|
|
) THEN NULL
|
|
ELSE assigned_user_id
|
|
END
|
|
WHERE
|
|
uuid = $1
|
|
AND status_id IN (
|
|
SELECT id FROM conversation_statuses WHERE name NOT IN ('Open')
|
|
)
|
|
|
|
-- name: get-conversation-by-message-id
|
|
SELECT
|
|
c.id,
|
|
c.uuid,
|
|
c.assigned_team_id,
|
|
c.assigned_user_id
|
|
FROM conversation_messages m
|
|
JOIN conversations c ON m.conversation_id = c.id
|
|
WHERE m.id = $1;
|
|
|
|
-- name: delete-conversation
|
|
DELETE FROM conversations WHERE uuid = $1;
|
|
|
|
-- MESSAGE queries.
|
|
-- name: delete-message
|
|
DELETE FROM conversation_messages WHERE CASE
|
|
WHEN $1 > 0 THEN id = $1
|
|
ELSE uuid = $2
|
|
END;
|
|
|
|
-- name: get-message-source-ids
|
|
SELECT
|
|
source_id
|
|
FROM conversation_messages
|
|
WHERE conversation_id = $1
|
|
AND type in ('incoming', 'outgoing') and private = false
|
|
and source_id > ''
|
|
ORDER BY id DESC
|
|
LIMIT $2;
|
|
|
|
-- name: get-outgoing-pending-messages
|
|
SELECT
|
|
m.id,
|
|
m.created_at,
|
|
m.updated_at,
|
|
m.status,
|
|
m.type,
|
|
m.content,
|
|
m.text_content,
|
|
m.sender_type,
|
|
m.content_type,
|
|
m.conversation_id,
|
|
m.uuid,
|
|
m.private,
|
|
m.sender_type,
|
|
m.sender_id,
|
|
m.meta,
|
|
c.uuid as conversation_uuid,
|
|
m.content_type,
|
|
m.source_id,
|
|
m.meta,
|
|
ARRAY(SELECT jsonb_array_elements_text(m.meta->'cc')) AS cc,
|
|
ARRAY(SELECT jsonb_array_elements_text(m.meta->'bcc')) AS bcc,
|
|
ARRAY(SELECT jsonb_array_elements_text(m.meta->'to')) AS to,
|
|
c.inbox_id,
|
|
c.uuid as conversation_uuid,
|
|
c.subject,
|
|
c.contact_id as message_receiver_id,
|
|
c.subject
|
|
FROM conversation_messages m
|
|
INNER JOIN conversations c ON c.id = m.conversation_id
|
|
WHERE m.status = 'pending' AND m.type = 'outgoing' AND m.private = false
|
|
AND NOT(m.id = ANY($1::INT[]))
|
|
|
|
-- name: get-message
|
|
SELECT
|
|
m.id,
|
|
m.created_at,
|
|
m.updated_at,
|
|
m.status,
|
|
m.type,
|
|
m.content,
|
|
m.text_content,
|
|
m.content_type,
|
|
m.conversation_id,
|
|
m.uuid,
|
|
m.private,
|
|
m.sender_type,
|
|
m.sender_id,
|
|
m.meta,
|
|
c.uuid as conversation_uuid,
|
|
u.id AS "author.id",
|
|
u.first_name AS "author.first_name",
|
|
u.last_name AS "author.last_name",
|
|
u.email AS "author.email",
|
|
u.avatar_url AS "author.avatar_url",
|
|
u.availability_status AS "author.availability_status",
|
|
u.type AS "author.type",
|
|
u.last_active_at AS "author.last_active_at",
|
|
COALESCE(
|
|
json_agg(
|
|
json_build_object(
|
|
'name', media.filename,
|
|
'content_type', media.content_type,
|
|
'uuid', media.uuid,
|
|
'size', media.size,
|
|
'content_id', media.content_id,
|
|
'disposition', media.disposition
|
|
) ORDER BY media.filename
|
|
) FILTER (WHERE media.id IS NOT NULL),
|
|
'[]'::json
|
|
) AS attachments
|
|
FROM conversation_messages m
|
|
INNER JOIN conversations c ON c.id = m.conversation_id
|
|
JOIN users u ON m.sender_id = u.id
|
|
LEFT JOIN media ON media.model_type = 'messages' AND media.model_id = m.id
|
|
WHERE m.uuid = $1
|
|
GROUP BY
|
|
m.id, m.created_at, m.updated_at, m.status, m.type, m.content, m.uuid, m.private, m.sender_type, c.uuid,
|
|
u.id, u.first_name, u.last_name, u.email, u.avatar_url, u.availability_status, u.type, u.last_active_at
|
|
ORDER BY m.created_at;
|
|
|
|
-- name: get-messages
|
|
SELECT
|
|
COUNT(*) OVER() AS total,
|
|
m.id,
|
|
m.created_at,
|
|
m.updated_at,
|
|
m.status,
|
|
m.type,
|
|
m.content,
|
|
m.text_content,
|
|
m.content_type,
|
|
m.conversation_id,
|
|
m.uuid,
|
|
m.private,
|
|
m.sender_id,
|
|
m.sender_type,
|
|
m.meta,
|
|
$1::uuid AS conversation_uuid,
|
|
u.id AS "author.id",
|
|
u.first_name AS "author.first_name",
|
|
u.last_name AS "author.last_name",
|
|
u.email AS "author.email",
|
|
u.avatar_url AS "author.avatar_url",
|
|
u.availability_status AS "author.availability_status",
|
|
u.type AS "author.type",
|
|
u.last_active_at AS "author.last_active_at",
|
|
COALESCE(
|
|
(SELECT json_agg(
|
|
json_build_object(
|
|
'name', filename,
|
|
'content_type', content_type,
|
|
'uuid', uuid,
|
|
'size', size,
|
|
'content_id', content_id,
|
|
'disposition', disposition
|
|
) ORDER BY filename
|
|
) FROM media
|
|
WHERE model_type = 'messages' AND model_id = m.id),
|
|
'[]'::json) AS attachments
|
|
FROM conversation_messages m
|
|
JOIN users u ON m.sender_id = u.id
|
|
WHERE m.conversation_id = (
|
|
SELECT id FROM conversations WHERE uuid = $1 LIMIT 1
|
|
)
|
|
AND ($2::boolean IS NULL OR m.private = $2)
|
|
AND ($3::text[] IS NULL OR m.type::text = ANY($3))
|
|
AND (m.meta IS NULL OR NOT COALESCE((m.meta->>'continuity_email')::boolean, false))
|
|
ORDER BY m.created_at DESC %s
|
|
|
|
-- name: insert-message
|
|
WITH conversation_id AS (
|
|
SELECT id
|
|
FROM conversations
|
|
WHERE CASE
|
|
WHEN $3 > 0 THEN id = $3
|
|
ELSE uuid = $4
|
|
END
|
|
),
|
|
inserted_msg AS (
|
|
INSERT INTO conversation_messages (
|
|
"type", status, conversation_id, "content",
|
|
text_content, sender_id, sender_type, private,
|
|
content_type, source_id, meta
|
|
)
|
|
VALUES (
|
|
$1, $2, (SELECT id FROM conversation_id),
|
|
$5, $6, $7, $8, $9, $10, $11, $12
|
|
)
|
|
RETURNING *
|
|
)
|
|
SELECT * FROM inserted_msg;
|
|
|
|
-- name: message-exists-by-source-id
|
|
SELECT conversation_id
|
|
FROM conversation_messages
|
|
WHERE source_id = ANY($1::text []);
|
|
|
|
-- name: update-message-status
|
|
update conversation_messages set status = $1, updated_at = NOW() where uuid = $2;
|
|
|
|
-- name: get-latest-message
|
|
SELECT
|
|
m.created_at,
|
|
m.updated_at,
|
|
m.status,
|
|
m.type,
|
|
m.content,
|
|
m.uuid,
|
|
m.private,
|
|
m.sender_id,
|
|
m.sender_type,
|
|
m.meta
|
|
FROM conversation_messages m
|
|
WHERE m.conversation_id = $1
|
|
AND m.type = ANY($2)
|
|
AND m.status = ANY($3)
|
|
AND m.private = NOT $4
|
|
ORDER BY m.created_at DESC
|
|
LIMIT 1;
|
|
|
|
-- name: update-message-source-id
|
|
UPDATE conversation_messages SET source_id = $1 WHERE id = $2;
|
|
|
|
-- name: get-offline-livechat-conversations
|
|
SELECT
|
|
c.id,
|
|
c.uuid,
|
|
c.contact_id,
|
|
c.inbox_id,
|
|
c.contact_last_seen_at,
|
|
c.last_continuity_email_sent_at,
|
|
i.linked_email_inbox_id,
|
|
u.email as contact_email,
|
|
u.first_name as contact_first_name,
|
|
u.last_name as contact_last_name,
|
|
c.reference_number,
|
|
c.meta->>'continuity_email_subject' as continuity_email_subject
|
|
FROM conversations c
|
|
JOIN users u ON u.id = c.contact_id
|
|
JOIN inboxes i ON i.id = c.inbox_id
|
|
WHERE i.channel = 'livechat'
|
|
AND i.enabled = TRUE
|
|
AND i.linked_email_inbox_id IS NOT NULL
|
|
AND c.contact_last_seen_at IS NOT NULL
|
|
AND c.contact_last_seen_at < NOW() - MAKE_INTERVAL(mins => $1)
|
|
AND EXISTS (
|
|
SELECT 1 FROM conversation_messages cm
|
|
WHERE cm.conversation_id = c.id
|
|
AND cm.created_at > c.contact_last_seen_at
|
|
AND cm.type = 'outgoing'
|
|
AND cm.private = false
|
|
AND (cm.meta IS NULL OR NOT COALESCE((cm.meta->>'continuity_email')::boolean, false))
|
|
AND (cm.meta IS NULL OR NOT COALESCE((cm.meta->>'continuity_emailed')::boolean, false))
|
|
)
|
|
AND u.email > ''
|
|
AND (c.last_continuity_email_sent_at IS NULL
|
|
OR c.last_continuity_email_sent_at < NOW() - MAKE_INTERVAL(mins => $2))
|
|
AND c.inbox_id = $3;
|
|
|
|
-- name: get-unread-messages
|
|
SELECT
|
|
m.id,
|
|
m.created_at,
|
|
m.updated_at,
|
|
m.status,
|
|
m.type,
|
|
m.content,
|
|
m.text_content,
|
|
m.uuid,
|
|
m.private,
|
|
m.sender_id,
|
|
m.sender_type,
|
|
m.meta,
|
|
u.first_name as "sender.first_name",
|
|
u.last_name as "sender.last_name",
|
|
u.type as "sender.type",
|
|
COALESCE((SELECT string_agg(md.filename, ',') FROM media md WHERE md.model_id = m.id AND md.model_type = 'messages'), '') AS attachment_names
|
|
FROM conversation_messages m
|
|
LEFT JOIN users u ON u.id = m.sender_id
|
|
WHERE m.conversation_id = $1
|
|
AND m.created_at > $2
|
|
AND m.type = 'outgoing'
|
|
AND m.private = false
|
|
AND (m.meta IS NULL OR NOT COALESCE((m.meta->>'continuity_email')::boolean, false))
|
|
AND (m.meta IS NULL OR NOT COALESCE((m.meta->>'continuity_emailed')::boolean, false))
|
|
ORDER BY m.created_at ASC
|
|
LIMIT $3;
|
|
|
|
-- name: mark-messages-continuity-emailed
|
|
UPDATE conversation_messages
|
|
SET meta = COALESCE(meta, '{}'::jsonb) || '{"continuity_emailed": true}'::jsonb
|
|
WHERE id = ANY($1::int[]);
|
|
|
|
-- name: update-continuity-email-tracking
|
|
UPDATE conversations
|
|
SET last_continuity_email_sent_at = NOW(),
|
|
meta = jsonb_set(COALESCE(meta, '{}'::jsonb), '{continuity_email_subject}', to_jsonb($2::text))
|
|
WHERE id = $1;
|
|
|
|
-- name: upsert-conversation-draft
|
|
INSERT INTO conversation_drafts (conversation_id, user_id, content, meta, updated_at)
|
|
VALUES ($1, $2, $3, $4, NOW())
|
|
ON CONFLICT (conversation_id, user_id)
|
|
DO UPDATE SET content = EXCLUDED.content, meta = EXCLUDED.meta, updated_at = NOW()
|
|
RETURNING *;
|
|
|
|
-- name: get-all-user-drafts
|
|
SELECT cd.id, cd.conversation_id, cd.user_id, cd.content, cd.meta, cd.created_at, cd.updated_at, c.uuid as conversation_uuid
|
|
FROM conversation_drafts cd
|
|
INNER JOIN conversations c ON cd.conversation_id = c.id
|
|
WHERE cd.user_id = $1
|
|
ORDER BY cd.updated_at DESC;
|
|
|
|
-- name: delete-conversation-draft
|
|
DELETE FROM conversation_drafts
|
|
WHERE conversation_id IN (
|
|
SELECT id FROM conversations
|
|
WHERE ($1 > 0 AND id = $1) OR ($2::uuid IS NOT NULL AND uuid = $2::uuid)
|
|
) AND user_id = $3;
|
|
|
|
-- name: delete-stale-drafts
|
|
DELETE FROM conversation_drafts
|
|
WHERE created_at < $1;
|
|
|
|
-- name: insert-mention
|
|
INSERT INTO conversation_mentions (conversation_id, message_id, mentioned_user_id, mentioned_team_id, mentioned_by_user_id)
|
|
VALUES ($1, $2, $3, $4, $5);
|
|
|
|
-- name: mark-conversation-unread
|
|
INSERT INTO conversation_last_seen (user_id, conversation_id, last_seen_at)
|
|
VALUES (
|
|
$1,
|
|
(SELECT id FROM conversations WHERE uuid = $2),
|
|
(SELECT created_at - INTERVAL '1 second' FROM conversation_messages
|
|
WHERE conversation_id = (SELECT id FROM conversations WHERE uuid = $2)
|
|
ORDER BY created_at DESC LIMIT 1)
|
|
)
|
|
ON CONFLICT (conversation_id, user_id)
|
|
DO UPDATE SET
|
|
last_seen_at = (SELECT created_at - INTERVAL '1 second' FROM conversation_messages
|
|
WHERE conversation_id = (SELECT id FROM conversations WHERE uuid = $2)
|
|
ORDER BY created_at DESC LIMIT 1),
|
|
updated_at = NOW();
|
|
|
|
-- name: get-active-livechat-conversations-by-agent
|
|
SELECT c.uuid, c.contact_id, c.inbox_id
|
|
FROM conversations c
|
|
JOIN inboxes i ON i.id = c.inbox_id
|
|
JOIN users u ON u.id = c.contact_id
|
|
WHERE c.assigned_user_id = $1
|
|
AND i.channel = 'livechat'
|
|
AND i.enabled = TRUE
|
|
AND i.deleted_at IS NULL
|
|
AND u.availability_status = 'online'
|
|
ORDER BY c.last_interaction_at DESC
|
|
LIMIT 50;
|