-
Notifications
You must be signed in to change notification settings - Fork 429
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: introduce dunning billing status (#2976)
- Loading branch information
Showing
7 changed files
with
366 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
from rest_framework.exceptions import ValidationError | ||
from rest_framework.serializers import CharField, Serializer | ||
|
||
|
||
class PaymentFailedInvoiceSerializer(Serializer): | ||
dunning_status = CharField(allow_null=False) | ||
subscription_id = CharField(allow_null=False) | ||
|
||
def validate_dunning_status(self, value): | ||
if value != "in_progress": | ||
raise ValidationError("To be valid dunning must be in progress") | ||
return value | ||
|
||
|
||
class PaymentSucceededInvoiceSerializer(Serializer): | ||
subscription_id = CharField(allow_null=False) | ||
|
||
|
||
class PaymentFailedContentSerializer(Serializer): | ||
invoice = PaymentFailedInvoiceSerializer(required=True) | ||
|
||
|
||
class PaymentSucceededContentSerializer(Serializer): | ||
invoice = PaymentSucceededInvoiceSerializer(required=True) | ||
|
||
|
||
class PaymentFailedSerializer(Serializer): | ||
content = PaymentFailedContentSerializer(required=True) | ||
|
||
|
||
class PaymentSucceededSerializer(Serializer): | ||
content = PaymentSucceededContentSerializer(required=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import logging | ||
|
||
from rest_framework import status | ||
from rest_framework.exceptions import ValidationError | ||
from rest_framework.request import Request | ||
from rest_framework.response import Response | ||
|
||
from organisations.models import Subscription | ||
from organisations.subscriptions.constants import ( | ||
SUBSCRIPTION_BILLING_STATUS_ACTIVE, | ||
SUBSCRIPTION_BILLING_STATUS_DUNNING, | ||
) | ||
|
||
from .serializers import PaymentFailedSerializer, PaymentSucceededSerializer | ||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
def payment_failed(request: Request) -> Response: | ||
serializer = PaymentFailedSerializer(data=request.data) | ||
|
||
try: | ||
serializer.is_valid(raise_exception=True) | ||
except ValidationError: | ||
logger.warning( | ||
"Serializer failure during chargebee payment failed processing", | ||
exc_info=True, | ||
) | ||
return Response(status=status.HTTP_200_OK) | ||
|
||
subscription_id = serializer.validated_data["content"]["invoice"]["subscription_id"] | ||
|
||
try: | ||
subscription = Subscription.objects.get(subscription_id=subscription_id) | ||
except Subscription.DoesNotExist: | ||
logger.warning( | ||
"No matching subscription for chargebee payment " | ||
f"failed webhook for subscription id {subscription_id}" | ||
) | ||
return Response(status=status.HTTP_200_OK) | ||
except Subscription.MultipleObjectsReturned: | ||
logger.warning( | ||
"Multiple matching subscriptions for chargebee payment " | ||
f"failed webhook for subscription id {subscription_id}" | ||
) | ||
return Response(status=status.HTTP_200_OK) | ||
|
||
subscription.billing_status = SUBSCRIPTION_BILLING_STATUS_DUNNING | ||
subscription.save() | ||
|
||
return Response(status=status.HTTP_200_OK) | ||
|
||
|
||
def payment_succeeded(request: Request) -> Response: | ||
serializer = PaymentSucceededSerializer(data=request.data) | ||
|
||
try: | ||
serializer.is_valid(raise_exception=True) | ||
except ValidationError: | ||
logger.warning( | ||
"Serializer failure during chargebee payment failed processing", | ||
exc_info=True, | ||
) | ||
return Response(status=status.HTTP_200_OK) | ||
|
||
subscription_id = serializer.validated_data["content"]["invoice"]["subscription_id"] | ||
|
||
try: | ||
subscription = Subscription.objects.get(subscription_id=subscription_id) | ||
except Subscription.DoesNotExist: | ||
logger.warning( | ||
"No matching subscription for chargebee payment " | ||
f"succeeded webhook for subscription id {subscription_id}" | ||
) | ||
return Response(status=status.HTTP_200_OK) | ||
except Subscription.MultipleObjectsReturned: | ||
logger.warning( | ||
"Multiple matching subscriptions for chargebee payment " | ||
f"succeeded webhook for subscription id {subscription_id}" | ||
) | ||
return Response(status=status.HTTP_200_OK) | ||
|
||
subscription.billing_status = SUBSCRIPTION_BILLING_STATUS_ACTIVE | ||
subscription.save() | ||
|
||
return Response(status=status.HTTP_200_OK) |
18 changes: 18 additions & 0 deletions
18
api/organisations/migrations/0049_subscription_billing_status.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Generated by Django 3.2.23 on 2023-11-15 16:43 | ||
|
||
from django.db import migrations, models | ||
|
||
|
||
class Migration(migrations.Migration): | ||
|
||
dependencies = [ | ||
('organisations', '0048_add_default_subscription_to_orphaned_organisations'), | ||
] | ||
|
||
operations = [ | ||
migrations.AddField( | ||
model_name='subscription', | ||
name='billing_status', | ||
field=models.CharField(blank=True, choices=[('ACTIVE', 'Active'), ('DUNNING', 'Dunning')], max_length=20, null=True), | ||
), | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.