Skip to content

Commit

Permalink
fix: Handle null cancellation dates (#4589)
Browse files Browse the repository at this point in the history
  • Loading branch information
zachaysan authored Sep 9, 2024
1 parent 4bf7b9d commit 603889c
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 3 deletions.
11 changes: 8 additions & 3 deletions api/organisations/chargebee/webhook_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,15 @@ def process_subscription(request: Request) -> Response: # noqa: C901
return Response(status=status.HTTP_200_OK)

if subscription["status"] in ("non_renewing", "cancelled"):
existing_subscription.prepare_for_cancel(
datetime.fromtimestamp(subscription.get("current_term_end")).replace(
cancellation_date = subscription.get("current_term_end")
if cancellation_date is not None:
cancellation_date = datetime.fromtimestamp(cancellation_date).replace(
tzinfo=timezone.utc
),
)
else:
cancellation_date = timezone.now()
existing_subscription.prepare_for_cancel(
cancellation_date,
update_chargebee=False,
)
return Response(status=status.HTTP_200_OK)
Expand Down
40 changes: 40 additions & 0 deletions api/tests/unit/organisations/test_unit_organisations_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
from organisations.permissions.permissions import CREATE_PROJECT
from organisations.subscriptions.constants import (
CHARGEBEE,
FREE_PLAN_ID,
MAX_API_CALLS_IN_FREE_PLAN,
MAX_SEATS_IN_FREE_PLAN,
SUBSCRIPTION_BILLING_STATUS_ACTIVE,
Expand Down Expand Up @@ -635,6 +636,7 @@ def test_when_subscription_is_set_to_non_renewing_then_cancellation_date_set_and
current_term_end = int(datetime.timestamp(cancellation_date))
subscription.subscription_id = "subscription-id"
subscription.save()

data = {
"content": {
"subscription": {
Expand Down Expand Up @@ -663,6 +665,44 @@ def test_when_subscription_is_set_to_non_renewing_then_cancellation_date_set_and
mocked_cancel_chargebee_subscription.assert_not_called()


@pytest.mark.freeze_time("2023-01-19T09:09:47.325132+00:00")
@mock.patch("organisations.models.cancel_chargebee_subscription")
def test_when_subscription_is_set_to_non_renewing_then_cancellation_date_set_and_current_term_end_is_missing(
mocked_cancel_chargebee_subscription: MagicMock,
chargebee_subscription: Subscription,
staff_user: FFAdminUser,
staff_client: APIClient,
settings: SettingsWrapper,
) -> None:
# Given
data = {
"content": {
"subscription": {
"status": "non_renewing",
"id": chargebee_subscription.subscription_id,
# Note the missing current_term_end field.
},
"customer": {"email": staff_user.email},
}
}
url = reverse("api-v1:chargebee-webhook")

settings.ORG_SUBSCRIPTION_CANCELLED_ALERT_RECIPIENT_LIST = ["[email protected]"]

# When
staff_client.post(url, data=json.dumps(data), content_type="application/json")

# Then
chargebee_subscription.refresh_from_db()
# Cancellation date is set to None because the missing current_term_end field
# means that the cancellation is processed immediately and the subscription
# reverts to being a free plan, so there's no more cancelation date set.
assert chargebee_subscription.cancellation_date is None
assert chargebee_subscription.plan == FREE_PLAN_ID
assert len(mail.outbox) == 1
mocked_cancel_chargebee_subscription.assert_not_called()


def test_when_subscription_is_cancelled_then_cancellation_date_set_and_alert_sent(
subscription: Subscription,
staff_user: FFAdminUser,
Expand Down

0 comments on commit 603889c

Please sign in to comment.