From aed15c351d19813667de04245e9cb41560c15651 Mon Sep 17 00:00:00 2001 From: Zach Aysan Date: Mon, 27 Nov 2023 13:49:21 -0500 Subject: [PATCH] feat: Rebuild chargebee caches (#3028) --- .../chargebee/webhook_event_types.py | 17 ++++++++ .../chargebee/webhook_handlers.py | 7 +++ api/organisations/views.py | 8 ++-- .../test_unit_organisations_views.py | 43 ++++++++++++++++++- 4 files changed, 71 insertions(+), 4 deletions(-) create mode 100644 api/organisations/chargebee/webhook_event_types.py diff --git a/api/organisations/chargebee/webhook_event_types.py b/api/organisations/chargebee/webhook_event_types.py new file mode 100644 index 000000000000..da509c94d446 --- /dev/null +++ b/api/organisations/chargebee/webhook_event_types.py @@ -0,0 +1,17 @@ +PAYMENT_FAILED = "payment_failed" +PAYMENT_SUCCEEDED = "payment_succeeded" +PLAN_CREATED = "plan_created" +PLAN_UPDATED = "plan_updated" +PLAN_DELETED = "plan_deleted" +ADDON_CREATED = "addon_created" +ADDON_UPDATED = "addon_updated" +ADDON_DELETED = "addon_deleted" + +CACHE_REBUILD_TYPES = { + PLAN_CREATED, + PLAN_UPDATED, + PLAN_DELETED, + ADDON_CREATED, + ADDON_UPDATED, + ADDON_DELETED, +} diff --git a/api/organisations/chargebee/webhook_handlers.py b/api/organisations/chargebee/webhook_handlers.py index f0770666332e..ce64a4a960fe 100644 --- a/api/organisations/chargebee/webhook_handlers.py +++ b/api/organisations/chargebee/webhook_handlers.py @@ -5,6 +5,7 @@ from rest_framework.request import Request from rest_framework.response import Response +from organisations.chargebee.tasks import update_chargebee_cache from organisations.models import Subscription from organisations.subscriptions.constants import ( SUBSCRIPTION_BILLING_STATUS_ACTIVE, @@ -16,6 +17,12 @@ logger = logging.getLogger(__name__) +def cache_rebuild_event(request: Request) -> Response: + logger.info("Chargebee plan or addon webhook fired, rebuilding cache.") + update_chargebee_cache.delay() + return Response(status=status.HTTP_200_OK) + + def payment_failed(request: Request) -> Response: serializer = PaymentFailedSerializer(data=request.data) diff --git a/api/organisations/views.py b/api/organisations/views.py index 7d23e63fe552..17399fa39f36 100644 --- a/api/organisations/views.py +++ b/api/organisations/views.py @@ -20,7 +20,7 @@ from rest_framework.response import Response from rest_framework.throttling import ScopedRateThrottle -from organisations.chargebee import webhook_handlers +from organisations.chargebee import webhook_event_types, webhook_handlers from organisations.exceptions import OrganisationHasNoPaidSubscription from organisations.models import ( Organisation, @@ -274,10 +274,12 @@ def chargebee_webhook(request: Request) -> Response: """ event_type = request.data.get("event_type") - if event_type == "payment_failed": + if event_type == webhook_event_types.PAYMENT_FAILED: return webhook_handlers.payment_failed(request) - if event_type == "payment_succeeded": + if event_type == webhook_event_types.PAYMENT_SUCCEEDED: return webhook_handlers.payment_succeeded(request) + if event_type in webhook_event_types.CACHE_REBUILD_TYPES: + return webhook_handlers.cache_rebuild_event(request) if request.data.get("content") and "subscription" in request.data.get("content"): subscription_data: dict = request.data["content"]["subscription"] diff --git a/api/tests/unit/organisations/test_unit_organisations_views.py b/api/tests/unit/organisations/test_unit_organisations_views.py index 8f7aa977d82e..0007990c77da 100644 --- a/api/tests/unit/organisations/test_unit_organisations_views.py +++ b/api/tests/unit/organisations/test_unit_organisations_views.py @@ -1497,9 +1497,50 @@ def test_payment_failed_chargebee_webhook_no_subscription_id( assert subscription.billing_status == SUBSCRIPTION_BILLING_STATUS_ACTIVE +def test_cache_rebuild_event_chargebee_webhook( + staff_client: FFAdminUser, + mocker: MockerFixture, +) -> None: + # Given + data = { + "id": "ev_XpbG6hnQqGFm2n3O", + "occurred_at": 1341085213, + "source": "api", + "user": "full_access_key_v1", + "object": "event", + "api_version": "v2", + "content": { + "addon": { + "id": "support", + "name": "Support", + "description": "This is addon added when support is needed", + "type": "quantity", + "charge_type": "recurring", + "price": 1000, + "period": 1, + "period_unit": "month", + "status": "deleted", + } + }, + "event_type": "addon_deleted", + } + + url = reverse("api-v1:chargebee-webhook") + task = mocker.patch( + "organisations.chargebee.webhook_handlers.update_chargebee_cache" + ) + # When + response = staff_client.post( + url, data=json.dumps(data), content_type="application/json" + ) + # Then + assert response.status_code == 200 + task.delay.assert_called_once_with() + + def test_payment_succeeded_chargebee_webhook( staff_client: FFAdminUser, subscription: Subscription -): +) -> None: # Given subscription.billing_status = SUBSCRIPTION_BILLING_STATUS_DUNNING subscription.subscription_id = "best_id"