diff --git a/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb b/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb index 046a67a..a3f7f7f 100644 --- a/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb +++ b/app/controllers/discourse_subscriptions/admin/subscriptions_controller.rb @@ -26,7 +26,9 @@ module DiscourseSubscriptions end def destroy + params.require(:id) begin + refund_subscription(params[:id]) if params[:refund] subscription = ::Stripe::Subscription.delete(params[:id]) customer = Customer.find_by( @@ -49,6 +51,18 @@ module DiscourseSubscriptions render_json_error e.message end end + + private + + # this will only refund the most recent subscription payment + def refund_subscription(subscription_id) + subscription = ::Stripe::Subscription.retrieve(subscription_id) + invoice = ::Stripe::Invoice.retrieve(subscription[:latest_invoice]) if subscription[:latest_invoice] + payment_intent = invoice[:payment_intent] if invoice[:payment_intent] + refund = ::Stripe::Refund.create({ + payment_intent: payment_intent, + }) + end end end end diff --git a/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 b/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 index fa4ba1e..f4b51f9 100644 --- a/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 +++ b/assets/javascripts/discourse/controllers/admin-plugins-discourse-subscriptions-subscriptions.js.es6 @@ -1,3 +1,12 @@ import Controller from "@ember/controller"; +import showModal from "discourse/lib/show-modal"; -export default Controller.extend({}); +export default Controller.extend({ + actions: { + showCancelModal(subscription) { + showModal("admin-cancel-subscription", { + model: subscription, + }); + }, + }, +}); diff --git a/assets/javascripts/discourse/models/admin-subscription.js.es6 b/assets/javascripts/discourse/models/admin-subscription.js.es6 index 73e6ecc..0641244 100644 --- a/assets/javascripts/discourse/models/admin-subscription.js.es6 +++ b/assets/javascripts/discourse/models/admin-subscription.js.es6 @@ -19,9 +19,13 @@ const AdminSubscription = EmberObject.extend({ return getURL(`/admin/users/${metadata.user_id}/${metadata.username}`); }, - destroy() { + destroy(refund) { + const data = { + refund: refund, + }; return ajax(`/s/admin/subscriptions/${this.id}`, { method: "delete", + data, }).then((result) => AdminSubscription.create(result)); }, }); diff --git a/assets/javascripts/discourse/routes/admin-plugins-discourse-subscriptions-subscriptions.js.es6 b/assets/javascripts/discourse/routes/admin-plugins-discourse-subscriptions-subscriptions.js.es6 index 1432e3c..42c6a86 100644 --- a/assets/javascripts/discourse/routes/admin-plugins-discourse-subscriptions-subscriptions.js.es6 +++ b/assets/javascripts/discourse/routes/admin-plugins-discourse-subscriptions-subscriptions.js.es6 @@ -1,6 +1,6 @@ +import I18n from "I18n"; import Route from "@ember/routing/route"; import AdminSubscription from "discourse/plugins/discourse-subscriptions/discourse/models/admin-subscription"; -import I18n from "I18n"; export default Route.extend({ model() { @@ -8,29 +8,24 @@ export default Route.extend({ }, actions: { - cancelSubscription(subscription) { - bootbox.confirm( - I18n.t( - "discourse_subscriptions.user.subscriptions.operations.destroy.confirm" - ), - I18n.t("no_value"), - I18n.t("yes_value"), - (confirmed) => { - if (confirmed) { - subscription.set("loading", true); - - subscription - .destroy() - .then((result) => subscription.set("status", result.status)) - .catch((data) => - bootbox.alert(data.jqXHR.responseJSON.errors.join("\n")) - ) - .finally(() => { - subscription.set("loading", false); - }); - } - } - ); + cancelSubscription(model) { + const subscription = model.subscription; + const refund = model.refund; + subscription.set("loading", true); + subscription + .destroy(refund) + .then((result) => { + subscription.set("status", result.status); + this.send("closeModal"); + bootbox.alert(I18n.t("discourse_subscriptions.admin.canceled")); + }) + .catch((data) => + bootbox.alert(data.jqXHR.responseJSON.errors.join("\n")) + ) + .finally(() => { + subscription.set("loading", false); + this.refresh(); + }); }, }, }); diff --git a/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs b/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs index ee6d91a..fcf5877 100644 --- a/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs +++ b/assets/javascripts/discourse/templates/admin/plugins-discourse-subscriptions-subscriptions.hbs @@ -34,7 +34,7 @@ {{#if subscription.loading}} {{loading-spinner size="small"}} {{else}} - {{d-button disabled=subscription.canceled label="cancel" action=(route-action "cancelSubscription" subscription) icon="times"}} + {{d-button disabled=subscription.canceled label="cancel" action=(action "showCancelModal" subscription) icon="times"}} {{/if}} diff --git a/assets/javascripts/discourse/templates/modal/admin-cancel-subscription.hbs b/assets/javascripts/discourse/templates/modal/admin-cancel-subscription.hbs new file mode 100644 index 0000000..0f114c3 --- /dev/null +++ b/assets/javascripts/discourse/templates/modal/admin-cancel-subscription.hbs @@ -0,0 +1,21 @@ +
+ {{#d-modal-body rawTitle=(i18n "discourse_subscriptions.user.subscriptions.operations.destroy.confirm")}} + {{input type="checkbox" checked=refund}} + {{i18n "discourse_subscriptions.admin.ask_refund"}} + {{/d-modal-body}} + + + +
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index 4cb991c..b712a78 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -148,3 +148,5 @@ en: plan: Plan status: Status created_at: Created + ask_refund: Refund the last payment made by the customer? + canceled: "The subscription is canceled." diff --git a/spec/requests/admin/subscriptions_controller_spec.rb b/spec/requests/admin/subscriptions_controller_spec.rb index 338f950..cb5b693 100644 --- a/spec/requests/admin/subscriptions_controller_spec.rb +++ b/spec/requests/admin/subscriptions_controller_spec.rb @@ -99,6 +99,21 @@ module DiscourseSubscriptions delete "/s/admin/subscriptions/sub_12345.json" }.not_to change { user.groups.count } end + + it "refunds if params[:refund] present" do + ::Stripe::Subscription + .expects(:delete) + .with('sub_12345') + .returns( + plan: { product: 'pr_34578' }, + customer: 'c_123' + ) + ::Stripe::Subscription.expects(:retrieve).with('sub_12345').returns(latest_invoice: 'in_123') + ::Stripe::Invoice.expects(:retrieve).with('in_123').returns(payment_intent: 'pi_123') + ::Stripe::Refund.expects(:create).with(payment_intent: 'pi_123') + + delete "/s/admin/subscriptions/sub_12345.json", params: { refund: true } + end end end end