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/api2/doc/endpoints/form_leads.py
import logging
import traceback
import re
import uuid
import os
from html.parser import HTMLParser
from enum import Enum
from buyercall.lib.util_bandwidth import bw_client
from flask import (
    Blueprint,
    make_response,
    request,
    jsonify,
    current_app as app)
from buyercall.lib.util_crypto import AESCipher
from datetime import datetime
import json
from buyercall.extensions import db
from flask import Blueprint, jsonify, make_response
from buyercall.lib.util_rest import rest_partnership_account, rest_partnership, \
    requires_auth, rest_is_partnership_account, rest_is_partnership, rest_api_token_id
from flask_restx import Resource
from buyercall.blueprints.api2.doc import serializers
from buyercall.blueprints.api2.restplus import api
from buyercall.blueprints.contacts.models import Contact
from buyercall.blueprints.form_leads.models import ExternalForm, ExternalFormField, \
    FormLeadField, FormLead, ExternalFormFieldDefinition
from buyercall.blueprints.partnership.models import Partnership, PartnershipAccount, PartnershipCreditTie, PartnershipAccountCreditTie
from sqlalchemy import func, or_, and_, extract
from buyercall.blueprints.widgets.routing import (
    add_widget_lead, Routing
)
from buyercall.blueprints.filters import format_phone_number

log = logging.getLogger(__name__)
ns = api.namespace('Form Leads', description='Operations related to form leads.', path='/accounts')
email_regex = re.compile(r'\S+@\S+\.\S+')
phone_regex = re.compile(r'^\+?[0-9]{10,12}$')


class MLStripper(HTMLParser):
    def __init__(self):
        super().__init__()
        self.reset()
        self.fed = []
    def handle_data(self, d):
        self.fed.append(d)
    def get_data(self):
        return ''.join(self.fed)


def strip_tags(html):
    s = MLStripper()
    s.feed(html)
    return s.get_data()


class Form_Lead_Post_Type(Enum):
    PARTIAL_POST_INITIAL = 1    # The initial post of a partial post. Mainly has the required fields.
    PARTIAL_POST_FOLLOW_UP = 2  # The next post of a partial post. Contains the remaining fields.
    FULL_POST = 3               # The complete post. Includes required and non required fields.


class MessageBuilder():

    def build_message(self, current_message, new_message):

        if current_message is not None and len(current_message) > 0:
            current_message += ", " + str(new_message)
        else:
            current_message += str(new_message)

        return current_message


class TypeSwitcher(object):
    """
    The purpose of this class is to test the lead form field values against the defined requirements.
    """


    def valid(self, type_string, id_string, value_string, min_value, max_value):
        method_name = type_string + "_type"
        method = getattr(self, method_name, lambda: "Invalid")

        return method(id_string, value_string, min_value, max_value)

    def boolean_type(self, id_string, value_string, min_value, max_value):
        try:
            if isinstance(value_string, bool):
                return True, ""
            else:
                return False, "Field id '" + id_string + "' value '" + value_string \
                       + "' is not boolean format. "
        except Exception:
            return False, "Field id '" + str(id_string) + "' value '" \
                   + str(value_string) + "' is an invalid boolean. "

    def datetime_type(self, id_string, value_string, min_value, max_value):
        try:
            error_message = ""

            if len(value_string) > 0:
                date_value = datetime.strptime(value_string,"%m/%d/%Y")
            return True, error_message
        except Exception:
            return False, "Field id '" + id_string + "' value '" \
                   + value_string + "' is not a valid date (m/d/Y). "

    def decimal_type(self, id_string, value_string, min_value, max_value):
        try:
            error_message = ""
            float_value = float(value_string)
            result = True

            if min_value != max_value:
                if min_value:
                    if float_value < min_value:
                        error_message = "Field id '" + id_string + "' value '" \
                                        + value_string + "' is less than the minimum allowed value of '" \
                                        + str(min_value) + "'. "
                        result = False

                if max_value:
                    if float_value > max_value:
                        error_message += "Field id '" + id_string + "' value '" \
                                         + value_string + "' is more than the maximum allowed value of '" \
                                         + str(max_value) + "'. "
                        result = False

            return result, error_message
        except ValueError:
            return False, "Field id '" + id_string + "' value '" \
                   + value_string + "' is not float format. "

    def integer_type(self, id_string, value_string, min_value, max_value):
        try:
            error_message = ""
            integer_value = int(value_string)
            result = True

            if min_value != max_value:
                if min_value:
                    if integer_value < min_value:
                        error_message = "Field id '" + id_string + "' value '" \
                                        + value_string + "' is less than the minimum allowed value of '" \
                                        + str(min_value) + "'. "
                        result = False

                if max_value:
                    if integer_value > max_value:
                        error_message += "Field id '" + id_string + "' value '" \
                                         + value_string + "' is more than the maximum allowed value of '" \
                                         + str(max_value) + "'. "
                        result = False

            return result, error_message
        except ValueError:
            return False, "Field id '" + id_string + "' value '" \
                   + value_string + "' is not integer format. "

    def phone_type(self, id_string, value_string, min_value, max_value):
        error_message = ""
        result = True

        if len(value_string) < min_value:
            error_message = "Field id '" + id_string + "' value '" \
                            + value_string + "' length should be at least '" \
                            + str(min_value) + "'. "
            result = False
        elif len(value_string) > max_value:
            error_message = "Field id '" + id_string + "' value '" \
                            + value_string + "' length should be at most '" \
                            + str(max_value) + "'. "
            result = False

        if result and not phone_regex.match(value_string):
            error_message = "Field id '" + id_string + "' value '" \
                            + value_string + "' is not a valid phone number '" \
                            + str(max_value) + "'. "
            result = False

        return result, error_message

    def varchar_type(self, id_string, value_string, min_value, max_value):
        error_message = ""
        result = True

        if min_value == max_value and max_value == 0:
            return result, error_message

        if min_value == max_value and max_value != 0:
            if len(value_string) != max_value:
                error_message = "Field id '" + id_string + "' value '" \
                                + value_string + "' length should be '" \
                                + str(max_value) + "'. "
                result = False
        else:
            if min_value:
                if len(value_string) < min_value:
                    error_message = "Field id '" + id_string + "' value '" \
                                    + value_string + "' length should be at least '" \
                                    + str(min_value) + "'. "
                    result = False

            if max_value:
                if len(value_string) > max_value:
                    error_message += "Field id '" + id_string + "' value '" \
                                     + value_string + "' length should be less than '" \
                                     + str(max_value) + "'. "
                    result = False

        if 'email' in id_string:
            if not email_regex.match(value_string):
                error_message += "Field id '" + id_string + "' value '" \
                                + value_string + "' is not a valid email'. "
                result = False

        return result, error_message


@ns.route('/<int:paid>/form/<int:fid>/form_leads')
@api.doc(responses={200: 'OK',
                    400: 'Error performing operation.',
                    401: 'Unauthorized request.'},
         params={'fid': 'The form Id',
                 'paid': 'The partner account Id'})
