From 35c1e6e53bb19f06dffa376409e5a23a819ba1a3 Mon Sep 17 00:00:00 2001 From: yackob03 <jacob.moshenko@gmail.com> Date: Wed, 2 Oct 2013 02:05:53 -0400 Subject: [PATCH] Allow user to unsubscribe and change their plan. --- endpoints/api.py | 22 ++++++++++++++++++- static/js/controllers.js | 39 ++++++++++++++++++++++++++++++++- static/partials/user-admin.html | 12 +++++----- 3 files changed, 65 insertions(+), 8 deletions(-) diff --git a/endpoints/api.py b/endpoints/api.py index 96e0ca01d..a550a58cf 100644 --- a/endpoints/api.py +++ b/endpoints/api.py @@ -365,13 +365,13 @@ def subscribe(): request_data = request.get_json() plan = request_data['plan'] - card = request_data['token'] user = current_user.db_user private_repos = model.get_private_repo_count(user.username) if not user.stripe_id: # Create the customer and plan simultaneously + card = request_data['token'] cus = stripe.Customer.create(email=user.email, plan=plan, card=card) user.stripe_id = cus.id user.save() @@ -384,6 +384,11 @@ def subscribe(): # Change the plan cus = stripe.Customer.retrieve(user.stripe_id) cus.plan = plan + + # User may have been a previous customer who is resubscribing + if 'token' in request_data: + cus.card = request_data['token'] + cus.save() return jsonify(subscription_view(cus.subscription, private_repos)) @@ -399,3 +404,18 @@ def get_subscription(): return jsonify(subscription_view(cus.subscription, private_repos)) abort(404) + + + +@app.route('/api/user/plan', methods=['DELETE']) +@api_login_required +def cancel_subscription(): + user = current_user.db_user + + if user.stripe_id: + private_repos = model.get_private_repo_count(user.username) + cus = stripe.Customer.retrieve(user.stripe_id) + cus.cancel_subscription() + return make_response('Deleted', 204) + + abort(404) \ No newline at end of file diff --git a/static/js/controllers.js b/static/js/controllers.js index d397ba0ba..988fe4a31 100644 --- a/static/js/controllers.js +++ b/static/js/controllers.js @@ -461,6 +461,7 @@ function UserAdminCtrl($scope, Restangular) { $scope.subscribedPlan = planDict[sub.plan]; $scope.planUsagePercent = sub.usedPrivateRepos * 100 / $scope.subscribedPlan.privateRepos; $scope.planLoading = false; + $scope.planChanging = false; } $scope.planLoading = true; @@ -470,9 +471,13 @@ function UserAdminCtrl($scope, Restangular) { $scope.planLoading = false; }); + $scope.planChanging = false; $scope.subscribe = function(planId) { var submitToken = function(token) { $scope.$apply(function() { + $scope.planChanging = true; + $scope.errorMessage = undefined; + var subscriptionDetails = { token: token.id, plan: planId, @@ -483,7 +488,7 @@ function UserAdminCtrl($scope, Restangular) { var createSubscriptionRequest = Restangular.one('user/plan'); createSubscriptionRequest.customPUT(subscriptionDetails).then(subscribedToPlan, function() { // Failure - $scope.errorMessage = 'Unable to process subscription change.'; + $scope.errorMessage = 'Unable to subscribe.'; }); }); }; @@ -501,4 +506,36 @@ function UserAdminCtrl($scope, Restangular) { token: submitToken }); }; + + $scope.changeSubscription = function(planId) { + $scope.planChanging = true; + $scope.errorMessage = undefined; + + var subscriptionDetails = { + plan: planId, + }; + + var changeSubscriptionRequest = Restangular.one('user/plan'); + changeSubscriptionRequest.customPUT(subscriptionDetails).then(subscribedToPlan, function() { + // Failure + $scope.errorMessage = 'Unable to change subscription.'; + $scope.planChanging = false; + }); + }; + + $scope.cancelSubscription = function() { + $scope.planChanging = true; + $scope.errorMessage = undefined; + var unsubscribeRequest = Restangular.one('user/plan'); + unsubscribeRequest.customDELETE().then(function() { + $scope.subscription = undefined; + $scope.subscribedPlan = undefined; + $scope.planUsagePercent = 0; + $scope.planChanging = false; + }, function() { + // Failure + $scope.errorMessage = 'Unable to unsubscribe.'; + $scope.planChanging = false; + }); + }; } \ No newline at end of file diff --git a/static/partials/user-admin.html b/static/partials/user-admin.html index fb70a249e..2173898e1 100644 --- a/static/partials/user-admin.html +++ b/static/partials/user-admin.html @@ -1,4 +1,7 @@ <div class="container"> + <div class="loading" ng-show="planLoading || planChanging"> + <div class="spin"></div> + </div> <div class="row" ng-show="errorMessage"> <div class="col-md-12"> <div class="alert alert-danger">{{ errorMessage }}</div> @@ -17,13 +20,13 @@ <div class="panel-body"> {{ plan.privateRepos }} Private Repositories<br> <button class="btn btn-primary" ng-hide="subscription" ng-click="subscribe(plan.stripeId)">Subscribe</button> - <button class="btn" ng-show="subscription && (subscription.plan != plan.stripeId)" ng-click="subscribe(plan.stripeId)">Change</button> - <button class="btn btn-danger" ng-show="subscription.plan == plan.stripeId" ng-click="cancel()">Cancel</button> + <button class="btn" ng-show="subscription && (subscription.plan != plan.stripeId)" ng-click="changeSubscription(plan.stripeId)">Change</button> + <button class="btn btn-danger" ng-show="subscription.plan == plan.stripeId" ng-click="cancelSubscription()">Cancel</button> </div> </div> </div> </div> - <div class="row" ng-hide="planLoading"> + <div class="row" ng-show="subscription"> <div class="col-md-6"> <div class="panel panel-default"> <div class="panel-heading"> @@ -39,7 +42,4 @@ </div> </div> </div> - <div class="loading" ng-show="planLoading"> - <div class="spin"></div> - </div> </div> \ No newline at end of file