Skip to content

Commit 9fa6366

Browse files
committed
Fix #1491 as a shop owner I can bulk stop all subscriptions in my shop
1 parent 1be54a3 commit 9fa6366

3 files changed

Lines changed: 115 additions & 3 deletions

File tree

subscribie/blueprints/admin/__init__.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,61 @@ def stripe_create_charge():
384384
return jsonify(paymentIntent.status)
385385

386386

387+
@background_task
388+
def do_delete_stripe_subscription(
389+
subscription_id, app=None
390+
):
391+
"""Stop (delete) stripe_subscription via its
392+
Stripe subscription_id
393+
"""
394+
with app.app_context():
395+
stripe.api_key = get_stripe_secret_key()
396+
connect_account_id = get_stripe_connect_account_id()
397+
subscription = Subscription.query.filter_by(
398+
stripe_subscription_id=subscription_id
399+
).first()
400+
401+
log.info(f"Deleting (stopping) Strip subscription {subscription_id}")
402+
if subscription_id is None:
403+
log.error("subscription_id cannot be None")
404+
return False
405+
try:
406+
try:
407+
stripe_subscription = stripe.Subscription.retrieve(
408+
subscription_id, stripe_account=connect_account_id
409+
)
410+
411+
stripe.Subscription.delete(
412+
subscription_id, stripe_account=connect_account_id
413+
)
414+
log.debug(f"Subscription deleted ({subscription_id})")
415+
416+
# instead of inserting cancel directly into the db,
417+
# it refresh status after cancellation
418+
update_stripe_subscription_statuses()
419+
flash("Subscription cancelled")
420+
421+
except stripe._error.InvalidRequestError as e:
422+
if e.code == "resource_missing":
423+
msg = (
424+
"stripe subscription id: "
425+
f"{subscription_id} does not exist "
426+
f"for account {connect_account_id}. "
427+
"perhaps show owner has switched from test mode "
428+
"to live mode and has a new stripe connect account"
429+
)
430+
log.warning(msg)
431+
subscription.stripe_status = "resource_missing"
432+
database.session.commit()
433+
msg = f"Error could not retrieve subscription ({subscription_id}) to stop (is it deleted already?)" # noqa: E501
434+
log.error(f"{msg}. {e}")
435+
return False
436+
except Exception as e:
437+
msg = f"Error deleting subscription ({subscription_id})"
438+
log.error(f"{msg}. {e}")
439+
raise
440+
441+
387442
@background_task
388443
def do_pause_stripe_subscription_payment_collection(
389444
subscription_id, pause_collection_behavior="keep_as_draft", app=None
@@ -481,6 +536,24 @@ def do_pause_all_stripe_subscriptions(app=None):
481536
f"Error trying to pause subscription {subscription.uuid}. Error: {e}" # noqa: E501
482537
)
483538

539+
@background_task
540+
def do_stop_all_stripe_subscriptions(app=None):
541+
# For each Subscription object, get it's Stripe subscription
542+
# object and stop it using stop_stripe_subscription.
543+
with app.app_context():
544+
subscriptions = Subscription.query.all()
545+
for subscription in subscriptions:
546+
log.debug(f"Attempting to stop subscription {subscription.uuid}")
547+
stripe_subscription_id = subscription.stripe_subscription_id
548+
try:
549+
do_delete_stripe_subscription(
550+
stripe_subscription_id, app=current_app
551+
)
552+
except Exception as e:
553+
log.error(
554+
f"Error trying to stop subscription {subscription.uuid}. Error: {e}" # noqa: E501
555+
)
556+
484557

485558
@admin.route("/stripe/subscriptions/<subscription_id>/actions/pause")
486559
@login_required
@@ -521,6 +594,14 @@ def pause_all_subscribers_subscriptions():
521594
return """All payment collections are being paused in the background. You can move away from this page.""" # noqa: E501
522595

523596