class ApiFormLeadsGet(Resource):
    """
    # DISABLE ENDPOINT
    @requires_auth
    def get(self, paid, fid):
    """
    """
        Retrieves all the form leads for a form for a partnership account.

        <p>
        The Form Lead API GET endpoint should be used to retrieve information on all form leads
        associated with a partner account and a form.
        </p>
        <br />
        <p>
        You will require a partner authentication token and a partner account id to make a
        successful request. A response will
        be returned, similar to the example below, based
        on a successful request:
        <br />
        <br />
        </p>
        <pre class="code-background" style="color: white">
        {
            "form_leads": [
                {
                  "cellphonefield": "6554043321",
                  "cityfield": "Seattle",
                  "contact_id": 5,
                  "created_on": "2018-11-05 22:18:45",
                  "cumemberfield": "432455432",
                  "datepicker": "05-05-2014",
                  "email_sent": true,
                  "emailfield": "hv13@hotmail.com",
                  "external_api_lead_id": null,
                  "firstnamefield": "Bob Dennis",
                  "id": 6,
                  "incomefield": "5000",
                  "lastnamefield": "Mallery",
                  "lead-id-field": "6",
                  "phonefield": "7732909650",
                  "privacypolicyfield": "yes",
                  "statefield": "WA",
                  "streetfield": "12 East Rd",
                  "updated_on": "2018-11-05 22:19:31",
                  "zipfield": "98107"
                },
                {
                  "cellphonefield": "6554043321",
                  "cityfield": "Chicaho",
                  "contact_id": 5,
                  "created_on": "2019-01-14 23:43:48",
                  "cumemberfield": "123456789",
                  "datepicker": "04-03-2016",
                  "email_sent": true,
                  "emailfield": "harry@buyercall.com",
                  "external_api_lead_id": null,
                  "firstnamefield": "Bob",
                  "id": 91,
                  "incomefield": "50000",
                  "lastnamefield": "Bart",
                  "lead-id-field": "91",
                  "phonefield": "7732909650",
                  "privacypolicyfield": "yes",
                  "statefield": "KS",
                  "streetfield": "12 East Rd",
                  "updated_on": "2019-01-14 23:44:36",
                  "zipfield": "60640"
                },
            ]
        }
        </pre>

    """
    """
        if rest_is_partnership and rest_partnership is not None:
            form_lead_list = []
            partnership_account = PartnershipAccount \
                .query \
                .filter(and_(PartnershipAccount.id == paid, PartnershipAccount.partnership_id == rest_partnership.id)) \
                .first()

            if partnership_account is not None:
                form_leads = FormLead.query\
                    .filter(FormLead.partnership_account_id == paid,
                            FormLead.form_id == fid)\
                    .all()

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

                    for form_lead in form_leads:
                        add_form_lead = {
                            'id': form_lead.id,
                            'created_on': form_lead.interaction_time,
                            'updated_on': form_lead.updated_datetime,
                            'external_api_lead_id': form_lead.external_api_lead_id,
                            'email_sent': form_lead.email_sent,
                            'contact_id': form_lead.contact_id
                        }

                        if form_lead.fields is not None:
                            for form_lead_field in form_lead.fields:
                                try:
                                    processed_field_value = '' if form_lead_field.field_value is None else cipher.decrypt(
                                        form_lead_field.field_value)
                                except Exception:
                                    processed_field_value = form_lead_field.field_value

                                add_form_lead[form_lead_field.field_id] = processed_field_value

                        form_lead_list.append(add_form_lead)

                    return jsonify(
                        form_leads=form_lead_list
                    )
                else:
                    return api.abort(400, message='No form leads found.')
            else:
                return api.abort(400, message='Partnership account not found.')
        else:
            return api.abort(401, message='Unauthorized request.')
    """
    @api.response(204, 'Form lead successfully created.')
    @api.expect(serializers.form_lead_add, validate=True)
    @requires_auth
    def post(self, paid, fid):
        """
        Add a form lead for a partnership account.
        <P>
        This Form Lead API POST endpoint can be used to add form leads for an account associated with a partnership.
        </P>
         <br />
        <p>
        You will require a partner authentication token, a partner account Id as well as a form Id to make a
        successful request. A response will
        be returned, similar to the example below, based
        on a successful request:
        <br />
        <br />
        </p>
        <pre class="code-background" style="color: white">
        {
          "contact_id": 92,
          "form_id": 9,
          "form_lead_id": 202,
          "partnership_account_id": 1
        }
        </pre>

        """
        if rest_is_partnership and rest_partnership is not None:
            error_message = ""
            error_not_supported = ""
            error_required = ""
            contact_first_name = ""
            contact_last_name = ""
            contact_email_address = ""
            contact_phone_number = ""
            contact_address_1 = ""
            contact_address_2 = ""
            contact_city = ""
            contact_state = ""
            contact_zip = ""
            contact_country = ""
            contact_rep = ""
            contact_campaign = ""
            contact_dob = ""
            in_veh_year = None
            in_veh_make = ""
            in_veh_model = ""
            in_veh_vin = ""
            in_veh_trim = ""
            in_veh_stock = ""
            in_veh_price = None
            in_veh_mileage = None
            in_veh_condition = ""
            in_veh_url = ""
            ti_veh_year = None
            ti_veh_make = ""
            ti_veh_model = ""
            ti_veh_vin = ""
            ti_veh_mileage = None
            ti_veh_price = None
            ti_veh_condition = ""

            form_fields = []
            lead = None
            required_fields = None
            partial_submit = ""
            post_type = 3  # Default to full post
            result_fields = {}

            partnership_account = PartnershipAccount \
                .query \
                .filter(and_(PartnershipAccount.id == paid,
                             PartnershipAccount.partnership_id == rest_partnership.id)) \
                .first()

            if partnership_account is not None:
                received = request.get_json()
                result_fields = received
                if 'form_lead_id' in result_fields:
                    del result_fields['form_lead_id']

                lead_id = -1

                if 'form_lead_id' in received:
                    lead_id = received['form_lead_id']

                if request.headers.get('partial-submit') is not None:
                    partial_submit = request.headers.get('partial-submit').lower()

                if partial_submit == 'yes' and lead_id == -1:
                    log.info('Partial submit detected - Processing first portion of partial submit.')
                    post_type = Form_Lead_Post_Type.PARTIAL_POST_INITIAL
                elif lead_id > 0:
                    log.info('Partial submit detected - Processing second portion of partial submit.')
                    lead = FormLead.query\
                        .filter(and_(FormLead.id == lead_id, FormLead.partnership_account_id == paid))\
                        .first()

                    if lead is None:
                        log.error("Error creating lead. Second portion of partial submit failed. Lead ID " + str(
                            lead_id) + " not found.")
                        return api.abort(code=400, message="Error creating lead. Lead ID " + str(lead_id) + " not found.")

                    else:
                        post_type = Form_Lead_Post_Type.PARTIAL_POST_FOLLOW_UP

                elif lead_id < 1:
                    log.info('Full submit detected - Processing second portion of partial submit.')
                    post_type = Form_Lead_Post_Type.FULL_POST

                form = ExternalForm.query\
                    .filter(and_(ExternalForm.partnership_account_id == paid,
                                 ExternalForm.id == fid,
                                 ExternalForm.is_deactivated == False))\
                    .first()

                if form is not None:
                    field_definitions = ExternalFormFieldDefinition.api_get_field_definitions()
                    form_fields = ExternalFormField.get_form_fields(form.id)
                    message_builder = MessageBuilder()
                    type_switcher = TypeSwitcher()

                    if post_type != Form_Lead_Post_Type.PARTIAL_POST_FOLLOW_UP:
                        required_fields = ['firstname', 'lastname', 'phonenumber', 'email']
                        #['firstname', 'lastname', 'phone', 'email', 'state', 'city', 'date_of_birth', 'address_1']

                    for result_field in result_fields:
                        if result_field in required_fields:
                            required_fields.remove(result_field)

                        if result_field in form_fields:
                            form_fields.remove(result_field)

                        if result_field in field_definitions:
                            valid = False
                            message = ""
                            form_definition = field_definitions[result_field]

                            if form_definition.type == 'varchar':
                                result_fields[result_field] = strip_tags(result_fields[result_field])
                            if result_fields[result_field] != '':
                                valid, message = type_switcher.valid(form_definition.type, result_field,
                                                                     result_fields[result_field],
                                                                     form_definition.min_length, form_definition.max_length)
                                if not valid:
                                    error_message += message
                        else:
                            error_not_supported = message_builder.build_message(error_not_supported, result_field)

                    if required_fields is not None and len(required_fields) > 0:
                        for field_id in required_fields:
                            error_required = message_builder.build_message(error_required, str(field_id))
                else:
                    return api.abort(code=400, message="Error creating lead. Form " + str(fid) + " not found.")

                if len(error_message) > 0 or len(error_required) > 0 or len(error_not_supported) > 0:
                    final_error_message = ""

                    if len(error_message) > 0:
                        final_error_message += "Field validation error(s): " + error_message

                    if len(error_not_supported) > 0:
                        final_error_message += "Field(s) not supported: " + error_not_supported

                    if len(error_required) > 0:
                        final_error_message += "Field(s) required: " + error_required

                    return api.abort(code=400, message="Error creating form lead. " + final_error_message)
                else:
                    for form_field_id in form_fields:
                        result_fields[form_field_id] = ""

                    if post_type == Form_Lead_Post_Type.FULL_POST or Form_Lead_Post_Type.PARTIAL_POST_INITIAL:
                        lead = FormLead()
                        lead.form = form
                        lead.partnership_account_id = form.partnership_account_id

                    for current_field in result_fields:
                        field_id = current_field
                        field_value = result_fields[field_id]

                        if field_value is not None:
                            if field_id == 'firstname' or field_id == 'firstnamefield':
                                contact_first_name = strip_tags(field_value)

                            if field_id == 'lastname' or field_id == 'lastnamefield':
                                contact_last_name = strip_tags(field_value)

                            if field_id == 'email' or field_id == 'emailfield':
                                contact_email_address = strip_tags(field_value)

                            if field_id == 'phonenumber' or field_id == 'phonefield':
                                contact_phone_number = strip_tags(field_value)

                            if field_id == 'address_1' or field_id == 'streetfield':
                                contact_address_1 = strip_tags(field_value)

                            if field_id == 'address_2':
                                contact_address_2 = strip_tags(field_value)

                            if field_id == 'city' or field_id == 'citytfield' or field_id == 'cityfield':
                                contact_city = strip_tags(field_value)

                            if field_id == 'state' or field_id == 'statefield':
                                contact_state = strip_tags(field_value)

                            if field_id == 'zip' or field_id == 'zipfield':
                                contact_zip = strip_tags(field_value)

                            if field_id == 'country' or field_id == 'countryfield':
                                contact_country = strip_tags(field_value)

                            if field_id == 'birthday' or field_id == 'datepicker':
                                contact_dob = field_value

                            if field_id == 'repfield':
                                contact_rep = strip_tags(field_value)

                            if field_id == 'campaign' or field_id == 'campaignfield':
                                contact_campaign = strip_tags(field_value)

                            if field_id == 'vehicle_year' or field_id == 'vehicleyearfield':
                                in_veh_year = field_value

                            if field_id == 'vehicle_make' or field_id == 'vehiclemakefield':
                                in_veh_make = strip_tags(field_value)

                            if field_id == 'vehicle_model' or field_id == 'vehiclemodelfield':
                                in_veh_model = strip_tags(field_value)

                            if field_id == 'vin' or field_id == 'vinfield':
                                in_veh_vin = strip_tags(field_value)

                            if field_id == 'vehicle_trim' or field_id == 'vehicletrimfield':
                                in_veh_trim = strip_tags(field_value)

                            if field_id == 'stock_number' or field_id == 'stockfield':
                                in_veh_stock = strip_tags(field_value)

                            if field_id == 'vehicle_purchase_price' or field_id == 'vehiclepurchasepricefield':
                                in_veh_price = field_value

                            if field_id == 'vehicle_mileage' or field_id == 'vehiclemileagefield':
                                in_veh_mileage = field_value

                            if field_id == 'vehicle_condition' or field_id == 'vehicleconditionfield':
                                in_veh_condition = strip_tags(field_value)

                            if field_id == 'listing_url' or field_id == 'listingurlfield':
                                in_veh_url = field_value

                            if field_id == 'trade_in_vehicle_year' or field_id == 'tradeinvehicleyearfield':
                                ti_veh_year = field_value

                            if field_id == 'trade_in_vehicle_make' or field_id == 'tradeinvehiclemakefield':
                                ti_veh_make = strip_tags(field_value)

                            if field_id == 'trade_in_vehicle_model' or field_id == 'tradeinvehiclemodelfield':
                                ti_veh_model = strip_tags(field_value)

                            if field_id == 'trade_in_vehicle_vin' or field_id == 'tradeinvehiclevinfield':
                                ti_veh_vin = strip_tags(field_value)

                            if field_id == 'trade_in_vehicle_value' or field_id == 'tradeinvehiclevaluefield':
                                ti_veh_price = field_value

                            if field_id == 'trade_in_vehicle_mileage' or field_id == 'tradeinvehiclemileagefield':
                                ti_veh_mileage = field_value

                            if field_id == 'trade_in_vehicle_condition' or field_id == 'tradeinvehicleconditionfield':
                                ti_veh_condition = strip_tags(field_value)

                        field = FormLeadField(field_id, field_value)
                        encrypt_key = app.config['CRYPTO_SECRET_KEY']

                        if field.field_value is not None and field.field_value is not "":
                            cipher = AESCipher(encrypt_key)
                            encoded = cipher.encrypt(str(field.field_value))
                            field.field_value = encoded
                            lead.fields.append(field)
                        else:
                            lead.fields.append(field)

                    result, lead, error_message = FormLead.api_create(lead)

                    if result:
                        # Create lead contact.
                        # Must not be done for the second portion of the "partial" post as this will create a duplicate.
                        if post_type == Form_Lead_Post_Type.PARTIAL_POST_INITIAL or post_type == Form_Lead_Post_Type.FULL_POST:
                            from ....form_leads.form_tasks import add_form_contact
                            form_lead_id = lead.id
                            add_form_contact(form_lead_id, contact_first_name, contact_last_name, contact_email_address,
                                             contact_phone_number, contact_address_1, contact_address_2, contact_city,
                                             contact_state, contact_zip, contact_country, contact_rep, in_veh_year,
                                             in_veh_make, in_veh_model, in_veh_vin, in_veh_trim, in_veh_stock,
                                             in_veh_price, in_veh_mileage, in_veh_condition, in_veh_url, ti_veh_year,
                                             ti_veh_make, ti_veh_model, ti_veh_vin, ti_veh_price, ti_veh_mileage,
                                             ti_veh_condition, paid, lead.updated_on, contact_dob, campaign=contact_campaign)

                        # Perform partial post tasks and return lead id.
                        if post_type == Form_Lead_Post_Type.PARTIAL_POST_INITIAL:
                            if lead.email_sent is False and form.partial_data_email:
                                from ....form_leads.views import send_notifications
                                send_notifications(lead)
                                lead.email_sent = True
                                log.debug('A partial form submit email notification has been sent')
                                db.session.commit()
                            return jsonify(lead_id=lead.id)

                        # Perform complete form post tasks.
                        if post_type == Form_Lead_Post_Type.PARTIAL_POST_FOLLOW_UP or post_type == Form_Lead_Post_Type.FULL_POST:
                            if lead.email_sent is False and form.full_submit_email:
                                from ....form_leads.views import send_notifications
                                send_notifications(lead)
                                lead.email_sent = True
                                log.debug('A full form submit email notification has been sent')
                                db.session.commit()

                        # Check if email auto responder is turned on and send email
                        if form.send_auto_email:
                            sender_domain = 'buyercall.com'
                            partner = Partnership.query.filter(Partnership.id == partnership_account.partnership_id).first()
                            if partner is not None:
                                if partner.email_sender:
                                    sender_domain = partner.email_sender.split("@")[1]
                            account_email_address = re.sub('[^A-Za-z0-9]+', '',
                                                           partnership_account.name).lower() + '@' + sender_domain

                            from ....form_leads.form_tasks import send_email_auto_responds
                            send_email_auto_responds(contact_email_address, contact_first_name, form.display_name,
                                                     partnership_account.name, account_email_address,
                                                     form.send_auto_email_subject, form.send_auto_email_msg)
                            log.info('An auto email responds message has been sent to lead id {}'.format(lead.id))

                        # Check if sms auto responder is turned on and send text message
                        if form.send_auto_sms:
                            from ....form_leads.form_tasks import send_sms_auto_responds
                            send_sms_auto_responds(contact_phone_number, contact_first_name, form.display_name,
                                                   partnership_account.name, form.send_auto_sms_inbound_id,
                                                  form.send_auto_sms_msg)
                            log.info('An auto sms responds message has been sent to lead id {}'.format(lead.id))

                        # Try and retrieve the credit score for the lead
                        credit_credentials = PartnershipAccountCreditTie.partner_account_seven_hundred_credit_info(
                            paid, 'prequalify')
                        service_provider = '700Credit'
                        if not credit_credentials:
                            credit_credentials = PartnershipAccountCreditTie.partner_account_finserv_credit_info(
                                paid, 'prequalify')
                            service_provider = 'Finserv'
                        if not credit_credentials:
                            partner_account = PartnershipAccount.query.filter(
                                PartnershipAccount.id == paid).first()
                            try:
                                credit_credentials = PartnershipCreditTie.partner_finserv_credit_info(
                                    partner_account.partnership_id, 'prequalify')
                            except:
                                log.error("Unable to set partnership id for lead {} and got error : {}".format(
                                    lead.id, traceback.format_exc()))
                            service_provider = 'Finserv'
                        try:
                            if form.auto_prequalify_credit and credit_credentials:
                                from buyercall.blueprints.contacts.contact_tasks import pull_prequalify_credit
                                if credit_credentials.experian_enabled:
                                    bureau = 'experian'
                                elif credit_credentials.transunion_enabled:
                                    bureau = 'transunion'
                                elif credit_credentials.equifax_enabled:
                                    bureau = 'equifax'
                                else:
                                    bureau = ''

                                pull_prequalify_credit(bureau,
                                                       'prequalify',
                                                       lead.contact_id, paid,
                                                       contact_first_name,
                                                       contact_last_name,
                                                       contact_address_1,
                                                       contact_city,
                                                       contact_state,
                                                       contact_zip,
                                                       service_provider,
                                                       contact_dob)
                        except:
                            log.error("Cannot check credit on form lead {} and got error : {}".format(lead.id,
                                                                                                      traceback.format_exc()))

                        try:
                            if form.routing:
                                widget_lead = add_widget_lead(
                                    form.routing,
                                    firstName=contact_first_name,
                                    lastName=contact_last_name,
                                    emailAddress=contact_email_address,
                                    phoneNumber=contact_phone_number
                                )
                                client = bw_client(partnership_account.partnership_id, 'voice')
                                r = Routing(client)
                                r.call_lead(form.routing, widget_lead)
                        except:
                            log.error("Cannot add or call lead: {}".format(traceback.format_exc()))

                        if lead.id > 0:
                            if post_type == Form_Lead_Post_Type.FULL_POST:
                                return jsonify(
                                    partnership_account_id=paid,
                                    form_id=form.id,
                                    form_lead_id=lead.id,
                                    contact_id=lead.contact_id
                                )
                            else:
                                return True, 200
                        else:
                            return api.abort(code=400, message="Error creating lead.")
                    else:
                        return api.abort(code=400, message="Error creating lead. " + str(error_message))
            else:
                return api.abort(404, message='Partnership account not found.')
        else:
            return api.abort(401)


