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.')