Skip to content

Commit

Permalink
Merge pull request #421 from GooeyAI/autorecharge-after-oneoff
Browse files Browse the repository at this point in the history
Store Stripe billing info + auto recharge without subscription + cancel button for subscriptions
  • Loading branch information
nikochiko authored Aug 23, 2024
2 parents f7ecf1a + 20f0fa9 commit bb334bc
Show file tree
Hide file tree
Showing 14 changed files with 573 additions and 375 deletions.
5 changes: 0 additions & 5 deletions app_users/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,3 @@ class AppUsersConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "app_users"
verbose_name = "App Users"

def ready(self):
from . import signals

assert signals
19 changes: 0 additions & 19 deletions app_users/signals.py

This file was deleted.

54 changes: 54 additions & 0 deletions app_users/tasks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import stripe
from loguru import logger

from app_users.models import PaymentProvider, TransactionReason
from celeryapp.celeryconfig import app
from payments.models import Subscription
from payments.plans import PricingPlan
from payments.webhooks import set_user_subscription


@app.task
def save_stripe_default_payment_method(
*,
payment_intent_id: str,
uid: str,
amount: int,
charged_amount: int,
reason: TransactionReason,
):
pi = stripe.PaymentIntent.retrieve(payment_intent_id, expand=["payment_method"])
pm = pi.payment_method
if not (pm and pm.customer):
logger.error(
f"Failed to retrieve payment method for payment intent {payment_intent_id}"
)
return

# update customer's defualt payment method
# note: 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
logger.info(
f"Updating default payment method for customer {pm.customer} to {pm.id}"
)
stripe.Customer.modify(
pm.customer,
invoice_settings=dict(default_payment_method=pm),
)

# if user doesn't already have a active billing/autorecharge info, so we don't need to do anything
# set user's subscription to the free plan
if (
reason == TransactionReason.ADDON
and not Subscription.objects.filter(
user__uid=uid, payment_provider__isnull=False
).exists()
):
set_user_subscription(
uid=uid,
plan=PricingPlan.STARTER,
provider=PaymentProvider.STRIPE,
external_id=None,
amount=amount,
charged_amount=charged_amount,
)
69 changes: 24 additions & 45 deletions daras_ai_v2/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
from daras_ai_v2.exceptions import InsufficientCredits
from daras_ai_v2.fastapi_tricks import get_route_path
from daras_ai_v2.grid_layout_widget import grid_layout
from daras_ai_v2.gui_confirm import confirm_modal
from daras_ai_v2.html_spinner_widget import html_spinner
from daras_ai_v2.manage_api_keys_widget import manage_api_keys
from daras_ai_v2.meta_preview_url import meta_preview_url
Expand Down Expand Up @@ -697,10 +698,29 @@ def _render_options_modal(
save_as_new_button = gui.button(
f"{save_as_new_icon} Save as New", className="w-100"
)
delete_button = not published_run.is_root() and gui.button(
f'<i class="fa-regular fa-trash"></i> Delete',
className="w-100 text-danger",
)

if not published_run.is_root():
confirm_delete_modal, confirmed = confirm_modal(
title="Are you sure?",
key="--delete-run-modal",
text=f"""
Are you sure you want to delete this published run?
**{published_run.title}**
This will also delete all the associated versions.
""",
button_label="Delete",
button_class="border-danger bg-danger text-white",
)
if gui.button(
f'<i class="fa-regular fa-trash"></i> Delete',
className="w-100 text-danger",
):
confirm_delete_modal.open()
if confirmed:
published_run.delete()
raise gui.RedirectException(self.app_url())

if duplicate_button:
duplicate_pr = self.duplicate_published_run(
Expand Down Expand Up @@ -730,47 +750,6 @@ def _render_options_modal(
gui.write("#### Version History", className="mb-4")
self._render_version_history()

confirm_delete_modal = gui.Modal("Confirm Delete", key="confirm-delete-modal")
if delete_button:
confirm_delete_modal.open()
if confirm_delete_modal.is_open():
modal.empty()
with confirm_delete_modal.container():
self._render_confirm_delete_modal(
published_run=published_run,
modal=confirm_delete_modal,
)

def _render_confirm_delete_modal(
self,
*,
published_run: PublishedRun,
modal: gui.Modal,
):
gui.write(
"Are you sure you want to delete this published run? "
f"_({published_run.title})_"
)
gui.caption("This will also delete all the associated versions.")
with gui.div(className="d-flex"):
confirm_button = gui.button(
'<span class="text-danger">Confirm</span>',
type="secondary",
className="w-100",
)
cancel_button = gui.button(
"Cancel",
type="secondary",
className="w-100",
)

if confirm_button:
published_run.delete()
raise gui.RedirectException(self.app_url())

if cancel_button:
modal.close()

def _render_admin_options(self, current_run: SavedRun, published_run: PublishedRun):
if (
not self.is_current_user_admin()
Expand Down
Loading

0 comments on commit bb334bc

Please sign in to comment.