mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-05 17:05:46 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
9d0da45c09
@ -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();
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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 [
|
||||
{
|
||||
@ -106,7 +106,7 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
|
||||
formatValue: formatLongNumber,
|
||||
},
|
||||
{
|
||||
value: uniqueCount,
|
||||
value: unique_count,
|
||||
label: formatMessage(labels.uniqueCustomers),
|
||||
formatValue: formatLongNumber,
|
||||
},
|
||||
@ -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>
|
||||
|
@ -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(
|
||||
@ -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(
|
||||
@ -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;
|
||||
@ -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
|
||||
@ -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 },
|
||||
);
|
||||
@ -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]);
|
||||
@ -185,7 +252,7 @@ async function clickhouseQuery(
|
||||
sum: number;
|
||||
avg: number;
|
||||
count: number;
|
||||
uniqueCount: number;
|
||||
unique_count: number;
|
||||
}[]
|
||||
>(
|
||||
`
|
||||
@ -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
|
||||
|
@ -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
|
||||
`,
|
||||
|
Loading…
Reference in New Issue
Block a user