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/partnership/views.py
import os
import csv
import sys
import traceback
import logging as log
from buyercall.lib.util_crypto import AESCipher
from flask import (
    Blueprint,
    make_response,
    flash,
    render_template,
    request,
    redirect,
    url_for,
    current_app as app
)
from flask_babel import gettext as _
from flask_babel import ngettext as _n
from flask_login import login_required, current_user, logout_user, login_user
from buyercall.lib.supervisor_manager import current_supervisor_user
from buyercall.lib.supervisor_manager import (
    login_user as supervisor_login_user
)
from sqlalchemy.sql.elements import and_
from sqlalchemy import asc, desc, func, extract
from contextlib import closing
from io import StringIO
from buyercall.blueprints.user.decorators import role_required
from buyercall.blueprints.admin.forms import SearchForm, BulkDeleteForm, UserForm, UserCancelSubscriptionForm
from buyercall.blueprints.reports.models import Report, ReportUserTie
from buyercall.extensions import db
from sqlalchemy.sql import text
from buyercall.blueprints.user.models import User
from buyercall.blueprints.leads.models import Lead
from buyercall.blueprints.partnership.models import Partnership, \
    PartnershipAccount, PartnershipAccountGroup, PartnershipAccountGroupTie, \
    ExternalApiServiceProviders, ExternalApiServiceProvidersPartnershipAccountTie, PartnershipCpaasProviders, \
    PartnershipCreditTie
from buyercall.blueprints.billing.models.subscription import Subscription
from buyercall.blueprints.user.decorators import anonymous_required
from wtforms import Label
from datetime import date
from datetime import datetime
import math
from buyercall.blueprints.partnership.forms import PartnershipAccountForm, PartnershipForm, \
    ExternalApiServiceProvider, PartnershipTwilioApiForm, PartnershipBandwidthApiForm, PartnerFinservPrequalifyForm

partnership = Blueprint('partnership', __name__, template_folder='templates')
log = log.getLogger(__name__)


@partnership.before_request
def before_request():
    if request.path.find('partnership/partnership_invite') == -1:
        # @login_required
        if not current_user.is_authenticated:
            return app.login_manager.unauthorized()
        # @role_required('partner')
        if current_user.role not in ['partner']:
            if current_user.role == 'admin':
                if not current_user.is_admin_user_with_groups:
                    flash(_('You do not have permission to do that.'), 'danger')
                    return redirect('/')
                elif current_user.is_admin_user_with_groups and current_user.is_viewing_partnership \
                        and current_user.get_user_viewing_partnership_account_subscription_plan == 'partnershipsingle':
                    if request.path.find('company_accounts/switch_back') == -1:
                        return redirect(url_for('contacts.contact_list'))
                elif current_user.is_admin_user_with_groups and current_user.is_viewing_partnership:
                    if request.path.find('company_accounts/switch_back') == -1:
                        return redirect(url_for('dashboard.user_dashboard'))
            else:
                flash(_('You do not have permission to do that.'), 'danger')
                return redirect('/')
    # @anonymous_required()
    elif current_user.is_authenticated:
        return redirect('/settings')


# Account Groups ------------------------------------------------------------------
@role_required('admin')
@partnership.route('/company_accounts/group_act_as', methods=['POST'])
def group_act_as():
    if current_user.is_authenticated and current_user.is_admin_user_with_groups:
        target_partnership_account = PartnershipAccount.query\
            .filter(PartnershipAccount.id == int(request.form.get('account_id'))).first()

        if target_partnership_account is None:
            flash(_("Such Account does not exist"))
            return redirect(url_for('partnership.company_accounts'))

        if not User.is_in_same_group(current_user.id, target_partnership_account.id):
            flash(_("You don't have access to load this account"))
            return redirect(url_for('partnership.company_accounts'))

        if User.set_user_viewing_partnership_account(current_user.id, target_partnership_account.id):
            if current_user.get_user_viewing_partnership_account_subscription_plan == 'partnershipsingle':
                return redirect(url_for('contacts.contact_list'))
            else:
                return redirect(url_for('dashboard.user_dashboard'))
        else:
            flash(_("Error loading this account"))
            return redirect(url_for('partnership.company_accounts'))
    else:
        return redirect(url_for('user.login'))


@role_required('admin')
@partnership.route('/company_accounts')
def company_accounts():
    search_form = SearchForm()
    bulk_form = BulkDeleteForm()

    partnership_account_groups_list = None
    company_account_name = ''

    if current_user.is_admin_user_with_groups and not current_user.is_viewing_partnership:

        group_tie = PartnershipAccountGroup.query.filter(
            and_(PartnershipAccountGroupTie.partnership_account_id == current_user.partnership_account_id,
                 PartnershipAccountGroupTie.partnership_account_group_id == PartnershipAccountGroup.id,
                 PartnershipAccountGroupTie.partnership_account_group_id == current_user.partnership_account_group_id)
        ).first()

        company_account_name = group_tie.name
        sort_by = PartnershipAccount.sort_by(request.args.get('sort', 'name'),
                                             request.args.get('direction', 'asc'))
        table = 'partnership_accounts'
        order_values = '{0}.{1} {2}'.format(table, sort_by[0], sort_by[1])

        if request.args.get('sort', 'name') == 'count':
            table = 'partnership_accounts'
            sort_by = 'count(users.partnership_account_id)', sort_by[1]
            order_values = '{1} {2}'.format(table, sort_by[0], sort_by[1])

        partnership_account_groups_list = PartnershipAccount \
            .query \
            .with_entities(PartnershipAccount.active, PartnershipAccount.id, PartnershipAccount.name) \
            .filter(PartnershipAccount.search(request.args.get('q', ''))) \
            .filter(and_(PartnershipAccountGroupTie.partnership_account_group_id == group_tie.id,
                         PartnershipAccount.id == PartnershipAccountGroupTie.partnership_account_id)) \
            .all()

        return render_template('company_accounts/index.jinja2',
                               form=search_form,
                               bulk_form=bulk_form,
                               company_account=company_account_name,
                               partnership_account_groups=partnership_account_groups_list)
    else:
        if current_user.role == 'admin':
            return redirect(url_for('dashboard.user_dashboard'))
        elif current_user.role == 'partner':
            return redirect(url_for('partnership.accounts'))
        else:
            return redirect(url_for('user.settings'))


@partnership.route('/company_accounts/switch_back', methods=['GET'])
@login_required
def switch_back():

    if current_user.is_admin_user_with_groups:
        User.set_user_viewing_partnership_account(current_user.id, -1)

        return redirect(url_for('partnership.company_accounts'))
    else:
        return redirect(url_for('user.settings'))


