diff --git a/src/queries/sql/reports/getRevenueChart.ts b/src/queries/sql/reports/getRevenueChart.ts index a7c491f2e..d95b42bf2 100644 --- a/src/queries/sql/reports/getRevenueChart.ts +++ b/src/queries/sql/reports/getRevenueChart.ts @@ -1,4 +1,5 @@ import clickhouse from '@/lib/clickhouse'; +import { EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -28,7 +29,7 @@ async function relationalQuery( ) { const { startDate, endDate, unit = 'day', timezone = 'utc', currency } = parameters; const { getDateSQL, rawQuery, parseFilters } = prisma; - const { queryParams, filterQuery, cohortQuery, joinSessionQuery } = parseFilters({ + const { queryParams, filterQuery, cohortQuery, joinSessionQuery, dateQuery } = parseFilters({ ...filters, websiteId, startDate, @@ -36,34 +37,40 @@ async function relationalQuery( currency, }); - const joinQuery = - filterQuery || cohortQuery - ? `join (select * - from website_event - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - and event_type = 2) website_event - on website_event.website_id = revenue.website_id - and website_event.session_id = revenue.session_id - and website_event.event_id = revenue.event_id` - : ''; - const chart = await rawQuery( ` + with + filtered_sessions as ( + select distinct website_event.website_id, website_event.session_id + from website_event + ${cohortQuery} + ${joinSessionQuery} + where website_event.website_id = {{websiteId::uuid}} + and website_event.event_type != ${EVENT_TYPE.performance} + ${dateQuery} + ${filterQuery} + ), + filtered_revenue as ( + select + revenue.event_id, + revenue.event_name, + revenue.created_at, + revenue.revenue + from revenue + join filtered_sessions + on filtered_sessions.website_id = revenue.website_id + and filtered_sessions.session_id = revenue.session_id + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + and upper(revenue.currency) = {{currency}} + ) select - revenue.event_name x, - ${getDateSQL('revenue.created_at', unit, timezone)} t, - sum(revenue.revenue) y, - count(revenue.event_id) count - from revenue - ${joinQuery} - ${cohortQuery} - ${joinSessionQuery} - where revenue.website_id = {{websiteId::uuid}} - and revenue.created_at between {{startDate}} and {{endDate}} - and upper(revenue.currency) = {{currency}} - ${filterQuery} - group by x, t + filtered_revenue.event_name x, + ${getDateSQL('filtered_revenue.created_at', unit, timezone)} t, + sum(filtered_revenue.revenue) y, + count(filtered_revenue.event_id) count + from filtered_revenue + group by x, t order by t `, queryParams, @@ -79,7 +86,7 @@ async function clickhouseQuery( ) { const { startDate, endDate, unit = 'day', timezone = 'utc', currency } = parameters; const { getDateSQL, rawQuery, parseFilters } = clickhouse; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ + const { filterQuery, cohortQuery, dateQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, @@ -87,33 +94,40 @@ async function clickhouseQuery( currency, }); - const joinQuery = filterQuery - ? `any left join ( - select * - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = 2) website_event - on website_event.website_id = website_revenue.website_id - and website_event.session_id = website_revenue.session_id - and website_event.event_id = website_revenue.event_id` - : ''; - const chart = await rawQuery<{ x: string; t: string; y: number; count: number }[]>( ` + with + filtered_sessions as ( + select website_id, session_id + from website_event + ${cohortQuery} + where website_id = {websiteId:UUID} + and event_type != ${EVENT_TYPE.performance} + ${dateQuery} + ${filterQuery} + group by website_id, session_id + ), + filtered_revenue as ( + select + website_revenue.event_id, + website_revenue.event_name, + website_revenue.created_at, + website_revenue.revenue + from website_revenue + any inner join filtered_sessions + on filtered_sessions.website_id = website_revenue.website_id + and filtered_sessions.session_id = website_revenue.session_id + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and upper(website_revenue.currency) = {currency:String} + ) select - website_revenue.event_name x, - ${getDateSQL('website_revenue.created_at', unit, timezone)} t, - sum(website_revenue.revenue) y, - count(website_revenue.event_id) count - from website_revenue - ${joinQuery} - ${cohortQuery} - where website_revenue.website_id = {websiteId:UUID} - and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} - and upper(website_revenue.currency) = {currency:String} - ${filterQuery} - group by x, t + filtered_revenue.event_name x, + ${getDateSQL('filtered_revenue.created_at', unit, timezone)} t, + sum(filtered_revenue.revenue) y, + count(filtered_revenue.event_id) count + from filtered_revenue + group by x, t order by t `, queryParams, diff --git a/src/queries/sql/reports/getRevenueMetrics.ts b/src/queries/sql/reports/getRevenueMetrics.ts index c1a9bcaf9..fd9bf9863 100644 --- a/src/queries/sql/reports/getRevenueMetrics.ts +++ b/src/queries/sql/reports/getRevenueMetrics.ts @@ -1,6 +1,7 @@ import clickhouse from '@/lib/clickhouse'; import { EMAIL_DOMAINS, + EVENT_TYPE, LLM_DOMAINS, PAID_AD_PARAMS, SEARCH_DOMAINS, @@ -44,42 +45,51 @@ async function relationalQuery( ): Promise { const { startDate, endDate, currency } = parameters; const { rawQuery, parseFilters } = prisma; - const { queryParams, filterQuery, cohortQuery, joinSessionQuery } = parseFilters({ + const { queryParams, filterQuery, cohortQuery, joinSessionQuery, dateQuery } = parseFilters({ ...filters, websiteId, startDate, endDate, currency, }); - - const joinQuery = - filterQuery || cohortQuery - ? `join (select * - from website_event - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - and event_type = 2) website_event - on website_event.website_id = revenue.website_id - and website_event.session_id = revenue.session_id - and website_event.event_id = revenue.event_id` - : ''; + const filteredSessionsQuery = ` + filtered_sessions as ( + select distinct website_event.website_id, website_event.session_id + from website_event + ${cohortQuery} + ${joinSessionQuery} + where website_event.website_id = {{websiteId::uuid}} + and website_event.event_type != ${EVENT_TYPE.performance} + ${dateQuery} + ${filterQuery} + ) + `; + const filteredRevenueQuery = ` + filtered_revenue as ( + select revenue.website_id, revenue.session_id, revenue.created_at, revenue.revenue + from revenue + join filtered_sessions + on filtered_sessions.website_id = revenue.website_id + and filtered_sessions.session_id = revenue.session_id + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + and upper(revenue.currency) = {{currency}} + ) + `; if (type === 'country') { return rawQuery( ` + with + ${filteredSessionsQuery}, + ${filteredRevenueQuery} select session.country as "name", - sum(revenue) as "value" - from revenue - ${joinQuery} + sum(filtered_revenue.revenue) as "value" + from filtered_revenue join session - on session.website_id = revenue.website_id - and session.session_id = revenue.session_id - ${cohortQuery} - where revenue.website_id = {{websiteId::uuid}} - and revenue.created_at between {{startDate}} and {{endDate}} - and upper(revenue.currency) = {{currency}} - ${filterQuery} + on session.website_id = filtered_revenue.website_id + and session.session_id = filtered_revenue.session_id group by session.country order by value desc `, @@ -90,20 +100,17 @@ async function relationalQuery( if (type === 'region') { return rawQuery( ` + with + ${filteredSessionsQuery}, + ${filteredRevenueQuery} select session.country, session.region as "name", - sum(revenue.revenue) as "value" - from revenue - ${joinQuery} + sum(filtered_revenue.revenue) as "value" + from filtered_revenue join session - on session.website_id = revenue.website_id - and session.session_id = revenue.session_id - ${cohortQuery} - where revenue.website_id = {{websiteId::uuid}} - and revenue.created_at between {{startDate}} and {{endDate}} - and upper(revenue.currency) = {{currency}} - ${filterQuery} + on session.website_id = filtered_revenue.website_id + and session.session_id = filtered_revenue.session_id group by session.country, session.region order by value desc `, @@ -114,22 +121,23 @@ async function relationalQuery( if (type === 'referrer') { return rawQuery( ` - WITH events AS ( + with + ${filteredSessionsQuery}, + events as ( select revenue.website_id, revenue.session_id, sum(revenue.revenue) as "value" from revenue - ${joinQuery} - ${cohortQuery} - ${joinSessionQuery} + join filtered_sessions + on filtered_sessions.website_id = revenue.website_id + and filtered_sessions.session_id = revenue.session_id where revenue.website_id = {{websiteId::uuid}} and revenue.created_at between {{startDate}} and {{endDate}} and upper(revenue.currency) = {{currency}} - ${filterQuery} group by revenue.website_id, revenue.session_id), - revenue_data AS ( + revenue_data as ( select e.website_id, e.session_id, @@ -165,22 +173,23 @@ async function relationalQuery( return rawQuery( ` - WITH events AS ( + with + ${filteredSessionsQuery}, + events as ( select revenue.website_id, revenue.session_id, sum(revenue.revenue) as "value" from revenue - ${joinQuery} - ${cohortQuery} - ${joinSessionQuery} + join filtered_sessions + on filtered_sessions.website_id = revenue.website_id + and filtered_sessions.session_id = revenue.session_id where revenue.website_id = {{websiteId::uuid}} and revenue.created_at between {{startDate}} and {{endDate}} and upper(revenue.currency) = {{currency}} - ${filterQuery} group by revenue.website_id, revenue.session_id), - revenue_data AS ( + revenue_data as ( select e.website_id, e.session_id, @@ -195,7 +204,7 @@ async function relationalQuery( group by session_id ) we on we.session_id = e.session_id), - revenue_prefix AS ( + revenue_prefix as ( select case when we.utm_medium ilike '%cp%' OR we.utm_medium ilike '%ppc%' OR @@ -253,48 +262,60 @@ async function clickhouseQuery( ): Promise { const { startDate, endDate, currency } = parameters; const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ + const { filterQuery, cohortQuery, dateQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, endDate, currency, }); - - const joinQuery = filterQuery - ? `any left join ( - select * + const filteredSessionsQuery = ` + filtered_sessions as ( + select + website_id, + session_id, + any(country) as country, + any(region) as region from website_event + ${cohortQuery} where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = 2) website_event - on website_event.website_id = website_revenue.website_id - and website_event.session_id = website_revenue.session_id - and website_event.event_id = website_revenue.event_id` - : ''; + and event_type != ${EVENT_TYPE.performance} + ${dateQuery} + ${filterQuery} + group by website_id, session_id + ) + `; + const filteredRevenueQuery = ` + filtered_revenue as ( + select + website_revenue.website_id, + website_revenue.session_id, + website_revenue.created_at, + website_revenue.revenue + from website_revenue + any inner join filtered_sessions + on filtered_sessions.website_id = website_revenue.website_id + and filtered_sessions.session_id = website_revenue.session_id + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and upper(website_revenue.currency) = {currency:String} + ) + `; if (type === 'country') { return rawQuery<{ name: string; value: number }[]>( ` + with + ${filteredSessionsQuery}, + ${filteredRevenueQuery} select - website_event.country as "name", - sum(website_revenue.revenue) as "value" - from website_revenue - any left join ( - select * - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = 2) website_event - on website_event.website_id = website_revenue.website_id - and website_event.session_id = website_revenue.session_id - and website_event.event_id = website_revenue.event_id - ${cohortQuery} - where website_revenue.website_id = {websiteId:UUID} - and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} - and upper(website_revenue.currency) = {currency:String} - ${filterQuery} - group by website_event.country + filtered_sessions.country as "name", + sum(filtered_revenue.revenue) as "value" + from filtered_revenue + any inner join filtered_sessions + on filtered_sessions.website_id = filtered_revenue.website_id + and filtered_sessions.session_id = filtered_revenue.session_id + group by filtered_sessions.country order by value desc `, queryParams, @@ -304,26 +325,18 @@ async function clickhouseQuery( if (type === 'region') { return rawQuery<{ name: string; value: number; country: string }[]>( ` + with + ${filteredSessionsQuery}, + ${filteredRevenueQuery} select - website_event.country, - website_event.region as "name", - sum(website_revenue.revenue) as "value" - from website_revenue - any left join ( - select * - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = 2) website_event - on website_event.website_id = website_revenue.website_id - and website_event.session_id = website_revenue.session_id - and website_event.event_id = website_revenue.event_id - ${cohortQuery} - where website_revenue.website_id = {websiteId:UUID} - and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} - and upper(website_revenue.currency) = {currency:String} - ${filterQuery} - group by 1,2 + filtered_sessions.country, + filtered_sessions.region as "name", + sum(filtered_revenue.revenue) as "value" + from filtered_revenue + any inner join filtered_sessions + on filtered_sessions.website_id = filtered_revenue.website_id + and filtered_sessions.session_id = filtered_revenue.session_id + group by 1, 2 order by value desc `, queryParams, @@ -333,34 +346,39 @@ async function clickhouseQuery( if (type === 'referrer') { return rawQuery<{ name: string; value: number }[]>( ` - WITH events AS ( - select distinct - website_id, - session_id, - sum(revenue) as "value" - from website_revenue - ${joinQuery} - ${cohortQuery} - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and upper(currency) = {currency:String} - ${filterQuery} - group by 1,2), + with + ${filteredSessionsQuery}, + events as ( + select + website_revenue.website_id, + website_revenue.session_id, + sum(website_revenue.revenue) as "value" + from website_revenue + any inner join filtered_sessions + on filtered_sessions.website_id = website_revenue.website_id + and filtered_sessions.session_id = website_revenue.session_id + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and upper(website_revenue.currency) = {currency:String} + group by 1, 2 + ), - revenue AS ( - select + revenue as ( + select e.website_id, e.session_id, e.value, we.min_date as created_at - from events e - join (select session_id, min(created_at) min_date - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - group by 1 - ) we - on we.session_id = e.session_id) + from events e + join ( + select session_id, min(created_at) min_date + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + group by 1 + ) we + on we.session_id = e.session_id + ) select website_event.referrer_domain as "name", @@ -383,37 +401,42 @@ async function clickhouseQuery( return rawQuery<{ name: string; value: number }[]>( ` - WITH events AS ( - select distinct - website_id, - session_id, - sum(revenue) as "value" - from website_revenue - ${joinQuery} - ${cohortQuery} - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and upper(currency) = {currency:String} - ${filterQuery} - group by 1,2), + with + ${filteredSessionsQuery}, + events as ( + select + website_revenue.website_id, + website_revenue.session_id, + sum(website_revenue.revenue) as "value" + from website_revenue + any inner join filtered_sessions + on filtered_sessions.website_id = website_revenue.website_id + and filtered_sessions.session_id = website_revenue.session_id + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and upper(website_revenue.currency) = {currency:String} + group by 1, 2 + ), - revenue AS ( - select - e.website_id, - e.session_id, - e.value, - we.min_date as created_at - from events e - join (select session_id, min(created_at) min_date - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - group by 1 - ) we - on we.session_id = e.session_id), + revenue as ( + select + e.website_id, + e.session_id, + e.value, + we.min_date as created_at + from events e + join ( + select session_id, min(created_at) min_date + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + group by 1 + ) we + on we.session_id = e.session_id + ), - channels AS ( - select + channels as ( + select case when multiSearchAny(lower(utm_medium), ['cp', 'ppc', 'retargeting', 'paid']) != 0 then 'paid' else 'organic' end prefix, case when referrer_domain = '' and url_query = '' then 'direct' @@ -444,16 +467,18 @@ async function clickhouseQuery( when referrer_domain != hostname and referrer_domain != '' then 'referral' else 'Unknown' end AS "name", sum(revenue.value) as "value" - from revenue - any left join ( - select * - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64}) website_event - on website_event.website_id = revenue.website_id - and website_event.session_id = revenue.session_id - and website_event.created_at = revenue.created_at - group by 1, 2) + from revenue + any left join ( + select * + from website_event + where website_id = {websiteId:UUID} + and created_at between {startDate:DateTime64} and {endDate:DateTime64} + ) website_event + on website_event.website_id = revenue.website_id + and website_event.session_id = revenue.session_id + and website_event.created_at = revenue.created_at + group by 1, 2 + ) select name, sum(value) value from channels diff --git a/src/queries/sql/reports/getRevenueStats.ts b/src/queries/sql/reports/getRevenueStats.ts index d3f0dbb46..aebc70031 100644 --- a/src/queries/sql/reports/getRevenueStats.ts +++ b/src/queries/sql/reports/getRevenueStats.ts @@ -1,4 +1,5 @@ import clickhouse from '@/lib/clickhouse'; +import { EVENT_TYPE } from '@/lib/constants'; import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db'; import prisma from '@/lib/prisma'; import type { QueryFilters } from '@/lib/types'; @@ -28,7 +29,7 @@ async function relationalQuery( ): Promise { const { startDate, endDate, currency } = parameters; const { rawQuery, parseFilters } = prisma; - const { queryParams, filterQuery, cohortQuery, joinSessionQuery } = parseFilters({ + const { queryParams, filterQuery, cohortQuery, joinSessionQuery, dateQuery } = parseFilters({ ...filters, websiteId, startDate, @@ -36,37 +37,36 @@ async function relationalQuery( currency, }); - const joinQuery = - filterQuery || cohortQuery - ? `join (select * - from website_event - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}} - and event_type = 2) website_event - on website_event.website_id = revenue.website_id - and website_event.session_id = revenue.session_id - and website_event.event_id = revenue.event_id` - : ''; - const total = await rawQuery( ` + with + filtered_sessions as ( + select distinct website_event.website_id, website_event.session_id + from website_event + ${cohortQuery} + ${joinSessionQuery} + where website_event.website_id = {{websiteId::uuid}} + and website_event.event_type != ${EVENT_TYPE.performance} + ${dateQuery} + ${filterQuery} + ), + filtered_revenue as ( + select revenue.website_id, revenue.session_id, revenue.event_id, revenue.revenue + from revenue + join filtered_sessions + on filtered_sessions.website_id = revenue.website_id + and filtered_sessions.session_id = revenue.session_id + where revenue.website_id = {{websiteId::uuid}} + and revenue.created_at between {{startDate}} and {{endDate}} + and upper(revenue.currency) = {{currency}} + ) select - sum(revenue.revenue) as sum, - count(distinct revenue.event_id) as count, - count(distinct revenue.session_id) as unique_count, - (select count(distinct session_id) - from website_event - where website_id = {{websiteId::uuid}} - and created_at between {{startDate}} and {{endDate}}) as total_sessions - from revenue - ${joinQuery} - ${cohortQuery} - ${joinSessionQuery} - where revenue.website_id = {{websiteId::uuid}} - and revenue.created_at between {{startDate}} and {{endDate}} - and upper(revenue.currency) = {{currency}} - ${filterQuery} - `, + sum(filtered_revenue.revenue) as sum, + count(distinct filtered_revenue.event_id) as count, + count(distinct filtered_revenue.session_id) as unique_count, + (select count(*) from filtered_sessions) as total_sessions + from filtered_revenue + `, queryParams, ).then(result => result?.[0]); @@ -83,7 +83,7 @@ async function clickhouseQuery( ): Promise { const { startDate, endDate, currency } = parameters; const { rawQuery, parseFilters } = clickhouse; - const { filterQuery, cohortQuery, queryParams } = parseFilters({ + const { filterQuery, cohortQuery, dateQuery, queryParams } = parseFilters({ ...filters, websiteId, startDate, @@ -91,18 +91,6 @@ async function clickhouseQuery( currency, }); - const joinQuery = filterQuery - ? `any left join ( - select * - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64} - and event_type = 2) website_event - on website_event.website_id = website_revenue.website_id - and website_event.session_id = website_revenue.session_id - and website_event.event_id = website_revenue.event_id` - : ''; - const total = await rawQuery<{ sum: number; count: number; @@ -110,21 +98,33 @@ async function clickhouseQuery( total_sessions: number; }>( ` + with + filtered_sessions as ( + select website_id, session_id + from website_event + ${cohortQuery} + where website_id = {websiteId:UUID} + and event_type != ${EVENT_TYPE.performance} + ${dateQuery} + ${filterQuery} + group by website_id, session_id + ), + filtered_revenue as ( + select website_revenue.website_id, website_revenue.session_id, website_revenue.event_id, website_revenue.revenue + from website_revenue + any inner join filtered_sessions + on filtered_sessions.website_id = website_revenue.website_id + and filtered_sessions.session_id = website_revenue.session_id + where website_revenue.website_id = {websiteId:UUID} + and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} + and upper(website_revenue.currency) = {currency:String} + ) select - sum(website_revenue.revenue) as sum, - uniqExact(website_revenue.event_id) as count, - uniqExact(website_revenue.session_id) as unique_count, - (select uniqExact(session_id) - from website_event - where website_id = {websiteId:UUID} - and created_at between {startDate:DateTime64} and {endDate:DateTime64}) as total_sessions - from website_revenue - ${joinQuery} - ${cohortQuery} - where website_revenue.website_id = {websiteId:UUID} - and website_revenue.created_at between {startDate:DateTime64} and {endDate:DateTime64} - and upper(website_revenue.currency) = {currency:String} - ${filterQuery} + sum(filtered_revenue.revenue) as sum, + uniqExact(filtered_revenue.event_id) as count, + uniqExact(filtered_revenue.session_id) as unique_count, + (select count() from filtered_sessions) as total_sessions + from filtered_revenue `, queryParams, ).then(result => result?.[0]); diff --git a/src/queries/sql/reports/revenueFilters.test.ts b/src/queries/sql/reports/revenueFilters.test.ts new file mode 100644 index 000000000..c79fbe002 --- /dev/null +++ b/src/queries/sql/reports/revenueFilters.test.ts @@ -0,0 +1,103 @@ +import { beforeEach, expect, test, vi } from 'vitest'; +import { getRevenueChart } from './getRevenueChart'; +import { getRevenueMetrics } from './getRevenueMetrics'; +import { getRevenueStats } from './getRevenueStats'; + +const { rawQueryMock, parseFiltersMock, getDateSQLMock } = vi.hoisted(() => ({ + rawQueryMock: vi.fn(), + parseFiltersMock: vi.fn(), + getDateSQLMock: vi.fn(), +})); + +vi.mock('@/lib/db', () => ({ + CLICKHOUSE: 'clickhouse', + PRISMA: 'prisma', + runQuery: vi.fn((queries: Record unknown>) => queries.prisma()), +})); + +vi.mock('@/lib/prisma', () => ({ + default: { + rawQuery: rawQueryMock, + parseFilters: parseFiltersMock, + getDateSQL: getDateSQLMock, + }, +})); + +vi.mock('@/lib/clickhouse', () => ({ + default: { + rawQuery: vi.fn(), + parseFilters: vi.fn(), + getDateSQL: vi.fn(), + }, +})); + +const parameters = { + startDate: new Date('2026-05-18T00:00:00.000Z'), + endDate: new Date('2026-05-19T00:00:00.000Z'), + currency: 'EUR', + unit: 'day', + timezone: 'utc', +}; + +beforeEach(() => { + rawQueryMock.mockReset(); + parseFiltersMock.mockReset(); + getDateSQLMock.mockReset(); + + parseFiltersMock.mockReturnValue({ + queryParams: {}, + filterQuery: 'and website_event.utm_source = {{utmSource}}', + cohortQuery: '', + joinSessionQuery: '', + dateQuery: 'and created_at between {{startDate}} and {{endDate}}', + }); + + getDateSQLMock.mockReturnValue('bucketed_date'); +}); + +test('getRevenueStats aggregates revenue from filtered sessions', async () => { + rawQueryMock.mockResolvedValue([ + { + sum: 0, + count: 0, + unique_count: 0, + total_sessions: 0, + }, + ]); + + await getRevenueStats('website-1', parameters, {}); + + const [query] = rawQueryMock.mock.calls[0]; + + expect(query).toContain('filtered_sessions as'); + expect(query).toContain('join filtered_sessions'); + expect(query).toContain('(select count(*) from filtered_sessions) as total_sessions'); + expect(query).not.toContain('and website_event.event_id = revenue.event_id'); +}); + +test('getRevenueChart buckets filtered revenue instead of revenue rows joined by event id', async () => { + rawQueryMock.mockResolvedValue([]); + + await getRevenueChart('website-1', parameters, {}); + + const [query] = rawQueryMock.mock.calls[0]; + + expect(query).toContain('filtered_sessions as'); + expect(query).toContain('filtered_revenue as'); + expect(query).toContain('from filtered_revenue'); + expect(query).toContain('bucketed_date'); + expect(query).not.toContain('and website_event.event_id = revenue.event_id'); +}); + +test('getRevenueMetrics uses the filtered session set for screen-load breakdowns', async () => { + rawQueryMock.mockResolvedValue([]); + + await getRevenueMetrics('website-1', parameters, {}, 'country'); + + const [query] = rawQueryMock.mock.calls[0]; + + expect(query).toContain('filtered_sessions as'); + expect(query).toContain('filtered_revenue as'); + expect(query).toContain('sum(filtered_revenue.revenue) as "value"'); + expect(query).not.toContain('and website_event.event_id = revenue.event_id'); +});