HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
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)