# Accounts  -----------------------------------------------------------------------
@partnership.route('/accounts', defaults={'page': 1})
@partnership.route('/accounts/page/<int:page>')
@login_required
def accounts(page):
    if current_user.role != 'admin':
        search_form = SearchForm()
        bulk_form = BulkDeleteForm()

        sort_by = PartnershipAccount.sort_by(request.args.get('sort', 'name'),
                                             request.args.get('direction', 'asc'))
        table = 'partnership_accounts'
        order_values = '{0}.{1} {2}'.format(table, sort_by[0], sort_by[1])

        if request.args.get('sort', 'name') == 'count':
            table = 'partnership_accounts'
            sort_by = 'count(users.partnership_account_id)', sort_by[1]
            order_values = '{1} {2}'.format(table, sort_by[0], sort_by[1])

        order_query = text(order_values)

        paginated_accounts = PartnershipAccount.query.with_entities(
            PartnershipAccount.active,
            PartnershipAccount.id,
            PartnershipAccount.name,
            func.count(User.partnership_account_id).label('count')
        ).outerjoin(
            User,
            and_(
                User.partnership_account_id == PartnershipAccount.id,
                User.partnership_account_id is not None,
                User.partnership_id == current_user.partnership_id,
                User.role == 'admin'
            ))\
            .filter(PartnershipAccount.partnership_id == current_user.partnership_id) \
            .filter(PartnershipAccount.search(request.args.get('q', ''))) \
            .order_by(order_query) \
            .group_by(PartnershipAccount.active, PartnershipAccount.id, PartnershipAccount.name,
                      User.partnership_account_id) \
            .paginate(page, 20, True)

        # Create domain section of partner token url
        token_domain = current_user.partnership.partner_url
        if not token_domain:
            token_domain = 'https://buyercall.com'

        return render_template('accounts/index.jinja2',
                               form=search_form, bulk_form=bulk_form,
                               partnership_accounts=paginated_accounts,
                               domain=token_domain)
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/all_admins')
def admins():
    if current_user.role != 'admin':
        return redirect(url_for('partnership.accounts', page=1))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/accounts/<int:id>')
