Skip to content

Commit 03cd11b

Browse files
committed
metrics: Compute trial exclusion from bucket end instead of date_trunc
_not_in_trial / _in_trial truncated both trial_end and the bucket timestamp and compared those. `trial_end < t + interval` gives the same answer without the date_trunc calls on either side.
1 parent 9c5ebe7 commit 03cd11b

2 files changed

Lines changed: 56 additions & 4 deletions

File tree

server/polar/metrics/metrics.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,15 @@ def _not_in_trial(t: ColumnElement[datetime], i: TimeInterval) -> ColumnElement[
3333
buckets = t.table.c
3434
return or_(
3535
buckets.trial_end.is_(None),
36-
i.sql_date_trunc(cast(SQLColumnExpression[datetime], buckets.trial_end))
37-
<= i.sql_date_trunc(t),
36+
buckets.trial_end < t + i.sql_interval(),
3837
)
3938

4039

4140
def _in_trial(t: ColumnElement[datetime], i: TimeInterval) -> ColumnElement[bool]:
4241
buckets = t.table.c
4342
return and_(
4443
buckets.trial_end.is_not(None),
45-
i.sql_date_trunc(cast(SQLColumnExpression[datetime], buckets.trial_end))
46-
> i.sql_date_trunc(t),
44+
buckets.trial_end >= t + i.sql_interval(),
4745
)
4846

4947

server/tests/metrics/test_service.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3514,6 +3514,60 @@ async def test_trial_excluded_from_mrr(
35143514
assert mar.trial_monthly_recurring_revenue == 0
35153515
assert mar.trial_committed_monthly_recurring_revenue == 0
35163516

3517+
async def test_trial_mrr_is_stable_across_now_values(
3518+
self,
3519+
metrics_harness: MetricsHarness,
3520+
metrics_session: AsyncSession,
3521+
) -> None:
3522+
case = QUERY_CASES_BY_LABEL["trial_excluded_from_mrr"]
3523+
org_ctx = metrics_harness.organizations[case.org_key]
3524+
auth_subject = _metrics_auth_subject(
3525+
metrics_harness.user,
3526+
metrics_harness.unauthorized_user,
3527+
org_ctx.organization,
3528+
case.auth_type,
3529+
)
3530+
3531+
async def get_metrics(now: datetime) -> MetricsResponse:
3532+
return await metrics_service.get_metrics(
3533+
metrics_session,
3534+
auth_subject,
3535+
start_date=case.start_date,
3536+
end_date=case.end_date,
3537+
timezone=ZoneInfo(case.timezone),
3538+
interval=case.interval,
3539+
organization_id=[org_ctx.organization.id]
3540+
if case.organization_id_filter or case.auth_type == "user"
3541+
else None,
3542+
product_id=[org_ctx.product_ids[k] for k in case.product_keys] or None,
3543+
billing_type=list(case.billing_types) or None,
3544+
customer_id=[org_ctx.customer_ids[k] for k in case.customer_keys]
3545+
or None,
3546+
metrics=list(case.metrics) if case.metrics is not None else None,
3547+
now=now,
3548+
)
3549+
3550+
early = await get_metrics(datetime(2024, 2, 1, tzinfo=UTC))
3551+
later = await get_metrics(datetime(2024, 6, 1, tzinfo=UTC))
3552+
3553+
assert len(early.periods) == len(later.periods) == 3
3554+
for early_period, later_period in zip(
3555+
early.periods, later.periods, strict=True
3556+
):
3557+
assert early_period.timestamp == later_period.timestamp
3558+
assert (
3559+
early_period.monthly_recurring_revenue
3560+
== later_period.monthly_recurring_revenue
3561+
)
3562+
assert (
3563+
early_period.trial_monthly_recurring_revenue
3564+
== later_period.trial_monthly_recurring_revenue
3565+
)
3566+
assert (
3567+
early_period.trial_committed_monthly_recurring_revenue
3568+
== later_period.trial_committed_monthly_recurring_revenue
3569+
)
3570+
35173571
async def test_mrr_subscription_forever_discount(
35183572
self,
35193573
metrics_harness: MetricsHarness,

0 commit comments

Comments
 (0)