Allow user to unsubscribe and change their plan.

This commit is contained in:
yackob03 2013-10-02 02:05:53 -04:00
parent da8eccef11
commit 35c1e6e53b
3 changed files with 65 additions and 8 deletions

View file

@ -365,13 +365,13 @@ def subscribe():
request_data = request.get_json() request_data = request.get_json()
plan = request_data['plan'] plan = request_data['plan']
card = request_data['token']
user = current_user.db_user user = current_user.db_user
private_repos = model.get_private_repo_count(user.username) private_repos = model.get_private_repo_count(user.username)
if not user.stripe_id: if not user.stripe_id:
# Create the customer and plan simultaneously # Create the customer and plan simultaneously
card = request_data['token']
cus = stripe.Customer.create(email=user.email, plan=plan, card=card) cus = stripe.Customer.create(email=user.email, plan=plan, card=card)
user.stripe_id = cus.id user.stripe_id = cus.id
user.save() user.save()
@ -384,6 +384,11 @@ def subscribe():
# Change the plan # Change the plan
cus = stripe.Customer.retrieve(user.stripe_id) cus = stripe.Customer.retrieve(user.stripe_id)
cus.plan = plan 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() cus.save()
return jsonify(subscription_view(cus.subscription, private_repos)) return jsonify(subscription_view(cus.subscription, private_repos))
@ -399,3 +404,18 @@ def get_subscription():
return jsonify(subscription_view(cus.subscription, private_repos)) return jsonify(subscription_view(cus.subscription, private_repos))
abort(404) 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)

View file

@ -461,6 +461,7 @@ function UserAdminCtrl($scope, Restangular) {
$scope.subscribedPlan = planDict[sub.plan]; $scope.subscribedPlan = planDict[sub.plan];
$scope.planUsagePercent = sub.usedPrivateRepos * 100 / $scope.subscribedPlan.privateRepos; $scope.planUsagePercent = sub.usedPrivateRepos * 100 / $scope.subscribedPlan.privateRepos;
$scope.planLoading = false; $scope.planLoading = false;
$scope.planChanging = false;
} }
$scope.planLoading = true; $scope.planLoading = true;
@ -470,9 +471,13 @@ function UserAdminCtrl($scope, Restangular) {
$scope.planLoading = false; $scope.planLoading = false;
}); });
$scope.planChanging = false;
$scope.subscribe = function(planId) { $scope.subscribe = function(planId) {
var submitToken = function(token) { var submitToken = function(token) {
$scope.$apply(function() { $scope.$apply(function() {
$scope.planChanging = true;
$scope.errorMessage = undefined;
var subscriptionDetails = { var subscriptionDetails = {
token: token.id, token: token.id,
plan: planId, plan: planId,
@ -483,7 +488,7 @@ function UserAdminCtrl($scope, Restangular) {
var createSubscriptionRequest = Restangular.one('user/plan'); var createSubscriptionRequest = Restangular.one('user/plan');
createSubscriptionRequest.customPUT(subscriptionDetails).then(subscribedToPlan, function() { createSubscriptionRequest.customPUT(subscriptionDetails).then(subscribedToPlan, function() {
// Failure // Failure
$scope.errorMessage = 'Unable to process subscription change.'; $scope.errorMessage = 'Unable to subscribe.';
}); });
}); });
}; };
@ -501,4 +506,36 @@ function UserAdminCtrl($scope, Restangular) {
token: submitToken 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;
});
};
} }

View file

@ -1,4 +1,7 @@
<div class="container"> <div class="container">
<div class="loading" ng-show="planLoading || planChanging">
<div class="spin"></div>
</div>
<div class="row" ng-show="errorMessage"> <div class="row" ng-show="errorMessage">
<div class="col-md-12"> <div class="col-md-12">
<div class="alert alert-danger">{{ errorMessage }}</div> <div class="alert alert-danger">{{ errorMessage }}</div>
@ -17,13 +20,13 @@
<div class="panel-body"> <div class="panel-body">
{{ plan.privateRepos }} Private Repositories<br> {{ plan.privateRepos }} Private Repositories<br>
<button class="btn btn-primary" ng-hide="subscription" ng-click="subscribe(plan.stripeId)">Subscribe</button> <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" 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="cancel()">Cancel</button> <button class="btn btn-danger" ng-show="subscription.plan == plan.stripeId" ng-click="cancelSubscription()">Cancel</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="row" ng-hide="planLoading"> <div class="row" ng-show="subscription">
<div class="col-md-6"> <div class="col-md-6">
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"> <div class="panel-heading">
@ -39,7 +42,4 @@
</div> </div>
</div> </div>
</div> </div>
<div class="loading" ng-show="planLoading">
<div class="spin"></div>
</div>
</div> </div>