def account_admins(id):
    if current_user.role != 'admin':
        search_form = SearchForm()
        bulk_form = BulkDeleteForm()

        sort_by = User.sort_by(request.args.get('sort', 'name'),
                               request.args.get('direction', 'asc'))
        table = 'users'

        order_values = '{0}.{1} {2}'.format(table, sort_by[0], sort_by[1])

        order_query = text(order_values)
        if request.args.get('sort', 'name') == 'name':
            order_query = asc(User.name.expression) if sort_by[1] == 'asc' else desc(User.name.expression)

        partnership_account_var = PartnershipAccount.query.get(id)

        paginated_users = User.query \
            .join(User.partnership) \
            .join(User.partnership_account) \
            .filter(User.partnership_account_id == id, User.partnership_id == current_user.partnership_id,
                    User.role == 'admin') \
            .filter(User.search(request.args.get('q', ''))) \
            .filter(User.is_deactivated.is_(False)) \
            .order_by(order_query) \
            .all()

        return render_template('admins/index.jinja2',
                               form=search_form, bulk_form=bulk_form,
                               users=paginated_users, partnership_account=partnership_account_var)
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/account/<int:id>/edit', methods=['GET', 'POST'])
def account_edit(id):

    if current_user.role == 'partner' or (current_user.is_admin_user_with_groups
                                          and not current_user.is_viewing_partnership):

        if current_user.is_admin_user_with_groups:
            if not User.is_in_same_group(current_user.id, id):
                flash(_("You don't have access to load this account"), 'danger')
                return redirect(url_for('partnership.company_accounts'))

        # TODO: Confirm that super user can view from other partners.
        partnership_account = PartnershipAccount.query.filter(
            PartnershipAccount.id == id,
            PartnershipAccount.partnership_id == current_user.partnership_id,
        ).first()

        imports_allowed = partnership_account.import_leads

        if partnership_account is None:
            if current_user.role == 'partner':
                flash(_('This account does not exist.'), 'danger')
                return redirect(url_for('partnership.accounts', page=1))
            else:
                flash(_("This account does not exist."), 'danger')
                return redirect(url_for('partnership.company_accounts'))

        # Get current year, month
        now = datetime.now()
        year = now.year
        month = now.month
        previous_month = month-1

        # Total minute usage queries for an account
        partnership_account_total_minutes = Lead.query.with_entities(Lead.duration) \
            .filter(Lead.partnership_account_id == id).all()

        new_total_duration = [i.duration for i in partnership_account_total_minutes]
        total_duration_list = list()
        for total in new_total_duration:
            if not total:
                total_zero = float(0)
                total_duration_list.append(total_zero)
            else:
                total_float_duration = math.ceil(float(total) / 60.0)
                total_duration_list.append(total_float_duration)

        total_minutes = int(sum(total_duration_list))

        # Current monthly minute usage queries for an account
        partnership_account_month_minutes = Lead.query.with_entities(Lead.duration) \
            .filter(Lead.partnership_account_id == id) \
            .filter(extract('year', Lead.created_on) == year) \
            .filter(extract('month', Lead.created_on) == month).all()

        new_call_duration = [i.duration for i in partnership_account_month_minutes]
        call_duration_list = list()
        for duration in new_call_duration:
            if not duration:
                duration_zero = float(0)
                call_duration_list.append(duration_zero)
            else:
                float_duration = math.ceil(float(duration) / 60.0)
                call_duration_list.append(float_duration)

        month_minutes = int(sum(call_duration_list))

        # The previous month's minute usage
        partnership_account_previous_month_minutes = Lead.query.with_entities(Lead.duration) \
            .filter(Lead.partnership_account_id == id) \
            .filter(extract('year', Lead.created_on) == year) \
            .filter(extract('month', Lead.created_on) == previous_month).all()

        previous_new_call_duration = [i.duration for i in partnership_account_previous_month_minutes]
        previous_call_duration_list = list()
        for previous_duration in previous_new_call_duration:
            if not previous_duration:
                previous_duration_zero = float(0)
                previous_call_duration_list.append(previous_duration_zero)
            else:
                previous_float_duration = math.ceil(float(previous_duration) / 60.0)
                previous_call_duration_list.append(previous_float_duration)

        previous_month_minutes = int(sum(previous_call_duration_list))

        # Monthly unique call count
        monthly_unique_calls = Lead.query.filter(extract('month', Lead.created_on) == month) \
            .filter(extract('year', Lead.created_on) == year) \
            .filter(Lead.partnership_account_id == id) \
            .distinct(Lead.phonenumber).count()

        # Total unique call count
        total_unique_calls = Lead.query.filter(Lead.partnership_account_id == id) \
            .distinct(Lead.phonenumber).count()

        # Total call count
        total_calls = Lead.query.filter(Lead.partnership_account_id == id).count()

        from buyercall.blueprints.phonenumbers.models import Phone
        # Total tracking phone numbers
        total_tracking_pn = Phone.query.filter(Phone.partnership_account_id == id)\
            .filter(Phone.type == 'tracking', Phone.is_deactivated == '0').count()
        # Total priority phone numbers
        total_priority_pn = Phone.query.filter(Phone.partnership_account_id == id) \
            .filter(Phone.type == 'priority', Phone.is_deactivated == '0').count()

        from buyercall.blueprints.form_leads.models import FormLead
        # Current month's form leads total
        monthly_form_leads = FormLead.query.filter(extract('month', FormLead.created_on) == month) \
            .filter(extract('year', FormLead.created_on) == year) \
            .filter(FormLead.partnership_account_id == id).count()

        # Previous month's form leads total
        previous_month_form_leads = FormLead.query.filter(extract('month', FormLead.created_on) == previous_month) \
            .filter(extract('year', FormLead.created_on) == year) \
            .filter(FormLead.partnership_account_id == id).count()

        # Total form leads
        total_form_leads = FormLead.query.filter(FormLead.partnership_account_id == id).count()

        from buyercall.blueprints.form_leads.models import ExternalForm
        # Previous month's form leads total
        total_forms = ExternalForm.query.filter(ExternalForm.partnership_account_id == id).count()

        # Get partnership account group
        selected_group = 0
        partnership_account_group = PartnershipAccountGroupTie\
            .query\
            .filter(PartnershipAccountGroupTie.partnership_account_id == partnership_account.id).first()
        # if partnership_account_group:
        #    selected_group = partnership_account_group.partnership_account_group_id

        if partnership_account is None:
            flash(_('This account does not exist.'), 'danger')
            return redirect(url_for('partnership.accounts', page=1))

        form = PartnershipAccountForm(obj=partnership_account)
        # form.partnership_account_group_id.choices = [(g.id, g.name) for g in PartnershipAccountGroup \
        #    .query \
        #    .order_by(PartnershipAccountGroup.name.asc()) \
        #    .all()]
        # form.partnership_account_group_id.choices.insert(0, (0, ''))

        # Get external service provider
        selected_external_provider_id = 0
        partnership_account_provider = ExternalApiServiceProvidersPartnershipAccountTie \
            .query \
            .filter(ExternalApiServiceProvidersPartnershipAccountTie.partnership_account_id == partnership_account.id) \
            .join(ExternalApiServiceProviders) \
            .filter(ExternalApiServiceProviders.name == 'AMS 2000') \
            .first()

        if partnership_account_provider is not None:
            encrypt_key = app.config['CRYPTO_SECRET_KEY']
            cipher = AESCipher(encrypt_key)

            if partnership_account_provider.username is not None and partnership_account_provider.username is not '':
                decrypted_username = cipher.decrypt(partnership_account_provider.username)

            if partnership_account_provider.password is not None and partnership_account_provider.password is not '':
                decrypted_password = cipher.decrypt(partnership_account_provider.password)

            if partnership_account_provider.secret is not None and partnership_account_provider.secret is not '':
                decrypted_secret = cipher.decrypt(partnership_account_provider.secret)

            external_service_provider_form = ExternalApiServiceProvider(
                external_api_service_provider_id=partnership_account_provider.external_api_service_provider_id,
                username=decrypted_username,
                password=decrypted_password,
                url=partnership_account_provider.url,
                token_url=partnership_account_provider.token_url,
                client_id=partnership_account_provider.client_id,
                source=partnership_account_provider.source,
                app_source=partnership_account_provider.app_source,
                secret=decrypted_secret)
        else:
            external_service_provider_form = ExternalApiServiceProvider()

        external_service_provider_form.external_api_service_provider_id.choices = [
            (g.id, g.name) for g in ExternalApiServiceProviders.query.filter(
                ExternalApiServiceProviders.name == 'AMS 2000'
            ).order_by(ExternalApiServiceProviders.name.asc()).all()
        ]
        external_service_provider_form.external_api_service_provider_id.choices.insert(0, (0, ''))

        if partnership_account_provider:
            selected_external_provider_id = partnership_account_provider.external_api_service_provider_id

        del form.billing_type

        if form.validate_on_submit():
            form.populate_obj(partnership_account)

            # Set the partnership account group id in the db
            # form_partnership_account_group_id = request.form.get('partnership_account_group_id')
            # PartnershipAccountGroupTie.update(form_partnership_account_group_id, partnership_account.id)

            partnership_account.save()

            flash(_('Account has been saved successfully.'), 'success')

            if current_user.is_admin_user_with_groups:
                return redirect(url_for('partnership.company_accounts'))
            else:
                return redirect(url_for('partnership.accounts', page=1))
        else:
            pass

        return render_template('accounts/edit.jinja2',
                               form=form,
                               api_form=external_service_provider_form,
                               account=partnership_account,
                               imports_allowed=imports_allowed,
                               selected_external_service_provider_id=selected_external_provider_id,
                               # selected_group_id=selected_group,
                               total_minutes=total_minutes,
                               month_minutes=month_minutes,
                               total_unique_calls=total_unique_calls,
                               monthly_unique_calls=monthly_unique_calls,
                               total_calls=total_calls,
                               total_tracking_pn=total_tracking_pn,
                               total_priority_pn=total_priority_pn,
                               monthly_form_leads=monthly_form_leads,
                               previous_month_form_leads=previous_month_form_leads,
                               total_form_leads=total_form_leads,
                               total_forms=total_forms,
                               previous_month_minutes=previous_month_minutes)
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


