File: //proc/thread-self/root/home/arjun/projects/buyercall/buyercall/blueprints/contacts/endpoints.py
import logging as log
from flask_login.utils import login_required
from flask import (current_app as app)
from buyercall.blueprints.user.decorators import api_role_required
from buyercall.lib.util_rest import api_jsonify
from flask_login import current_user
from flask import Blueprint, request
from buyercall.blueprints.contacts.models import Contact, ContactChannelTie, ContactTags, Lead, Message, Status
from buyercall.blueprints.contacts.serializers import ContactTagSchema
from flask import Blueprint, jsonify
from datetime import datetime, date, timedelta
from dateutil import rrule
from sqlalchemy import extract, or_, and_, desc, func, text
from pytz import timezone
from .models import Contact, ContactNotes, Lead, Message, CreditReports, Campaigns, BdcStatuses, Status, \
MarketingSources, ContactVehicle
from buyercall.blueprints.agents.models import Agent
from buyercall.blueprints.form_leads.models import FormLead, FormLeadField
from sqlalchemy.orm import contains_eager
from buyercall.blueprints.filters import format_phone_number
from buyercall.lib.util_crypto import AESCipher
from flask import current_app as app
import re
from sqlalchemy.orm import contains_eager, load_only
from buyercall.blueprints.filters import format_phone_number, format_phone_number_bracket
from buyercall.lib.util_datetime import tza_to_leadtime
email_regex = re.compile(r'\S+@\S+\.\S+')
phone_regex = re.compile(r'^\+?[0-9]{10,12}$')
from buyercall.extensions import db
contact_api = Blueprint('contactsapi', __name__, url_prefix='/api/contacts')
logger = log.getLogger(__name__)
# INBOX APIS
# ----------
@login_required
def account_leads():
success = True
message = "Account leads fetched successfully!"
status_code = 200
data = []
partnership_account_id = current_user.partnership_account_id or 1
leads = Contact.query.filter(Contact.partnership_account_id == partnership_account_id).all()
for lead in leads:
_lead = {
"leadId": lead.sid,
"name": f'{lead.firstname} {lead.lastname}',
"primaryTags": ['Hot', 'Qualified Lead'],
"secondaryTags": ['Pre-approved'],
"manualStatus": lead.status
}
contact_sources = []
contact_channel_ties = ContactChannelTie.query.filter(ContactChannelTie.contact == lead.id).all()
for cct in contact_channel_ties:
contact_sources.append(cct.source_obj)
unique_contact_sources = list(set(contact_sources))
_sources = []
for source in unique_contact_sources:
_sources.append({
"id": source.sid,
"name": source.name
})
_lead['sources'] = _sources
data.append(_lead)
return api_jsonify(data, status_code, message, success)
@api_role_required('agent', 'admin', 'partner', 'sysadmin')
def get_contact_tags():
message = "Contact tags fetched successfully"
contact_tags = ContactTags.query.filter(ContactTags.is_active == True, ContactTags.tag_type == 'secondary').all()
return api_jsonify(data=ContactTagSchema(many=True).dump(contact_tags), message=message)
@api_role_required('agent', 'admin', 'partner', 'sysadmin')
def get_tags_by_contact(contact_sid):
message = "Tags of the contact fetched successfully!"
contact = Contact.get_by_sid(contact_sid)
if contact:
contact_tags = ContactTags.query.filter(ContactTags.is_active == True, ContactTags.contacts.any(id=contact.id))
return api_jsonify(data=ContactTagSchema(many=True).dump(contact_tags), message=message)
message = "Contact not found"
return api_jsonify({}, status_code=404, message=message, success=False)
@api_role_required('agent', 'admin', 'partner', 'sysadmin')
def create_contact_tag():
message = "Contact tag created successfully"
status_code = 201
success = True
received = request.get_json() or {}
name = received.get('name', '')
if name:
existing_tag = ContactTags.get_by_name(name)
if not existing_tag:
contact_tag = ContactTags.create(name=name.lower(), tag_type='secondary')
else:
message = f"The tag '{name}' already exists"
status_code = 401
success = False
else:
message = "Invalid parameters"
status_code = 401
success = False
return api_jsonify(message=message, status_code=status_code, success=success)
def days_between(d1, d2):
d1 = datetime.strptime(d1, "%m%d%Y")
d2 = datetime.strptime(d2, "%m%d%Y")
return abs((d2 - d1).days)
@api_role_required('agent', 'admin', 'partner', 'sysadmin')
def manage_tag_by_contact(contact_sid):
message = "Tags of the contact updated successfully!"
contact = Contact.get_by_sid(contact_sid)
if contact:
received = request.get_json()
tags = received.get('tags', [])
if tags:
contact_tags = ContactTags.get_by_sids(tags)
contact.contact_tags = contact_tags
contact.save()
return api_jsonify(message=message)
else:
message = "No tags found"
else:
message = "Contact not found"
return api_jsonify({}, status_code=404, message=message, success=False)
@login_required
def contacts_data():
"""Return server side data."""
phone_list = []
lead_list = []
form_list = []
message_list = []
filtered_contact_list = []
filtered_phone_list = []
filtered_message_list = []
filtered_form_list = []
partnership_account_id = current_user.partnership_account_id
partnership_account_group_viewing = current_user.is_viewing_partnership
print(partnership_account_id)
print(partnership_account_group_viewing)
# Check if being viewed by super partner
if partnership_account_group_viewing:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
search = request.args.get('search[value]', '')
order = int(request.args.get('order[0][column]', '-1'))
direction = request.args.get('order[0][dir]', 'asc')
offset = int(request.args.get('start', 0))
limit = int(request.args.get('length', 99))
date_from = str(request.args.get('df'))
date_to = str(request.args.get('dt'))
print(date_from, date_to, "#######")
assigned_agent = (request.args.get('aa'))
print(assigned_agent, "#######--assigned_agent")
form_check = str(request.args.get('stf'))
phone_check = str(request.args.get('stp'))
sms_check = str(request.args.get('sts'))
import_check = str(request.args.get('sis'))
api_check = str(request.args.get('sas'))
adf_import_check = str(request.args.get('sais'))
phone_source = str(request.args.get('ps'))
sms_source = str(request.args.get('ms'))
marketing_source = str(request.args.get('mks'))
form_source = str(request.args.get('fs'))
call_status = str(request.args.get('cs'))
call_bdc_status = str(request.args.get('cbs'))
print(form_check, phone_check, sms_check, import_check, api_check, "#######--assigned_agent")
print(adf_import_check, phone_source, sms_source, marketing_source, form_source)
print(call_status, call_bdc_status)
date_difference = days_between(date_from, date_to)
print(date_difference, "++++++++++++++")
# filter initiation section - check box filter
filter_by_phone_check = text('')
filter_by_sms_check = text('')
filter_by_form_check = text('')
all_check = False
# filter initiation section - external source type filters
filter_by_api_check = text('')
filter_by_adf_import_check = text('')
filter_by_import_check = text('')
# filter initiation section - drop down filters
filter_by_assigned_agent = text('')
filter_by_form = text('')
filter_by_call_status = text('')
filter_by_call_bdc_status = text('')
filter_by_marketing_source = text('')
filter_by_assigned_agent_id = text('')
assigned_agent_id = -1
# filter initiation section - source
filter_by_phone_source = text('')
filter_by_sms_source = text('')
filter_by_sms_inbound_source = text('')
filter_by_form_source = text('')
filter_by_phone_complete_source = text('')
filter_by_sms_complete_source = text('')
filter_by_form_complete_source = text('')
# set the date filters
converted_dateFrom = datetime.strptime(date_from, "%m%d%Y").replace(tzinfo=timezone('UTC'))
converted_dateTo = datetime.strptime(date_to, "%m%d%Y").replace(tzinfo=timezone('UTC'))
filter_by_date = and_(
func.date(Contact.updated_on) >= converted_dateFrom,
func.date(Contact.updated_on) <= converted_dateTo
)
lead_filter_by_date = and_(
func.date(Lead.created_on) >= converted_dateFrom,
func.date(Lead.created_on) <= converted_dateTo
)
message_filter_by_date = and_(
func.date(Message.created_on) >= converted_dateFrom,
func.date(Message.created_on) <= converted_dateTo
)
form_filter_by_date = and_(
func.date(FormLead.created_on) >= converted_dateFrom,
func.date(FormLead.created_on) <= converted_dateTo
)
# set the data permission restrictions
filter_by = (Contact.partnership_account_id == partnership_account_id)
# Lead phone number filter section
if phone_source and phone_source != 'null' and phone_source != 'None':
if phone_source.count('-') == 4:
filter_by_phone_source = text("widgets.guid = '" + phone_source + "'")
else:
filter_by_phone_source = text("phonenumbers.id = " + phone_source)
phone_list = Lead.query.outerjoin(Lead.widget).outerjoin(Lead.inbound).options(
contains_eager(Lead.widget).load_only('id', 'name'),
contains_eager(Lead.inbound).load_only('id', 'friendly_name'),
).join(Contact).filter(filter_by)\
.filter(filter_by_phone_source)\
.with_entities('leads.contact_id')\
.distinct().all()
if phone_list is not None:
filter_by_phone_complete_source = and_(Contact.id.in_(phone_list))
# Message filter section
if sms_source and sms_source != 'null' and sms_source != 'None':
filter_by_sms_source = text("phonenumbers.id = {}".format(sms_source))
filter_by_sms_inbound_source = (Message.inbound_id == sms_source)
message_list = Message.query.outerjoin(
Message.inbound
).options(
contains_eager(Message.inbound).load_only('id'),
).join(
Contact
).filter(filter_by).filter(
filter_by_sms_source
).with_entities('messages.contact_id').distinct().all()
if message_list is not None:
filter_by_sms_complete_source = and_(Contact.id.in_(message_list))
# Form lead filter section
if form_source and form_source != 'null' and form_source != 'None':
filter_by_form = text("form_leads.id = {}".format(form_source))
filter_by_form_source = text("external_forms.id = {}".format(form_source))
form_list = FormLead.query.outerjoin(
FormLead.form
).options(
contains_eager(FormLead.form).load_only('id'),
).join(Contact)\
.filter(filter_by)\
.filter(filter_by_form_source)\
.with_entities('form_leads.contact_id')\
.distinct().all()
if form_list is not None:
filter_by_form_complete_source = and_(Contact.id.in_(form_list))
# Assigned agent filter section
if assigned_agent != 'null' and assigned_agent:
formatted_assigned_agent = assigned_agent.replace("'", "''")
filter_by_assigned_agent = and_(text("contacts.agent_assigned = '" + formatted_assigned_agent + "'"))
assigned_agent_id = Agent.query\
.filter(and_(Agent.partnership_account_id == partnership_account_id, Agent.full_name.like(assigned_agent)))\
.with_entities('id')\
.first()
if assigned_agent_id is not None:
filter_by_assigned_agent_id = and_(text("leads.agent_assigned_id = " + str(assigned_agent_id[0])))
# Form check filter section
if form_check == '1' or form_check == 1:
filter_by_form_check = and_(Contact.form_count > 0)
# Message check filter section
if sms_check == '1' or sms_check == 1:
filter_by_sms_check = and_(Contact.sms_count > 0)
# Phone check filter section
if phone_check == '1' or phone_check == 1:
filter_by_phone_check = and_(Contact.phone_count > 0)
if (
(form_check == '1' or form_check == 1) and (sms_check == '1' or sms_check == 1)
and (phone_check == '1' or phone_check == 1)
) or (
(form_check == '0' or form_check == 0) and (sms_check == '0' or sms_check == 0)
and (phone_check == '0' or phone_check == 0)
):
all_check = True
# Call status filter section
if call_status != 'null' and call_status:
filter_by_call_status = and_(text("contacts.status = '{}'".format(call_status)))
# Call status filter section
if current_user.is_bdc_user and call_bdc_status != 'null' and call_bdc_status:
filter_by_call_bdc_status = and_(text("contacts.bdc_status = '{}'".format(call_bdc_status)))
# Marketing source filter section
if marketing_source != 'null' and marketing_source:
if marketing_source == 'no_source':
formatted_marketing_source = marketing_source.replace("'", "''")
filter_by_marketing_source = and_(
or_(text("contacts.marketing_source = '" + formatted_marketing_source + "'"),
text("contacts.marketing_source = '""'")))
else:
filter_by_marketing_source = and_((text("contacts.marketing_source = '" + marketing_source + "'")))
# Source type - API
if api_check == '1' or api_check == 1:
filter_by_api_check = and_(Contact.external_source_type == 'api')
# Source type - ADF Import
if adf_import_check == '1' or adf_import_check == 1:
filter_by_adf_import_check = and_(Contact.external_source_type == 'adf_import')
# Source type - Import
if import_check == '1' or import_check == 1:
filter_by_import_check = and_(Contact.external_source_type == 'import')
# define data columns for the searching data view window
columns_search = [
Contact.id,
Contact.firstname,
Contact.lastname,
Contact.phonenumber_1,
Contact.email,
Status.status,
Contact.agent_assigned
]
# define data columns for the shifting data view window
columns_window = [
Contact.id,
Contact.firstname,
Contact.phonenumber_1,
Contact.email,
Contact.source,
Contact.created_on,
Contact.updated_on,
Contact.status,
Contact.agent_assigned,
Contact.credit_score,
#Contact.phone_source,
Contact.lastname,
#Contact.caller_id
Contact.sid
]
# define data columns for the counts
columns_total = [
Contact.id
]
# define/execute main query
total = Contact.query\
.filter(filter_by) \
.filter(filter_by_date) \
.filter(filter_by_sms_check) \
.filter(filter_by_phone_check)\
.filter(filter_by_form_check)\
.filter(filter_by_call_status) \
.filter(filter_by_call_bdc_status) \
.filter(filter_by_marketing_source) \
.filter(filter_by_assigned_agent) \
.filter(filter_by_phone_complete_source)\
.filter(filter_by_sms_complete_source)\
.filter(filter_by_form_complete_source)\
.filter(filter_by_api_check) \
.filter(filter_by_adf_import_check) \
.filter(filter_by_import_check)
filtered = total
if search:
total_list = total.with_entities(*columns_search).all()
searched_result_list = [x for x in total_list
if x.firstname.lower() + ' ' + x.lastname.lower() == search.lower()
or x.email.lower() == search.lower()
or x.firstname.lower() == search.lower()
or x.lastname.lower() == search.lower()
or x.phonenumber_1 == search
or x.status.lower() == search.lower()
or x.agent_assigned == search]
searched_result_ids = [x.id for x in searched_result_list]
filtered = Contact.query.join(Status, Contact.status == Status.status)\
.filter(Contact.id.in_(searched_result_ids))
sorted_ = filtered.with_entities(*columns_window)
if order in range(len(columns_window)):
order_pred = columns_window[order]
if direction == 'desc':
order_pred = desc(order_pred)
sorted_ = sorted_.order_by(order_pred)
sorted_ = sorted_.offset(offset).limit(limit)
data = [
{i: row[i] for i in range(len(row))
} for row in sorted_.all()
]
print(data,"+++++data")
try:
for lp_data in data:
if lp_data[9] is not None:
encrypt_key = app.config['CRYPTO_SECRET_KEY']
cipher = AESCipher(encrypt_key)
lp_data[9] = cipher.decrypt(lp_data[9])
else:
lp_data[9] = 'Unknown'
except Exception as e:
print(e)
print(data,"+++++data")
user = current_user
value = None
if user.agent:
if user.agent.timezone:
if user.agent.timezone == 'US/Eastern':
value = 'EST'
elif user.agent.timezone == 'US/Central':
value = 'CST'
elif user.agent.timezone == 'US/Mountain':
value = 'MST'
elif user.agent.timezone == 'US/Pacific':
value = 'PST'
else:
value = None
for user in data:
if user.get(2):
user[2] = format_phone_number_bracket(user[2])
if user.get(4):
user[4] = user[4].replace('-', ' ')
if user.get(5):
user[5] = f'{user[5].strftime("%b %d, %I:%M %p ")} {value}'
if user.get(6):
user[6] = f'{user[6].strftime("%b %d, %I:%M %p ")} {value}'
print(data,"+++++data")
# set specific columns for the total count
filtered_total = filtered.with_entities(*columns_total)
for c in filtered_total.all():
filtered_contact_list.append(c[0])
# total lead count
total_leads = len(filtered_contact_list)
# total call count
if phone_check == '1' or phone_check == 1 or all_check:
phone_query = Lead.query.outerjoin(
Lead.widget
).outerjoin(
Lead.inbound
).options(
contains_eager(Lead.widget).load_only('id', 'name'),
contains_eager(Lead.inbound).load_only('id', 'friendly_name')
).filter(Lead.partnership_account_id == partnership_account_id)\
.filter(filter_by_phone_source).with_entities(Lead.phonenumber)\
.filter(lead_filter_by_date)\
.filter(filter_by_assigned_agent_id)\
total_phone = phone_query.count()
total_unique_phone = phone_query.distinct().count()
for phone in phone_query.with_entities(Lead.id).all():
filtered_phone_list.append(phone[0])
else:
total_phone = 0
total_unique_phone = 0
# total message count
if sms_check == '1' or sms_check == 1 or all_check:
messages_query = Message.query\
.filter(Message.partnership_account_id == current_user.partnership_account_id)\
.filter(filter_by_sms_inbound_source)\
.with_entities(Message.from_)\
.filter(message_filter_by_date)
if messages_query is not None:
total_messages = messages_query.count()
total_unique_messages = messages_query.distinct().count()
for message in messages_query.with_entities(Message.id).all():
filtered_message_list.append(message[0])
else:
total_messages = 0
total_unique_messages = 0
else:
total_messages = 0
total_unique_messages = 0
# total form lead count
if form_check == '1' or form_check == 1 or all_check:
form_query = FormLead.query\
.filter(FormLead.partnership_account_id == partnership_account_id)\
.filter(form_filter_by_date)\
.filter(filter_by_form) \
.filter(FormLead.contact_id > 0)\
.with_entities(FormLead.form_id)
total_formleads = form_query.count()
# total_unique_formleads = form_query.distinct().count()
for form in form_query.with_entities(FormLead.id).all():
filtered_form_list.append(form[0])
total_unique_formleads_query = FormLeadField.query\
.filter(or_(FormLeadField.field_id == 'phonefield', FormLeadField.field_id == 'phonenumber'))\
.filter(FormLeadField.lead_id.in_(filtered_form_list)) \
.with_entities(FormLeadField.field_value).distinct().all()
total_unique_formleads_list = []
for i in total_unique_formleads_query:
if i is not None:
formatted_phonenumber = format_phone_number(i[0])
if formatted_phonenumber not in total_unique_formleads_list:
total_unique_formleads_list.append(formatted_phonenumber)
total_unique_formleads = len(total_unique_formleads_list)
else:
total_formleads = 0
total_unique_formleads = 0
graph_labels = []
if date_difference <= 31:
for i in range((converted_dateTo - converted_dateFrom).days + 1):
graph_labels.append((converted_dateFrom + timedelta(days=i)).strftime('%d/%m'))
elif 32 <= date_difference <= 366:
daysLater = converted_dateFrom + timedelta(days=date_difference)
for dt in rrule.rrule(rrule.MONTHLY, dtstart=converted_dateFrom, until=daysLater):
graph_labels.append(dt.strftime('%m/%Y'))
elif date_difference > 366:
daysLater = converted_dateFrom + timedelta(days=date_difference)
for dt in rrule.rrule(rrule.YEARLY, dtstart=converted_dateFrom, until=daysLater):
graph_labels.append(dt.strftime('%Y'))
return jsonify(
recordsFiltered=total_leads,
recordsTotal=total_leads,
data=data,
totalLeads=total_leads,
totalPhone=total_phone,
totalUniquePhone=total_unique_phone,
totalMessages=total_messages,
totalUniqueMessages=total_unique_messages,
totalFormLeads=total_formleads,
totalUniqueFormLeads=total_unique_formleads,
offset=offset
)
@login_required
def contacts_add():
print("------------")
partnership_account_id = current_user.partnership_account_id
viewing_partnership_account = current_user.is_viewing_partnership
missing_message = []
invalid_message = []
error_message = []
success = False
# Check if being viewed by super partner
if viewing_partnership_account:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
data = request.get_json()
if data:
request_firstname = data.get('firstname')
print(request_firstname)
request_lastname = data.get('lastname')
request_status = data.get('status')
request_marketing_source = data.get('marketing_source')
request_agent_assigned_id = data.get('agent_assigned_id')
request_agent_assigned_text = data.get('agent_assigned_text')
request_phonenumber = data.get('phonenumber')
request_email = data.get('email')
request_contact_note = data.get('note')
request_address_1 = data.get('address1')
request_address_2 = data.get('address2')
request_city = data.get('city')
request_state = data.get('state')
request_country = data.get('country')
request_zip = data.get('zip')
request_birthday = data.get('birthday')
request_do_not_call = data.get('donotcall')
request_unsubscribed = data.get('unsubscribed')
agent_assigned = None
agent_assigned_id = None
# if not request_firstname:
# missing_message.append('firstname')
# if not request_lastname:
# missing_message.append('lastname')
# if request_email:
# request_email = request_email.lower()
# if not email_regex.match(request_email):
# invalid_message.append('Email is invalid.')
if not request_phonenumber or request_phonenumber == "+1":
missing_message.append('phonenumber')
else:
try:
phonenumber_exists = Contact\
.query\
.filter(Contact.partnership_account_id == partnership_account_id)\
.filter(or_(
Contact.phonenumber_1 == format_phone_number(request_phonenumber),
Contact.phonenumber_1 == request_phonenumber))\
.first()
except Exception as e:
print(e, "------")
if phonenumber_exists:
error_message.append('Phonenumber already exists.')
elif not phone_regex.match(request_phonenumber):
invalid_message.append('Phonenumber is invalid.')
if request_status != "Select status..." and request_status != "":
request_status = request_status
else:
request_status = 'no status'
if request_marketing_source == "Select marketing source..." or request_marketing_source == "":
request_marketing_source = 'no source'
if request_agent_assigned_text != "Select agent..." and request_agent_assigned_text != "":
agent_assigned = request_agent_assigned_text
agent_assigned_id = request_agent_assigned_id
if request_birthday and request_birthday != "":
try:
datetime.strptime(request_birthday, '%m/%d/%Y')
except ValueError:
invalid_message.append('Birthday is invalid, it should be in mm/dd/yyyy format.')
if not error_message and not missing_message and not invalid_message:
new_contact = Contact()
new_contact.email = request_email
new_contact.status = request_status
new_contact.marketing_source = request_marketing_source
new_contact.firstname = request_firstname
new_contact.lastname = request_lastname
new_contact.phonenumber_1 = format_phone_number(request_phonenumber)
new_contact.agent_assigned = agent_assigned
new_contact.agent_id = agent_assigned_id
new_contact.partnership_account_id = partnership_account_id
new_contact.address_1 = request_address_1
new_contact.address_2 = request_address_2
new_contact.city = request_city
new_contact.state = request_state
new_contact.country = request_country
new_contact.zip = request_zip
new_contact.birthday = request_birthday
new_contact.is_do_not_call = request_do_not_call
new_contact.is_unsubscribe = request_unsubscribed
new_contact.external_source_type = 'import'
db.session.add(new_contact)
db.session.commit()
from buyercall.blueprints.mobile.utils import send_agent_push_notification
send_agent_push_notification(new_contact)
if request_contact_note:
ContactNotes.create({
'text': request_contact_note,
'contact_id': new_contact.id,
'created_on': datetime.now(),
'updated_on': datetime.now(),
'user_id': int(current_user.id),
'is_enabled': True,
'partnership_account_id': int(partnership_account_id)
})
success = True
else:
log.error('No request parameters received to add lead.')
return jsonify({
'error_message': error_message,
'missing_message': missing_message,
'invalid_message': invalid_message,
'success': success
})
def contacts_add_bulk():
print("------------")
partnership_account_id = current_user.partnership_account_id
viewing_partnership_account = current_user.is_viewing_partnership
missing_message = []
invalid_message = []
error_message = []
success = False
# Check if being viewed by super partner
if viewing_partnership_account:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
data = request.get_json()
if data:
contacts_data = data.get('contacts')
if contacts_data:
for contact_data in contacts_data:
request_firstname = contact_data.get('firstname')
request_lastname = contact_data.get('lastname')
request_status = contact_data.get('status')
request_marketing_source = contact_data.get('marketing_source')
request_agent_assigned_id = contact_data.get('agent_assigned_id')
request_agent_assigned_text = contact_data.get('agent_assigned_text')
request_phonenumber = contact_data.get('phonenumber')
request_email = contact_data.get('email')
request_contact_note = contact_data.get('note')
request_address_1 = contact_data.get('address1')
request_address_2 = contact_data.get('address2')
request_city = contact_data.get('city')
request_state = contact_data.get('state')
request_country = contact_data.get('country')
request_zip = contact_data.get('zip')
request_birthday = contact_data.get('birthday')
request_do_not_call = contact_data.get('donotcall')
request_unsubscribed = contact_data.get('unsubscribed')
agent_assigned = None
agent_assigned_id = None
# Validation checks...
# (similar to the ones in the original function)
if not error_message and not missing_message and not invalid_message:
new_contact = Contact()
new_contact.email = request_email
new_contact.status = request_status
new_contact.marketing_source = request_marketing_source
new_contact.firstname = request_firstname
new_contact.lastname = request_lastname
new_contact.phonenumber_1 = format_phone_number(request_phonenumber)
new_contact.agent_assigned = agent_assigned
new_contact.agent_id = agent_assigned_id
new_contact.partnership_account_id = partnership_account_id
new_contact.address_1 = request_address_1
new_contact.address_2 = request_address_2
new_contact.city = request_city
new_contact.state = request_state
new_contact.country = request_country
new_contact.zip = request_zip
new_contact.birthday = request_birthday
new_contact.is_do_not_call = request_do_not_call
new_contact.is_unsubscribe = request_unsubscribed
new_contact.external_source_type = 'import'
db.session.add(new_contact)
db.session.commit()
success = True
else:
error_message.append('No contact data provided.')
else:
error_message.append('No data received.')
return jsonify({
'error_message': error_message,
'missing_message': missing_message,
'invalid_message': invalid_message,
'success': success
})
@login_required
def contacts_advanced_filters():
"""Return server side filter data."""
phone_source_result = {}
message_source_result = {}
form_source_result = {}
status_result = {}
bdc_status_result = {}
marketing_result = {}
assigned_agent_result = {}
partnership_account_id = current_user.partnership_account_id
partnership_account_group_viewing = current_user.is_viewing_partnership
# Check if being viewed by super partner
if partnership_account_group_viewing:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
filter_by_lead = and_(
Lead.partnership_account_id == partnership_account_id,
Lead.contact_id == Contact.id,
Contact.partnership_account_id == partnership_account_id
)
filter_by_sms = and_(
Message.partnership_account_id == partnership_account_id,
Message.contact_id == Contact.id,
Contact.partnership_account_id == partnership_account_id
)
filter_by_form = and_(
FormLead.partnership_account_id == partnership_account_id,
FormLead.contact_id == Contact.id,
Contact.partnership_account_id == partnership_account_id
)
filter_by_partnership_account = and_(
Contact.partnership_account_id == partnership_account_id,
Contact.agent_assigned != ""
)
# populate agent result
agent_data = Contact.query.with_entities(text('contacts.agent_assigned')).filter(filter_by_partnership_account).distinct()
for i in agent_data:
if i:
if i[0]:
id = i[0]
name = i[0]
assigned_agent_result[id] = name
# populate phone result
inbound_data = Lead.query.join(Lead.contact)\
.outerjoin(Lead.inbound).options(
contains_eager(Lead.inbound)
).with_entities(
text('phonenumbers.id'),
text('phonenumbers.friendly_name'),
text('phonenumbers.phonenumber')
).filter(filter_by_lead).distinct()
outbound_data = Lead.query.join(Lead.contact)\
.outerjoin(Lead.widget).options(
contains_eager(Lead.widget)
).with_entities(text('widgets.guid'), text('widgets.name')).filter(filter_by_lead).distinct()
for i in inbound_data:
if i:
if i[0] and i[2]:
id = str(i[0])
name = str(i[2])
friendly_name = str(i[1])
phone_source_result[id] = '{} ({})'.format(name, friendly_name)
for i in outbound_data:
if i:
if i[0] and i[1]:
id = str(i[0])
name = str(i[1])
phone_source_result[id] = name
# populate message result
message_data = Message.query.join(Message.contact)\
.outerjoin(Message.inbound).options(
contains_eager(Message.inbound)
).with_entities(
text('phonenumbers.id'),
text('phonenumbers.friendly_name'),
text('phonenumbers.phonenumber')).filter(filter_by_sms).distinct()
for i in message_data:
if i:
if i[0] and i[2]:
id = str(i[0])
name = str(i[2])
friendly_name = str(i[1])
message_source_result[id] = '{} ({})'.format(name, friendly_name)
# populate form lead result
form_data = FormLead.query.join(FormLead.contact)\
.outerjoin(FormLead.form).options(
contains_eager(FormLead.form)
).with_entities(text('external_forms.id'), text('external_forms.display_name')).filter(filter_by_form).distinct()
for i in form_data:
if i:
if i[0] and i[1]:
id = str(i[0])
name = str(i[1])
form_source_result[id] = name
# populate bdc status result
bdc_status_list = BdcStatuses.get_assigned_status_list(partnership_account_id)
for item in bdc_status_list:
id = item.status
bdc_status_result[id] = item.display_name
# populate status result
status_list = Status.get_assigned_status_list(partnership_account_id)
for item in status_list:
id = item.status
status_result[id] = item.display_name
# populate marketing result
marketing_list = MarketingSources.get_assigned_source_list(partnership_account_id)
for item in marketing_list:
id = item.source
marketing_result[id] = item.display_name
agents = [(g.id, g.full_name) for g in Agent
.query
.filter((Agent.partnership_account_id == partnership_account_id),
Agent.is_deactivated.is_(False))
.order_by('firstname')]
# Populate marketing result
marketing_result_list = {}
marketing_list = MarketingSources.get_assigned_source_list(partnership_account_id)
for item in marketing_list:
marketing_id = item.source
marketing_result_list[marketing_id] = item.display_name
# Populate status result
status_result = {}
status_list = Status.get_assigned_status_list(partnership_account_id)
for item in status_list:
status_id = item.status
status_result[status_id] = item.display_name
campaign_list, default_campaign = Campaigns.get_assigned_campaign_list_as_dict(partnership_account_id)
filters_result = {
'phone_source_data': phone_source_result,
'message_source_data': message_source_result,
'form_source_data': form_source_result,
'assigned_agent_data': assigned_agent_result,
'bdc_status_data': bdc_status_result,
'status_data': status_result,
'marketing_data': marketing_result,
}
leads_result = {
'status_choice':status_result,
'agents_list': agents,
'marketing_result_list': marketing_result_list,
'campaign_list':campaign_list,
'default_campaign':default_campaign
}
response = {'leads': leads_result, 'filters': filters_result}
return jsonify(response)
@login_required
def contacts_edit(contact_sid):
partnership_account_id = current_user.partnership_account_id
viewing_partnership_account = current_user.is_viewing_partnership
missing_message = []
invalid_message = []
error_message = []
success = False
# Check if being viewed by super partner
if viewing_partnership_account:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
# Import the partnership account model
from ..partnership.models import PartnershipAccount
partnership_account = PartnershipAccount\
.query\
.filter(PartnershipAccount.id == partnership_account_id)\
.first()
data = request.get_json()
if data:
# Retrieve the existing contact
existing_contact = Contact.get_by_sid(contact_sid)
if existing_contact:
contact_vehicle = ContactVehicle.query.filter(ContactVehicle.contact_id == existing_contact.id).first()
request_firstname = data.get('firstname')
request_lastname = data.get('lastname')
request_status = data.get('status')
request_marketing_source = data.get('marketing_source')
request_agent_assigned_id = data.get('agent_assigned_id')
request_agent_assigned_text = data.get('agent_assigned_text')
request_phonenumber = data.get('phonenumber')
request_email = data.get('email')
request_contact_note = data.get('note')
request_address_1 = data.get('address1')
request_address_2 = data.get('address2')
request_city = data.get('city')
request_state = data.get('state')
request_country = data.get('country')
request_zip = data.get('zip')
request_birthday = data.get('birthday')
request_do_not_call = data.get('donotcall')
request_unsubscribed = data.get('unsubscribed')
campaign_id = data.get('campaignId')
social_security = data.get('social_security')
# Update the existing contact with new data
if request_email:
existing_contact.email = request_email
if request_status:
existing_contact.status = request_status
if request_marketing_source:
existing_contact.marketing_source = request_marketing_source
if request_firstname:
existing_contact.firstname = request_firstname
if request_lastname:
existing_contact.lastname = request_lastname
if request_agent_assigned_id:
existing_contact.agent_assigned = request_agent_assigned_id
if request_agent_assigned_id:
existing_contact.agent_id = request_agent_assigned_id
if request_address_1:
existing_contact.address_1 = request_address_1
if request_address_2:
existing_contact.address_2 = request_address_2
if request_city:
existing_contact.city = request_city
if request_state:
existing_contact.state = request_state
if request_country:
existing_contact.country = request_country
if request_zip:
existing_contact.zip = request_zip
if request_birthday:
existing_contact.birthday = request_birthday
if request_do_not_call is not None:
existing_contact.is_do_not_call = request_do_not_call
if request_unsubscribed is not None:
existing_contact.is_unsubscribe = request_unsubscribed
if campaign_id:
try:
existing_contact.campaign_id = int(campaign_id)
except ValueError:
invalid_message.append('Invalid campaign ID.')
if social_security:
existing_contact.social_security = social_security
if partnership_account.business_type == 'automotive':
update_contact_vehicle(existing_contact, data, contact_vehicle)
# try:
db.session.commit()
success = True
# except Exception as e:
# db.session.rollback()
# error_message.append(str(e))
else:
error_message.append('Contact not found.')
else:
error_message.append('No request parameters received to edit contact.')
return jsonify({
'error_message': error_message,
'missing_message': missing_message,
'invalid_message': invalid_message,
'success': success
})
@login_required
def contacts_details(contact_sid):
print("------------")
partnership_account_id = current_user.partnership_account_id
viewing_partnership_account = current_user.is_viewing_partnership
error_message = []
success = False
from ..partnership.models import PartnershipAccount
partnership_account = PartnershipAccount\
.query\
.filter(PartnershipAccount.id == partnership_account_id)\
.first()
# Check if being viewed by super partner
if viewing_partnership_account:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
# Retrieve the contact based on contact_sid
existing_contact = Contact.get_by_sid(contact_sid)
import json
try:
contact_vehicle = ContactVehicle.query.filter(ContactVehicle.contact_id == existing_contact.id).first()
contact_vehicle_data = {
'created_on': contact_vehicle.created_on.strftime('%Y-%m-%d %H:%M:%S'), # Convert to string
'updated_on': contact_vehicle.updated_on.strftime('%Y-%m-%d %H:%M:%S'), # Convert to string
'id': contact_vehicle.id,
'contact_id': contact_vehicle.contact_id,
'current_vin': contact_vehicle.current_vin,
'current_make': contact_vehicle.current_make,
'current_model': contact_vehicle.current_model,
'current_year': contact_vehicle.current_year,
'current_mileage': contact_vehicle.current_mileage,
'current_condition': contact_vehicle.current_condition,
'current_value': contact_vehicle.current_value, # Convert Decimal to float
'interest_vin': contact_vehicle.interest_vin,
'interest_make': contact_vehicle.interest_make,
'interest_model': contact_vehicle.interest_model,
'interest_trim': contact_vehicle.interest_trim,
'interest_stock': contact_vehicle.interest_stock,
'interest_year': contact_vehicle.interest_year,
'interest_price': contact_vehicle.interest_price, # Convert Decimal to float
'interest_status': contact_vehicle.interest_status,
'interest_mileage': contact_vehicle.interest_mileage,
'interest_condition': contact_vehicle.interest_condition,
'interest_listing_url': contact_vehicle.interest_listing_url
}
contact_vehicle = (contact_vehicle_data)
except Exception as e:
contact_vehicle = {}
print(e,"contact_vehicle=======")
if existing_contact:
# If contact is found, return contact details
contact_data = {
'id': existing_contact.id,
'firstname': existing_contact.firstname,
'lastname': existing_contact.lastname,
'email': existing_contact.email,
'phonenumber': existing_contact.phonenumber_1,
'status': existing_contact.status,
'marketing_source': existing_contact.marketing_source,
'agent_assigned_id': existing_contact.agent_id,
'agent_assigned_text': existing_contact.agent_assigned,
'address1': existing_contact.address_1,
'address2': existing_contact.address_2,
'city': existing_contact.city,
'state': existing_contact.state,
'country': existing_contact.country,
'zip': existing_contact.zip,
'birthday': existing_contact.birthday,
'do_not_call': existing_contact.is_do_not_call,
'unsubscribed': existing_contact.is_unsubscribe,
'contact_notes': get_contact_notes(existing_contact.id), # Include ContactNotes
# Add other fields as needed
'business_type': partnership_account.business_type,
'credit_score': existing_contact.credit_score
}
try:
# Return the contact notes of this contact
all_contact_notes = ContactNotes.query.join(Contact).filter(
ContactNotes.contact_id == existing_contact.id,
ContactNotes.partnership_account_id == partnership_account_id,
ContactNotes.is_enabled == 't'
).order_by(desc(ContactNotes.created_on)).all()
except Exception as e:
all_contact_notes = []
print(e)
try:
# Return all calls for this contact
previous_calls = Lead.query.filter(
Lead.partnership_account_id == partnership_account_id,
Lead.contact_id == existing_contact.id
).options(
load_only("firstname", "lastname", "starttime", "call_type", "status")
).order_by(text('starttime desc')).limit(10).all()
except Exception as e:
previous_calls = []
print(e,"previous_calls")
try:
# Return all messages for this contact
previous_messages_raw = Message.query.filter(
Message.partnership_account_id == partnership_account_id,
Message.contact_id == existing_contact.id
).order_by(text('messages.created_on desc')).limit(100).all()
previous_messages = []
for msg in previous_messages_raw:
if msg.media_url and msg.media_url[:1] == '[':
bracket_msg_list = str(msg.media_url).replace("[", "").replace("]", "").replace(" ", "")
bracket_msg_list_split = bracket_msg_list.split(",")
msg.media_url = bracket_msg_list_split
previous_messages.append(msg)
elif msg.media_url and msg.media_url[:1] == '{':
replace_msg_str = str(msg.media_url).replace("{", "").replace("}", "").replace(" ", "")
media_str_links = replace_msg_str.split(",")
msg.media_url = media_str_links
previous_messages.append(msg)
elif msg.media_url and msg.media_url[:1] not in ['[', '{']:
single_link = str(msg.media_url).split(",")
single_link_list = []
for s in single_link:
single_link_list.append(s)
msg.media_url = single_link_list
previous_messages.append(msg)
else:
previous_messages.append(msg)
except Exception as e:
previous_messages_raw = []
print(e,"previous_messages")
try:
# Return all form lead for this contact
previous_forms = FormLead.query.filter(
FormLead.partnership_account_id == partnership_account_id,
FormLead.contact_id == existing_contact.id
).order_by(text('form_leads.created_on desc')).limit(10).all()
except Exception as e:
previous_forms = []
print(e,"previous_forms")
# Return the credit reports for this contact
try:
credit_reports_data = CreditReports.contact_credit_score_object(existing_contact.id, partnership_account_id)
credit_reports = [report.to_dict() for report in credit_reports_data]
except Exception as e:
credit_reports = []
print(e,"credit_reports")
success = True
else:
error_message.append('Contact not found.')
return jsonify({
'error_message': error_message,
'success': success,
'contact': contact_data if success else None,
'contact_notes':all_contact_notes if success else None,
'previous_calls':previous_calls if success else None,
'previous_forms': previous_forms if success else None,
'previous_messages_raw': previous_messages_raw if success else None,
'credit_reports' : credit_reports if success else None,
'contact_vehicle' : contact_vehicle if success else None,
})
def get_contact_notes(contact_id):
contact_note = ContactNotes.query.filter_by(contact_id=contact_id).first()
return contact_note.text if contact_note else None
@login_required
def set_campaigns():
result = False
partnership_account_id = current_user.partnership_account_id
partnership_account_group_viewing = current_user.is_viewing_partnership
# Check if being viewed by super partner
if partnership_account_group_viewing:
partnership_account_id = current_user.get_user_viewing_partnership_account_id
data = request.get_json()
campaign_id = data.get('id', '')
campaign_text = data.get('text', '')
print(campaign_id,"campaign_id------")
if (int(campaign_id) < 0):
print(campaign_id,"campaign_id------")
result = Campaigns.add_campaign(campaign_text, partnership_account_id)
else:
result = Campaigns.update_campaign(campaign_id, campaign_text, partnership_account_id)
return jsonify({
"result": result
})
def update_contact_vehicle(contact, data, contact_vehicle=None):
for key, value in data.items():
if value == "":
data[key] = None
if contact_vehicle:
# Update existing contact_vehicle if data is provided
if data:
edit_current_year = data.get('current_year')
if edit_current_year == 0:
edit_current_year = None
edit_interest_year = data.get('interest_year')
if edit_interest_year == 0:
edit_interest_year = None
ContactVehicle.update(contact_id=contact.id,
current_vin=data.get('current_vin'),
current_make=data.get('current_make'),
current_model=data.get('current_model'),
current_year=edit_current_year,
current_mileage=data.get('current_mileage'),
current_condition=data.get('current_condition'),
current_value=data.get('current_value'),
interest_vin=data.get('interest_vin'),
interest_make=data.get('interest_make'),
interest_model=data.get('interest_model'),
interest_year=edit_interest_year,
interest_trim=data.get('interest_trim'),
interest_stock=data.get('interest_stock'),
interest_price=data.get('interest_price'),
interest_status=data.get('interest_status'),
interest_mileage=data.get('interest_mileage'),
interest_condition=data.get('interest_condition'),
interest_listing_url=data.get('interest_listing_url')
)
else:
# Create new ContactVehicle if contact_vehicle doesn't exist
new_contact_vehicle = ContactVehicle(
contact_id=contact.id,
current_vin=data.get('current_vin'),
current_make=data.get('current_make'),
current_model=data.get('current_model'),
current_year=data.get('current_year'),
current_mileage=data.get('current_mileage'),
current_condition=data.get('current_condition'),
current_value=data.get('current_value'),
interest_vin=data.get('interest_vin'),
interest_make=data.get('interest_make'),
interest_model=data.get('interest_model'),
interest_year=data.get('interest_year'),
interest_trim=data.get('interest_trim'),
interest_stock=data.get('interest_stock'),
interest_price=data.get('interest_price'),
interest_status=data.get('interest_status'),
interest_mileage=data.get('interest_mileage'),
interest_condition=data.get('interest_condition'),
interest_listing_url=data.get('interest_listing_url')
)
db.session.add(new_contact_vehicle)
db.session.commit()
@login_required
def contacts_credit_details(contact_sid):
existing_contact = Contact.get_by_sid(contact_sid)
partnership_account_id = current_user.partnership_account_id
try:
credit_reports_data = CreditReports.contact_credit_score_object(existing_contact.id, partnership_account_id)
credit_reports = [report.to_dict() for report in credit_reports_data]
success = True
except Exception as e:
credit_reports = []
print(e,"credit_reports")
success = False
return jsonify({
'success': success,
'credit_reports' : credit_reports if success else None
})