File: //home/arjun/projects/buyercall_new/buyercall/buyercall/blueprints/billing/views/billing.py
from flask import Blueprint, current_app, render_template, url_for, request, \
redirect, flash
from flask_login import login_required, current_user
from flask_babel import gettext as _
import logging
from config import settings
from buyercall.lib.util_json import render_json
from buyercall.blueprints.billing.forms import CreditCardForm, \
UpdateSubscriptionForm, CancelSubscriptionForm
from buyercall.blueprints.billing.models.coupon import Coupon
from buyercall.blueprints.billing.models.subscription import Subscription
from buyercall.blueprints.billing.models.invoice import Invoice
from buyercall.blueprints.billing.decorators import subscription_required, \
handle_stripe_exceptions
from buyercall.blueprints.user.decorators import role_required
from sqlalchemy.sql.elements import and_, or_
billing = Blueprint('billing', __name__, template_folder='../templates',
url_prefix='/subscription')
log = logging.getLogger(__name__)
@billing.before_request
@login_required
def check_accessibility():
if (current_user.role == 'admin' and current_user.partnership_or_partnership_account.billing_type == 'partnership')\
or (current_user.role == 'partner' and
current_user.partnership_or_partnership_account.billing_type == 'account') \
or current_user.partnership_or_partnership_account.billing_type == 'invoice':
return redirect(url_for('user.settings'))
@billing.route('/pricing')
@login_required
@role_required('admin', 'partner')
def pricing():
dep = 'partnership'
if current_user.role == 'admin':
dep = 'partnership_account'
current_subscription = getattr(current_user, dep).subscription
if current_user.is_authenticated and current_subscription and current_subscription.status == 'active':
return redirect(url_for('billing.update'))
form = UpdateSubscriptionForm()
return render_template('billing/pricing.jinja2', form=form,
plans=settings.STRIPE_PLANS)
@billing.route('/pricing_invoice_uer34lk4s')
@login_required
@role_required('admin', 'partner')
def pricing_invoice():
dep = 'partnership'
if current_user.role == 'admin':
dep = 'partnership_account'
if current_user.is_authenticated and getattr(current_user, dep).subscription:
return redirect(url_for('billing.update'))
form = UpdateSubscriptionForm()
return render_template('billing/pricing_invoice.jinja2', form=form,
plans=settings.STRIPE_PLANS)
@billing.route('/pricing_small_business')
@login_required
@role_required('admin', 'partner')
def pricing_small_business():
dep = 'partnership'
if current_user.role == 'admin':
dep = 'partnership_account'
if current_user.is_authenticated and getattr(current_user, dep).subscription:
return redirect(url_for('billing.update'))
form = UpdateSubscriptionForm()
return render_template('billing/pricing_small_business.jinja2', form=form,
plans=settings.STRIPE_PLANS)
@billing.route('/coupon_code', methods=['POST'])
@login_required
@role_required('admin', 'partner', 'sysadmin', 'limitsysadmin')
def coupon_code():
code = request.form.get('coupon_code')
if code is None:
return render_json(422,
{'error': _('Discount code cannot be processed.')})
coupon = Coupon.find_by_code(code)
if coupon is None:
return render_json(404, {'error': _('Discount code not found.')})
return render_json(200, {'data': coupon.serialize()})
@billing.route('/create', methods=['GET', 'POST'])
@handle_stripe_exceptions
@login_required
@role_required('admin', 'partner')
def create():
if current_user.partnership_or_partnership_account.has_active_subscription:
flash(_('You already have an active subscription.'), 'info')
return redirect(url_for('user.settings'))
plan = request.args.get('plan')
log.debug('The selected plan is {}'.format(plan))
active_plan = Subscription.get_plan_by_id(plan)
# Guard against an invalid or missing plan.
if active_plan is None and request.method == 'GET':
return redirect(url_for('billing.pricing'))
stripe_key = current_app.config.get('STRIPE_PUBLISHABLE_KEY')
# log.debug('The current user is {} and the plan is {}'.format(current_user, plan))
if plan == 'invoice':
subscription = Subscription()
created = subscription.create_invoice_subscription(
user=current_user, plan=plan
)
log.debug('the created dict is {}'.format(created))
if created:
flash(_('Awesome, thanks for subscribing!'), 'success')
else:
flash(_('You must enable Javascript for this request.'), 'warn')
return redirect(url_for('user.welcome'))
form = CreditCardForm(stripe_key=stripe_key, plan=plan)
if form.validate_on_submit():
subscription = Subscription()
log.debug('the subscription parameters are name: {}, plan: {}, coupon: {}, token: {}, quantity: {}'.format(
request.form.get('name'),
request.form.get('plan'),
request.form.get('coupon_code'),
request.form.get('stripe_token'),
request.form.get('quantity')))
created = subscription.create(user=current_user,
name=request.form.get('name'),
plan=request.form.get('plan'),
coupon=request.form.get('coupon_code'),
token=request.form.get('stripe_token'),
quantity=request.form.get('quantity'))
log.debug('the created dict is {}'.format(created))
if not created:
flash(_('Failed to create subscription.'), 'error')
return redirect(url_for('user.settings'))
flash(_('Awesome, thanks for subscribing!'), 'success')
return redirect(url_for('user.welcome'))
return render_template('billing/payment_method.jinja2',
form=form, plan=active_plan)
@billing.route('/update', methods=['GET', 'POST'])
@handle_stripe_exceptions
@subscription_required
@login_required
@role_required('admin', 'partner')
def update():
subscription = current_user.partnership_or_partnership_account.subscription
current_plan = subscription.plan
active_plan = Subscription.get_plan_by_id(current_plan)
new_plan = Subscription.get_new_plan(request.form.keys())
plan = Subscription.get_plan_by_id(new_plan)
# Guard against an invalid, missing or identical plan.
is_same_plan = new_plan == active_plan['id']
if ((new_plan and not plan) or is_same_plan) and request.method == 'POST':
return redirect(url_for('billing.update'))
form = UpdateSubscriptionForm()
if form.validate_on_submit():
updated = subscription.update(user=current_user,
coupon=request.form.get('coupon_code'),
plan=plan.get('id'))
if updated:
flash(_('Your subscription has been updated.'), 'success')
return redirect(url_for('user.settings'))
return render_template('billing/pricing.jinja2',
form=form,
plans=settings.STRIPE_PLANS,
active_plan=active_plan)
@billing.route('/cancel', methods=['GET', 'POST'])
@handle_stripe_exceptions
@login_required
@role_required('admin', 'partner')
def cancel():
subscription = current_user.partnership_or_partnership_account.subscription
if not subscription:
flash(_('You do not have an active subscription.'), 'error')
return redirect(url_for('user.settings'))
form = CancelSubscriptionForm()
if form.validate_on_submit():
cancelled = subscription.cancel(user=current_user)
if cancelled:
flash(_(
'Sorry to see you go, your subscription has been cancelled.'),
'success')
return redirect(url_for('user.settings'))
return render_template('billing/cancel.jinja2', form=form)
@billing.route('/update_payment_method', methods=['GET', 'POST'])
@handle_stripe_exceptions
@login_required
@role_required('admin', 'partner', 'sysadmin', 'limitsysadmin')
def update_payment_method():
subscription = current_user.partnership_or_partnership_account.subscription
if not subscription.credit_card:
flash(_('You do not have a payment method on file.'), 'error')
return redirect(url_for('user.settings'))
active_plan = Subscription.get_plan_by_id(
subscription.plan)
card_last4 = str(subscription.credit_card.last4)
stripe_key = current_app.config.get('STRIPE_PUBLISHABLE_KEY')
form = CreditCardForm(stripe_key=stripe_key,
plan=active_plan,
name=subscription.credit_card.cc_name)
if form.validate_on_submit():
updated = subscription.update_payment_method(user=current_user,
name=request.form.get(
'name'),
token=request.form.get(
'stripe_token'))
if updated:
flash(_('Your payment method has been updated.'), 'success')
else:
flash(_('You must enable Javascript for this request.'), 'warning')
return redirect(url_for('user.settings'))
return render_template('billing/payment_method.jinja2', form=form,
plan=active_plan, card_last4=card_last4)
@billing.route('/billing_history')
@handle_stripe_exceptions
@login_required
@role_required('admin', 'partner')
def billing_history():
subscription = current_user.partnership_or_partnership_account.subscription
invoices = Invoice.query.filter(
or_(
and_(current_user.role == 'partner', Invoice.partnership_id == current_user.partnership_id),
and_(current_user.role == 'admin', Invoice.partnership_account_id == current_user.partnership_account_id)
)
) \
.order_by(Invoice.created_on.desc()).limit(12)
if subscription:
upcoming = Invoice.upcoming(subscription.payment_id)
coupon = Coupon.query \
.filter(Coupon.code == subscription.coupon).first()
else:
upcoming = None
coupon = None
return render_template('billing/billing_history.jinja2',
invoices=invoices, upcoming=upcoming, coupon=coupon)