# This is a csv containing all partner account data
@login_required
@partnership.route('/accounts/csv', methods=['GET'])
def partner_accounts_csv():

    if current_user.role != 'admin':
        header = [
            '#', 'id', 'name', 'active', 'created_on', 'partnership_id', 'partner_account_code', 'issues.issue_count',
            'total_min_usage', 'current_month_min_usage', 'previous_month_minutes', 'total_calls', 'total_unique_calls',
            'current_month_unique_calls', 'previous_month_unique_calls', 'total_active_phonenumbers',
            'total_tracking_phonenumbers', 'total_priority_phonenumbers', 'total_forms', 'total_form_leads',
            'current_month_form_leads', 'previous_month_form_leads'
        ]

        params = {'partnership_id': current_user.partnership_id}

        query = text("""SELECT result.id
            ,result.name
            ,result.is_active
            ,result.created_on
            ,result.partnership_id
            ,result.partner_account_code
            ,issue_count
        FROM (
            SELECT partnership_accounts.id
                ,partnership_accounts.name
                ,partnership_accounts.is_active
                ,partnership_accounts.created_on
                ,partnership_accounts.partnership_id
                ,partnership_accounts.partner_account_code
                ,COUNT(issues.id) AS issue_count
            FROM partnership_accounts
            LEFT OUTER JOIN issues ON issues.partnership_account_id = partnership_accounts.id
            WHERE partnership_accounts.partnership_id = :partnership_id
            GROUP BY partnership_accounts.id
            ) result""")

        connection = db.engine.connect()
        partnership_accounts = connection.execute(query, params)

        # Build the CSV
        row_no = 0
        with closing(StringIO()) as out:
            writer = csv.writer(out)
            writer.writerow(header)
            for account in partnership_accounts:

                # Get current year, month
                now = datetime.now()
                year = now.year
                month = now.month
                previous_month = month - 1

                # Get total minutes for an account
                partnership_account_total_minutes = Lead.query.with_entities(Lead.duration) \
                    .filter(Lead.partnership_account_id == account.id).all()

                # If there's more than 0 minutes round the seconds up
                # to nearest minute and add them together
                new_call_duration = [i.duration for i in partnership_account_total_minutes]
                call_duration_list = list()
                for duration in new_call_duration:
                    if not duration:
                        duration_zero = float(0)
                        call_duration_list.append(duration_zero)
                    else:
                        float_duration = math.ceil(float(duration) / 60.0)
                        call_duration_list.append(float_duration)

                total_minutes = int(sum(call_duration_list))

                # Get Current month minute usage for account
                partnership_account_month_minutes = Lead.query.with_entities(Lead.duration) \
                    .filter(Lead.partnership_account_id == account.id) \
                    .filter(extract('year', Lead.created_on) == year) \
                    .filter(extract('month', Lead.created_on) == month).all()

                # If there's more than 0 minutes round the seconds up
                # to nearest minute and add them together

                new_call_duration = [i.duration for i in partnership_account_month_minutes]
                call_duration_list = list()
                for duration in new_call_duration:
                    if not duration:
                        duration_zero = float(0)
                        call_duration_list.append(duration_zero)
                    else:
                        float_duration = math.ceil(float(duration) / 60.0)
                        call_duration_list.append(float_duration)

                month_minutes = int(sum(call_duration_list))

                # The previous month's minute usage
                partnership_account_previous_month_minutes = Lead.query.with_entities(Lead.duration) \
                    .filter(Lead.partnership_account_id == account.id) \
                    .filter(extract('year', Lead.created_on) == year) \
                    .filter(extract('month', Lead.created_on) == previous_month).all()

                previous_new_call_duration = [i.duration for i in partnership_account_previous_month_minutes]
                previous_call_duration_list = list()
                for previous_duration in previous_new_call_duration:
                    if not previous_duration:
                        previous_duration_zero = float(0)
                        previous_call_duration_list.append(previous_duration_zero)
                    else:
                        previous_float_duration = math.ceil(float(previous_duration) / 60.0)
                        previous_call_duration_list.append(previous_float_duration)

                previous_month_minutes = int(sum(previous_call_duration_list))

                # Monthly unique call count
                monthly_unique_calls = Lead.query.filter(extract('month', Lead.created_on) == month) \
                    .filter(extract('year', Lead.created_on) == year) \
                    .filter(Lead.partnership_account_id == account.id) \
                    .distinct(Lead.phonenumber).count()

                # Total unique call count
                total_unique_calls = Lead.query.filter(Lead.partnership_account_id == account.id) \
                    .distinct(Lead.phonenumber).count()

                # Total previous unique call count
                previous_month_unique_calls = Lead.query.filter(Lead.partnership_account_id == account.id) \
                    .filter(extract('month', Lead.created_on) == previous_month) \
                    .filter(extract('year', Lead.created_on) == year)\
                    .distinct(Lead.phonenumber).count()

                # Total call count
                total_calls = Lead.query.filter(Lead.partnership_account_id == account.id).count()

                from buyercall.blueprints.phonenumbers.models import Phone
                # Total tracking phone numbers
                total_tracking_pn = Phone.query.filter(Phone.partnership_account_id == account.id) \
                    .filter(Phone.type == 'tracking', Phone.is_deactivated == '0').count()
                # Total priority phone numbers
                total_priority_pn = Phone.query.filter(Phone.partnership_account_id == account.id) \
                    .filter(Phone.type == 'priority', Phone.is_deactivated == '0').count()

                # Total active phonenumbers
                total_active_pn = total_tracking_pn + total_priority_pn

                from buyercall.blueprints.form_leads.models import FormLead
                # Current month's form leads total
                monthly_form_leads = FormLead.query.filter(extract('month', FormLead.created_on) == month) \
                    .filter(extract('year', FormLead.created_on) == year) \
                    .filter(FormLead.partnership_account_id == account.id).count()

                # Previous month's form leads total
                previous_month_form_leads = FormLead.query.filter(
                    extract('month', FormLead.created_on) == previous_month) \
                    .filter(extract('year', FormLead.created_on) == year) \
                    .filter(FormLead.partnership_account_id == account.id).count()

                # Total form leads
                total_form_leads = FormLead.query.filter(FormLead.partnership_account_id == account.id).count()

                from buyercall.blueprints.form_leads.models import ExternalForm
                # Previous month's form leads total
                total_forms = ExternalForm.query.filter(ExternalForm.partnership_account_id == account.id).count()

                row_no += 1
                csv_row = [
                    row_no, account.id, account.name, account.is_active,
                    account.created_on, account.partnership_id, account.partner_account_code, account['issue_count'],
                    total_minutes, month_minutes, previous_month_minutes, total_calls, total_unique_calls,
                    monthly_unique_calls, previous_month_unique_calls, total_active_pn, total_tracking_pn,
                    total_priority_pn, total_forms, total_form_leads, monthly_form_leads, previous_month_form_leads
                ]
                writer.writerow(csv_row)

            filename = 'Partnership Accounts - Usage Report - {}.csv'.format(
                date.today().strftime('%Y-%m-%d')
            )

            resp = make_response(out.getvalue())
            resp.headers['Content-Type'] = 'text/csv'
            resp.headers['Content-Disposition'] = \
                'attachment; filename="{}"'.format(filename)
            return resp
    else:
        return''


