Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 71 additions & 84 deletions reports/README.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ This report tracks customer churn in dollar terms, showing both the total churne

The snapshot view is: `v_report_churn_percent_and_total_usd`

## Database Indices

The churn reports requires some additional database indices to be created. See [churn-indices.ddl](churn-indices.ddl)

## Churn Percent Configuration

```
Expand All @@ -18,13 +22,13 @@ curl -v \
"reportPrettyName": "Churn Percent (Monthly and Annual)",
"sourceTableName": "report_churn_percent",
"refreshProcedureName": "refresh_report_churn_percent",
"refreshFrequency": "DAILY"}' \
"refreshFrequency": "HOURLY"}' \
"http://127.0.0.1:8080/plugins/killbill-analytics/reports"
```

## Churn Percentage Report UI


![churn-percent.png.png](churn-percent.png)

## Churn Amount Configuration

Expand All @@ -47,3 +51,4 @@ curl -v \
## Churn Amount Report UI


![churn-amount.png](churn-amount.png)
Binary file added reports/churn/churn-amount.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions reports/churn/churn-indices.ddl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
CREATE INDEX idx_ai_tenant_bundle ON analytics_invoice_items(tenant_record_id, bundle_id, invoice_original_amount_charged, invoice_balance);
CREATE INDEX idx_ast_bundle_tenant_event ON analytics_subscription_transitions(bundle_id, tenant_record_id, event, next_start_date, next_end_date, next_billing_period);
CREATE INDEX idx_subs_id_tenant ON subscriptions(id, tenant_record_id);
CREATE INDEX idx_se_sub_tenant_type ON subscription_events(subscription_id, tenant_record_id, user_type);
Binary file added reports/churn/churn-percent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions reports/new_subscriptions_daily/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Daily New Subscriptions Report

Compute the total amount of new subscriptions created per day for each tenant.

The snapshot view is: `v_report_new_subscriptions_daily`

## Report Creation

```
curl -v \
-X POST \
-u admin:password \
-H "X-Killbill-ApiKey:bob" \
-H "X-Killbill-ApiSecret:lazar" \
-H 'Content-Type: application/json' \
-d '{"reportName": "report_new_subscriptions_daily",
"reportType": "TIMELINE",
"reportPrettyName": "Daily New Subscriptions",
"sourceTableName": "report_new_subscriptions_daily",
"refreshProcedureName": "refresh_report_new_subscriptions_daily",
"refreshFrequency": "HOURLY"}' \
"http://127.0.0.1:8080/plugins/killbill-analytics/reports"
```


## Sample Data

| Tenant Record Id | Slug | Day | Count |
|------------------|------------------------------------|------------|-------|
| 1 | blowdart-monthly-notrial-evergreen | 2025-08-20 | 9 |
| 1 | pistol-monthly-notrial-evergreen | 2025-08-20 | 2 |
| 1 | pistol-monthly-notrial-evergreen | 2025-09-01 | 5 |
| 1 | blowdart-monthly-notrial-evergreen | 2025-09-02 | 6 |
| 25 | gold-monthly-notrial-evergreen | 2025-09-02 | 5 |
| 25 | silver-monthly-notrial-evergreen | 2025-09-03 | 6 |


The first row in the above table indicates that on the date `2025-08-20`, the tenant with record id=1 had 9 new subscriptions created.


## Report UI:


