Skip to content

Commit

Permalink
Fix revenue report bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
franciscao633 committed Oct 9, 2024
1 parent 7de52d6 commit 1a2ae43
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 70 deletions.
6 changes: 5 additions & 1 deletion src/app/(main)/reports/revenue/RevenueParameters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ export function RevenueParameters() {
const { id, parameters } = report || {};
const { websiteId, dateRange } = parameters || {};
const queryEnabled = websiteId && dateRange;
const { data: values = [] } = useRevenueValues(websiteId, dateRange.startDate, dateRange.endDate);
const { data: values = [] } = useRevenueValues(
websiteId,
dateRange?.startDate,
dateRange?.endDate,
);

const handleSubmit = (data: any, e: any) => {
e.stopPropagation();
Expand Down
2 changes: 1 addition & 1 deletion src/app/(main)/reports/revenue/RevenueTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export function RevenueTable() {
{row => row.count}
</GridColumn>
<GridColumn name="currency" label={formatMessage(labels.uniqueCustomers)} alignment="end">
{row => row.uniqueCount}
{row => row.unique_count}
</GridColumn>
</GridTable>
);
Expand Down
48 changes: 25 additions & 23 deletions src/app/(main)/reports/revenue/RevenueView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
const metricData = useMemo(() => {
if (!data) return [];

const { sum, avg, count, uniqueCount } = data.total;
const { sum, avg, count, unique_count } = data.total;

return [
{
Expand All @@ -106,7 +106,7 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
formatValue: formatLongNumber,
},
{
value: uniqueCount,
value: unique_count,
label: formatMessage(labels.uniqueCustomers),
formatValue: formatLongNumber,
},
Expand All @@ -121,29 +121,31 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
return <MetricCard key={label} value={value} label={label} formatValue={formatValue} />;
})}
</MetricsBar>
<BarChart
minDate={dateRange?.startDate}
maxDate={dateRange?.endDate}
data={chartData}
unit={dateRange?.unit}
stacked={true}
currency={currency}
renderXLabel={renderDateLabels(dateRange?.unit, locale)}
isLoading={isLoading}
/>
{data && (
<GridRow columns="two">
<ListTable
metric={formatMessage(labels.country)}
data={data?.country.map(({ name, value }) => ({
x: name,
y: value,
z: (value / data?.total.sum) * 100,
}))}
renderLabel={renderCountryName}
<>
<BarChart
minDate={dateRange?.startDate}
maxDate={dateRange?.endDate}
data={chartData}
unit={dateRange?.unit}
stacked={true}
currency={currency}
renderXLabel={renderDateLabels(dateRange?.unit, locale)}
isLoading={isLoading}
/>
<PieChart type="doughnut" data={countryData} />
</GridRow>
<GridRow columns="two">
<ListTable
metric={formatMessage(labels.country)}
data={data?.country.map(({ name, value }) => ({
x: name,
y: Number(value),
z: (value / data?.total.sum) * 100,
}))}
renderLabel={renderCountryName}
/>
<PieChart type="doughnut" data={countryData} />
</GridRow>
</>
)}
{showTable && <RevenueTable />}
</div>
Expand Down
153 changes: 110 additions & 43 deletions src/queries/analytics/reports/getRevenue.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import { CLICKHOUSE, getDatabaseType, POSTGRESQL, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';

export async function getRevenue(
Expand Down Expand Up @@ -27,50 +27,118 @@ async function relationalQuery(
endDate: Date;
unit: string;
timezone: string;
currency: string;
},
): Promise<{
chart: { time: string; sum: number; avg: number; count: number; uniqueCount: number }[];
total: { sum: number; avg: number; count: number; uniqueCount: number };
chart: { x: string; t: string; y: number }[];
country: { name: string; value: number }[];
total: { sum: number; avg: number; count: number; unique_count: number };
table: {
currency: string;
sum: number;
avg: number;
count: number;
unique_count: number;
}[];
}> {
const { startDate, endDate, timezone = 'UTC', unit = 'day' } = criteria;
const { startDate, endDate, timezone = 'UTC', unit = 'day', currency } = criteria;
const { getDateSQL, rawQuery } = prisma;
const db = getDatabaseType();
const like = db === POSTGRESQL ? 'ilike' : 'like';

const chartRes = await rawQuery(
`
select
${getDateSQL('website_event.created_at', unit, timezone)} time,
sum(case when data_key = {{revenueProperty}} then number_value else 0 end) sum,
avg(case when data_key = {{revenueProperty}} then number_value else 0 end) avg,
count(case when data_key = {{revenueProperty}} then 1 else 0 end) count,
count(distinct {{userProperty}}) uniqueCount
from event_data
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and event_name = {{eventType}}
and data_key in ({{revenueProperty}} , {{userProperty}})
group by 1
we.event_name x,
${getDateSQL('ed.created_at', unit, timezone)} t,
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) y
from event_data ed
join website_event we
on we.event_id = ed.website_event_id
join (select website_event_id
from event_data
where data_key ${like} '%currency%'
and string_value = {{currency}}) currency
on currency.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
group by x, t
order by t
`,
{ websiteId, startDate, endDate },
{ websiteId, startDate, endDate, unit, timezone, currency },
);

const countryRes = await rawQuery(
`
select
s.country as name,
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) value
from event_data ed
join website_event we
on we.event_id = ed.website_event_id
join session s
on s.session_id = we.session_id
join (select website_event_id
from event_data
where data_key ${like} '%currency%'
and string_value = 'USD') currency
on currency.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
group by s.country
`,
{ websiteId, startDate, endDate, currency },
);

const totalRes = await rawQuery(
`
select
sum(case when data_key = {{revenueProperty}} then number_value else 0 end) sum,
avg(case when data_key = {{revenueProperty}} then number_value else 0 end) avg,
count(case when data_key = {{revenueProperty}} then 1 else 0 end) count,
count(distinct {{userProperty}}) uniqueCount
from event_data
where website_event.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and event_name = {{eventType}}
and data_key in ({{revenueProperty}} , {{userProperty}})
group by 1
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as sum,
avg(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as avg,
count(distinct event_id) as count,
count(distinct session_id) as unique_count
from event_data ed
join website_event we
on we.event_id = ed.website_event_id
join (select website_event_id
from event_data
where data_key ${like} '%currency%'
and string_value = 'USD') currency
on currency.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
`,
{ websiteId, startDate, endDate, currency },
).then(result => result?.[0]);

const tableRes = await rawQuery(
`
select
c.currency,
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as sum,
avg(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as avg,
count(distinct ed.website_event_id) as count,
count(distinct we.session_id) as unique_count
from event_data ed
join website_event we
on we.event_id = ed.website_event_id
join (select website_event_id, string_value as currency
from event_data
where data_key ${like} '%currency%') c
on c.website_event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and ed.data_key ${like} '%revenue%'
group by c.currency
order by sum desc;
`,
{ websiteId, startDate, endDate },
{ websiteId, startDate, endDate, unit, timezone, currency },
);

return { chart: chartRes, total: totalRes };
return { chart: chartRes, country: countryRes, total: totalRes, table: tableRes };
}

async function clickhouseQuery(
Expand All @@ -85,13 +153,13 @@ async function clickhouseQuery(
): Promise<{
chart: { x: string; t: string; y: number }[];
country: { name: string; value: number }[];
total: { sum: number; avg: number; count: number; uniqueCount: number };
total: { sum: number; avg: number; count: number; unique_count: number };
table: {
currency: string;
sum: number;
avg: number;
count: number;
uniqueCount: number;
unique_count: number;
}[];
}> {
const { startDate, endDate, timezone = 'UTC', unit = 'day', currency } = criteria;
Expand All @@ -114,7 +182,7 @@ async function clickhouseQuery(
from event_data
where positionCaseInsensitive(data_key, 'currency') > 0
and string_value = {currency:String}) currency
on currency.event_id = event_data.event_id
on currency.event_id = event_data.event_id
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'revenue') > 0
Expand All @@ -139,17 +207,16 @@ async function clickhouseQuery(
from event_data
where positionCaseInsensitive(data_key, 'currency') > 0
and string_value = {currency:String}) c
on c.event_id = ed.event_id
on c.event_id = ed.event_id
join (select distinct website_id, session_id, country
from website_event_stats_hourly
where website_id = {websiteId:UUID}) s
on ed.website_id = s.website_id
on ed.website_id = s.website_id
and ed.session_id = s.session_id
where ed.website_id = {websiteId:UUID}
and ed.created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(ed.data_key, 'revenue') > 0
group by s.country
`,
{ websiteId, startDate, endDate, currency },
);
Expand All @@ -158,23 +225,23 @@ async function clickhouseQuery(
sum: number;
avg: number;
count: number;
uniqueCount: number;
unique_count: number;
}>(
`
select
sum(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as sum,
avg(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as avg,
uniqExact(event_id) as count,
uniqExact(session_id) as uniqueCount
uniqExact(session_id) as unique_count
from event_data
join (select event_id
from event_data
where positionCaseInsensitive(data_key, 'currency') > 0
and string_value = {currency:String}) currency
on currency.event_id = event_data.event_id
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'revenue') > 0
on currency.event_id = event_data.event_id
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'revenue') > 0
`,
{ websiteId, startDate, endDate, currency },
).then(result => result?.[0]);
Expand All @@ -185,7 +252,7 @@ async function clickhouseQuery(
sum: number;
avg: number;
count: number;
uniqueCount: number;
unique_count: number;
}[]
>(
`
Expand All @@ -194,12 +261,12 @@ async function clickhouseQuery(
sum(coalesce(toDecimal64(ed.number_value, 2), toDecimal64(ed.string_value, 2))) as sum,
avg(coalesce(toDecimal64(ed.number_value, 2), toDecimal64(ed.string_value, 2))) as avg,
uniqExact(ed.event_id) as count,
uniqExact(ed.session_id) as uniqueCount
uniqExact(ed.session_id) as unique_count
from event_data ed
join (select event_id, string_value as currency
from event_data
where positionCaseInsensitive(data_key, 'currency') > 0) c
ON c.event_id = ed.event_id
on c.event_id = ed.event_id
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and positionCaseInsensitive(data_key, 'revenue') > 0
Expand Down
4 changes: 2 additions & 2 deletions src/queries/analytics/reports/getRevenueValues.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ async function relationalQuery(
`
select distinct string_value as currency
from event_data
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
where website_id = {{websiteId::uuid}}
and created_at between {{startDate}} and {{endDate}}
and data_key ${like} '%currency%'
order by currency
`,
Expand Down

0 comments on commit 1a2ae43

Please sign in to comment.