@partnership.route('/account/<int:id>/edit/api_access', methods=['POST'])
def account_edit_api_access(id):
    encrypt_key = app.config['CRYPTO_SECRET_KEY']
    partnership_account = PartnershipAccount\
        .query\
        .filter(PartnershipAccount.id == id,
                PartnershipAccount.partnership_id == current_user.partnership_id
                )\
        .first()

    if partnership_account is not None:
        api_url = request.form.get('url')
        api_token_url = request.form.get('token_url')
        api_client_id = request.form.get('client_id')
        api_username = request.form.get('username')
        api_password = request.form.get('password')
        api_secret = request.form.get('secret')
        api_source = request.form.get('source')
        api_app_source = request.form.get('app_source')
        api_external_api_service_provider_id = request.form.get('external_api_service_provider_id')

        if api_username is not None and api_username is not '':
            cipher = AESCipher(encrypt_key)
            api_username = cipher.encrypt(api_username)

        if api_password is not None and api_password is not '':
            cipher = AESCipher(encrypt_key)
            api_password = cipher.encrypt(api_password)

        if api_secret is not None and api_secret is not '':
            cipher = AESCipher(encrypt_key)
            api_secret = cipher.encrypt(api_secret)

        if api_external_api_service_provider_id is None or \
            api_external_api_service_provider_id == '' or \
            int(api_external_api_service_provider_id) <= 0:
            flash(_('Error updating partnership account API details.'), 'danger')
            return redirect(url_for('partnership.accounts', page=1))

        try:
            # api_record_exists = ExternalApiServiceProvidersPartnershipAccountTie.exists(
            # partnership_account.id, api_external_api_service_provider_id)
            # if int(api_record_exists) > 0 and (api_external_api_service_provider_id is None or int(
            # api_external_api_service_provider_id) == 0):
            #    result = ExternalApiServiceProvidersPartnershipAccountTie.delete(
            #    api_record_exists, partnership_account.id)
            #
            #    if result:
            #        flash(_('Account has been changed successfully.'), 'success')
            #    else:
            #        flash(_('Error updating partnership account API details.'), 'danger')
            #    return redirect(url_for('partnership.accounts', page=1))
            if api_external_api_service_provider_id is not None and int(api_external_api_service_provider_id) > 0:
                ExternalApiServiceProvidersPartnershipAccountTie.update(
                    api_external_api_service_provider_id,
                    partnership_account.id,
                    api_client_id,
                    api_username,
                    api_password,
                    api_url,
                    api_token_url,
                    api_source,
                    api_app_source,
                    api_secret
                 )

                flash(_('Account has been changed successfully.'), 'success')
                return redirect(url_for('partnership.accounts', page=1))
        except Exception as e:
            log.error('Error updating partnership account API details: {}'.format(sys.exc_info()[0]))
            flash(_('Error updating partnership account API details.'), 'danger')
            return redirect(url_for('partnership.accounts', page=1))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/account/<int:id>/edit/login_access', methods=['POST'])
def account_edit_login_access(id):
    if current_user.role != 'admin':
        partnership_account = PartnershipAccount.query.filter(
            PartnershipAccount.id == id,
            PartnershipAccount.partnership_id == current_user.partnership_id
        ).first()
        status = request.form.get('status', 'off')

        if partnership_account is None:
            flash(_('This account does not exist.'), 'danger')
            return redirect(url_for('partnership.accounts', page=1))

        status = not (True if status == 'on' else False)

        db.session.query(PartnershipAccount) \
            .filter(PartnershipAccount.id == id) \
            .update({"active": status}, synchronize_session='fetch')

        db.session.query(User) \
            .filter(User.partnership_account_id == id, User.role.in_(['admin', 'agent'])) \
            .update({"active": status}, synchronize_session='fetch')

        db.session.commit()

        flash(_('Account has been changed successfully.'), 'success')
        return redirect(url_for('partnership.accounts', page=1))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/account/<int:id>/edit/lead_import_access', methods=['POST'])
def account_edit_lead_import_access(id):
    if current_user.role != 'admin':
        partnership_account = PartnershipAccount.query.filter(PartnershipAccount.id == id,
                                                              PartnershipAccount.partnership_id == current_user.partnership_id,
                                                              ).first()
        status = request.form.get('status', 'false')

        if partnership_account is None:
            flash(_('This account does not exist.'), 'danger')
            return redirect(url_for('partnership.accounts', page=1))

        status = (True if status == 'true' else False)

        db.session.query(PartnershipAccount) \
            .filter(PartnershipAccount.id == id) \
            .update({"import_leads": status}, synchronize_session='fetch')

        db.session.commit()

        flash(_('Account has been changed successfully.'), 'success')
        return redirect(url_for('partnership.accounts', page=1))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/account/<int:id>/edit/edit_twillio', methods=['POST'])
def account_edit_twillio(id):
    if current_user.role != 'admin':
        partnership_account = PartnershipAccount.query.filter(
            PartnershipAccount.id == id,
            PartnershipAccount.partnership_id == current_user.partnership_id,
        ).first()
        status = request.form.get('status', 'off')

        if partnership_account is None or partnership_account.subscription is None:
            flash(_('This account does not exist.'), 'danger')
            return redirect(url_for('partnership.accounts', page=1))

        status = not (True if status == 'on' else False)

        if status:
            partnership_account.subscription.activate_twilio_account()
        else:
            partnership_account.subscription.suspend_twilio_account()

        flash(_('Account has been changed successfully.'), 'success')
        return redirect(url_for('partnership.accounts', page=1))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/account/<int:id>/edit/close_subscription', methods=['POST'])
def account_close_subscription(id):
    if current_user.role != 'admin':
        partnership_account = PartnershipAccount.query.filter(
            PartnershipAccount.id == id,
            PartnershipAccount.partnership_id == current_user.partnership_id,
        ).first()
        if partnership_account is None or partnership_account.subscription is None:
            flash(_('This account does not exist.'), 'danger')
            return redirect(url_for('partnership.accounts', page=1))

        partnership_account.subscription.close_twilio_account()

        flash(_('Account has been changed successfully.'), 'success')
        return redirect(url_for('partnership.accounts', page=1))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


# TODO: needs review
@partnership.route('/admins/<int:id>/edit', methods=['GET', 'POST'])
def admins_edit(id):

    if current_user.role != 'admin':
        user = User.query.filter(User.id == id, User.partnership_id == current_user.partnership_id,
                                 User.role == 'admin', User.is_deactivated.is_(False)).first()
        if user is None:
            flash(_('This user does not exist.'), 'danger')
            return redirect(url_for('partnership.admins'))

        form = UserForm(obj=user)
        form.role = Label('lbl_role', _('%s' % user.role))
        form.role.label = {'text': 'Privileges'}

        form.reports_list.choices = []
        rework_reports = [(report.id, report.name) for report in Report.query.all()]
        for r in rework_reports:
            if r != (3, 'Partner Channel Account Report'):
                form.reports_list.choices.append(r)

        if form.validate_on_submit():
            if User.is_last_admin(user,
                                  'admin',
                                  request.form.get('active')):
                flash(_('This is the last admin within the account, you cannot do that.'),
                      'danger')
                return redirect(url_for('partnership.admins_edit', id=id))

            del form.role
            form.populate_obj(user)

            if user.username == '':
                user.username = None
            user.save()

            user.reports = list()
            # re-adding reports
            for id in form.reports_list.data:
                link = ReportUserTie()
                link.report_id = id
                link.user_id = user.id
                db.session.add(link)
            db.session.commit()

            flash(_('User has been saved successfully.'), 'success')
            return redirect(url_for('partnership.account_admins', id=user.partnership_account_id))
        else:
            form.reports_list.process_data([link.report.id for link in user.reports])

        return render_template('admins/edit.jinja2', form=form, user=user)
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