@ns.route('/<int:paid>/form/<int:fid>/equifax/form_leads')
@api.doc(responses={200: 'OK',
                    400: 'Error performing operation.',
                    401: 'Unauthorized request.'},
         params={'fid': 'The form Id',
                 'paid': 'The partner account Id'})
class ApiFormEquifaxLeads(Resource):
    @api.response(204, 'Form lead successfully created.')
    @api.expect(serializers.form_equifax_lead_add, validate=True)
    @requires_auth
    def post(self, paid, fid):
        """
        Add an Equifax form lead for a partnership account.
        <P>
        This Form Lead API POST endpoint can be used to add Equifax form leads for an account associated with a
        partnership.
        </P>
         <br />
        <p>
        You will require a partner authentication token, a partner account Id as well as a form Id to make a
        successful request. A response will
        be returned, similar to the example below, based
        on a successful request:
        <br />
        <br />
        </p>
        <pre class="code-background" style="color: white">
        {
          "contact_id": 92,
          "form_id": 9,
          "form_lead_id": 202,
          "partnership_account_id": 1
        }
        </pre>

        """
        if rest_is_partnership and rest_partnership is not None:
            error_message = ""
            error_not_supported = ""
            error_required = ""
            contact_first_name = ""
            contact_last_name = ""
            contact_email_address = ""
            contact_phone_number = ""
            contact_address_1 = ""
            contact_address_2 = ""
            contact_city = ""
            contact_state = ""
            contact_zip = ""
            contact_dob = ""
            contact_country = ""
            contact_campaign = ""
            in_veh_year = None
            in_veh_make = ""
            in_veh_model = ""
            in_veh_vin = ""
            in_veh_trim = ""
            in_veh_stock = ""
            in_veh_price = None
            in_veh_mileage = None
            in_veh_condition = ""
            in_veh_url = ""
            ti_veh_year = None
            ti_veh_make = ""
            ti_veh_model = ""
            ti_veh_vin = ""
            ti_veh_mileage = None
            ti_veh_price = None
            ti_veh_condition = ""
            contact_rep = ""
            form_fields = []
            lead = None
            required_fields = None
            partial_submit = ""
            post_type = 3  # Default to full post
            result_fields = {}

            partnership_account = PartnershipAccount \
                .query \
                .filter(and_(PartnershipAccount.id == paid,
                             PartnershipAccount.partnership_id == rest_partnership.id)) \
                .first()

            if partnership_account is not None:
                received = request.get_json()
                result_fields = received
                if 'form_lead_id' in result_fields:
                    del result_fields['form_lead_id']

                lead_id = -1

                if 'form_lead_id' in received:
                    lead_id = received['form_lead_id']

                if request.headers.get('partial-submit') is not None:
                    partial_submit = request.headers.get('partial-submit').lower()

                if partial_submit == 'yes' and lead_id == -1:
                    log.info('Partial submit detected - Processing first portion of partial submit.')
                    post_type = Form_Lead_Post_Type.PARTIAL_POST_INITIAL
                elif lead_id > 0:
                    log.info('Partial submit detected - Processing second portion of partial submit.')
                    lead = FormLead.query \
                        .filter(and_(FormLead.id == lead_id, FormLead.partnership_account_id == paid)) \
                        .first()

                    if lead is None:
                        log.error("Error creating lead. Second portion of partial submit failed. Lead ID " + str(
                            lead_id) + " not found.")
                        return api.abort(code=400,
                                         message="Error creating lead. Lead ID " + str(lead_id) + " not found.")

                    else:
                        post_type = Form_Lead_Post_Type.PARTIAL_POST_FOLLOW_UP

                elif lead_id < 1:
                    log.info('Full submit detected - Processing second portion of partial submit.')
                    post_type = Form_Lead_Post_Type.FULL_POST

                form = ExternalForm.query \
                    .filter(and_(ExternalForm.partnership_account_id == paid,
                                 ExternalForm.id == fid,
                                 ExternalForm.is_deactivated.is_(False))).first()

                if form is not None:
                    field_definitions = ExternalFormFieldDefinition.api_get_field_definitions()
                    form_fields = ExternalFormField.get_form_fields(form.id)
                    message_builder = MessageBuilder()
                    type_switcher = TypeSwitcher()

                    if post_type != Form_Lead_Post_Type.PARTIAL_POST_FOLLOW_UP:
                        required_fields = ['phonenumber']
                        # ['firstname', 'lastname', 'phone', 'email', 'state', 'city', 'date_of_birth', 'address_1']

                    for result_field in result_fields:
                        if result_field in required_fields:
                            required_fields.remove(result_field)

                        if result_field in form_fields:
                            form_fields.remove(result_field)

                        if result_field not in ['score', 'call_result']:
                            if result_field in field_definitions:
                                valid = False
                                message = ""
                                form_definition = field_definitions[result_field]

                                if form_definition.type == 'varchar':
                                    result_fields[result_field] = strip_tags(result_fields[result_field])
                                if result_fields[result_field] != '':
                                    valid, message = type_switcher.valid(form_definition.type, result_field,
                                                                         result_fields[result_field],
                                                                         form_definition.min_length, form_definition.max_length)
                                    if not valid:
                                        error_message += message
                            else:
                                error_not_supported = message_builder.build_message(error_not_supported, result_field)

                    if required_fields is not None and len(required_fields) > 0:
                        for field_id in required_fields:
                            error_required = message_builder.build_message(error_required, str(field_id))
                else:
                    return api.abort(code=400, message="Error creating lead. Form " + str(fid) + " not found.")

                if len(error_message) > 0 or len(error_required) > 0 or len(error_not_supported) > 0:
                    final_error_message = ""

                    if len(error_message) > 0:
                        final_error_message += "Field validation error(s): " + error_message

                    if len(error_not_supported) > 0:
                        final_error_message += "Field(s) not supported: " + error_not_supported

                    if len(error_required) > 0:
                        final_error_message += "Field(s) required: " + error_required

                    return api.abort(code=400, message="Error creating form lead. " + final_error_message)
                else:
                    for form_field_id in form_fields:
                        result_fields[form_field_id] = ""

                    if post_type == Form_Lead_Post_Type.FULL_POST or Form_Lead_Post_Type.PARTIAL_POST_INITIAL:
                        lead = FormLead()
                        lead.form = form
                        lead.partnership_account_id = form.partnership_account_id

                    encrypt_key = app.config['CRYPTO_SECRET_KEY']
                    cipher = AESCipher(encrypt_key)

                    if 'score' in result_fields and 'call_result' in result_fields:
                        eq_data_available = True
                    else:
                        eq_data_available = False

                    for current_field in result_fields:
                        field_id = current_field
                        field_value = result_fields[field_id]

                        if field_value is not None:

                            if field_id == 'firstname' or field_id == 'firstnamefield':
                                if field_value == '':
                                    if eq_data_available:
                                        eq_field_value = \
                                            result_fields['call_result']['consumers']['equifaxUSConsumerCreditReport'][
                                                0]['subjectName'].get('firstName', '')
                                        field_value = eq_field_value
                                        contact_first_name = field_value
                                    else:
                                        contact_first_name = strip_tags(field_value)
                                else:
                                    contact_first_name = strip_tags(field_value)

                            if field_id == 'middlename' or field_id == 'middlenamefield':
                                if field_value == '':
                                    if eq_data_available:
                                        eq_field_value = \
                                            result_fields['call_result']['consumers']['equifaxUSConsumerCreditReport'][
                                                0]['subjectName'].get('middleName', '')
                                        field_value = eq_field_value

                            if field_id == 'lastname' or field_id == 'lastnamefield':
                                if field_value == '':
                                    if eq_data_available:
                                        eq_field_value = \
                                            result_fields['call_result']['consumers']['equifaxUSConsumerCreditReport'][
                                                0]['subjectName'].get('lastName', '')
                                        field_value = eq_field_value
                                        contact_last_name = field_value
                                    else:
                                        contact_last_name = strip_tags(field_value)
                                else:
                                    contact_last_name = strip_tags(field_value)

                            if field_id == 'email' or field_id == 'emailfield':
                                contact_email_address = strip_tags(field_value)

                            if field_id == 'phonenumber' or field_id == 'phonefield':
                                contact_phone_number = strip_tags(field_value)

                            if field_id == 'address_1' or field_id == 'streetfield':
                                if field_value == '':
                                    if eq_data_available:
                                        try:
                                            if result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['addresses'][0]\
                                                    .get('streetType', ''):
                                                eq_street_type = result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['addresses'][0]['streetType']
                                            else:
                                                eq_street_type = ''
                                            eq_field_value = \
                                                result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['addresses'][0][
                                                    'houseNumber'] + " " + result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['addresses'][0].get(
                                                    'streetName', '') + " " + eq_street_type
                                            field_value = eq_field_value
                                            contact_address_1 = field_value
                                        except:
                                            contact_address_1 = ''
                                    else:
                                        contact_address_1 = strip_tags(field_value)
                                else:
                                    contact_address_1 = strip_tags(field_value)

                            if field_id == 'address_2':
                                contact_address_2 = strip_tags(field_value)

                            if field_id == 'city' or field_id == 'citytfield' or field_id == 'cityfield':
                                if field_value == '':
                                    if eq_data_available:
                                        try:
                                            eq_field_value = \
                                                result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['addresses'][0].get(
                                                    'cityName', '')
                                            field_value = eq_field_value
                                            contact_city = field_value
                                        except:
                                            contact_city = ''
                                    else:
                                        contact_city = strip_tags(field_value)
                                else:
                                    contact_city = strip_tags(field_value)

                            if field_id == 'state' or field_id == 'statefield':
                                if field_value == '':
                                    if eq_data_available:
                                        try:
                                            eq_field_value = \
                                                result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['addresses'][0].get(
                                                    'stateAbbreviation', '')
                                            field_value = eq_field_value
                                            contact_state = field_value
                                        except:
                                            contact_state = ''
                                    else:
                                        contact_state = strip_tags(field_value)
                                else:
                                    contact_state = strip_tags(field_value)

                            if field_id == 'zip' or field_id == 'zipfield':
                                if field_value == '':
                                    if eq_data_available:
                                        try:
                                            eq_field_value = \
                                                result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['addresses'][0].get(
                                                    'zipCode', '')
                                            field_value = eq_field_value
                                            contact_zip = field_value
                                        except:
                                            contact_zip = ''
                                    else:
                                        contact_zip = strip_tags(field_value)
                                else:
                                    contact_zip = strip_tags(field_value)

                            if field_id == 'country' or field_id == 'countryfield':
                                contact_country = strip_tags(field_value)

                            if field_id == 'birthday' or field_id == 'datepicker':
                                if field_value == '':
                                    if eq_data_available:
                                        try:
                                            eq_field_value = \
                                                result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0].get('birthDate', '')
                                            field_value = eq_field_value
                                            contact_dob = field_value
                                        except:
                                            contact_dob = ''
                                    else:
                                        contact_dob = field_value
                                else:
                                    contact_dob = field_value

                            if field_id == 'repfield':
                                contact_rep = strip_tags(field_value)

                            if field_id == 'employer' or field_id == 'employerfield':
                                if field_value == '':
                                    if eq_data_available:
                                        try:
                                            eq_field_value = \
                                                result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0]['employments'][
                                                    0].get('employer', '')
                                            field_value = eq_field_value
                                        except:
                                            field_value = ''

                            if field_id == 'ssn' or field_id in ['ssnfield', 'cumemberfield']:
                                if field_value == '':
                                    if eq_data_available:
                                        try:
                                            eq_field_value = \
                                                result_fields['call_result']['consumers'][
                                                    'equifaxUSConsumerCreditReport'][0].get('subjectSocialNum', '')
                                            field_value = eq_field_value
                                        except:
                                            field_value = ''

                            if field_id == 'campaign' or field_id == 'campaignfield':
                                contact_campaign = strip_tags(field_value)

                            if field_id == 'vehicle_year' or field_id == 'vehicleyearfield':
                                in_veh_year = field_value

                            if field_id == 'vehicle_make' or field_id == 'vehiclemakefield':
                                in_veh_make = strip_tags(field_value)

                            if field_id == 'vehicle_model' or field_id == 'vehiclemodelfield':
                                in_veh_model = strip_tags(field_value)

                            if field_id == 'vin' or field_id == 'vinfield':
                                in_veh_vin = strip_tags(field_value)

                            if field_id == 'vehicle_trim' or field_id == 'vehicletrimfield':
                                in_veh_trim = strip_tags(field_value)

                            if field_id == 'stock_number' or field_id == 'stockfield':
                                in_veh_stock = strip_tags(field_value)

                            if field_id == 'vehicle_purchase_price' or field_id == 'vehiclepurchasepricefield':
                                in_veh_price = field_value

                            if field_id == 'vehicle_mileage' or field_id == 'vehiclemileagefield':
                                in_veh_mileage = field_value

                            if field_id == 'vehicle_condition' or field_id == 'vehicleconditionfield':
                                in_veh_condition = strip_tags(field_value)

                            if field_id == 'listing_url' or field_id == 'listingurlfield':
                                in_veh_url = field_value

                            if field_id == 'trade_in_vehicle_year' or field_id == 'tradeinvehicleyearfield':
                                ti_veh_year = field_value

                            if field_id == 'trade_in_vehicle_make' or field_id == 'tradeinvehiclemakefield':
                                ti_veh_make = strip_tags(field_value)

                            if field_id == 'trade_in_vehicle_model' or field_id == 'tradeinvehiclemodelfield':
                                ti_veh_model = strip_tags(field_value)

                            if field_id == 'trade_in_vehicle_vin' or field_id == 'tradeinvehiclevinfield':
                                ti_veh_vin = strip_tags(field_value)

                            if field_id == 'trade_in_vehicle_value' or field_id == 'tradeinvehiclevaluefield':
                                ti_veh_price = field_value

                            if field_id == 'trade_in_vehicle_mileage' or field_id == 'tradeinvehiclemileagefield':
                                ti_veh_mileage = field_value

                            if field_id == 'trade_in_vehicle_condition' or field_id == 'tradeinvehicleconditionfield':
                                ti_veh_condition = strip_tags(field_value)

                        field = FormLeadField(field_id, field_value)

                        if field.field_value is not None and field.field_value is not "":
                            try:
                                encoded = cipher.encrypt(str(field.field_value))
                                field.field_value = encoded
                                lead.fields.append(field)
                            except:
                                lead.fields.append(field)
                                from buyercall.lib.util_ses_email import send_ses_email
                                email_message = 'The field value: ' + \
                                                str(field.field_value) + ' did not encrypt. this was for form: ' + \
                                                str(fid) + ' and partnership account id: ' + str(paid)
                                send_ses_email(recipients=['admin@buyercall.com'],
                                               p_id=partnership_account.partnership_id,
                                               subject='Encryption failed',
                                               text=email_message)
                        else:
                            lead.fields.append(field)

                    result, lead, error_message = FormLead.api_create(lead)

                    if result:
                        # Create lead contact.
                        # Must not be done for the second portion of the "partial" post as this will create a duplicate.
                        if post_type == Form_Lead_Post_Type.PARTIAL_POST_INITIAL or post_type == Form_Lead_Post_Type.FULL_POST:
                            from ....form_leads.form_tasks import add_form_contact
                            form_lead_id = lead.id
                            add_form_contact(form_lead_id, contact_first_name, contact_last_name, contact_email_address,
                                             contact_phone_number, contact_address_1, contact_address_2, contact_city,
                                             contact_state, contact_zip, contact_country, contact_rep, in_veh_year,
                                             in_veh_make, in_veh_model, in_veh_vin, in_veh_trim, in_veh_stock,
                                             in_veh_price, in_veh_mileage, in_veh_condition, in_veh_url, ti_veh_year,
                                             ti_veh_make, ti_veh_model, ti_veh_vin, ti_veh_price, ti_veh_mileage,
                                             ti_veh_condition, paid, lead.updated_on, contact_dob, eq_lead=True,
                                             campaign=contact_campaign)

                        if eq_data_available:
                            try:
                                # Save Equifax credit data
                                link = result_fields['call_result']['links'][0]['href']
                                trans_id = link.rsplit('/', 1)[-1]
                                # Set the credit report table
                                from ....contacts.models import CreditReports
                                credit_table = CreditReports()
                                # Add an entry to credit reports table with Equifax API data
                                credit_table.service_provider = 'Offerlogix'
                                credit_table.transaction_id = cipher.encrypt(trans_id)
                                credit_table.credit_score = cipher.encrypt(str(result_fields['score']))
                                credit_table.score_card_name = result_fields['call_result']['consumers'][
                                    'equifaxUSConsumerCreditReport'][0]['identifier']
                                credit_table.contact_id = lead.contact_id
                                credit_table.credit_bureau = 'equifax'
                                credit_table.product_type = 'prequalify'
                                credit_table.partnership_account_id = paid
                                credit_table.description = result_fields['call_result']['status']
                                credit_table.is_successful = True
                                credit_table.trades = cipher.encrypt(json.dumps(
                                    {'score': result_fields['score'],
                                     'call_result': result_fields['call_result']
                                     }
                                ))

                                credit_table.save()
                                db.session.commit()
                            except:
                                return api.abort(code=400, message="Unable to save credit data.")

                        # Perform partial post tasks and return lead id.
                        if post_type == Form_Lead_Post_Type.PARTIAL_POST_INITIAL:
                            if lead.email_sent is False and form.partial_data_email:
                                from ....form_leads.views import send_notifications
                                send_notifications(lead)
                                lead.email_sent = True
                                log.debug('A partial form submit email notification has been sent')
                                db.session.commit()
                            return jsonify(lead_id=lead.id)

                        # Perform complete form post tasks.
                        if post_type == Form_Lead_Post_Type.PARTIAL_POST_FOLLOW_UP or post_type == Form_Lead_Post_Type.FULL_POST:
                            if lead.email_sent is False and form.full_submit_email:
                                from ....form_leads.views import send_notifications
                                send_notifications(lead)
                                lead.email_sent = True
                                log.debug('A full form submit email notification has been sent')
                                db.session.commit()

                        # Check if email auto responder is turned on and send email
                        if form.send_auto_email:
                            sender_domain = 'buyercall.com'
                            partner = Partnership.query.filter(
                                Partnership.id == partnership_account.partnership_id).first()
                            if partner is not None:
                                if partner.email_sender:
                                    sender_domain = partner.email_sender.split("@")[1]
                            account_email_address = re.sub('[^A-Za-z0-9]+', '',
                                                           partnership_account.name).lower() + '@' + sender_domain

                            from ....form_leads.form_tasks import send_email_auto_responds
                            send_email_auto_responds(contact_email_address, contact_first_name, form.display_name,
                                                     partnership_account.name, account_email_address,
                                                     form.send_auto_email_subject, form.send_auto_email_msg)
                            log.info('An auto email responds message has been sent to lead id {}'.format(lead.id))

                        # Check if sms auto responder is turned on and send text message
                        if form.send_auto_sms:
                            from ....form_leads.form_tasks import send_sms_auto_responds
                            send_sms_auto_responds(contact_phone_number, contact_first_name, form.display_name,
                                                   partnership_account.name, form.send_auto_sms_inbound_id,
                                                   form.send_auto_sms_msg)
                            log.info('An auto sms responds message has been sent to lead id {}'.format(lead.id))

                        try:
                            if form.routing:
                                widget_lead = add_widget_lead(
                                    form.routing,
                                    firstName=contact_first_name,
                                    lastName=contact_last_name,
                                    emailAddress=contact_email_address,
                                    phoneNumber=contact_phone_number
                                )
                                client = bw_client(partnership_account.partnership_id, 'voice')
                                r = Routing(client)
                                r.call_lead(form.routing, widget_lead)
                        except:
                            log.error("Cannot add or call lead: {}".format(traceback.format_exc()))

                        if lead.id > 0:
                            if post_type == Form_Lead_Post_Type.FULL_POST:
                                eq_file_upload_url = 'https://' + app.config['SERVER_DOMAIN'] + '/api/v2/accounts/' \
                                                     + str(paid) + '/form/' + str(fid) \
                                                     + '/equifax/form_leads/' + str(lead.id)

                                if rest_partnership.partner_url and rest_partnership.id != 1:
                                    base_url = rest_partnership.partner_url.replace('https://', '').replace('www', '')

                                else:
                                    base_url = app.config['SERVER_DOMAIN']

                                contact_credit_history_url = ('https://' + base_url + '/contacts/edit/'
                                                              + str(lead.contact_id) + '#credit')
                                return jsonify(
                                    partnership_account_id=paid,
                                    form_id=form.id,
                                    form_lead_id=lead.id,
                                    form_lead_file_upload_url=eq_file_upload_url,
                                    contact_credit_url=contact_credit_history_url
                                )
                            else:
                                return True, 200
                        else:
                            return api.abort(code=400, message="Error creating lead.")
                    else:
                        return api.abort(code=400, message="Error creating lead. " + str(error_message))
            else:
                return api.abort(404, message='Partnership account not found.')
        else:
            return api.abort(401)


