Skip to content

Commit

Permalink
Move logic to add free subscription after addon to celery task
Browse files Browse the repository at this point in the history
  • Loading branch information
nikochiko committed Aug 14, 2024
1 parent e7570c9 commit 2066ec8
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 40 deletions.
46 changes: 6 additions & 40 deletions app_users/signals.py
Original file line number Diff line number Diff line change
@@ -1,54 +1,20 @@
import stripe
from loguru import logger
from django.db.models.signals import post_save
from django.dispatch import receiver

from app_users.models import AppUserTransaction, PaymentProvider, TransactionReason
from payments.plans import PricingPlan
from payments.webhooks import set_user_subscription
from app_users.tasks import after_stripe_addon


@receiver(post_save, sender=AppUserTransaction)
def after_stripe_addon(instance: AppUserTransaction, **kwargs):
def transaction_post_save(instance: AppUserTransaction, **kwargs):
if not (
instance.payment_provider == PaymentProvider.STRIPE
and instance.reason == TransactionReason.ADDON
):
return

set_default_payment_method(instance)
set_free_subscription_on_user(instance)


def set_default_payment_method(instance: AppUserTransaction):
# update customer's defualt payment method
# note... that if a customer has an active subscription, the payment method attached there will be preferred
# see `stripe_get_default_payment_method` in payments/models.py module
invoice = stripe.Invoice.retrieve(instance.invoice_id, expand=["payment_intent"])
if (
invoice.payment_intent
and invoice.payment_intent.status == "succeeded"
and invoice.payment_intent.payment_method
):
logger.info(
f"Updating default payment method for customer {invoice.customer} to {invoice.payment_intent.payment_method}"
)
stripe.Customer.modify(
invoice.customer,
invoice_settings={
"default_payment_method": invoice.payment_intent.payment_method
},
)


def set_free_subscription_on_user(instance: AppUserTransaction):
user = instance.user
if user.subscription:
return

set_user_subscription(
provider=PaymentProvider.STRIPE,
plan=PricingPlan.STARTER,
uid=user.uid,
external_id=None,
)
try:
after_stripe_addon.delay(instance.pk)
except Exception as e:
logger.exception(e)
62 changes: 62 additions & 0 deletions app_users/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import stripe
from loguru import logger

from app_users.models import AppUserTransaction
from celeryapp.celeryconfig import app
from payments.webhooks import set_free_subscription_for_user


@app.task
def after_stripe_addon(txn_id: int):
txn = AppUserTransaction.objects.get(id=txn_id)

default_pm = stripe_set_default_payment_method(txn)
if default_pm and not txn.user.subscription:
# user is not on an existing subscription... add one so that user can configure auto recharge
subscription = set_free_subscription_for_user(uid=txn.user.uid)
if (
subscription.auto_recharge_enabled
and not subscription.monthly_spending_budget
):
subscription.monthly_spending_budget = int(3 * txn.charged_amount / 100)
subscription.monthly_spending_notification_threshold = int(
0.8 * subscription.monthly_spending_budget
)
subscription.save(
update_fields=[
"monthly_spending_budget",
"monthly_spending_notification_threshold",
]
)


def stripe_set_default_payment_method(
instance: AppUserTransaction,
) -> stripe.PaymentMethod | None:
# update customer's defualt payment method
# note... that if a customer has an active subscription, the payment method attached there will be preferred
# see `stripe_get_default_payment_method` in payments/models.py module
invoice = stripe.Invoice.retrieve(
instance.invoice_id, expand=["payment_intent", "payment_intent.payment_method"]
)
if (
invoice.payment_intent
and invoice.payment_intent.status == "succeeded"
and invoice.payment_intent.payment_method
):
if not invoice.payment_intent.payment_method.customer:
logger.info(
"Can't save payment method because it's not attached to a customer"
)
return

logger.info(
f"Updating default payment method for customer {invoice.customer} to {invoice.payment_intent.payment_method}"
)
stripe.Customer.modify(
invoice.customer,
invoice_settings={
"default_payment_method": invoice.payment_intent.payment_method
},
)
return invoice.payment_intent.payment_method

0 comments on commit 2066ec8

Please sign in to comment.