# TODO: DISCUSS PARTNERSHIP REMOVAL LOGIC
# TODO: needs review
@partnership.route('/accounts/bulk_delete', methods=['POST'])
def accounts_bulk_delete():

    if current_user.role != 'admin':
        form = BulkDeleteForm()

        # db.session.query(User) \
        #     .filter(User.partnership_id.in_(ids)) \
        #     .update({"active": False}, synchronize_session='fetch')
        #
        # # TODO: cancel subscription for all admin users
        #
        # db.session.query(PartnershipAccount) \
        #     .filter(PartnershipAccount.partnership_id.in_(ids)) \
        #     .update({"active": False}, synchronize_session='fetch')

        if form.validate_on_submit():
            ids = User.get_bulk_action_ids(request.form.get('scope'),
                                           request.form.getlist('bulk_ids'),
                                           omit_ids=[current_user.id],
                                           query=request.args.get('q', ''))

            # Prevent circular imports.
            from buyercall.blueprints.billing.tasks import delete_users

            delete_users.delay(ids)

            flash(_n('%(num)d user was scheduled to be deleted.',
                     '%(num)d users were scheduled to be deleted.',
                     num=len(ids)), 'success')
        else:
            flash(_('No users were deleted, something went wrong.'), 'danger')

        return redirect(url_for('partnership.accounts'))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


# TODO: DISCUSS PARTNERSHIP SUBSCRIPTION LOGIC
# TODO: needs review
@partnership.route('/accounts/cancel_subscription', methods=['POST'])
def accounts_cancel_subscription():

    if current_user.role != 'admin':
        form = UserCancelSubscriptionForm()

        if form.validate_on_submit():
            user = User.query.get(request.form.get('id'))

            if user:
                subscription = Subscription()
                if subscription.cancel(user):
                    flash(_('Subscription has been cancelled for %(user)s.',
                            user=user.name), 'success')
            else:
                flash(_('No subscription was cancelled, something went wrong.'),
                      'danger')

        return redirect(url_for('partnership.accounts'))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/accounts/act_as', methods=['POST'])
def act_as():

    if current_user.role != 'admin':
        s = current_supervisor_user
        u = current_user

        target_user = User.query.get(request.form.get('account_id'))

        if target_user is None:
            flash(_('Such Account does not exist'))
            return redirect(url_for('partnership.accounts'))

        if target_user.partnership_id != current_user.partnership_id:
            flash(_("You don't have access to load this account"))
            return redirect(url_for('partnership.accounts'))

        if not current_supervisor_user.is_authenticated:
            supervisor_login_user(u, remember=True, force=True)

        logout_user()
        login_user(target_user, remember=True, force=True)

        return redirect(url_for('user.settings'))
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/partnership/partnership_invite', methods=['GET', 'POST'])
@anonymous_required()
def partnership_invite(reset_token=None):
    from buyercall.blueprints.user.models import User
    from buyercall.blueprints.partnership.forms import PartnershipSignupForm

    form = PartnershipSignupForm(reset_token=request.args.get('reset_token'))

    u = User.deserialize_token(form.reset_token.data)
    if u is None:
        flash(_('Your reset token has expired or was tampered with.'),
              'danger')
        return redirect(url_for('user.login'))

    if form.validate_on_submit():
        form.populate_obj(u)
        u.password = User.encrypt_password(request.form.get('password', None))
        u.save()

        if login_user(u):
            flash(_('Successfully signed up.'), 'success')
            return redirect(url_for('user.welcome'))

    partner = Partnership.query.filter(Partnership.id == u.partnership_id).first()
    if partner is None:
        partner_name = ''
    else:
        partner_name = partner.name

    return render_template('partnership/signup.jinja2', form=form, user=u, partner_name=partner_name)