@ns.route('/<int:paid>/form/<int:fid>/equifax/form_leads/<int:flid>')
@api.doc(responses={200: 'OK',
                    400: 'Error performing operation.',
                    401: 'Unauthorized request.',
                    404: 'Contact not found.'},
         params={'fid': 'The form Id',
                'flid': 'The form lead Id',
                'paid': 'The partner account Id'})
class ApiFormEquifaxLeadFile(Resource):
    @api.response(204, 'Form lead successfully updated.')
    @api.expect(serializers.form_equifax_lead_file_add, validate=False)
    @requires_auth
    def put(self, paid, fid, flid):
        """
        Add a file to an Equifax form lead

        <p>
        The Equifax Form Lead API POST endpoint should be used to attach a credit file to an Equifax lead.
        </p>
        <br />
        <p>
        You will require a partner authentication token, a partner account id, form id and form lead id to make a
        successful request.
        </p>


        """
        allowed_ext = ['pdf']
        if rest_is_partnership and rest_partnership is not None:
            partnership_account = PartnershipAccount \
                .query \
                .filter(and_(PartnershipAccount.id == paid,
                             PartnershipAccount.partnership_id == rest_partnership.id)) \
                .first()

            if partnership_account is not None:
                form_lead = FormLead.query \
                    .filter(FormLead.partnership_account_id == paid,
                            FormLead.form_id == fid,
                            FormLead.id == flid) \
                    .first()
                if form_lead is not None:
                    received = request.files
                    if received:
                        file = received['file']
                        if file:
                            file_name = received['file'].filename
                            content_type = received['file'].content_type
                            file_ext = file_name.rsplit('.', 1)[1]
                            if file_ext in allowed_ext and content_type == 'application/pdf':
                                contact_id = form_lead.contact_id
                                file.save(os.path.join(app.config['UPLOAD_FOLDER'], f"eq-pdf-{contact_id}"))
                                file_path = os.path.join(app.config['UPLOAD_FOLDER'], f"eq-pdf-{contact_id}")
                                bucket = app.config['EQ_PDF_BUCKET']
                                hex_value = uuid.uuid4().hex
                                key = '{}_{}/{}_{}_{}'.format(partnership_account.name,
                                                              partnership_account.id, contact_id, 'eq-pdf', hex_value)
                                from buyercall.lib.util_boto3_s3 import upload_file
                                upload_file(file_path, bucket, key, content_type)
                                os.remove(file_path)
                                from ....contacts.models import CreditReports
                                credit_report = CreditReports.query.filter(CreditReports.contact_id == contact_id).first()
                                if credit_report:
                                    encrypt_key = app.config['CRYPTO_SECRET_KEY']
                                    cipher = AESCipher(encrypt_key)
                                    iframe_url = '{}::{}'.format(app.config['EQ_PDF_BUCKET'], key)
                                    credit_report.iframe_url = cipher.encrypt(iframe_url)
                                    db.session.commit()

                                result = {
                                    'form_lead_id': form_lead.id,
                                    'file_uploaded': received['file'].filename
                                }
                                return jsonify(
                                    result
                                )
                            else:
                                return api.abort(400, message='The file extension is not acceptable.')
                        else:
                            return api.abort(400, message='No file was detected in the request.')
                    else:
                        return api.abort(400, message='The request is in-complete. No payload received.')
                else:
                    return api.abort(400, message='Form lead not found.')
            else:
                return api.abort(400, message='Partnership account not found.')
        else:
            return api.abort(401, message='Unauthorized request.')