597+
@admin.route("/stripe/subscriptions/all/actions/stop")
598+
@login_required
599+
def stop_all_subscribers_subscriptions():
600+
"""Bulk action to stop all subscriptions in the shop"""
601+
do_stop_all_stripe_subscriptions() # Background task
602+
return """All subscriptions are being stopped in the background. You can move away from this page.""" # noqa: E501
603+
604+
524605
@admin.route("/stripe/subscriptions/<subscription_id>/actions/resume")
525606
@login_required
526607
def resume_stripe_subscription(subscription_id):

subscribie/blueprints/admin/templates/admin/dashboard.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,11 @@ <h3 class="card-title justify-content-between d-flex">Stats</h3>
117117
<div class="px-3 py-3 my-3">
118118
<p class="card-subtitle mb-3 text-muted">
119119
Perform bulk actions across all subscribers such as
120-
pause all Subscribers payment collections.
120+
pause all Subscribers payment collections, or permanently stop all subscriptions.
121121
</p>
122122
<a class="btn btn-success btn-block"
123123
href="{{ url_for('admin.subscribers_bulk_operations_index') }}">
124-
Pause all Subscribers payment collections
124+
Pause all Subscribers payment collections, or stop all collections permanently.
125125
</a>
126126
</div>
127127
</div>

subscribie/blueprints/admin/templates/admin/subscribers_bulk_operations_index.html

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ <h2 class="text-center text-dark mb-3">Subscribers Bulk Operations</h2>
1717
<main>
1818
<div class="section">
1919
<div class="container">
20-
{% if 'confirm' not in request.args %}
20+
{% if 'confirm' not in request.args and 'confirm_stop_all_subscriptions' not in request.args %}
2121
<div class="col-md-12">
2222
<p>These bulk operations effect <em>all</em> Subscribers in your shop. This can save you time, for example,
2323
if you want to pause payment collection from every subscriber in your shop.</p>
@@ -34,6 +34,37 @@ <h3>Pause payment collection for every Subscription</h3>
3434
</a>
3535
</div>
3636
</div>
37+
<hr />
38+
<div class="col-md-12">
39+
<h3>Stop all Subscriptions</h3>
40+
<p>Stop <em>permanently</em> all current Subscriptions in this shop. Stopped Subscriptions cannot be re-started. Invoices are no longer raised
41+
for stopped subscriptions. </p>
42+
<p>If you intend to resume payment collection for <a href=""></a> Subscription at a later date, then you should pause
43+
the subscription rather than stop them.
44+
</p>
45+
<div class="">
46+
<a href="{{ url_for('admin.subscribers_bulk_operations_index', confirm_stop_all_subscriptions=0) }}" class="btn btn-danger">
47+
Stop permanently every Subscription in this Shop
48+
</a>
49+
</div>
50+
</div>
51+
52+
{% elif 'confirm_stop_all_subscriptions' in request.args %}
53+
<div class="col-md-12">
54+
<h3>Are you sure you want to cancel <em>all</em> Subscriptions for every Subscriber?</h3>
55+
<p>Once cancelled, no payment collections will take place, and no future invoices will be generated for those
56+
Subscriptions.
57+
</p>
58+
<p>This shop currently has {{ num_active_subscribers }} active <a href="{{ url_for('admin.subscribers', action='show_active') }}">subscriptions</a>.</p>
59+
<div class="">
60+
<a href="{{ url_for('admin.stop_all_subscribers_subscriptions', confirm=1) }}" class="btn btn-danger">
61+
<span class="cancel-yes">Yes</span>
62+
</a>
63+
<a href="{{ url_for('admin.subscribers_bulk_operations_index') }}" class="btn btn-success">
64+
<span class="cancel-no">No</span>
65+
</a>
66+
</div>
67+
</div>
3768
{% else %}
3869
<div class="col-md-12">
3970
<h3>Are you sure you want to pause payment collection for <em>all</em> Subscriptions for every Subscriber?</h3>

0 commit comments

Comments
 (0)