From 6b39d818b20d30488ca83447064a9832978a83e4 Mon Sep 17 00:00:00 2001 From: 1AhmedYasser <26207361+1AhmedYasser@users.noreply.github.com> Date: Thu, 15 Jan 2026 00:05:20 +0200 Subject: [PATCH 1/6] chore(618): Added backoffice and general knowledge and validate --- GUI/src/components/ChatEvent/Markdownify.tsx | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/GUI/src/components/ChatEvent/Markdownify.tsx b/GUI/src/components/ChatEvent/Markdownify.tsx index 331f12d2..c0e0c799 100644 --- a/GUI/src/components/ChatEvent/Markdownify.tsx +++ b/GUI/src/components/ChatEvent/Markdownify.tsx @@ -53,14 +53,15 @@ const hasSpecialFormat = (m: string) => m.includes('\n\n') && m.indexOf('.') > 0 function formatMessage(message?: string): string { if (!message) return ''; - return message - .replace(/&#x([0-9A-Fa-f]+);/g, (_, hex) => - String.fromCharCode(parseInt(hex, 16)) - ) - .replace(/(^|\n)(\d{4})\.\s/g, (match, prefix, year) => { - const remainingText = message.substring( - message.indexOf(match) + match.length - ); + const filteredMessage = message + .replaceAll(/\\?\$b\w*/g, '') + .replaceAll(/\\?\$v\w*/g, '') + .replaceAll(/\\?\$g\w*/g, ''); + + return filteredMessage + .replaceAll(/&#x([0-9A-Fa-f]+);/g, (_, hex) => String.fromCharCode(parseInt(hex, 16))) + .replaceAll(/(^|\n)(\d{4})\.\s/g, (match, prefix, year) => { + const remainingText = filteredMessage.substring(filteredMessage.indexOf(match) + match.length); const sentenceEnd = remainingText.indexOf('\n\n'); if (sentenceEnd !== -1) { const currentSentence = remainingText.substring(0, sentenceEnd); @@ -70,7 +71,7 @@ function formatMessage(message?: string): string { } return `${prefix}${year}\\. `; }) - .replace(/(?<=\n)\d+\.\s/g, hasSpecialFormat(message) ? '\n\n$&' : '$&'); + .replace(/(?<=\n)\d+\.\s/g, hasSpecialFormat(filteredMessage) ? '\n\n$&' : '$&'); } const Markdownify: React.FC = ({ message, sanitizeLinks = false }) => ( From e44a5118b7f7abac4225793418a2d5ed46dc9ec8 Mon Sep 17 00:00:00 2001 From: 1AhmedYasser <26207361+1AhmedYasser@users.noreply.github.com> Date: Thu, 15 Jan 2026 00:19:51 +0200 Subject: [PATCH 2/6] chore(618): Enhanced markdownify --- GUI/src/components/ChatEvent/Markdownify.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GUI/src/components/ChatEvent/Markdownify.tsx b/GUI/src/components/ChatEvent/Markdownify.tsx index c0e0c799..d5d5932e 100644 --- a/GUI/src/components/ChatEvent/Markdownify.tsx +++ b/GUI/src/components/ChatEvent/Markdownify.tsx @@ -59,7 +59,7 @@ function formatMessage(message?: string): string { .replaceAll(/\\?\$g\w*/g, ''); return filteredMessage - .replaceAll(/&#x([0-9A-Fa-f]+);/g, (_, hex) => String.fromCharCode(parseInt(hex, 16))) + .replaceAll(/&#x([0-9A-Fa-f]+);/g, (_, hex: string) => String.fromCharCode(parseInt(hex, 16))) .replaceAll(/(^|\n)(\d{4})\.\s/g, (match, prefix, year) => { const remainingText = filteredMessage.substring(filteredMessage.indexOf(match) + match.length); const sentenceEnd = remainingText.indexOf('\n\n'); From e510caba95e17e005c6c247504c9c22c18b0651b Mon Sep 17 00:00:00 2001 From: 1AhmedYasser <26207361+1AhmedYasser@users.noreply.github.com> Date: Thu, 15 Jan 2026 00:30:21 +0200 Subject: [PATCH 3/6] chore(618): Bumped packaged version --- GUI/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GUI/package.json b/GUI/package.json index a04207b3..a6b5403b 100644 --- a/GUI/package.json +++ b/GUI/package.json @@ -7,7 +7,7 @@ "@buerokratt-ria/menu": "^0.2.9", "@buerokratt-ria/header": "^0.1.47", "@buerokratt-ria/styles": "^0.0.1", - "@buerokratt-ria/common-gui-components": "^0.0.33", + "@buerokratt-ria/common-gui-components": "^0.0.36", "@fontsource/roboto": "^4.5.8", "@formkit/auto-animate": "^1.0.0-beta.6", "@hookform/resolvers": "^2.9.11", From e17f097429f141d0a0d4eb04d9f1dc395b81ed1a Mon Sep 17 00:00:00 2001 From: 1AhmedYasser <26207361+1AhmedYasser@users.noreply.github.com> Date: Tue, 20 Jan 2026 14:09:30 +0200 Subject: [PATCH 4/6] chore(1714): Added five rating scale support --- ...dback-avg-feedback-to-buerokratt-chats.sql | 15 +- .../POST/feedback-buerokratt-chats-nps.sql | 45 +- .../POST/feedback-chats-distribution.sql | 36 +- .../feedback-chats-with-negative-feedback.sql | 219 ++++---- .../POST/feedback-csa-chats-feedback-nps.sql | 38 +- .../feedback-selected-csa-feedback-nps.sql | 93 ++-- DSL/Resql/analytics/POST/get-chat-by-id.sql | 107 ++-- .../analytics/POST/get-cs-all-ended-chats.sql | 491 ++++++++++-------- 8 files changed, 608 insertions(+), 436 deletions(-) diff --git a/DSL/Resql/analytics/POST/feedback-avg-feedback-to-buerokratt-chats.sql b/DSL/Resql/analytics/POST/feedback-avg-feedback-to-buerokratt-chats.sql index c8c14160..1c3314dd 100644 --- a/DSL/Resql/analytics/POST/feedback-avg-feedback-to-buerokratt-chats.sql +++ b/DSL/Resql/analytics/POST/feedback-avg-feedback-to-buerokratt-chats.sql @@ -1,5 +1,16 @@ +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +) SELECT date_trunc(:metric, ended) AS date_time, - ROUND(1.0 * SUM(CASE WHEN feedback_rating IS NOT NULL THEN feedback_rating ELSE 0 END) / NULLIF(COUNT(DISTINCT base_id), 0), 1) AS avg + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN ROUND(1.0 * SUM(CASE WHEN feedback_rating_five IS NOT NULL THEN feedback_rating_five ELSE 0 END) / NULLIF(COUNT(DISTINCT base_id), 0), 1) + ELSE ROUND(1.0 * SUM(CASE WHEN feedback_rating IS NOT NULL THEN feedback_rating ELSE 0 END) / NULLIF(COUNT(DISTINCT base_id), 0), 1) + END AS avg FROM chat WHERE ( array_length(ARRAY[:urls]::TEXT[], 1) IS NULL @@ -9,7 +20,7 @@ WHERE ( :showTest = TRUE OR chat.test = FALSE ) - AND EXISTS + AND EXISTS (SELECT 1 FROM message WHERE message.chat_base_id = chat.base_id diff --git a/DSL/Resql/analytics/POST/feedback-buerokratt-chats-nps.sql b/DSL/Resql/analytics/POST/feedback-buerokratt-chats-nps.sql index 50140616..4ea49384 100644 --- a/DSL/Resql/analytics/POST/feedback-buerokratt-chats-nps.sql +++ b/DSL/Resql/analytics/POST/feedback-buerokratt-chats-nps.sql @@ -1,15 +1,30 @@ -WITH chat_buerokratt AS ( +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +), +chat_buerokratt AS ( SELECT DISTINCT base_id, first_value(ended) OVER ( PARTITION BY base_id ORDER BY updated ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING ) AS ended, - last_value(feedback_rating) OVER ( - PARTITION BY base_id - ORDER BY updated - ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING - ) AS feedback_rating + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN last_value(feedback_rating_five) OVER ( + PARTITION BY base_id + ORDER BY updated + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) + ELSE last_value(feedback_rating) OVER ( + PARTITION BY base_id + ORDER BY updated + ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + ) + END AS feedback_rating_dynamic FROM chat WHERE ( array_length(ARRAY[:urls]::TEXT[], 1) IS NULL @@ -26,7 +41,11 @@ WITH chat_buerokratt AS ( AND message.author_role = 'buerokratt' ) AND status = 'ENDED' - AND feedback_rating IS NOT NULL + AND CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN feedback_rating_five IS NOT NULL + ELSE feedback_rating IS NOT NULL + END AND ended::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz ), point_nps AS ( @@ -34,9 +53,9 @@ point_nps AS ( COALESCE( CAST(( ( - SUM(CASE WHEN feedback_rating BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - - SUM(CASE WHEN feedback_rating BETWEEN 0 AND 6 THEN 1 ELSE 0 END) - ) / NULLIF(COUNT(feedback_rating), 0) * 100 + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 0 AND 6 THEN 1 ELSE 0 END) + ) / NULLIF(COUNT(feedback_rating_dynamic), 0) * 100 ) AS int), 0) AS nps FROM chat_buerokratt GROUP BY date_time @@ -46,9 +65,9 @@ period_nps AS ( SELECT COALESCE( CAST(( ( - SUM(CASE WHEN feedback_rating BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - - SUM(CASE WHEN feedback_rating BETWEEN 0 AND 6 THEN 1 ELSE 0 END) - ) / NULLIF(COUNT(feedback_rating), 0) * 100 + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 0 AND 6 THEN 1 ELSE 0 END) + ) / NULLIF(COUNT(feedback_rating_dynamic), 0) * 100 ) AS int), 0) AS nps FROM chat_buerokratt ) diff --git a/DSL/Resql/analytics/POST/feedback-chats-distribution.sql b/DSL/Resql/analytics/POST/feedback-chats-distribution.sql index 5e1efeb7..678e14a3 100644 --- a/DSL/Resql/analytics/POST/feedback-chats-distribution.sql +++ b/DSL/Resql/analytics/POST/feedback-chats-distribution.sql @@ -1,14 +1,28 @@ -WITH chats_filtered AS ( +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +), +chats_filtered AS ( SELECT DISTINCT base_id, first_value(created) OVER ( PARTITION BY base_id ORDER BY updated ) AS created, - last_value(feedback_rating) OVER ( - PARTITION BY base_id - ORDER BY updated - ) AS feedback_rating + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN last_value(feedback_rating_five) OVER ( + PARTITION BY base_id + ORDER BY updated + ) + ELSE last_value(feedback_rating) OVER ( + PARTITION BY base_id + ORDER BY updated + ) + END AS feedback_rating_dynamic FROM chat WHERE ( array_length(ARRAY[:urls]::TEXT[], 1) IS NULL @@ -19,7 +33,11 @@ WITH chats_filtered AS ( OR chat.test = FALSE ) AND STATUS = 'ENDED' - AND feedback_rating IS NOT NULL + AND CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN feedback_rating_five IS NOT NULL + ELSE feedback_rating IS NOT NULL + END AND created::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz AND ( (:chat_type = 'buerokratt' AND EXISTS ( @@ -46,7 +64,7 @@ WITH chats_filtered AS ( ) ) SELECT - COUNT(CASE WHEN feedback_rating BETWEEN 9 AND 10 THEN 1 END) AS promoters, - COUNT(CASE WHEN feedback_rating BETWEEN 7 AND 8 THEN 1 END) AS passives, - COUNT(CASE WHEN feedback_rating BETWEEN 0 AND 6 THEN 1 END) AS detractors + COUNT(CASE WHEN feedback_rating_dynamic BETWEEN 9 AND 10 THEN 1 END) AS promoters, + COUNT(CASE WHEN feedback_rating_dynamic BETWEEN 7 AND 8 THEN 1 END) AS passives, + COUNT(CASE WHEN feedback_rating_dynamic BETWEEN 0 AND 6 THEN 1 END) AS detractors FROM chats_filtered; diff --git a/DSL/Resql/analytics/POST/feedback-chats-with-negative-feedback.sql b/DSL/Resql/analytics/POST/feedback-chats-with-negative-feedback.sql index 81ce16f4..d32d9710 100644 --- a/DSL/Resql/analytics/POST/feedback-chats-with-negative-feedback.sql +++ b/DSL/Resql/analytics/POST/feedback-chats-with-negative-feedback.sql @@ -1,98 +1,112 @@ -WITH MaxChatHistoryComments AS ( +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +), +MaxChatHistoryComments AS ( SELECT MAX(id) AS maxId FROM chat_history_comments GROUP BY chat_id ), - ChatHistoryComments AS ( - SELECT - chc.comment, - chc.chat_id, - chc.created, - chc.author_display_name - FROM chat_history_comments chc - JOIN MaxChatHistoryComments m ON chc.id = m.maxId - ), - n_chats AS ( - SELECT - base_id, - MAX(created) AS created - FROM chat - WHERE STATUS = 'ENDED' - AND created::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz - AND feedback_rating IS NOT NULL - AND feedback_rating <= 5 -GROUP BY base_id - ), - c_chat AS ( -SELECT - base_id, - MIN(created) AS created, - MAX(ended) AS ended -FROM chat -GROUP BY base_id - ), - deduplicated_users AS ( -SELECT - id_code, - first_name, - last_name -FROM ( +ChatHistoryComments AS ( SELECT - id_code, - first_name, - last_name, - ROW_NUMBER() OVER (PARTITION BY id_code ORDER BY first_name, last_name) AS row_num - FROM "user" + chc.comment, + chc.chat_id, + chc.created, + chc.author_display_name + FROM chat_history_comments chc + JOIN MaxChatHistoryComments m ON chc.id = m.maxId +), +n_chats AS ( + SELECT + base_id, + MAX(created) AS created + FROM chat + WHERE STATUS = 'ENDED' + AND created::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz + AND CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN feedback_rating_five IS NOT NULL AND feedback_rating_five <= 5 + ELSE feedback_rating IS NOT NULL AND feedback_rating <= 5 + END + GROUP BY base_id +), +c_chat AS ( + SELECT + base_id, + MIN(created) AS created, + MAX(ended) AS ended + FROM chat + GROUP BY base_id +), +deduplicated_users AS ( + SELECT + id_code, + first_name, + last_name + FROM ( + SELECT + id_code, + first_name, + last_name, + ROW_NUMBER() OVER (PARTITION BY id_code ORDER BY first_name, last_name) AS row_num + FROM "user" ) ranked_users -WHERE row_num = 1 - ), - ChatUser AS ( -SELECT DISTINCT ON (id_code) - id_code, - display_name, - first_name, - last_name -FROM "user" -ORDER BY id_code, id DESC - ), - LatestOpenChat AS ( -SELECT DISTINCT ON (base_id) - base_id, - customer_support_id AS latest_open_csa -FROM chat -WHERE status = 'OPEN' -ORDER BY base_id, id DESC - ), - CSAFullNames AS ( -SELECT - c2.base_id, - ARRAY_AGG(DISTINCT TRIM( - CASE - WHEN c2.customer_support_id = 'chatbot' THEN c2.customer_support_display_name - ELSE COALESCE(NULLIF(TRIM(cu.first_name || ' ' || cu.last_name), ''), cu.display_name) - END - )) FILTER ( - WHERE NOT ( - c2.customer_support_id = 'chatbot' - AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> 'chatbot') - ) - ) AS all_csa_names, - ARRAY_AGG(DISTINCT c2.customer_support_id) FILTER ( - WHERE NOT ( - c2.customer_support_id = 'chatbot' - AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> 'chatbot') - ) - ) AS all_csa_ids -FROM chat c2 + WHERE row_num = 1 +), +ChatUser AS ( + SELECT DISTINCT ON (id_code) + id_code, + display_name, + first_name, + last_name + FROM "user" + ORDER BY id_code, id DESC +), +LatestOpenChat AS ( + SELECT DISTINCT ON (base_id) + base_id, + customer_support_id AS latest_open_csa + FROM chat + WHERE status = 'OPEN' + ORDER BY base_id, id DESC +), +CSAFullNames AS ( + SELECT + c2.base_id, + ARRAY_AGG(DISTINCT TRIM( + CASE + WHEN c2.customer_support_id = 'chatbot' THEN c2.customer_support_display_name + ELSE COALESCE(NULLIF(TRIM(cu.first_name || ' ' || cu.last_name), ''), cu.display_name) + END + )) FILTER ( + WHERE NOT ( + c2.customer_support_id = 'chatbot' + AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> 'chatbot') + ) + ) AS all_csa_names, + ARRAY_AGG(DISTINCT c2.customer_support_id) FILTER ( + WHERE NOT ( + c2.customer_support_id = 'chatbot' + AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> 'chatbot') + ) + ) AS all_csa_ids + FROM chat c2 LEFT JOIN ChatUser cu ON cu.id_code = c2.customer_support_id LEFT JOIN LatestOpenChat lo ON lo.base_id = c2.base_id -GROUP BY c2.base_id - ) + GROUP BY c2.base_id +) SELECT n_chats.base_id, c_chat.created, c_chat.ended, - chat.feedback_rating AS rating, + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN chat.feedback_rating_five + ELSE chat.feedback_rating + END AS rating, chat.feedback_text, deduplicated_users.first_name AS first_name, deduplicated_users.last_name AS last_name, @@ -100,15 +114,24 @@ SELECT CSAFullNames.all_csa_names AS all_csa_names, CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS total_pages FROM n_chats - LEFT JOIN chat ON n_chats.base_id = chat.base_id - LEFT JOIN c_chat ON c_chat.base_id = chat.base_id AND n_chats.created = chat.created - LEFT JOIN deduplicated_users ON chat.customer_support_id = deduplicated_users.id_code - LEFT JOIN ChatHistoryComments chc ON chat.base_id = chc.chat_id - LEFT JOIN CSAFullNames ON CSAFullNames.base_id = chat.base_id +LEFT JOIN chat ON n_chats.base_id = chat.base_id +LEFT JOIN c_chat ON c_chat.base_id = chat.base_id AND n_chats.created = chat.created +LEFT JOIN deduplicated_users ON chat.customer_support_id = deduplicated_users.id_code +LEFT JOIN ChatHistoryComments chc ON chat.base_id = chc.chat_id +LEFT JOIN CSAFullNames ON CSAFullNames.base_id = chat.base_id +CROSS JOIN rating_config rc WHERE ( LENGTH(:customerSupportIds) = 0 OR chat.customer_support_id = ANY(string_to_array(:customerSupportIds, ',')) - ) AND chat.feedback_rating IS NOT NULL AND chat.ended IS NOT NULL +) +AND ( + CASE + WHEN rc.is_five_rating_scale = 'true' + THEN chat.feedback_rating_five IS NOT NULL + ELSE chat.feedback_rating IS NOT NULL + END +) +AND chat.ended IS NOT NULL ORDER BY CASE WHEN :sorting = 'created desc' THEN n_chats.created END DESC, CASE WHEN :sorting = 'created asc' THEN n_chats.created END ASC, @@ -118,7 +141,19 @@ ORDER BY CASE WHEN :sorting = 'base_id asc' THEN n_chats.base_id END ASC, CASE WHEN :sorting = 'feedback desc' THEN feedback_text END DESC, CASE WHEN :sorting = 'feedback asc' THEN feedback_text END ASC, - CASE WHEN :sorting = 'rating desc' THEN feedback_rating END DESC, - CASE WHEN :sorting = 'rating asc' THEN feedback_rating END ASC + CASE WHEN :sorting = 'rating desc' THEN + CASE + WHEN rc.is_five_rating_scale = 'true' + THEN chat.feedback_rating_five + ELSE chat.feedback_rating + END + END DESC, + CASE WHEN :sorting = 'rating asc' THEN + CASE + WHEN rc.is_five_rating_scale = 'true' + THEN chat.feedback_rating_five + ELSE chat.feedback_rating + END + END ASC OFFSET ((GREATEST(:page, 1) - 1) * :page_size) - LIMIT :page_size; +LIMIT :page_size; diff --git a/DSL/Resql/analytics/POST/feedback-csa-chats-feedback-nps.sql b/DSL/Resql/analytics/POST/feedback-csa-chats-feedback-nps.sql index 2017bfc9..380270f6 100644 --- a/DSL/Resql/analytics/POST/feedback-csa-chats-feedback-nps.sql +++ b/DSL/Resql/analytics/POST/feedback-csa-chats-feedback-nps.sql @@ -1,13 +1,27 @@ -WITH chat_csas AS ( +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +), +chat_csas AS ( SELECT DISTINCT base_id, first_value(created) over ( PARTITION by base_id ORDER BY updated ) AS created, - last_value(feedback_rating) over ( - PARTITION by base_id - ORDER BY updated - ) AS feedback_rating + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN last_value(feedback_rating_five) over ( + PARTITION by base_id + ORDER BY updated + ) + ELSE last_value(feedback_rating) over ( + PARTITION by base_id + ORDER BY updated + ) + END AS feedback_rating_dynamic FROM chat WHERE ( array_length(ARRAY[:urls]::TEXT[], 1) IS NULL @@ -25,14 +39,18 @@ WITH chat_csas AS ( AND message.author_role = 'end-user' ) AND STATUS = 'ENDED' - AND feedback_rating IS NOT NULL + AND CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN feedback_rating_five IS NOT NULL + ELSE feedback_rating IS NOT NULL + END AND created::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz ), point_nps AS ( SELECT date_trunc(:metric, created)::text AS date_time, coalesce(CAST((( - SUM(CASE WHEN feedback_rating BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - - SUM(CASE WHEN feedback_rating BETWEEN 0 AND 6 THEN 1 ELSE 0 END) + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 0 AND 6 THEN 1 ELSE 0 END) ) / COUNT(base_id) * 100) AS int), 0) AS nps FROM chat_csas GROUP BY date_time @@ -40,8 +58,8 @@ point_nps AS ( ), period_nps AS ( SELECT coalesce(CAST((( - SUM(CASE WHEN feedback_rating BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - - SUM(CASE WHEN feedback_rating BETWEEN 0 AND 6 THEN 1 ELSE 0 END) + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 0 AND 6 THEN 1 ELSE 0 END) ) / COUNT(base_id) * 100) AS int), 0) AS nps FROM chat_csas ) diff --git a/DSL/Resql/analytics/POST/feedback-selected-csa-feedback-nps.sql b/DSL/Resql/analytics/POST/feedback-selected-csa-feedback-nps.sql index faee0151..501f6e92 100644 --- a/DSL/Resql/analytics/POST/feedback-selected-csa-feedback-nps.sql +++ b/DSL/Resql/analytics/POST/feedback-selected-csa-feedback-nps.sql @@ -1,4 +1,11 @@ -WITH ranked_chats AS ( +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +), +ranked_chats AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY base_id ORDER BY updated DESC) AS rn FROM chat @@ -7,45 +14,53 @@ WITH ranked_chats AS ( OR chat.end_user_url LIKE ANY(ARRAY[:urls]::TEXT[]) ) AND customer_support_id NOT IN ('', 'chatbot') AND STATUS = 'ENDED' - AND feedback_rating IS NOT NULL + AND CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN feedback_rating_five IS NOT NULL + ELSE feedback_rating IS NOT NULL + END AND created::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz - AND customer_support_id NOT IN (:excluded_csas) - AND EXISTS ( - SELECT 1 - FROM message - WHERE message.chat_base_id = chat.base_id - AND message.author_role = 'end-user' - ) - ), - chat_csas AS ( -SELECT base_id, - created, - customer_support_id, - customer_support_display_name, - feedback_rating -FROM ranked_chats -WHERE rn = 1 - ), - point_nps_by_csa AS ( -SELECT date_trunc(:metric, created)::text AS date_time, - customer_support_id, - TRIM(customer_support_display_name) AS customer_support_display_name, - COALESCE(CAST((( - SUM(CASE WHEN feedback_rating BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - - SUM(CASE WHEN feedback_rating BETWEEN 0 AND 6 THEN 1 ELSE 0 END) - ) / COUNT(base_id) * 100) AS int), 0) AS nps -FROM chat_csas -GROUP BY date_time, customer_support_id, customer_support_display_name - ), - period_nps_by_csa AS ( -SELECT customer_support_id, - TRIM(customer_support_display_name) AS customer_support_display_name, - MAX(CONCAT("user".first_name, ' ', "user".last_name)) AS customer_support_full_name, - COALESCE(CAST((( - SUM(CASE WHEN feedback_rating BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - - SUM(CASE WHEN feedback_rating BETWEEN 0 AND 6 THEN 1 ELSE 0 END) - ) / COUNT(base_id) * 100) AS int), 0) AS period_nps -FROM chat_csas + AND customer_support_id NOT IN (:excluded_csas) + AND EXISTS ( + SELECT 1 + FROM message + WHERE message.chat_base_id = chat.base_id + AND message.author_role = 'end-user' + ) +), +chat_csas AS ( + SELECT base_id, + created, + customer_support_id, + customer_support_display_name, + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN feedback_rating_five + ELSE feedback_rating + END AS feedback_rating_dynamic + FROM ranked_chats + WHERE rn = 1 +), +point_nps_by_csa AS ( + SELECT date_trunc(:metric, created)::text AS date_time, + customer_support_id, + TRIM(customer_support_display_name) AS customer_support_display_name, + COALESCE(CAST((( + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 0 AND 6 THEN 1 ELSE 0 END) + ) / COUNT(base_id) * 100) AS int), 0) AS nps + FROM chat_csas + GROUP BY date_time, customer_support_id, customer_support_display_name +), +period_nps_by_csa AS ( + SELECT customer_support_id, + TRIM(customer_support_display_name) AS customer_support_display_name, + MAX(CONCAT("user".first_name, ' ', "user".last_name)) AS customer_support_full_name, + COALESCE(CAST((( + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 9 AND 10 THEN 1 ELSE 0 END) * 1.0 - + SUM(CASE WHEN feedback_rating_dynamic BETWEEN 0 AND 6 THEN 1 ELSE 0 END) + ) / COUNT(base_id) * 100) AS int), 0) AS period_nps + FROM chat_csas LEFT JOIN "user" ON "user".id_code = chat_csas.customer_support_id GROUP BY customer_support_id, customer_support_display_name ) diff --git a/DSL/Resql/analytics/POST/get-chat-by-id.sql b/DSL/Resql/analytics/POST/get-chat-by-id.sql index e6fbbd8a..0b64b158 100644 --- a/DSL/Resql/analytics/POST/get-chat-by-id.sql +++ b/DSL/Resql/analytics/POST/get-chat-by-id.sql @@ -1,50 +1,23 @@ -WITH MaxChatHistoryComments AS ( +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +), +MaxChatHistoryComments AS ( SELECT MAX(id) AS maxId FROM chat_history_comments WHERE chat_id = :id ), - ChatHistoryComments AS ( - SELECT - chc.comment, - chc.chat_id - FROM chat_history_comments chc - JOIN MaxChatHistoryComments m ON chc.id = m.maxId - ) -SELECT - c.base_id AS id, - c.customer_support_id, - c.customer_support_display_name, - c.end_user_id, - c.end_user_first_name, - c.end_user_last_name, - c.status, - c.feedback_text, - c.feedback_rating, - c.end_user_email, - c.end_user_phone, - c.end_user_os, - c.end_user_url, - c.created, - c.updated, - c.ended, - c.external_id, - c.received_from, - c.received_from_name, - c.forwarded_to_name, - c.forwarded_to, - (CASE - WHEN (SELECT value - FROM configuration - WHERE key = 'is_csa_title_visible' - AND configuration.id IN (SELECT MAX(id) FROM configuration GROUP BY key) - AND deleted = false) = 'true' - THEN c.csa_title - ELSE '' -END) AS csa_title, - chc.comment AS comment, -- ✅ latest comment added - m.content AS last_message, - m.updated AS last_message_timestamp -FROM ( +ChatHistoryComments AS ( + SELECT + chc.comment, + chc.chat_id + FROM chat_history_comments chc + JOIN MaxChatHistoryComments m ON chc.id = m.maxId +), +latest_chat AS ( SELECT base_id, customer_support_id, @@ -55,6 +28,7 @@ FROM ( status, feedback_text, feedback_rating, + feedback_rating_five, end_user_email, end_user_phone, end_user_os, @@ -72,8 +46,51 @@ FROM ( WHERE base_id = :id ORDER BY updated DESC LIMIT 1 -) AS c +), +csa_title_config AS ( + SELECT value + FROM configuration + WHERE key = 'is_csa_title_visible' + AND id IN (SELECT MAX(id) FROM configuration WHERE key = 'is_csa_title_visible' GROUP BY key) + AND deleted = false +) +SELECT + c.base_id AS id, + c.customer_support_id, + c.customer_support_display_name, + c.end_user_id, + c.end_user_first_name, + c.end_user_last_name, + c.status, + c.feedback_text, + CASE + WHEN rc.is_five_rating_scale = 'true' + THEN c.feedback_rating_five + ELSE c.feedback_rating + END AS feedback_rating, + c.end_user_email, + c.end_user_phone, + c.end_user_os, + c.end_user_url, + c.created, + c.updated, + c.ended, + c.external_id, + c.received_from, + c.received_from_name, + c.forwarded_to_name, + c.forwarded_to, + (CASE + WHEN (SELECT COALESCE(value, 'false') FROM csa_title_config) = 'true' + THEN c.csa_title + ELSE '' + END) AS csa_title, + chc.comment AS comment, + m.content AS last_message, + m.updated AS last_message_timestamp +FROM latest_chat c +CROSS JOIN rating_config rc JOIN message AS m ON c.base_id = m.chat_base_id LEFT JOIN ChatHistoryComments chc ON c.base_id = chc.chat_id ORDER BY m.updated DESC -LIMIT 1; \ No newline at end of file +LIMIT 1; diff --git a/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql b/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql index 924d3bc1..ef18f247 100644 --- a/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql +++ b/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql @@ -1,99 +1,197 @@ -WITH MaxChatHistoryComments AS ( +WITH rating_config AS ( + SELECT value AS is_five_rating_scale + FROM configuration + WHERE key = 'isFiveRatingScale' + AND id IN (SELECT max(id) FROM configuration WHERE key = 'isFiveRatingScale' GROUP BY key) + AND NOT deleted +), +MaxChatHistoryComments AS ( SELECT MAX(id) AS maxId FROM chat_history_comments GROUP BY chat_id ), - ChatUser AS ( - SELECT DISTINCT ON (id_code) - id_code, - display_name, - first_name, - last_name -FROM "user" -ORDER BY id_code, id DESC - ), - ChatHistoryComments AS ( -SELECT - comment, - chat_id, - created, - author_display_name -FROM chat_history_comments +ChatUser AS ( + SELECT DISTINCT ON (id_code) + id_code, + display_name, + first_name, + last_name + FROM "user" + ORDER BY id_code, id DESC +), +ChatHistoryComments AS ( + SELECT + comment, + chat_id, + created, + author_display_name + FROM chat_history_comments JOIN MaxChatHistoryComments ON id = maxId - ), - MessageWithContent AS ( -SELECT - MAX(m.id) AS maxId, - MIN(m.id) AS minId, - m.chat_base_id -FROM message m -WHERE content <> '' - AND content <> 'message-read' -GROUP BY chat_base_id - ), - FirstContentMessage AS ( -SELECT m.created, m.chat_base_id -FROM message m +), +MessageWithContent AS ( + SELECT + MAX(m.id) AS maxId, + MIN(m.id) AS minId, + m.chat_base_id + FROM message m + WHERE content <> '' + AND content <> 'message-read' + GROUP BY chat_base_id +), +FirstContentMessage AS ( + SELECT m.created, m.chat_base_id + FROM message m JOIN MessageWithContent ON m.id = MessageWithContent.minId - ), - LastContentMessage AS ( -SELECT m.content, m.chat_base_id -FROM message m +), +LastContentMessage AS ( + SELECT m.content, m.chat_base_id + FROM message m JOIN MessageWithContent ON m.id = MessageWithContent.maxId - ), - TitleVisibility AS ( -SELECT value -FROM configuration -WHERE key = 'is_csa_title_visible' - AND NOT deleted -ORDER BY id DESC +), +TitleVisibility AS ( + SELECT value + FROM configuration + WHERE key = 'is_csa_title_visible' + AND NOT deleted + ORDER BY id DESC LIMIT 1 - ), - FulfilledMessages AS ( -SELECT MAX(m.id) AS maxId, m.chat_base_id -FROM message m -WHERE event = 'contact-information-fulfilled' -GROUP BY chat_base_id - ), - ContactsMessage AS ( -SELECT m.chat_base_id, m.content -FROM message m +), +FulfilledMessages AS ( + SELECT MAX(m.id) AS maxId, m.chat_base_id + FROM message m + WHERE event = 'contact-information-fulfilled' + GROUP BY chat_base_id +), +ContactsMessage AS ( + SELECT m.chat_base_id, m.content + FROM message m JOIN FulfilledMessages ON m.id = maxId - ), - MaxMessages AS ( -SELECT MAX(m.id) AS maxId, m.chat_base_id -FROM message m -GROUP BY chat_base_id - ), - Messages AS ( -SELECT m.event, m.updated, m.chat_base_id, m.author_id -FROM message m +), +MaxMessages AS ( + SELECT MAX(m.id) AS maxId, m.chat_base_id + FROM message m + GROUP BY chat_base_id +), +Messages AS ( + SELECT m.event, m.updated, m.chat_base_id, m.author_id + FROM message m JOIN MaxMessages ON id = maxId - ), - MaxChats AS ( -SELECT MAX(c.id) AS maxId, c.base_id -FROM chat c -WHERE ended IS NOT NULL - AND status = 'ENDED' - AND ( - array_length(ARRAY[:urls]::TEXT[], 1) IS NULL - OR c.end_user_url LIKE ANY(ARRAY[:urls]::TEXT[]) - ) - AND ( - :showTest = TRUE - OR c.test = FALSE - ) - AND c.ended::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz - AND c.feedback_rating IS NOT NULL - AND c.feedback_rating <= 5 -GROUP BY base_id - ), - EndedChatMessages AS ( -SELECT - c.base_id, +), +MaxChats AS ( + SELECT MAX(c.id) AS maxId, c.base_id + FROM chat c + WHERE ended IS NOT NULL + AND status = 'ENDED' + AND ( + array_length(ARRAY[:urls]::TEXT[], 1) IS NULL + OR c.end_user_url LIKE ANY(ARRAY[:urls]::TEXT[]) + ) + AND ( + :showTest = TRUE + OR c.test = FALSE + ) + AND c.ended::timestamptz BETWEEN :start::timestamptz AND :end::timestamptz + AND CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN c.feedback_rating_five IS NOT NULL AND c.feedback_rating_five <= 5 + ELSE c.feedback_rating IS NOT NULL AND c.feedback_rating <= 5 + END + GROUP BY base_id +), +EndedChatMessages AS ( + SELECT + c.base_id, + c.customer_support_id, + c.customer_support_display_name, + c.csa_title, + c.end_user_id, + c.end_user_first_name, + c.end_user_last_name, + c.end_user_email, + c.end_user_phone, + c.end_user_os, + c.end_user_url, + c.status, + c.updated, + c.ended, + c.forwarded_to_name, + c.received_from, + c.labels, + c.created, + c.feedback_text, + c.feedback_rating, + c.feedback_rating_five + FROM chat c + RIGHT JOIN MaxChats ON c.id = maxId +), +RatedChats AS ( + SELECT + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN MAX(c.feedback_rating_five) + ELSE MAX(c.feedback_rating) + END AS rating + FROM chat c + WHERE CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN c.feedback_rating_five IS NOT NULL + ELSE c.feedback_rating IS NOT NULL + END + GROUP BY base_id +), +RatedChatsCount AS ( + SELECT COUNT(rating) AS total FROM RatedChats +), +Promoters AS ( + SELECT COUNT(rating) AS p FROM RatedChats WHERE rating >= 9 +), +Detractors AS ( + SELECT COUNT(rating) AS d FROM RatedChats WHERE rating <= 6 +), +NPS AS ( + SELECT ROUND(((p / (GREATEST(total, 1) * 1.0)) - (d / (GREATEST(total, 1) * 1.0))) * 100.0, 2) AS nps + FROM RatedChatsCount + CROSS JOIN Promoters + CROSS JOIN Detractors +), +LatestOpenChat AS ( + SELECT DISTINCT ON (base_id) + base_id, + customer_support_id AS latest_open_csa + FROM chat + WHERE status = 'OPEN' + ORDER BY base_id, id DESC +), +CSAFullNames AS ( + SELECT + c2.base_id, + ARRAY_AGG(DISTINCT TRIM( + CASE + WHEN c2.customer_support_id = :csaId THEN c2.customer_support_display_name + ELSE COALESCE(NULLIF(TRIM(cu.first_name || ' ' || cu.last_name), ''), cu.display_name) + END + )) FILTER ( + WHERE NOT ( + c2.customer_support_id = :csaId + AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> :csaId) + ) + ) AS all_csa_names, + ARRAY_AGG(DISTINCT c2.customer_support_id) FILTER ( + WHERE NOT ( + c2.customer_support_id = :csaId + AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> :csaId) + ) + ) AS all_csa_ids + FROM chat c2 + LEFT JOIN ChatUser cu ON cu.id_code = c2.customer_support_id + LEFT JOIN LatestOpenChat lo ON lo.base_id = c2.base_id + GROUP BY c2.base_id +) +SELECT + c.base_id AS id, c.customer_support_id, c.customer_support_display_name, - c.csa_title, + (CASE WHEN TitleVisibility.value = 'true' THEN c.csa_title ELSE '' END) AS csa_title, c.end_user_id, c.end_user_first_name, c.end_user_last_name, @@ -102,144 +200,72 @@ SELECT c.end_user_os, c.end_user_url, c.status, + FirstContentMessage.created, c.updated, c.ended, c.forwarded_to_name, c.received_from, c.labels, - c.created, + s.comment, + s.created as comment_added_date, + s.author_display_name as comment_author, + mu.display_name AS user_display_name, + cu.first_name AS customer_support_first_name, + cu.last_name AS customer_support_last_name, + LastContentMessage.content AS last_message, + (CASE WHEN m.event = '' THEN NULL ELSE LOWER(m.event) END) AS last_message_event, + ContactsMessage.content AS contacts_message, + m.updated AS last_message_timestamp, c.feedback_text, - c.feedback_rating -FROM chat c - RIGHT JOIN MaxChats ON c.id = maxId - ), - RatedChats AS ( -SELECT MAX(c.feedback_rating) AS rating -FROM chat c -WHERE feedback_rating IS NOT NULL -GROUP BY base_id - ), - RatedChatsCount AS ( -SELECT COUNT(rating) AS total FROM RatedChats - ), - Promoters AS ( -SELECT COUNT(rating) AS p FROM RatedChats WHERE rating >= 9 - ), - Detractors AS ( -SELECT COUNT(rating) AS d FROM RatedChats WHERE rating <= 6 - ), - NPS AS ( -SELECT ROUND(((p / (GREATEST(total, 1) * 1.0)) - (d / (GREATEST(total, 1) * 1.0))) * 100.0, 2) AS nps -FROM RatedChatsCount - CROSS JOIN Promoters - CROSS JOIN Detractors - ), - LatestOpenChat AS ( -SELECT DISTINCT ON (base_id) - base_id, - customer_support_id AS latest_open_csa -FROM chat -WHERE status = 'OPEN' -ORDER BY base_id, id DESC - ), - CSAFullNames AS ( -SELECT - c2.base_id, - ARRAY_AGG(DISTINCT TRIM( - CASE - WHEN c2.customer_support_id = :csaId THEN c2.customer_support_display_name - ELSE COALESCE(NULLIF(TRIM(cu.first_name || ' ' || cu.last_name), ''), cu.display_name) - END - )) FILTER ( - WHERE NOT ( - c2.customer_support_id = :csaId - AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> :csaId) - ) - ) AS all_csa_names, - ARRAY_AGG(DISTINCT c2.customer_support_id) FILTER ( - WHERE NOT ( - c2.customer_support_id = :csaId - AND (lo.latest_open_csa IS NULL OR lo.latest_open_csa <> :csaId) - ) - ) AS all_csa_ids -FROM chat c2 - LEFT JOIN ChatUser cu ON cu.id_code = c2.customer_support_id - LEFT JOIN LatestOpenChat lo ON lo.base_id = c2.base_id -GROUP BY c2.base_id - ) -SELECT c.base_id AS id, - c.customer_support_id, - c.customer_support_display_name, - (CASE WHEN TitleVisibility.value = 'true' THEN c.csa_title ELSE '' END) AS csa_title, - c.end_user_id, - c.end_user_first_name, - c.end_user_last_name, - c.end_user_email, - c.end_user_phone, - c.end_user_os, - c.end_user_url, - c.status, - FirstContentMessage.created, - c.updated, - c.ended, - c.forwarded_to_name, - c.received_from, - c.labels, - s.comment, - s.created as comment_added_date, - s.author_display_name as comment_author, - mu.display_name AS user_display_name, - cu.first_name AS customer_support_first_name, - cu.last_name AS customer_support_last_name, - LastContentMessage.content AS last_message, - (CASE WHEN m.event = '' THEN NULL ELSE LOWER(m.event) END) AS last_message_event, - ContactsMessage.content AS contacts_message, - m.updated AS last_message_timestamp, - c.feedback_text, - c.feedback_rating, - nps, - CSAFullNames.all_csa_names AS all_csa, - CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS total_pages + CASE + WHEN (SELECT COALESCE(is_five_rating_scale, 'false') = 'true' FROM rating_config) + THEN c.feedback_rating_five + ELSE c.feedback_rating + END AS feedback_rating, + nps, + CSAFullNames.all_csa_names AS all_csa, + CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS total_pages FROM EndedChatMessages AS c - JOIN Messages AS m ON c.base_id = m.chat_base_id - LEFT JOIN ChatHistoryComments AS s ON s.chat_id = m.chat_base_id - LEFT JOIN ChatUser AS mu ON mu.id_code = m.author_id - LEFT JOIN ChatUser AS cu ON cu.id_code = c.customer_support_id - JOIN LastContentMessage ON c.base_id = LastContentMessage.chat_base_id - JOIN FirstContentMessage ON c.base_id = FirstContentMessage.chat_base_id - LEFT JOIN ContactsMessage ON ContactsMessage.chat_base_id = c.base_id - LEFT JOIN CSAFullNames ON CSAFullNames.base_id = c.base_id - CROSS JOIN TitleVisibility - CROSS JOIN NPS +JOIN Messages AS m ON c.base_id = m.chat_base_id +LEFT JOIN ChatHistoryComments AS s ON s.chat_id = m.chat_base_id +LEFT JOIN ChatUser AS mu ON mu.id_code = m.author_id +LEFT JOIN ChatUser AS cu ON cu.id_code = c.customer_support_id +JOIN LastContentMessage ON c.base_id = LastContentMessage.chat_base_id +JOIN FirstContentMessage ON c.base_id = FirstContentMessage.chat_base_id +LEFT JOIN ContactsMessage ON ContactsMessage.chat_base_id = c.base_id +LEFT JOIN CSAFullNames ON CSAFullNames.base_id = c.base_id +CROSS JOIN TitleVisibility +CROSS JOIN NPS +CROSS JOIN rating_config rc WHERE ( - ( - COALESCE(:customerSupportIds, '') = '' - OR EXISTS ( - SELECT 1 - FROM unnest(COALESCE(CSAFullNames.all_csa_ids, ARRAY[]::text[])) AS id - WHERE id = ANY(string_to_array(:customerSupportIds, ',')) - ) - OR ('-' = ANY(string_to_array(:customerSupportIds, ',')) AND array_length(CSAFullNames.all_csa_ids, 1) = 1 AND CSAFullNames.all_csa_ids[1] = '') - ) - AND ( - :search IS NULL OR :search = '' - OR LOWER(c.customer_support_display_name) LIKE LOWER('%' || :search || '%') - OR LOWER(c.end_user_first_name) LIKE LOWER('%' || :search || '%') - OR LOWER(ContactsMessage.content) LIKE LOWER('%' || :search || '%') - OR LOWER(s.comment) LIKE LOWER('%' || :search || '%') - OR LOWER(c.status) LIKE LOWER('%' || :search || '%') - OR LOWER(m.event) LIKE LOWER('%' || :search || '%') - OR LOWER(c.base_id) LIKE LOWER('%' || :search || '%') - OR TO_CHAR(FirstContentMessage.created, 'DD.MM.YYYY HH24:MI:SS') LIKE '%' || :search || '%' - OR TO_CHAR(c.ended, 'DD.MM.YYYY HH24:MI:SS') LIKE '%' || :search || '%' - OR EXISTS ( - SELECT 1 - FROM message AS msg - WHERE msg.chat_base_id = c.base_id - AND LOWER(msg.content) LIKE LOWER('%' || :search || '%') - ) - ) - ) + ( + COALESCE(:customerSupportIds, '') = '' + OR EXISTS ( + SELECT 1 + FROM unnest(COALESCE(CSAFullNames.all_csa_ids, ARRAY[]::text[])) AS id + WHERE id = ANY(string_to_array(:customerSupportIds, ',')) + ) + OR ('-' = ANY(string_to_array(:customerSupportIds, ',')) AND array_length(CSAFullNames.all_csa_ids, 1) = 1 AND CSAFullNames.all_csa_ids[1] = '') + ) + AND ( + :search IS NULL OR :search = '' + OR LOWER(c.customer_support_display_name) LIKE LOWER('%' || :search || '%') + OR LOWER(c.end_user_first_name) LIKE LOWER('%' || :search || '%') + OR LOWER(ContactsMessage.content) LIKE LOWER('%' || :search || '%') + OR LOWER(s.comment) LIKE LOWER('%' || :search || '%') + OR LOWER(c.status) LIKE LOWER('%' || :search || '%') + OR LOWER(m.event) LIKE LOWER('%' || :search || '%') + OR LOWER(c.base_id) LIKE LOWER('%' || :search || '%') + OR TO_CHAR(FirstContentMessage.created, 'DD.MM.YYYY HH24:MI:SS') LIKE '%' || :search || '%' + OR TO_CHAR(c.ended, 'DD.MM.YYYY HH24:MI:SS') LIKE '%' || :search || '%' + OR EXISTS ( + SELECT 1 + FROM message AS msg + WHERE msg.chat_base_id = c.base_id + AND LOWER(msg.content) LIKE LOWER('%' || :search || '%') + ) + ) +) ORDER BY CASE WHEN :sorting = 'created asc' THEN FirstContentMessage.created END ASC, CASE WHEN :sorting = 'created desc' THEN FirstContentMessage.created END DESC, @@ -260,21 +286,34 @@ ORDER BY CASE WHEN :sorting = 'labels asc' THEN c.labels END ASC, CASE WHEN :sorting = 'labels desc' THEN c.labels END DESC, CASE WHEN :sorting = 'status asc' THEN - CASE WHEN m.event IS NULL OR m.event = '' THEN NULL ELSE m.event END - END ASC NULLS LAST, + CASE WHEN m.event IS NULL OR m.event = '' THEN NULL ELSE m.event END + END ASC NULLS LAST, CASE WHEN :sorting = 'status desc' THEN - CASE WHEN m.event IS NULL OR m.event = '' THEN NULL ELSE m.event END - END DESC NULLS LAST, - CASE WHEN :sorting = 'feedbackRating desc' THEN c.feedback_rating END DESC NULLS LAST, - CASE WHEN :sorting = 'feedbackRating asc' THEN c.feedback_rating END ASC, + CASE WHEN m.event IS NULL OR m.event = '' THEN NULL ELSE m.event END + END DESC NULLS LAST, + CASE WHEN :sorting = 'feedbackRating desc' THEN + CASE + WHEN rc.is_five_rating_scale = 'true' + THEN c.feedback_rating_five + ELSE c.feedback_rating + END + END DESC NULLS LAST, + CASE WHEN :sorting = 'feedbackRating asc' THEN + CASE + WHEN rc.is_five_rating_scale = 'true' + THEN c.feedback_rating_five + ELSE c.feedback_rating + END + END ASC NULLS LAST, CASE WHEN :sorting = 'customerSupportFullName asc' THEN - COALESCE(NULLIF(array_to_string(CSAFullNames.all_csa_names, ', '), ''), - CASE WHEN c.customer_support_id = 'chatbot' THEN 'Bürokratt' END) - END ASC NULLS LAST, + COALESCE(NULLIF(array_to_string(CSAFullNames.all_csa_names, ', '), ''), + CASE WHEN c.customer_support_id = 'chatbot' THEN 'Bürokratt' END) + END ASC NULLS LAST, CASE WHEN :sorting = 'customerSupportFullName desc' THEN - COALESCE(NULLIF(array_to_string(CSAFullNames.all_csa_names, ', '), ''), - CASE WHEN c.customer_support_id = 'chatbot' THEN 'Bürokratt' END) - END DESC NULLS LAST, + COALESCE(NULLIF(array_to_string(CSAFullNames.all_csa_names, ', '), ''), + CASE WHEN c.customer_support_id = 'chatbot' THEN 'Bürokratt' END) + END DESC NULLS LAST, CASE WHEN :sorting = 'id asc' THEN c.base_id END ASC, CASE WHEN :sorting = 'id desc' THEN c.base_id END DESC OFFSET ((GREATEST(:page, 1) - 1) * :page_size) LIMIT :page_size; + From 9c77a665ad9bc4cb534202db967bf91a07ad1f1c Mon Sep 17 00:00:00 2001 From: 1AhmedYasser <26207361+1AhmedYasser@users.noreply.github.com> Date: Tue, 20 Jan 2026 19:34:41 +0200 Subject: [PATCH 5/6] chore(1714): Added is_five_rating_scale to ended chats --- DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql b/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql index ef18f247..95ae4cd0 100644 --- a/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql +++ b/DSL/Resql/analytics/POST/get-cs-all-ended-chats.sql @@ -222,6 +222,7 @@ SELECT THEN c.feedback_rating_five ELSE c.feedback_rating END AS feedback_rating, + is_five_rating_scale, nps, CSAFullNames.all_csa_names AS all_csa, CEIL(COUNT(*) OVER() / :page_size::DECIMAL) AS total_pages From fa0bf27ef1f29c8b8eaee3df6a0660264da8066c Mon Sep 17 00:00:00 2001 From: 1AhmedYasser <26207361+1AhmedYasser@users.noreply.github.com> Date: Tue, 20 Jan 2026 21:32:21 +0200 Subject: [PATCH 6/6] chore(1714): Bumped package version --- GUI/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GUI/package.json b/GUI/package.json index 06b65f67..6afd4f2e 100644 --- a/GUI/package.json +++ b/GUI/package.json @@ -7,7 +7,7 @@ "@buerokratt-ria/menu": "^0.2.10", "@buerokratt-ria/header": "^0.1.47", "@buerokratt-ria/styles": "^0.0.1", - "@buerokratt-ria/common-gui-components": "^0.0.36", + "@buerokratt-ria/common-gui-components": "^0.0.38", "@fontsource/roboto": "^4.5.8", "@formkit/auto-animate": "^1.0.0-beta.6", "@hookform/resolvers": "^2.9.11",