![daily-new-subscriptions.png](daily-new-subscriptions.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 19 additions & 0 deletions reports/new_subscriptions_daily/report_new_subscriptions_daily.ddl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
create table report_new_subscriptions_daily as select * from v_report_new_subscriptions_daily limit 0;

drop procedure if exists refresh_report_new_subscriptions_daily;
DELIMITER //
CREATE PROCEDURE refresh_report_report_new_subscriptions_daily()
BEGIN

DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
delete from report_new_subscriptions_daily;
insert into report_new_subscriptions_daily select * from v_report_new_subscriptions_daily;
COMMIT;

END;
//
DELIMITER ;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
create or replace view v_report_new_subscriptions_daily AS
select ast.tenant_record_id AS tenant_record_id,
ast.next_slug AS slug,
date_format(ast.next_start_date,'%Y-%m-%d') AS day,
count(0) AS count
from analytics_subscription_transitions ast
where ((1 = 1) and
(ast.event = 'START_BILLING_BASE') and
(ast.report_group = 'default')) group by
ast.tenant_record_id,ast.next_slug,
date_format(ast.next_start_date,'%Y-%m-%d')
43 changes: 43 additions & 0 deletions reports/overdue_accounts_summary/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Overdue Accounts Summary Report

Breakdown of current vs. overdue accounts by tenant.

The snapshot view is: [v_report_overdue_account_summary](v_report_overdue_account_summary.ddl)

## Report Creation

```
curl -v \
-X POST \
-u admin:password \
-H "X-Killbill-ApiKey:bob" \
-H "X-Killbill-ApiSecret:lazar" \
-H 'Content-Type: application/json' \
-d '{"reportName": "report_overdue_accounts_summary",
"reportType": "COUNTERS",
"reportPrettyName": "Overdue Accounts Summary",
"sourceTableName": "report_overdue_accounts_summary",
"refreshProcedureName": "refresh_report_overdue_accounts_summary",
"refreshFrequency": "HOURLY"}' \
"http://127.0.0.1:8080/plugins/killbill-analytics/reports"
```

## Sample Data

| Tenant Record Id | Label | Count |
|------------------|---------|-------|
| 515 | Overdue | 5 |
| 518 | Overdue | 1 |
| 1 | Overdue | 74 |
| 1 | Current | 23 |
| 256 | Overdue | 3 |


The first row in the above table indicates that the tenant with record id=1 had 5 accounts in the `Overdue` state.

## Report UI:

![overdue-accounts-summary.png](overdue-accounts-summary.png)



Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
create table report_overdue_accounts_summary as select * from v_report_overdue_accounts_summary limit 0;

drop procedure if exists refresh_report_overdue_accounts_summary;
DELIMITER //
CREATE PROCEDURE refresh_report_overdue_accounts_summary()
BEGIN

DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
START TRANSACTION;
delete from report_overdue_accounts_summary;
insert into report_overdue_accounts_summary select * from v_report_overdue_accounts_summary;
COMMIT;

END;
//
DELIMITER ;
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
create or replace view v_report_overdue_accounts_summary AS
select a.tenant_record_id AS tenant_record_id,
(case when (a.balance <= 0) then 'Current' else 'Overdue' end) AS label,
count(0) AS count
from analytics_accounts a
where
((1 = 1) and
(a.report_group = 'default'))
group by a.tenant_record_id,
(case when (a.balance <= 0) then 'Current' else 'Overdue' end)
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
# Payment Provider Conversion report

Compare the total number of transactions and the number of successful transactions that have occurred in a recent 15 minutes
period to the same metrics that occurred in the corresponding 15 minutes from 14 days ago.
Compare the total number of transactions and the number of successful transactions that have occurred in a recent 15 minutes period to the same metrics that occurred in the corresponding 15 minutes from 14 days ago.

The snapshot view is: `v_report_payment_provider_conversion`.

## History table configuration
## Report Creation

```
curl -v \
Expand All @@ -17,8 +16,8 @@ curl -v \
-d '{"reportName": "report_payment_provider_conversion",
"reportType": "TABLE",
"reportPrettyName": "Payment Provider Conversion",
"sourceTableName": "report_payment_provider_conversion_history",
"refreshProcedureName": "refresh_report_payment_provider_conversion_history",
"sourceTableName": "report_payment_provider_conversion",
"refreshProcedureName": "refresh_report_payment_provider_conversion",
"refreshFrequency": "HOURLY"}' \
"http://127.0.0.1:8080/plugins/killbill-analytics/reports"
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
create table report_payment_provider_conversion as select * from v_report_payment_provider_conversion limit 0;

drop procedure if exists refresh_report_payment_provider_conversion;
DELIMITER //
CREATE PROCEDURE refresh_report_payment_provider_conversion()
BEGIN

DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
DECLARE EXIT HANDLER FOR SQLWARNING ROLLBACK;

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
insert into report_payment_provider_conversion select * from v_report_payment_provider_conversion;

END;
//
DELIMITER ;
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
create or replace view v_report_payment_provider_conversion_sub1 as
SELECT
apa.plugin_name
, ifnull(apa.plugin_property_4,'unknown') as merchant_account
, ifnull(apa.plugin_property_5,'unknown') as payment_method
, apa.tenant_record_id
, sum(case when apa.payment_transaction_status='SUCCESS' then 1 else 0 end) as current_success_count
, count(1) as current_transaction_count
, count(distinct apa.account_id) as current_customer_count
FROM
analytics_payment_auths apa
WHERE 1=1
AND apa.created_date >= FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP()) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP()) - 15*60)%(15*60))
AND cast(FROM_UNIXTIME(UNIX_TIMESTAMP(apa.created_date) - UNIX_TIMESTAMP(apa.created_date)%(15*60)) as time) = cast(FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP()) - 15*60 - (UNIX_TIMESTAMP(NOW()) - 15*60)%(15*60)) as time)
GROUP BY
apa.plugin_name
, ifnull(apa.plugin_property_4,'unknown')
, ifnull(apa.plugin_property_5,'unknown')
, apa.tenant_record_id
UNION
SELECT
app.plugin_name
, ifnull(app.plugin_property_4,'unknown') as merchant_account
, ifnull(app.plugin_property_5,'unknown') as payment_method
, app.tenant_record_id
, sum(case when app.payment_transaction_status='SUCCESS' then 1 else 0 end) as current_success_count
, count(1) as current_transaction_count
, count(distinct app.account_id) as current_customer_count
FROM
analytics_payment_purchases app
WHERE 1=1
AND app.created_date >= FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP()) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP()) - 15*60)%(15*60))
AND cast(FROM_UNIXTIME(UNIX_TIMESTAMP(app.created_date) - UNIX_TIMESTAMP(app.created_date)%(15*60)) as time) = cast(FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP()) - 15*60 - (UNIX_TIMESTAMP(NOW()) - 15*60)%(15*60)) as time)
GROUP BY
app.plugin_name
, ifnull(app.plugin_property_4,'unknown')
, ifnull(app.plugin_property_5,'unknown')
, app.tenant_record_id
;

create or replace view v_report_payment_provider_conversion_sub2 as
SELECT
apa.plugin_name
, ifnull(apa.plugin_property_4,'unknown') as merchant_account
, ifnull(apa.plugin_property_5,'unknown') as payment_method
, apa.tenant_record_id
, sum(case when apa.payment_transaction_status='SUCCESS' then 1 else 0 end) as historical_success_count
, count(1) as historical_transaction_count
, count(distinct apa.account_id) as historical_customer_count
FROM
analytics_payment_auths apa
WHERE 1=1
AND apa.created_date < FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60)%(15*60) + 15*60)
AND cast(FROM_UNIXTIME(UNIX_TIMESTAMP(apa.created_date) - UNIX_TIMESTAMP(apa.created_date)%(15*60)) as time) = cast(FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60)%(15*60)) as time)
AND apa.created_date >= FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60)%(15*60))
GROUP BY
apa.plugin_name
, ifnull(apa.plugin_property_4,'unknown')
, ifnull(apa.plugin_property_5,'unknown')
, apa.tenant_record_id
UNION
SELECT
app.plugin_name
, ifnull(app.plugin_property_4,'unknown') as merchant_account
, ifnull(app.plugin_property_5,'unknown') as payment_method
, app.tenant_record_id
, sum(case when app.payment_transaction_status='SUCCESS' then 1 else 0 end) as historical_success_count
, count(1) as historical_transaction_count
, count(distinct app.account_id) as historical_customer_count
FROM
analytics_payment_purchases app
WHERE 1=1
AND app.created_date < FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60)%(15*60) + 15*60)
AND cast(FROM_UNIXTIME(UNIX_TIMESTAMP(app.created_date) - UNIX_TIMESTAMP(app.created_date)%(15*60)) as time) = cast(FROM_UNIXTIME(UNIX_TIMESTAMP(NOW() - interval '14' day) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60)%(15*60)) as time)
AND app.created_date >= FROM_UNIXTIME(UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60 - (UNIX_TIMESTAMP(UTC_TIMESTAMP() - interval '14' day) - 15*60)%(15*60))
GROUP BY
app.plugin_name
, ifnull(app.plugin_property_4,'unknown')
, ifnull(app.plugin_property_5,'unknown')
, app.tenant_record_id
;

create or replace view v_report_payment_provider_conversion as
with agg as (
select
rpccs1.plugin_name,
rpccs1.merchant_account,
rpccs1.payment_method,
rpccs1.tenant_record_id,
ifnull(sum(rpccs1.current_success_count),0) as current_success_count,
ifnull(sum(rpccs1.current_transaction_count),0) as current_transaction_count,
ifnull(sum(rpccs1.current_customer_count),0) as current_customer_count,
ifnull(sum(rpccs2.historical_success_count),0) as historical_success_count,
ifnull(sum(rpccs2.historical_transaction_count),0) as historical_transaction_count,
ifnull(sum(rpccs2.historical_customer_count),0) as historical_customer_count
from v_report_payment_provider_conversion_sub2 rpccs2
left join v_report_payment_provider_conversion_sub1 rpccs1
on rpccs1.plugin_name=rpccs2.plugin_name
and rpccs1.merchant_account=rpccs2.merchant_account
and rpccs1.payment_method=rpccs2.payment_method
and rpccs1.tenant_record_id=rpccs2.tenant_record_id
group by
rpccs1.plugin_name,
rpccs1.merchant_account,
rpccs1.payment_method,
rpccs1.tenant_record_id
)
select *,
case when historical_success_count > 0
then concat(round(((current_success_count-historical_success_count)/historical_success_count)*100,2),'%')
else '0%'
end as success_delta,
case when historical_transaction_count > 0
then concat(round(((current_transaction_count-historical_transaction_count)/historical_transaction_count)*100,2),'%')
else '0%'
end as transaction_delta,
case when historical_customer_count > 0
then concat(round(((current_customer_count-historical_customer_count)/historical_customer_count)*100,2),'%')
else '0%'
end as customer_delta,
sysdate() as refresh_date
from agg;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# Payment Provider Errors report
# Payment Provider Errors Report

Compute the top errors per provider and currency, per day.

The snapshot view is: `v_report_payment_provider_errors`

## Timeline configuration
## Report Creation

```
curl -v \
Expand All @@ -21,3 +21,7 @@ curl -v \
"refreshFrequency": "HOURLY"}' \
"http://127.0.0.1:8080/plugins/killbill-analytics/reports"
```

## Report UI:

![payment-provider-errors.png](payment-provider-errors.png)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading