mirror of
https://github.com/kremalicious/umami.git
synced 2025-02-06 01:15:42 +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 { id, parameters } = report || {};
|
||||||
const { websiteId, dateRange } = parameters || {};
|
const { websiteId, dateRange } = parameters || {};
|
||||||
const queryEnabled = websiteId && dateRange;
|
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) => {
|
const handleSubmit = (data: any, e: any) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
@ -29,7 +29,7 @@ export function RevenueTable() {
|
|||||||
{row => row.count}
|
{row => row.count}
|
||||||
</GridColumn>
|
</GridColumn>
|
||||||
<GridColumn name="currency" label={formatMessage(labels.uniqueCustomers)} alignment="end">
|
<GridColumn name="currency" label={formatMessage(labels.uniqueCustomers)} alignment="end">
|
||||||
{row => row.uniqueCount}
|
{row => row.unique_count}
|
||||||
</GridColumn>
|
</GridColumn>
|
||||||
</GridTable>
|
</GridTable>
|
||||||
);
|
);
|
||||||
|
@ -87,7 +87,7 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
|
|||||||
const metricData = useMemo(() => {
|
const metricData = useMemo(() => {
|
||||||
if (!data) return [];
|
if (!data) return [];
|
||||||
|
|
||||||
const { sum, avg, count, uniqueCount } = data.total;
|
const { sum, avg, count, unique_count } = data.total;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
@ -106,7 +106,7 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
|
|||||||
formatValue: formatLongNumber,
|
formatValue: formatLongNumber,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: uniqueCount,
|
value: unique_count,
|
||||||
label: formatMessage(labels.uniqueCustomers),
|
label: formatMessage(labels.uniqueCustomers),
|
||||||
formatValue: formatLongNumber,
|
formatValue: formatLongNumber,
|
||||||
},
|
},
|
||||||
@ -121,29 +121,31 @@ export function RevenueView({ isLoading }: RevenueViewProps) {
|
|||||||
return <MetricCard key={label} value={value} label={label} formatValue={formatValue} />;
|
return <MetricCard key={label} value={value} label={label} formatValue={formatValue} />;
|
||||||
})}
|
})}
|
||||||
</MetricsBar>
|
</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 && (
|
{data && (
|
||||||
<GridRow columns="two">
|
<>
|
||||||
<ListTable
|
<BarChart
|
||||||
metric={formatMessage(labels.country)}
|
minDate={dateRange?.startDate}
|
||||||
data={data?.country.map(({ name, value }) => ({
|
maxDate={dateRange?.endDate}
|
||||||
x: name,
|
data={chartData}
|
||||||
y: value,
|
unit={dateRange?.unit}
|
||||||
z: (value / data?.total.sum) * 100,
|
stacked={true}
|
||||||
}))}
|
currency={currency}
|
||||||
renderLabel={renderCountryName}
|
renderXLabel={renderDateLabels(dateRange?.unit, locale)}
|
||||||
|
isLoading={isLoading}
|
||||||
/>
|
/>
|
||||||
<PieChart type="doughnut" data={countryData} />
|
<GridRow columns="two">
|
||||||
</GridRow>
|
<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 />}
|
{showTable && <RevenueTable />}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import clickhouse from 'lib/clickhouse';
|
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';
|
import prisma from 'lib/prisma';
|
||||||
|
|
||||||
export async function getRevenue(
|
export async function getRevenue(
|
||||||
@ -27,50 +27,118 @@ async function relationalQuery(
|
|||||||
endDate: Date;
|
endDate: Date;
|
||||||
unit: string;
|
unit: string;
|
||||||
timezone: string;
|
timezone: string;
|
||||||
|
currency: string;
|
||||||
},
|
},
|
||||||
): Promise<{
|
): Promise<{
|
||||||
chart: { time: string; sum: number; avg: number; count: number; uniqueCount: number }[];
|
chart: { x: string; t: string; y: number }[];
|
||||||
total: { sum: number; avg: number; count: number; uniqueCount: 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 { getDateSQL, rawQuery } = prisma;
|
||||||
|
const db = getDatabaseType();
|
||||||
|
const like = db === POSTGRESQL ? 'ilike' : 'like';
|
||||||
|
|
||||||
const chartRes = await rawQuery(
|
const chartRes = await rawQuery(
|
||||||
`
|
`
|
||||||
select
|
select
|
||||||
${getDateSQL('website_event.created_at', unit, timezone)} time,
|
we.event_name x,
|
||||||
sum(case when data_key = {{revenueProperty}} then number_value else 0 end) sum,
|
${getDateSQL('ed.created_at', unit, timezone)} t,
|
||||||
avg(case when data_key = {{revenueProperty}} then number_value else 0 end) avg,
|
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) y
|
||||||
count(case when data_key = {{revenueProperty}} then 1 else 0 end) count,
|
from event_data ed
|
||||||
count(distinct {{userProperty}}) uniqueCount
|
join website_event we
|
||||||
from event_data
|
on we.event_id = ed.website_event_id
|
||||||
where website_event.website_id = {{websiteId::uuid}}
|
join (select website_event_id
|
||||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
from event_data
|
||||||
and event_name = {{eventType}}
|
where data_key ${like} '%currency%'
|
||||||
and data_key in ({{revenueProperty}} , {{userProperty}})
|
and string_value = {{currency}}) currency
|
||||||
group by 1
|
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(
|
const totalRes = await rawQuery(
|
||||||
`
|
`
|
||||||
select
|
select
|
||||||
sum(case when data_key = {{revenueProperty}} then number_value else 0 end) sum,
|
sum(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as sum,
|
||||||
avg(case when data_key = {{revenueProperty}} then number_value else 0 end) avg,
|
avg(coalesce(cast(number_value as decimal(10,2)), cast(string_value as decimal(10,2)))) as avg,
|
||||||
count(case when data_key = {{revenueProperty}} then 1 else 0 end) count,
|
count(distinct event_id) as count,
|
||||||
count(distinct {{userProperty}}) uniqueCount
|
count(distinct session_id) as unique_count
|
||||||
from event_data
|
from event_data ed
|
||||||
where website_event.website_id = {{websiteId::uuid}}
|
join website_event we
|
||||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
on we.event_id = ed.website_event_id
|
||||||
and event_name = {{eventType}}
|
join (select website_event_id
|
||||||
and data_key in ({{revenueProperty}} , {{userProperty}})
|
from event_data
|
||||||
group by 1
|
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(
|
async function clickhouseQuery(
|
||||||
@ -85,13 +153,13 @@ async function clickhouseQuery(
|
|||||||
): Promise<{
|
): Promise<{
|
||||||
chart: { x: string; t: string; y: number }[];
|
chart: { x: string; t: string; y: number }[];
|
||||||
country: { name: string; value: 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: {
|
table: {
|
||||||
currency: string;
|
currency: string;
|
||||||
sum: number;
|
sum: number;
|
||||||
avg: number;
|
avg: number;
|
||||||
count: number;
|
count: number;
|
||||||
uniqueCount: number;
|
unique_count: number;
|
||||||
}[];
|
}[];
|
||||||
}> {
|
}> {
|
||||||
const { startDate, endDate, timezone = 'UTC', unit = 'day', currency } = criteria;
|
const { startDate, endDate, timezone = 'UTC', unit = 'day', currency } = criteria;
|
||||||
@ -114,7 +182,7 @@ async function clickhouseQuery(
|
|||||||
from event_data
|
from event_data
|
||||||
where positionCaseInsensitive(data_key, 'currency') > 0
|
where positionCaseInsensitive(data_key, 'currency') > 0
|
||||||
and string_value = {currency:String}) currency
|
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}
|
where website_id = {websiteId:UUID}
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
and positionCaseInsensitive(data_key, 'revenue') > 0
|
and positionCaseInsensitive(data_key, 'revenue') > 0
|
||||||
@ -139,17 +207,16 @@ async function clickhouseQuery(
|
|||||||
from event_data
|
from event_data
|
||||||
where positionCaseInsensitive(data_key, 'currency') > 0
|
where positionCaseInsensitive(data_key, 'currency') > 0
|
||||||
and string_value = {currency:String}) c
|
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
|
join (select distinct website_id, session_id, country
|
||||||
from website_event_stats_hourly
|
from website_event_stats_hourly
|
||||||
where website_id = {websiteId:UUID}) s
|
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
|
and ed.session_id = s.session_id
|
||||||
where ed.website_id = {websiteId:UUID}
|
where ed.website_id = {websiteId:UUID}
|
||||||
and ed.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and ed.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
and positionCaseInsensitive(ed.data_key, 'revenue') > 0
|
and positionCaseInsensitive(ed.data_key, 'revenue') > 0
|
||||||
group by s.country
|
group by s.country
|
||||||
|
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, currency },
|
{ websiteId, startDate, endDate, currency },
|
||||||
);
|
);
|
||||||
@ -158,23 +225,23 @@ async function clickhouseQuery(
|
|||||||
sum: number;
|
sum: number;
|
||||||
avg: number;
|
avg: number;
|
||||||
count: number;
|
count: number;
|
||||||
uniqueCount: number;
|
unique_count: number;
|
||||||
}>(
|
}>(
|
||||||
`
|
`
|
||||||
select
|
select
|
||||||
sum(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as sum,
|
sum(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as sum,
|
||||||
avg(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as avg,
|
avg(coalesce(toDecimal64(number_value, 2), toDecimal64(string_value, 2))) as avg,
|
||||||
uniqExact(event_id) as count,
|
uniqExact(event_id) as count,
|
||||||
uniqExact(session_id) as uniqueCount
|
uniqExact(session_id) as unique_count
|
||||||
from event_data
|
from event_data
|
||||||
join (select event_id
|
join (select event_id
|
||||||
from event_data
|
from event_data
|
||||||
where positionCaseInsensitive(data_key, 'currency') > 0
|
where positionCaseInsensitive(data_key, 'currency') > 0
|
||||||
and string_value = {currency:String}) currency
|
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}
|
where website_id = {websiteId:UUID}
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
and positionCaseInsensitive(data_key, 'revenue') > 0
|
and positionCaseInsensitive(data_key, 'revenue') > 0
|
||||||
`,
|
`,
|
||||||
{ websiteId, startDate, endDate, currency },
|
{ websiteId, startDate, endDate, currency },
|
||||||
).then(result => result?.[0]);
|
).then(result => result?.[0]);
|
||||||
@ -185,7 +252,7 @@ async function clickhouseQuery(
|
|||||||
sum: number;
|
sum: number;
|
||||||
avg: number;
|
avg: number;
|
||||||
count: 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,
|
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,
|
avg(coalesce(toDecimal64(ed.number_value, 2), toDecimal64(ed.string_value, 2))) as avg,
|
||||||
uniqExact(ed.event_id) as count,
|
uniqExact(ed.event_id) as count,
|
||||||
uniqExact(ed.session_id) as uniqueCount
|
uniqExact(ed.session_id) as unique_count
|
||||||
from event_data ed
|
from event_data ed
|
||||||
join (select event_id, string_value as currency
|
join (select event_id, string_value as currency
|
||||||
from event_data
|
from event_data
|
||||||
where positionCaseInsensitive(data_key, 'currency') > 0) c
|
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}
|
where website_id = {websiteId:UUID}
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||||
and positionCaseInsensitive(data_key, 'revenue') > 0
|
and positionCaseInsensitive(data_key, 'revenue') > 0
|
||||||
|
@ -34,8 +34,8 @@ async function relationalQuery(
|
|||||||
`
|
`
|
||||||
select distinct string_value as currency
|
select distinct string_value as currency
|
||||||
from event_data
|
from event_data
|
||||||
where website_id = {websiteId:UUID}
|
where website_id = {{websiteId::uuid}}
|
||||||
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
and created_at between {{startDate}} and {{endDate}}
|
||||||
and data_key ${like} '%currency%'
|
and data_key ${like} '%currency%'
|
||||||
order by currency
|
order by currency
|
||||||
`,
|
`,
|
||||||
|
Loading…
Reference in New Issue
Block a user