Skip to content
Merged
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
54 changes: 42 additions & 12 deletions backend/apps/account_payment/webhooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,38 @@ def remove_user(email: str, group_key: str = None, event_context: str = None) ->
raise


def chatbot_trial_just_ended(event: Event) -> bool:
"""True if the subscription ended while it was still in trial."""
data = event.data or {}
previous_status = (data.get("previous_attributes") or {}).get("status")
if previous_status == "trialing":
return True

obj = data.get("object") or {}
trial_end = obj.get("trial_end")
ended_at = obj.get("canceled_at") or obj.get("ended_at")
if not trial_end or not ended_at:
return False
return int(ended_at) <= int(trial_end) + 3600


def maybe_send_chatbot_trial_ended_email(
wc: WebhookContext,
subscription: Subscription | None,
account: Account | None,
*,
had_chatbot_access: bool,
) -> None:
"""Send the trial-ended email if chatbot access was just revoked for a trial."""
if not account or not chatbot_trial_just_ended(wc.event):
return
if not had_chatbot_access or account.has_chatbot_access:
return
if not subscription_product_is_chatbot(subscription, wc.event, wc.event_context):
return
send_chatbot_trial_ended_email(account, event_context=wc.event_context)


def send_chatbot_trial_ended_email(account: Account, event_context: str = None) -> None:
"""Send the "your chatbot trial ended" email.

Expand Down Expand Up @@ -763,8 +795,7 @@ def handle_subscription(event: Event):
subscription = get_subscription(event, event_context=wc.event_context)
account = get_account_for_stripe_customer(event)

status = event.data.get("object", {}).get("status")
previous_status = event.data.get("previous_attributes", {}).get("status")
status = (event.data.get("object") or {}).get("status")

if status in ["trialing", "active"]:
if subscription:
Expand All @@ -791,18 +822,11 @@ def handle_subscription(event: Event):
subscription.is_active = False
subscription.save()

trial_just_ended = previous_status == "trialing" and account
had_chatbot_access = bool(account and account.has_chatbot_access)

apply_inactive_subscription_entitlements(wc, subscription, account)

if (
trial_just_ended
and had_chatbot_access
and not account.has_chatbot_access
and subscription_product_is_chatbot(subscription, wc.event, wc.event_context)
):
send_chatbot_trial_ended_email(account, event_context=wc.event_context)
maybe_send_chatbot_trial_ended_email(
wc, subscription, account, had_chatbot_access=had_chatbot_access
)


@webhooks.handler("customer.subscription.updated")
Expand Down Expand Up @@ -833,6 +857,8 @@ def subscribe(event: Event, **kwargs):
def unsubscribe(event: Event, **kwargs):
"""Revoke entitlements for a deleted Stripe subscription.

Also sends the chatbot trial-ended email if the subscription was still in trial.

Args:
event: The `customer.subscription.deleted` Stripe webhook event.
**kwargs: Unused; accepted for compatibility with the djstripe
Expand All @@ -849,7 +875,11 @@ def unsubscribe(event: Event, **kwargs):
subscription.save()

account = get_account_for_stripe_customer(event)
had_chatbot_access = bool(account and account.has_chatbot_access)
apply_inactive_subscription_entitlements(wc, subscription, account)
maybe_send_chatbot_trial_ended_email(
wc, subscription, account, had_chatbot_access=had_chatbot_access
)


@webhooks.handler("customer.subscription.paused")
Expand Down
Loading