@partnership.route('/partnership/settings', methods=['GET', 'POST'])
def settings():

    if current_user.role != 'admin':
        pship = current_user.partnership
        form = PartnershipForm(obj=pship)
        form.logo.label.text = 'Change Logo'
        del form.default_billing_type

        if form.validate_on_submit():
            with db.session.no_autoflush:
                try:
                    del form.logo
                    form.populate_obj(pship)

                    if len(request.files) > 0:
                        file = request.files['logo']
                        file.seek(0, os.SEEK_END)
                        file_length = file.tell()
                        if file_length == 0:
                            pass
                        elif file_length > 1 * 1024 * 1024:
                            flash('Logo is too big and was not saved. Max size is 1MB', 'danger')
                            return render_template('partnership/settings.jinja2', form=form)
                        else:
                            file.seek(0)
                            folder_name = '%s_%s' % (pship.id, pship.name)
                            file_name = file.filename
                            from buyercall.blueprints.partnership.tasks import upload_partnership_logo
                            upload_partnership_logo(folder_name, file)
                            pship.logo = '%s/%s' % (folder_name, file_name)
                            db.session.add(pship)
                            db.session.flush()

                    db.session.commit()

                    return redirect(url_for('user.settings'))
                except Exception as e:
                    form.logo = PartnershipForm(obj=pship).logo
                    flash(_("{}".format(e)), 'danger')
                    db.session.rollback()
        return render_template('partnership/settings.jinja2', form=form, partnership=pship)
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/partnership/twilio_credentials', methods=['GET', 'POST'])
def twilio_credentials():
    encrypt_key = app.config['CRYPTO_SECRET_KEY']
    if current_user.role == 'partner':
        partner = current_user.partnership
        # Check and Get the twilio record for a specific partner account thats active
        cpaas = PartnershipCpaasProviders.query.filter(
            PartnershipCpaasProviders.partnership_id == partner.id,
            PartnershipCpaasProviders.active.is_(True),
            PartnershipCpaasProviders.cpaas_provider_name == 'twilio'
        ).first()

        if cpaas is not None:
            cipher = AESCipher(encrypt_key)
            # Decrypt the credentials before pushing it through to the form
            if cpaas.cpaas_account_id is not None and cpaas.cpaas_account_id is not '':
                decrypted_username = cipher.decrypt(cpaas.cpaas_account_id)
            else:
                decrypted_username = ''

            if cpaas.cpaas_api_token is not None and cpaas.cpaas_api_token is not '':
                decrypted_token = cipher.decrypt(cpaas.cpaas_api_token)
            else:
                decrypted_token = ''

            # Pass the descrypted and other cpaas values to the form
            form = PartnershipTwilioApiForm(cpaas_account_id=decrypted_username,
                                            cpaas_api_token=decrypted_token,
                                            cpaas_caller_id=cpaas.cpaas_caller_id)

            if form.validate_on_submit():
                cipher = AESCipher(encrypt_key)
                try:
                    # On gathering the data from the form encrypt the twilio credentials
                    if form.cpaas_account_id.data:
                        cpaas.cpaas_account_id = cipher.encrypt(form.cpaas_account_id.data)
                    if form.cpaas_api_token.data:
                        cpaas.cpaas_api_token = cipher.encrypt(form.cpaas_api_token.data)
                    cpaas.cpaas_caller_id = form.cpaas_caller_id.data

                    cpaas.save()
                    db.session.commit()

                    flash(_('The Twilio API Credentials have been updated successfully.'), 'success')
                    return redirect(url_for('admin.integrations'))
                except Exception as e:
                    log.error(traceback.format_exc())
                    db.session.rollback()
                    flash(_("An error occurred while saving the Twilio API Credentials. Please contact support "
                            "for assistance."), 'danger')
        else:
            cpaas = PartnershipCpaasProviders()
            form = PartnershipTwilioApiForm(obj=cpaas)
            if form.validate_on_submit():
                cipher = AESCipher(encrypt_key)
                try:
                    cpaas.cpaas_provider_name = 'twilio'
                    cpaas.partnership_id = partner.id
                    if form.cpaas_account_id.data is not None and form.cpaas_account_id.data is not '':
                        cpaas.cpaas_account_id = cipher.encrypt(form.cpaas_account_id.data)
                    if form.cpaas_api_token.data is not None and form.cpaas_api_token.data is not '':
                        cpaas.cpaas_api_token = cipher.encrypt(form.cpaas_api_token.data)
                    cpaas.cpaas_caller_id = form.cpaas_caller_id.data
                    cpaas.save()
                    db.session.commit()

                    flash(_('The Twilio API Credentials have been updated successfully.'), 'success')
                    return redirect(url_for('admin.integrations'))
                except Exception as e:
                    log.error(traceback.format_exc())
                    db.session.rollback()
                    flash(_("An error occurred while saving the Twilio API Credentials. Please contact support "
                            "for assistance."), 'danger')
        return render_template('partnership/twilio_credentials.jinja2', form=form)
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/partnership/bandwidth_credentials', methods=['GET', 'POST'])
def bandwidth_credentials():
    encrypt_key = app.config['CRYPTO_SECRET_KEY']
    if current_user.role == 'partner':
        partner = current_user.partnership
        # Check and Get the Bandwidth record for a specific partner account thats active
        cpaas = PartnershipCpaasProviders.query\
            .filter(PartnershipCpaasProviders.partnership_id == partner.id,
                    PartnershipCpaasProviders.active.is_(True),
                    PartnershipCpaasProviders.cpaas_provider_name == 'bandwidth').first()

        if cpaas is not None:
            cipher = AESCipher(encrypt_key)
            # Decrypt the credentials before pushing it through to the form
            if cpaas.cpaas_user_id is not None and cpaas.cpaas_user_id is not '':
                decrypted_username = cipher.decrypt(cpaas.cpaas_user_id)
            else:
                decrypted_username = ''

            if cpaas.cpaas_api_token is not None and cpaas.cpaas_api_token is not '':
                decrypted_token = cipher.decrypt(cpaas.cpaas_api_token)
            else:
                decrypted_token = ''

            if cpaas.cpaas_api_secret is not None and cpaas.cpaas_api_secret is not '':
                decrypted_secret = cipher.decrypt(cpaas.cpaas_api_secret)
            else:
                decrypted_secret = ''

            if cpaas.cpaas_account_id is not None and cpaas.cpaas_account_id is not '':
                decrypted_account = cipher.decrypt(cpaas.cpaas_account_id)
            else:
                decrypted_account = ''

            if cpaas.cpaas_api_username is not None and cpaas.cpaas_api_username is not '':
                decrypted_api_username = cipher.decrypt(cpaas.cpaas_api_username)
            else:
                decrypted_api_username = ''

            if cpaas.cpaas_api_password is not None and cpaas.cpaas_api_password is not '':
                decrypted_api_password = cipher.decrypt(cpaas.cpaas_api_password)
            else:
                decrypted_api_password = ''

            if cpaas.cpaas_cnam_password is not None and cpaas.cpaas_cnam_password is not '':
                decrypted_cnam_password = cipher.decrypt(cpaas.cpaas_cnam_password)
            else:
                decrypted_cnam_password = ''

            # Pass the descrypted and other cpaas values to the form
            form = PartnershipBandwidthApiForm(cpaas_user_id=decrypted_username,
                                               cpaas_api_token=decrypted_token,
                                               cpaas_api_secret=decrypted_secret,
                                               cpaas_caller_id=cpaas.cpaas_caller_id,
                                               cpaas_account_id=decrypted_account,
                                               cpaas_api_username=decrypted_api_username,
                                               cpaas_api_password=decrypted_api_password,
                                               cpaas_site_id=cpaas.cpaas_site_id,
                                               cpaas_location_id=cpaas.cpaas_location_id,
                                               cpaas_sms_application_id=cpaas.cpaas_sms_application_id,
                                               cpaas_voice_application_id=cpaas.cpaas_voice_application_id,
                                               cpaas_cnam_password=decrypted_cnam_password)
            if form.validate_on_submit():
                cipher = AESCipher(encrypt_key)
                try:
                    # On gathering the data from the form encrypt the Bandwidth credentials
                    if form.cpaas_user_id.data is not None and form.cpaas_user_id.data is not '':
                        cpaas.cpaas_user_id = cipher.encrypt(form.cpaas_user_id.data)
                    if form.cpaas_api_token.data is not None and form.cpaas_api_token.data is not '':
                        cpaas.cpaas_api_token = cipher.encrypt(form.cpaas_api_token.data)
                    if form.cpaas_api_secret.data is not None and form.cpaas_api_secret.data is not '':
                        cpaas.cpaas_api_secret = cipher.encrypt(form.cpaas_api_secret.data)
                    if form.cpaas_account_id.data is not None and form.cpaas_account_id.data is not '':
                        cpaas.cpaas_account_id = cipher.encrypt(form.cpaas_account_id.data)
                    if form.cpaas_api_username.data is not None and form.cpaas_api_username.data is not '':
                        cpaas.cpaas_api_username = cipher.encrypt(form.cpaas_api_username.data)
                    if form.cpaas_api_password.data is not None and form.cpaas_api_password.data is not '':
                        cpaas.cpaas_api_password = cipher.encrypt(form.cpaas_api_password.data)
                    cpaas.cpaas_site_id = form.cpaas_site_id.data
                    cpaas.cpaas_location_id = form.cpaas_location_id.data
                    cpaas.cpaas_sms_application_id = form.cpaas_sms_application_id.data
                    cpaas.cpaas_voice_application_id = form.cpaas_voice_application_id.data
                    cpaas.cpaas_caller_id = form.cpaas_caller_id.data
                    if form.cpaas_cnam_password.data is not None and form.cpaas_cnam_password.data is not '':
                        cpaas.cpaas_cnam_password = cipher.encrypt(form.cpaas_cnam_password.data)

                    cpaas.save()
                    db.session.commit()

                    flash(_('The Bandwidth API Credentials have been updated successfully.'), 'success')
                    return redirect(url_for('admin.integrations'))
                except:
                    log.error(traceback.format_exc())
                    db.session.rollback()
                    flash(_("An error occurred while saving the Bandwidth API Credentials. Please contact support "
                            "for assistance."), 'danger')
        else:
            cpaas = PartnershipCpaasProviders()
            form = PartnershipBandwidthApiForm(obj=cpaas)
            if form.validate_on_submit():
                cipher = AESCipher(encrypt_key)
                try:
                    cpaas.cpaas_provider_name = 'bandwidth'
                    cpaas.partnership_id = partner.id
                    if form.cpaas_user_id.data is not None and form.cpaas_user_id.data is not '':
                        cpaas.cpaas_user_id = cipher.encrypt(form.cpaas_user_id.data)
                    if form.cpaas_api_token.data is not None and form.cpaas_api_token.data is not '':
                        cpaas.cpaas_api_token = cipher.encrypt(form.cpaas_api_token.data)
                    if form.cpaas_api_secret.data is not None and form.cpaas_api_secret.data is not '':
                        cpaas.cpaas_api_secret = cipher.encrypt(form.cpaas_api_secret.data)
                    if form.cpaas_account_id.data is not None and form.cpaas_account_id.data is not '':
                        cpaas.cpaas_account_id = cipher.encrypt(form.cpaas_account_id.data)
                    if form.cpaas_api_username.data is not None and form.cpaas_api_username.data is not '':
                        cpaas.cpaas_api_username = cipher.encrypt(form.cpaas_api_username.data)
                    if form.cpaas_api_password.data is not None and form.cpaas_api_password.data is not '':
                        cpaas.cpaas_api_password = cipher.encrypt(form.cpaas_api_password.data)
                    cpaas.cpaas_site_id = form.cpaas_site_id.data
                    cpaas.cpaas_location_id = form.cpaas_location_id.data
                    cpaas.cpaas_sms_application_id = form.cpaas_sms_application_id.data
                    cpaas.cpaas_voice_application_id = form.cpaas_voice_application_id.data
                    cpaas.cpaas_caller_id = form.cpaas_caller_id.data
                    if form.cpaas_cnam_password.data is not None and form.cpaas_cnam_password.data is not '':
                        cpaas.cpaas_cnam_password = cipher.encrypt(form.cpaas_cnam_password.data)

                    cpaas.save()
                    db.session.commit()

                    flash(_('The Bandwidth API Credentials have been updated successfully.'), 'success')
                    return redirect(url_for('admin.integrations'))
                except Exception as e:
                    log.error(traceback.format_exc())
                    db.session.rollback()
                    flash(_("An error occurred while saving the Bandwidth API Credentials. Please contact support"
                            "for assistance."), 'danger')
        return render_template('partnership/bandwidth_credentials.jinja2', form=form)
    else:
        flash(_('You do not have permission to do that.'), 'danger')
        return redirect('/')


