Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Rebuild chargebee caches #3028

Merged
merged 8 commits into from
Nov 27, 2023
17 changes: 17 additions & 0 deletions api/organisations/chargebee/webhook_event_types.py
Original file line number Diff line number Diff line change
@@ -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,
}
7 changes: 7 additions & 0 deletions api/organisations/chargebee/webhook_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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)

Expand Down
8 changes: 5 additions & 3 deletions api/organisations/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"]
Expand Down
43 changes: 42 additions & 1 deletion api/tests/unit/organisations/test_unit_organisations_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down