Team billing info and ability to cancel subscription.

master
Nick Sergeant 2015-10-25 22:36:19 -04:00
parent 79d077def9
commit 4127ba79b1
8 changed files with 123 additions and 45 deletions

View File

@ -23,6 +23,14 @@ jQuery(function($) {
var pre = $pres.eq(i);
pre.width(pre.parents('section.code').width() - 30);
});
$('form#cancel-team-subscription').submit(function() {
if (confirm('Are you sure you want to cancel your subscription?\n\nYou will no longer be able to create new Snipts under this team. This action is effective immediately and we unfortunately cannot issue any refunds.')) {
return true;
} else {
return false;
}
});
});
// Angular app init.

View File

@ -23,6 +23,7 @@ if (typeof angular !== 'undefined') {
// Controllers.
controllers.TeamController = function($scope, $timeout, TeamStorage) {
$scope.users = [];
$scope.search = '';
$scope.$watch('search', function(val) {
$timeout.cancel($scope.timeout);

View File

@ -12,6 +12,11 @@
{% endblock %}
{% block content %}
{% if 'team-cancelled' in request.GET %}
<div class="alert alert-success" style="margin: 30px;">
Your team plan has been succesfully cancelled.
</div>
{% endif %}
<section class="snipts" id="snipts" ng-controller="SniptListController"
{% if request.user.profile.list_view == 'C' %}
ng-cloak ng-show="$root.account.id"

View File

@ -1,5 +1,7 @@
{% extends "base.html" %}
{% load team_tags %}
{% block page-title %}Team Billing{% endblock %}
{% block body-class %}account {{ block.super }}{% endblock %}
@ -28,26 +30,29 @@
</aside>
<section class="content">
<div class="def" data-title="Plan">
25 users
{{ name }}
</div>
<div class="def" data-title="Price">
$49.00 USD / month
${{ amount|currency_convert }}.00 USD / {{ interval }}
</div>
<div class="def" data-title="Card">
xxxx-xxxx-xxxx-4242
xxxx-xxxx-xxxx-{{ last4 }}
</div>
<div class="def" data-title="Status">
Active
{{ status }}
</div>
<div class="def" data-title="Team since">
August 29, 2015
{{ team.created|date:'M d, Y' }}
</div>
<div class="def" data-title="Next bill date" ng-show="user.stripeAccount.status != 'inactive'">
November 29, 2015
{{ nextBill|to_date|date:'M d, Y' }}
</div>
<p class="alert alert-info group" style="padding-right: 8px;">
<a href="/{{ team.slug }}/billing/cancel/" class="btn btn-danger pull-right">Cancel subscription</a>
</p>
<form class="alert alert-info group" style="margin: 15px; padding-right: 8px;" id="cancel-team-subscription" action="/{{ team.slug }}/billing/cancel/" method="post">
{% csrf_token %}
<button type="submit" class="btn btn-danger pull-right">
Cancel subscription
</button>
</form>
</section>
</section>
{% endblock %}

View File

@ -1,3 +1,5 @@
import datetime
from django import template
register = template.Library()
@ -6,3 +8,13 @@ register = template.Library()
@register.filter
def user_is_member(team, user):
return team.user_is_member(user)
@register.filter
def currency_convert(amount):
return amount / 100
@register.filter
def to_date(timestamp):
return datetime.datetime.fromtimestamp(float(timestamp))

View File

@ -17,4 +17,7 @@ urlpatterns = \
name='team-members'),
url(r'^(?P<username>[^/]+)/billing/$',
views.team_billing,
name='team-billing'))
name='team-billing'),
url(r'^(?P<username>[^/]+)/billing/cancel/$',
views.cancel_team_subscription,
name='team-cancel-subscription'))

View File

@ -20,12 +20,76 @@ def for_teams(request):
return {}
@login_required
@render_to('teams/for-teams-complete.html')
def for_teams_complete(request):
if request.method == 'POST' and request.user.is_authenticated():
token = request.POST['token']
stripe.api_key = os.environ.get('STRIPE_SECRET_KEY',
settings.STRIPE_SECRET_KEY)
plan = request.POST['plan']
try:
customer = stripe.Customer.create(card=token,
plan=plan,
email=request.user.email)
except stripe.CardError, e:
error_message = e.json_body['error']['message']
return HttpResponseRedirect('/for-teams/?declined=%s' %
error_message or
'Your card was declined.')
team = Team(name=request.POST['team-name'],
email=request.POST['email'],
plan=plan,
owner=request.user)
team.stripe_id = customer.id
team.save()
user = User.objects.create_user(team.slug,
team.email,
str(uuid.uuid4()))
team.user = user
team.save()
return {
'team': team
}
else:
return HttpResponseBadRequest()
@login_required
@render_to('teams/team-billing.html')
def team_billing(request, username):
team = get_object_or_404(Team, slug=username, disabled=False)
if team.owner != request.user:
raise Http404
stripe.api_key = os.environ.get('STRIPE_SECRET_KEY',
settings.STRIPE_SECRET_KEY)
customer = stripe.Customer.retrieve(team.stripe_id)
data = {
'last4': customer.active_card.last4,
'created': customer.created,
'email': customer.email,
'team': team
}
if customer.subscription:
data['amount'] = customer.subscription.plan.amount
data['interval'] = customer.subscription.plan.interval
data['name'] = customer.subscription.plan.name
data['status'] = customer.subscription.status
data['nextBill'] = customer.subscription.current_period_end
else:
data['status'] = 'inactive'
return data
return {
'team': team
}
@ -72,42 +136,22 @@ def remove_team_member(request, username, member):
@login_required
@render_to('teams/for-teams-complete.html')
def for_teams_complete(request):
if request.method == 'POST' and request.user.is_authenticated():
def cancel_team_subscription(request, username):
token = request.POST['token']
stripe.api_key = os.environ.get('STRIPE_SECRET_KEY',
settings.STRIPE_SECRET_KEY)
if request.method != 'POST':
raise Http404
plan = request.POST['plan']
team = get_object_or_404(Team, slug=username, disabled=False)
if team.owner != request.user:
raise Http404
try:
customer = stripe.Customer.create(card=token,
plan=plan,
email=request.user.email)
except stripe.CardError, e:
error_message = e.json_body['error']['message']
return HttpResponseRedirect('/for-teams/?declined=%s' %
error_message or
'Your card was declined.')
stripe.api_key = os.environ.get('STRIPE_SECRET_KEY',
settings.STRIPE_SECRET_KEY)
customer = stripe.Customer.retrieve(team.stripe_id)
customer.delete()
team = Team(name=request.POST['team-name'],
email=request.POST['email'],
plan=plan,
owner=request.user)
team.stripe_id = customer.id
team.save()
team.disabled = True
team.stripe_id = None
team.save()
user = User.objects.create_user(team.slug,
team.email,
str(uuid.uuid4()))
team.user = user
team.save()
return {
'team': team
}
else:
return HttpResponseBadRequest()
return HttpResponseRedirect('/' + team.slug + '/?team-cancelled=true')

View File

@ -1,4 +1,4 @@
<a href="/signup" class="snipt-promo">
<button class="btn btn-success btn-large pull-right">Sign up &raquo;</button>
Sign up for Snipt!<br /><span style="font-size: 16px;">Post public snipts for free. Private snipts just $5/mo.</span>
Sign up for Snipt!<br /><span style="font-size: 16px;">Post public snipts for free.</span>
</a>