@partnership.route('/partnership/<int:pid>/finserv_prequalify_credit', methods=['POST', 'GET'])
@role_required('partner', 'sysadmin')
def partner_finserv_prequalify_credit(pid):
    credit_object = PartnershipCreditTie()
    form = PartnerFinservPrequalifyForm(obj=credit_object)
    partner_id = pid
    provider = 'Finserv'
    product = 'prequalify'
    credit_profile = PartnershipCreditTie.query\
        .filter(and_(PartnershipCreditTie.service_provider ==
                     provider, PartnershipCreditTie.product_type == product,
                     PartnershipCreditTie.partnership_id == partner_id)).first()
    if credit_profile is not None and credit_profile.product_type == 'prequalify':
        encrypt_key = app.config['CRYPTO_SECRET_KEY']
        cipher = AESCipher(encrypt_key)
        # Decrypt the credentials before pushing it through to the form
        if credit_profile.api_username is not None and credit_profile.api_username is not '':
            decrypted_username = cipher.decrypt(credit_profile.api_username)
        else:
            decrypted_username = ''

        if credit_profile.api_password is not None and credit_profile.api_password is not '':
            decrypted_password = cipher.decrypt(credit_profile.api_password)
        else:
            decrypted_password = ''
        if credit_profile.api_account is not None and credit_profile.api_account is not '':
            decrypted_account = cipher.decrypt(credit_profile.api_account)
        else:
            decrypted_account = ''
        # Pass the decrypted and other credit values to the form
        form = PartnerFinservPrequalifyForm(active=credit_profile.active,
                                            api_username=decrypted_username,
                                            api_password=decrypted_password,
                                            api_account=decrypted_account)
        if form.validate_on_submit():
            cipher = AESCipher(encrypt_key)
            try:
                # On gathering the data from the form encrypt the Bandwidth credentials
                credit_profile.active = form.active.data
                if form.api_username.data is not None and form.api_username.data is not '':
                    credit_profile.api_username = cipher.encrypt(form.api_username.data)
                if form.api_password.data is not None and form.api_password.data is not '':
                    credit_profile.api_password = cipher.encrypt(form.api_password.data)
                if form.api_account.data is not None and form.api_account.data is not '':
                    credit_profile.api_account = cipher.encrypt(form.api_account.data)
                credit_profile.experian_enabled = True
                credit_profile.save()
                db.session.commit()

                flash(_('The Finserv API Credentials have been updated successfully.'), 'success')
                return redirect(url_for('admin.integrations'))
            except:
                log.error(traceback.format_exc())
                db.session.rollback()
                flash(_("An error occurred while saving the Finserv API Credentials. Please contact support "
                        "for assistance."), 'danger')
    else:
        new_partner_credit_credentials_set(credit_object, provider, product, partner_id)
    return render_template('partnership/partner_finserv_prequalify_credit.jinja2', form=form)


def new_partner_credit_credentials_set(credit_object, provider, product_type, pid):
    encrypt_key = app.config['CRYPTO_SECRET_KEY']
    if product_type.lower() == 'prequalify' and provider == 'Finserv':
        form = PartnerFinservPrequalifyForm(obj=credit_object)
    else:
        flash(_('The product type and credit provider mapping is not available.'), 'danger')
        return redirect(url_for('admin.integrations'))
    if provider == 'Finserv':
        try:
            if form.validate_on_submit():
                cipher = AESCipher(encrypt_key)
                credit_object.service_provider = provider
                credit_object.active = form.active.data
                credit_object.partnership_id = pid
                credit_object.product_type = product_type
                if form.api_username.data is not None and form.api_username.data is not '':
                    credit_object.api_username = cipher.encrypt(form.api_username.data)
                if form.api_password.data is not None and form.api_password.data is not '':
                    credit_object.api_password = cipher.encrypt(form.api_password.data)
                if form.api_account.data is not None and form.api_account.data is not '':
                    credit_object.api_account = cipher.encrypt(form.api_account.data)
                credit_object.experian_enabled = True
                credit_object.save()
                db.session.commit()

                flash(_('The Finserv API Credentials have been updated successfully.'), 'success')
                return redirect(url_for('admin.integrations'))
        except Exception as e:
            log.error(traceback.format_exc())
            log.error(e)
            db.session.rollback()
            flash(_("An error occurred while saving the Finserv Credentials. Please contact support"
                    "for assistance."), 'danger')
    else:
        flash(_('A service provider was not found. Please contact support for assistance.'), 'success')
        return redirect(url_for('admin.integrations'))