File: //proc/1233/root/home/arjun/projects/buyercall/buyercall/blueprints/sources/endpoints.py
from datetime import datetime
from buyercall.blueprints.partnership.models import Partnership, PartnershipAccount
from buyercall.blueprints.sources.models import Source
from buyercall.blueprints.channels.models import ChannelType, Channel
from buyercall.blueprints.user.decorators import api_role_required
from buyercall.blueprints.user.models import User
from buyercall.lib.util_rest import api_jsonify
from sqlalchemy import and_, cast
from flask_login import current_user
from flask import Blueprint, request
import logging as log
from buyercall.blueprints.notification.utilities import send_notifications
from buyercall.extensions import db
from buyercall.blueprints.contacts.views import contact_exists
from buyercall.blueprints.contacts.models import Contact, ContactChannelTie
from buyercall.blueprints.email.models import Email
from buyercall.blueprints.chat.models import Chat
from buyercall.blueprints.sms.models import Message
from buyercall.blueprints.leads.models import Lead
from buyercall.lib.util_requests import send_request
from buyercall.lib.util_twilio import bw_client
from flask.views import MethodView
from buyercall.blueprints.sources.serializers import SourceInSchema, SourceOutSchema
from buyercall.lib.util_rest import BlueprintMixin
sources_api = Blueprint('sourcesapi', __name__, url_prefix='/api/sources')
logger = log.getLogger(__name__)
@api_role_required('admin', 'partner')
def create_source():
received = request.get_json()
success = True
message = "Source added successfully!"
status_code = 200
data = {}
if received:
partnership = Partnership.query.filter(Partnership.id == current_user.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
partnership_account = PartnershipAccount\
.query\
.filter(and_(PartnershipAccount.id == current_user.partnership_account_id, PartnershipAccount.partnership_id == partnership.id))\
.first()
params = {
'name': received.get('name', None),
'description': received.get('description', None),
'partnership_id': partnership.id,
'partnership_account_id': partnership_account.id if partnership_account else None,
'workflows': received.get('workflows', {}),
'created_by': current_user.id,
}
source = Source.create(**params)
if source:
data['id'] = source.sid
data['name'] = source.name
data['description'] = source.description
data['workflows'] = source.workflows
data['partnership_id'] = Partnership.get_sid_from_id(source.partnership_id)
data['partnership_account_id'] = PartnershipAccount.get_sid_from_id(
source.partnership_account_id) if source.partnership_account_id else None
data['partnershipName'] = Partnership.get_name(source.partnership_id)
data['partnershipAccountName'] = PartnershipAccount.get_name(
source.partnership_account_id) if source.partnership_account_id else None
data['updatedAt'] = source.updated_on or None
data['createdAt'] = source.created_on or None
created_user = None
updated_user = None
if source.updated_by:
updated_user = User.query.filter(User.id == source.updated_by).first()
if source.created_by:
created_user = User.query.filter(User.id == source.created_by).first()
data['updatedBy'] = f'{updated_user.firstname} {updated_user.lastname}' if updated_user else None
data['createdBy'] = f'{created_user.firstname} {created_user.lastname}' if created_user else None
data['updated_user_id'] = updated_user.sid if updated_user else None
data['created_user_id'] = created_user.sid if created_user else None
es_data = {
'user_id': current_user.sid,
'notify_message_type': 'SOURCE_CREATED',
'user_related_entities': "You've",
'other_user_related_entities': f'{current_user.firstname} {current_user.lastname}',
'hyperlink': f'{partnership.partner_url}/partnership/sources'
}
es_response = send_notifications(**es_data)
else:
message = "Source name already exists"
status_code = 401
success = False
else:
status_code = 401
message = "Invalid parameters!"
success = False
return api_jsonify(data, status_code, message, success)
@api_role_required('admin', 'partner')
def update_source(sid):
success = True
message = "Source updated successfully!"
status_code = 200
data = {}
received = request.get_json()
if received:
if sid:
source = Source.query.filter(Source.sid == sid).first()
partnership = Partnership.query.filter(Partnership.id == current_user.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
if source:
new_source_name = received.get('name', None)
if not source.is_name_exists(new_source_name):
source.name = new_source_name
source.description = received.get('description', None)
source.workflows = received.get('workflows', {})
source.updated_by = received.get('updated_by', current_user.id)
source.save()
data['id'] = source.sid
data['name'] = source.name
data['description'] = source.description
data['workflows'] = source.workflows
data['partnership_id'] = partnership.sid
data['partnership_account_id'] = PartnershipAccount.get_sid_from_id(
source.partnership_account_id) if source.partnership_account_id else None
data['partnershipName'] = partnership.name
data['partnershipAccountName'] = PartnershipAccount.get_name(
source.partnership_account_id) if source.partnership_account_id else None
data['updatedAt'] = source.updated_on or None
data['createdAt'] = source.created_on or None
created_user = None
updated_user = None
if source.updated_by:
updated_user = User.query.filter(User.id == source.updated_by).first()
if source.created_by:
created_user = User.query.filter(User.id == source.created_by).first()
data['updatedBy'] = f'{updated_user.firstname} {updated_user.lastname}' if updated_user else None
data['createdBy'] = f'{created_user.firstname} {created_user.lastname}' if created_user else None
data['updated_user_id'] = updated_user.sid if updated_user else None
data['created_user_id'] = created_user.sid if created_user else None
es_data = {
'user_id': current_user.sid,
'notify_message_type': 'SOURCE_EDITED',
'user_related_entities': "You've",
'other_user_related_entities': f'{current_user.firstname} {current_user.lastname}',
'hyperlink': f'{partnership.partner_url}/partnership/sources'
}
es_response = send_notifications(**es_data)
else:
status_code = 401
message = "Source name already exists!"
success = False
else:
status_code = 404
message = "Source not found!"
success = False
else:
status_code = 401
message = "Invalid parameters!"
success = False
else:
status_code = 401
message = "Invalid parameters!"
success = False
return api_jsonify(data, status_code, message, success)
@api_role_required('admin')
def get_sources():
success = True
message = "Sources fetched successfully!"
status_code = 200
data = []
partnership = Partnership.query.filter(Partnership.id == current_user.partnership_id).first()
if not partnership:
partnership = Partnership.query.get(1)
sources = Source.query.filter(Source.partnership_id == partnership.id, Source.partnership_account_id == current_user.partnership_account_id).order_by(
Source.updated_on.desc(), Source.created_on.desc())
for source in sources:
_data = {}
_data['id'] = source.sid
_data['name'] = source.name
_data['description'] = source.description
_data['partnership_id'] = Partnership.get_sid_from_id(source.partnership_id)
_data['partnership_account_id'] = PartnershipAccount.get_sid_from_id(
source.partnership_account_id) if source.partnership_account_id else None
_data['partnershipName'] = partnership.name or None
_data['partnershipAccountName'] = PartnershipAccount.get_name(
source.partnership_account_id) if source.partnership_account_id else None
_data['updatedAt'] = source.updated_on or None
_data['createdAt'] = source.created_on or None
created_user = None
updated_user = None
if source.updated_by:
updated_user = User.query.filter(User.id == source.updated_by).first()
if source.created_by:
created_user = User.query.filter(User.id == source.created_by).first()
_data['updatedBy'] = f'{updated_user.firstname} {updated_user.lastname}' if updated_user else None
_data['createdBy'] = f'{created_user.firstname} {created_user.lastname}' if created_user else None
_data['updated_user_id'] = updated_user.sid if updated_user else None
_data['created_user_id'] = created_user.sid if created_user else None
data.append(_data)
return api_jsonify(data, status_code, message, success)
@api_role_required('admin')
def get_source_by_id(sid):
success = True
message = "Source fetched successfully!"
status_code = 200
data = {}
source = Source.query.filter(Source.sid == sid, Source.partnership_account_id ==
current_user.partnership_account_id).first()
if source:
data['id'] = source.sid
data['name'] = source.name
data['description'] = source.description
data['partnership_id'] = Partnership.get_sid_from_id(source.partnership_id)
data['partnership_account_id'] = PartnershipAccount.get_sid_from_id(
source.partnership_account_id) if source.partnership_account_id else None
data['partnershipName'] = Partnership.get_name(source.partnership_id)
data['partnershipAccountName'] = PartnershipAccount.get_name(
source.partnership_account_id) if source.partnership_account_id else None
data['updatedAt'] = source.updated_on or None
data['createdAt'] = source.created_on or None
created_user = None
updated_user = None
if source.updated_by:
updated_user = User.query.filter(User.id == source.updated_by).first()
if source.created_by:
created_user = User.query.filter(User.id == source.created_by).first()
data['updatedBy'] = f'{updated_user.firstname} {updated_user.lastname}' if updated_user else None
data['createdBy'] = f'{created_user.firstname} {created_user.lastname}' if created_user else None
data['updated_user_id'] = updated_user.sid if updated_user else None
data['created_user_id'] = created_user.sid if created_user else None
# data['channels'] = []
# try:
# channels = db.session\
# .query()\
# .filter(Channel.source_id == source.id)\
# .with_entities(Channel.type, Channel.is_active, cast(Channel.content, String))\
# .group_by(Channel.type, Channel.is_active, cast(Channel.content, String))\
# .all()
# except:
# channels = []
# phone_channels = {'type': 'phonenumbers'}
# phone_channel_items = []
# is_phone_channel = False
# emails_channels = {'type': 'emails'}
# for channel in channels:
# channel_content = json.loads(channel[2])
# if channel[0] == 'phonenumbers':
# is_phone_channel = True
# _ch = {}
# _ch["isActive"] = channel_content.get('is_active', '')
# _ch["value"] = channel_content.get('phonenumber', '')
# _ch['id'] = channel_content.get('sid', '')
# phone_channel_items.append(_ch)
# elif channel[0] == 'emails':
# pass
# # append phone channels
# if is_phone_channel:
# phone_channels['items'] = phone_channel_items
# data['channels'].append(phone_channels)
else:
status_code = 404
message = "Source not found!"
success = False
return api_jsonify(data, status_code, message, success)
@api_role_required('admin')
def update_metadata(sid):
success = True
message = "Source updated successfully!"
status_code = 200
data = {}
received = request.get_json()
if received and sid:
active = received.get('active', False)
source = Source.query.filter(Source.sid == sid).first()
if source:
source.is_active = active
source.save()
else:
status_code = 404
message = "Source not found!"
success = False
else:
status_code = 401
message = "Invalid parameters!"
success = False
return api_jsonify(data, status_code, message, success)
@api_role_required('admin', 'partner')
def update_workflows(sid):
success = True
message = "Source updated successfully!"
status_code = 200
data = {}
received = request.get_json()
if received and sid:
workflows = received.get('workflows', False)
source = Source.query.filter(Source.sid == sid).first()
if source:
source.workflows = workflows
source.save()
else:
status_code = 404
message = "Source not found!"
success = False
else:
status_code = 401
message = "Invalid parameters!"
success = False
return api_jsonify(data, status_code, message, success)
@api_role_required('admin', 'partner')
def get_workflows(sid):
success = True
message = "Source workflows fetched successfully!"
status_code = 200
data = {}
if sid:
source = Source.query.filter(Source.sid == sid).first()
if source:
data = source.workflows
else:
status_code = 404
message = "Source not found!"
success = False
return api_jsonify(data, status_code, message, success)
def interaction_to_user():
""" """
json = request.get_json()
if 'firstName' in json and json['firstName'] in ['', ' '] or \
'lastName' in json and json['lastName'] in ['', ' '] or \
'phoneNumber' in json and json['phoneNumber'] in ['', ' '] or \
'emailAddress' in json and json['emailAddress'] in ['', ' '] or \
'channelType' not in json or 'sourceId' not in json or 'channelId' not in json:
return api_jsonify([], 422, "Missing parameters", False)
channel_id = json.get('channelId')
source_id = json.get('sourceId')
channel_type_id = json.get('channelTypeId')
partnership = Partnership.query.filter(Partnership.id == current_user.partnership_id).first()
channel_type = ChannelType.query.filter(ChannelType.sid == channel_type_id).first()
if not partnership:
partnership = Partnership.query.get(1)
partnership_account = PartnershipAccount.query.filter(
PartnershipAccount.id == current_user.partnership_account_id).first()
if channel_type.name == "CALL":
contact = contact_exists(json.get('emailAddress', None), json.get('phoneNumber', None))
if not contact:
contact = Contact(
phonenumber_1=json.get('phoneNumber', ''),
email=json.get('emailAddress', ''),
partnership_account_id=current_user.partnership_account_id
)
previous_lead = Lead.query.filter(
json.get('phoneNumber') == Lead.phonenumber, current_user.partnership_account_id == Lead.partnership_account_id
).first()
if previous_lead is not None:
progress_status = previous_lead.progress_status
agent_assigned = previous_lead.agent_assigned_id
else:
progress_status = 'no status'
agent_assigned = None
lead = Lead(
partnership_account_id=current_user.partnership_account_id,
firstname=json.get('firstName'),
lastname=json.get('lastName'),
email=json.get('emailAddress'),
phonenumber=json.get('phoneNumber'),
progress_status=progress_status,
question='',
starttime=datetime.utcnow(),
call_type='outbound',
status='ringing',
my_phone='',
additional_info='',
call_source='',
agent_assigned_id=agent_assigned,
originating_number='',
inbound_id=''
)
db.session.add(lead)
db.session.commit()
contact_channel = ContactChannelTie()
contact_channel.contact = contact
contact_channel.call = lead.id
contact_channel.source = Source.get_id_from_sid(source_id)
contact_channel.save()
payload = {
'lead_id': lead.sid,
'source_id': Source.get_id_from_sid(source_id),
'channelID': channel_id,
'channel_Type_Id': channel_type_id,
'partnership_id': partnership.sid,
'partnership_account_id': partnership_account.sid,
'agent_id': '',
'payload': {}
}
# Response to Node JS
response = send_request('/call-log', payload)
# call the agent/user
# Update that agent in call -- >
client = bw_client(partnership.id)
log.info('Calling Bandwidth number...')
# BandwidthRouting(client).call_lead(agent_assigned, lead_id=lead.id)
return api_jsonify({'lead': lead.sid}, 200, "Success", True)
elif channel_type == "CHAT":
try:
# chat = Chat.create(**json)
return api_jsonify({'contact': ''}, 200, "Success", True)
except Exception as e:
lead_id = None
return api_jsonify({'leadId': lead_id}, 200, "Success", True)
elif channel_type == "TEXT_MESSAGE":
try:
message = Message.create(**json)
except Exception as e:
lead_id = None
return api_jsonify({'leadId': lead_id}, 200, "Success", True)
elif channel_type == "EMAIL":
try:
pass
# email = Email.create(**json)
except Exception as e:
lead_id = None
return api_jsonify({'leadId': lead_id}, 200, "Success", True)
else:
pass
def interaction_to_lead(lead_id="", source_id="", channel_id="", channel_type="", payload={}):
if channel_type == "CALL":
# Update that agent in call
lead = Lead.query.filter(Lead.sid == lead_id).first()
channel_type = ChannelType.query.filter(ChannelType.name == channel_type).first()
partnership = Partnership.query.filter(Partnership.id == (current_user.partnership_id or 1)).first()
partnership_account = PartnershipAccount.query.filter(
PartnershipAccount.id == (current_user.partnership_account_id or 1)).first()
# TODO Make outbound bandwidth call here
# Update LEAD
# create payload for node
payload = {
'lead_id': lead.sid,
'source_id': Source.get_id_from_sid(source_id),
'channelID': channel_id,
'channel_Type_Id': channel_type.sid,
'partnership_id': partnership.sid,
'partnership_account_id': partnership_account.sid,
'agent_id': current_user.sid,
'payload': {}
}
# Response to Node JS
response = send_request('/call-log', payload)
elif channel_type == 'EMAIL':
# send email
# add to email table
email = ''
# create payload for node
payload = {
'lead_id': email.sid,
'source_id': Source.get_id_from_sid(source_id),
'channelID': channel_id,
'channel_Type_Id': channel_type.sid,
# 'partnership_id': partnership.sid,
# 'partnership_account_id': partnership_account.sid,
'agent_id': current_user.sid,
'payload': {}
}
# Response to Node JS
response = send_request('/call-log', payload)
return True
class SourceApi(MethodView, BlueprintMixin):
serializers = {
"get": {
'out': SourceOutSchema
},
'post': {
'in': SourceInSchema,
'out': SourceOutSchema
},
'put': {
'in': SourceInSchema,
'out': SourceOutSchema
},
'patch': {
'in': SourceInSchema,
'out': SourceOutSchema
}
}
permission_classes = {
"get": []
}
def get(self, source_id=None):
if not source_id:
queryset = Source.query.all()
serializer = self.get_serializer_class(many=True, key='out', only=('sid', 'name'))
else:
queryset = Source.query.filter(Source.sid == source_id).first()
serializer = self.get_serializer_class(key='out')
return api_jsonify(data=serializer.dump(queryset), message="Source(s) fetched successfully.")
def post(self):
serializer = self.get_serializer_class(key='in')
data = serializer.load(request.get_json())
# Add partnership and account details
data['partnership_id'] = current_user.partnership_id
data['partnership_account_id'] = current_user.partnership_account_id
if not Source.get_by_name(data.get('name', '')):
Source.create(**data)
message = "Source created successfully."
status_code = 302
success = True
else:
message = "Source name already exists."
status_code = 409
success = False
return api_jsonify(data=[], message=message, status_code=status_code, success=success)
def put(self, source_id):
serializer_in = self.get_serializer_class(key='in')
data = serializer_in.load(request.get_json())
if not Source.get_by_name(data.get('name', '')):
source = Source.update(source_id, **data)
message = "Source updated successfully."
status_code = 200
success = True
else:
message = "Source name already exists."
status_code = 409
success = False
serializer_out = self.get_serializer_class(key='out')
return api_jsonify(data=serializer_out.dump(source), status_code=status_code, message=message, success=success)