HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //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)