"""
# DISABLE ENDPOINT
@ns.route('/<int:paid>/form/<int:fid>/form_leads/<int:flid>')
@api.doc(responses={200: 'OK',
                    400: 'Error performing operation.',
                    401: 'Unauthorized request.',
                    404: 'Contact not found.'},
         params={'fid': 'The form Id',
                'flid': 'The form lead Id',
                'paid': 'The partner account Id'})
"""
class ApiFormLeadUpdate(Resource):
    @requires_auth
    def get(self, paid, fid, flid):
        """
        Retrieves the form lead for a form for a partnership account.

        <p>
        The Form Lead API GET endpoint should be used to retrieve information on a form lead
        associated with a partner accoun and a form.
        </p>
        <br />
        <p>
        You will require a partner authentication token and a partner account id to make a
        successful request. A response will
        be returned, similar to the example below, based
        on a successful request:
        <br />
        <br />
        </p>
        <pre class="code-background" style="color: white">
        {
          "cellphonefield": "798434543534",
          "cityfield": "SANTA MARIA",
          "contact_id": 50,
          "created_on": "2020-02-04 18:05:26",
          "cumemberfield": "666056157",
          "datepicker": "04-14-2008",
          "email_sent": true,
          "emailfield": "belinda@carter.com",
          "external_api_lead_id": null,
          "firstnamefield": "BELINDA",
          "id": 160,
          "incomefield": "6000",
          "lastnamefield": "CARTER",
          "lead-id-field": "160",
          "phonefield": "8034006566",
          "privacypolicyfield": "yes",
          "repfield": "",
          "statefield": "CA",
          "streetfield": "1456 IVORY DR",
          "updated_on": "2020-02-04 18:05:28",
          "zipfield": "93455"
        }
        </pre>

        """
        if rest_is_partnership and rest_partnership is not None:
            form_lead_field_list = []
            partnership_account = PartnershipAccount \
                .query \
                .filter(and_(PartnershipAccount.id == paid, PartnershipAccount.partnership_id == rest_partnership.id)) \
                .first()

            if partnership_account is not None:
                form_lead = FormLead.query\
                    .filter(FormLead.partnership_account_id == paid,
                            FormLead.form_id == fid,
                            FormLead.id == flid)\
                    .first()

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

                    result = {
                        'id': flid,
                        'created_on': form_lead.interaction_time,
                        'updated_on': form_lead.updated_datetime,
                        'external_api_lead_id': form_lead.external_api_lead_id,
                        'email_sent': form_lead.email_sent,
                        'contact_id': form_lead.contact_id
                    }

                    if form_lead.fields is not None:
                        for form_lead_field in form_lead.fields:
                            try:
                                processed_field_value = '' if form_lead_field.field_value is None else cipher.decrypt(form_lead_field.field_value)
                            except Exception:
                                processed_field_value = form_lead_field.field_value

                            result[form_lead_field.field_id] = processed_field_value

                    return jsonify(
                        result
                    )
                else:
                    return api.abort(400, message='Form lead not found.')
            else:
                return api.abort(400, message='Partnership account not found.')
        else:
            return api.abort(401, message='Unauthorized request.')


    @api.response(204, 'Form lead successfully updated.')
    @api.expect(serializers.form_lead_edit, validate=True)
    @requires_auth
    def put(self, paid, fid, flid):
        """
        Updates the form lead value of a lead of a form of a partnership account.

        <p>
        The Form Lead API GET endpoint should be used to retrieve information on a form lead
        associated with a partner account and a form.
        </p>
        <br />
        <p>
        You will require a partner authentication token and a partner account id to make a
        successful request.
        </p>


        """
        if rest_is_partnership and rest_partnership is not None:
            error_message = ""
            error_not_supported = ""
            contact_firstname = None
            contact_lastname = None
            contact_address_1 = None
            contact_address_2 = None
            contact_city = None
            contact_state = None
            contact_zip = None
            contact_birthday = None
            contact_email = None
            contact_country = None
            contact_api_token_id = int(rest_api_token_id)

            partnership_account = PartnershipAccount \
                .query \
                .filter(and_(PartnershipAccount.id == paid,
                             PartnershipAccount.partnership_id == rest_partnership.id)) \
                .first()

            if partnership_account is not None:
                received = request.get_json()
                result_fields = received

                form_lead = FormLead.query\
                    .filter(FormLead.partnership_account_id == paid,
                            FormLead.form_id == fid,
                            FormLead.id == flid)\
                    .first()

                if form_lead is not None:
                    field_definitions = ExternalFormFieldDefinition.api_get_field_definitions()
                    form_fields = ExternalFormField.get_form_fields(fid)
                    message_builder = MessageBuilder()
                    type_switcher = TypeSwitcher()
                    encrypt_key = app.config['CRYPTO_SECRET_KEY']
                    cipher = AESCipher(encrypt_key)

                    if 'firstname' in result_fields:
                        contact_firstname = strip_tags(result_fields['firstname'])

                    if 'lastname' in result_fields:
                        contact_lastname = strip_tags(result_fields['lastname'])

                    if 'address_1' in result_fields:
                        contact_address_1 = strip_tags(result_fields['address_1'])

                    if 'address_2' in result_fields:
                        contact_address_2 = strip_tags(result_fields['address_2'])

                    if 'city' in result_fields:
                        contact_city = strip_tags(result_fields['city'])

                    if 'state' in result_fields:
                        contact_state = strip_tags(result_fields['state'])

                    if 'zip' in result_fields:
                        contact_zip = strip_tags(result_fields['zip'])

                    if 'birthday' in result_fields:
                        log.error(str(result_fields))
                        contact_birthday = result_fields['birthday']

                    if 'email' in result_fields:
                        contact_email = strip_tags(result_fields['email'])

                    if 'country' in result_fields:
                        contact_country = strip_tags(result_fields['country'])

                    for result_field in result_fields:
                        field_id = result_field
                        field_value = result_fields[result_field]

                        if field_id in form_fields:
                            form_fields.remove(field_id)

                        if field_id in field_definitions:
                            form_definition = field_definitions[field_id]
                            valid = False
                            message = ""

                            if form_definition.type == 'varchar':
                                field_value = strip_tags(field_value)

                            valid, message = type_switcher.valid(form_definition.type,
                                                                field_id,
                                                                field_value,
                                                                form_definition.min_length,
                                                                form_definition.max_length)

                            if not valid:
                                error_message += message
                            else:
                                if field_value == "":
                                    result_fields[field_id] = ""
                                else:
                                    result_fields[field_id] = cipher.encrypt(str(field_value))
                        else:
                            error_not_supported = message_builder.build_message(error_not_supported, field_id)

                    if len(error_message) > 0 or len(error_not_supported) > 0:
                        final_error_message = ""

                        if len(error_message) > 0:
                            final_error_message += "Field validation error(s): " + error_message + ". "

                        if len(error_not_supported) > 0:
                            final_error_message += "Field(s) not supported: " + error_not_supported + ". "

                        return api.abort(code=400, message="Error updating lead. " + final_error_message)
                    else:

                        form_lead_updated, error_message = FormLead.api_update(fid, flid, result_fields, form_lead)

                        if form_lead_updated:
                            contact = Contact\
                                .query\
                                .filter(and_(Contact.id == form_lead.contact_id,
                                             Contact.partnership_account_id == paid))\
                                .first()

                            if contact is None:
                                log.error('Error updating contact. No contact linked to form lead ' + str(flid))
                            else:
                                contact_updated = Contact.api_update(paid, contact_api_token_id, contact.id,
                                                                         contact_firstname, contact_lastname, None,
                                                                         None, contact_birthday, None,
                                                                         None, contact_email, contact_address_1,
                                                                         contact_address_2, contact_city,
                                                                         contact_state, contact_country, contact_zip,
                                                                         None, None, None, None, None, None)

                                if not contact_updated:
                                    log.error('Error updating contact linked to form lead ' + str(flid))

                            return form_lead_updated, 204
                        else:
                            return api.abort(code=400, message="Error updating form. " + str(error_message))
                else:
                    return api.abort(400, message='Form lead not found.')
            else:
                return api.abort(400, message='Partnership account not found.')
        else:
            return api.abort(401, message='Unauthorized request.')