HEX
Server: Apache/2.4.52 (Ubuntu)
System: Linux spn-python 5.15.0-89-generic #99-Ubuntu SMP Mon Oct 30 20:42:41 UTC 2023 x86_64
User: arjun (1000)
PHP: 8.1.2-1ubuntu2.20
Disabled: NONE
Upload Files
File: //home/arjun/projects/buyercall_forms/buyercall/buyercall/blueprints/api2/doc/endpoints/calls.py
import logging

from datetime import datetime

from flask import jsonify, request
from flask_restx import Resource
from sqlalchemy import and_

from buyercall.lib.util_rest import rest_partnership, requires_auth, rest_is_partnership
from buyercall.blueprints.api2.doc import serializers
from buyercall.blueprints.phonenumbers.models import Phone
from buyercall.blueprints.filters import format_phone_number
from buyercall.blueprints.agents.models import Agent
from buyercall.blueprints.contacts.models import Contact
from buyercall.blueprints.api2.restplus import api
from buyercall.blueprints.partnership.models import PartnershipAccount
from buyercall.blueprints.leads.models import Lead
from buyercall.extensions import db


log = logging.getLogger(__name__)
ns = api.namespace('Calls', description='Operations related to calls.', path='/accounts')


@ns.route('/<int:paid>/calls')
@api.doc(responses={200: 'OK',
                    400: 'Error performing operation.',
                    401: 'Unauthorized request.'},
         params={'paid': 'The partner account Id'})
class Calls(Resource):
    """
    # DISABLE ENDPOINT
    @api.response(200, 'Call successfully triggered.')
    @api.expect(serializers.call_outbound, validate=True)
    @requires_auth
    def post(self, paid):
    """
    """
        Performs an outbound call.

        <p>
        The Calls API POST endpoint should be used to create an outbound call between a partner account agent and a lead
        or customer. The agent will be called first. When the agent picks up the phone will ring and a call to the
        lead or customer will be initiated. Once the lead or customer answers they will be connected to the agent.
        </p>
        <br />
        <p>
        This endpoint request is similar to a widget outbound call, except for a few key differences. This call request
        does not allow for any specific settings, such as greeting messages etc. and calls can only be assigned to a
        single agent. The widget outbound calls can handle additional settings, such as greeting messages and calls can
        be sent to multiple agents.
        </p>
        <br />
        <p>
        It's also important to note that only operational phone numbers with the type 'priority' can be used to perform
        outbound calls using this request endpoint. Phone numbers with types; 'tracking' or 'mobile' can not be used for
        outbound calls.
        </p>
        <br />
        <p>
         You will require a partner authentication token, a partner account id, an agent id
         and a phone number id to make a successful request.
    """
    """
        if rest_is_partnership and rest_partnership is not None:
            from buyercall.blueprints.phonenumbers.tasks import connect_lead_to_agent

            _new_contact = None
            progress_status = 'new lead'
            _contact_using = 'phone'

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

            if partnership_account is not None:
                received = request.json

                if received is not None:
                    try:

                        result_agent_id = received['agent_id']
                        result_phone_number_id = received['phone_number_id']
                        result_number = format_phone_number(received['number'])

                        routing = Phone.query\
                            .filter(and_(Phone.partnership_account_id == paid, Phone.id == result_phone_number_id))\
                            .first()
                        if not routing:
                            return api.abort(400, message='Error performing call. Cannot find routing phone number.')

                        agent = Agent.query\
                            .filter(and_(Agent.partnership_account_id == paid, Agent.id == result_agent_id))\
                            .first()

                        if not agent:
                            return api.abort(400, message='Error performing call. Cannot find agent.')

                        # check if contact exists... if not create a new one
                        contact = Contact.query\
                            .filter(Contact.phonenumber_1 == result_number)\
                            .filter(Contact.partnership_account_id == paid)\
                            .first()

                        if not contact:
                            contact_entry = Contact(
                                phonenumber_1=result_number,
                                partnership_account_id=paid
                            )
                            db.session.add(contact_entry)
                            db.session.commit()

                            log.info('The lead contact has been added')

                            new_contact = Contact.query\
                                .filter(Contact.phonenumber_1 == result_number)\
                                .filter(Contact.partnership_account_id == paid)\
                                .first()
                            contact = new_contact
                        else:
                            old_lead = Lead.query.filter(
                                Lead.partnership_account_id == paid,
                                Lead.contact_id == contact.id
                            ).first()

                            if old_lead:
                                progress_status = old_lead.progress_status

                        lead = Lead(
                            partnership_account_id=paid,
                            firstname=contact.firstname,
                            lastname=contact.lastname,
                            phonenumber=contact.phonenumber_1,
                            email=contact.email,
                            starttime=datetime.utcnow(),
                            call_type='outbound',
                            my_phone=routing.phonenumber,
                            inbound_id=routing.id,
                            agent_id=agent.id,
                            progress_status=progress_status,
                            status='ringing',
                            contact_id=contact.id
                        )
                        lead.save()

                        # A hack to specify how to contact the agent
                        if agent.app_number:
                            contact_using = 'app'
                        elif agent.mobile:
                            contact_using = 'mobile'
                        else:
                            contact_using = 'phone'

                        call_settings = {
                            'agents': [{
                                'id': agent.id,
                                'contactUsing': contact_using
                            }]
                        }

                        connect_lead_to_agent.delay(lead.id, agent.id, call_settings)

                        return 200
                    except Exception as e:
                        log.error('Error performing call. Error: ' + str(e))
                        return api.abort(400, message='Error performing call.')
                else:
                    return api.abort(400, message='Error performing call.')
            else:
                return api.abort(404, message='Partnership account not found.')
        else:
            api.abort(401)
    """

    @requires_auth
    def get(self, paid):
        """
        Retrieves all call lead details for a partnership account.

        <p>
        The Calls API GET endpoint should be used to retrieve information on all calls from all phone numbers
        associated with a partner account.
        </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">
           {
              "calls": [
                {
                  "agent_id": null,
                  "call_count": 0,
                  "call_source": "Beef Stew Inc",
                  "call_type": "inbound",
                  "caller_id": "",
                  "created_on": "2018-12-12 21:24:27",
                  "duration": null,
                  "endtime": null,
                  "id": 8,
                  "my_phone": "+18722217507",
                  "phonenumber": "+17732909650",
                  "phonenumber_id": 2,
                  "progress_status": "new lead",
                  "recording_url": "",
                  "starttime": "2018-12-12 21:24:27",
                  "status": "ringing",
                  "updated_on": "2018-12-12 21:24:27",
                  "widget_guid": "",
                  "originating_number": "+17732909650"
                },
                {
                  "agent_id": null,
                  "call_count": 0,
                  "call_source": "Beef Stew Inc",
                  "call_type": "inbound",
                  "caller_id": "",
                  "created_on": "2018-12-12 21:24:31",
                  "duration": null,
                  "endtime": null,
                  "id": 9,
                  "my_phone": "+18722217507",
                  "phonenumber": "+17732909650",
                  "phonenumber_id": 2,
                  "progress_status": "new lead",
                  "recording_url": "",
                  "starttime": "2018-12-12 21:24:31",
                  "status": "ringing",
                  "updated_on": "2018-12-12 21:24:31",
                  "widget_guid": "",
                  "originating_number": "+17732909650"
                }
              ]
            }
     </pre>
        """
        if rest_is_partnership and rest_partnership is not None:
            lead_list = []

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

            if partnership_account is not None:
                leads = Lead.query\
                    .filter(Lead.partnership_account_id == paid)\
                    .all()

                if leads is not None:
                    for lead in leads:

                        if lead.starttime is not None:
                            result_starttime = lead.starttime.strftime('%Y-%m-%d %H:%M:%S')
                        else:
                            result_starttime = None

                        if lead.endtime is not None:
                            result_stoptime = lead.endtime.strftime('%Y-%m-%d %H:%M:%S')
                        else:
                            result_stoptime = None

                        if lead.status is not None:
                            result_status = lead.status
                        else:
                            result_status = ''

                        if lead.widget_guid is not None:
                            result_widget_guid = lead.widget_guid
                        else:
                            result_widget_guid = ''

                        lead_add = {
                            'id': lead.id,
                            'created_on': lead.created_datetime,
                            'updated_on': lead.updated_datetime,
                            'agent_id': lead.agent_id,
                            'call_source': lead.source,
                            'progress_status': lead.progress_status,
                            'caller_id': lead.caller_id,
                            'phonenumber_id': lead.inbound_id,
                            'phonenumber': lead.phonenumber,
                            'my_phone': lead.my_phone,
                            'duration': lead.duration,
                            'starttime': result_starttime,
                            'endtime': result_stoptime,
                            'call_type': lead.call_type,
                            'status': result_status,
                            'recording_url': lead.recording_url,
                            'widget_guid': result_widget_guid,
                            'call_count': lead.call_count,
                            'originating_number': lead.originating_number
                        }
                        lead_list.append(lead_add)

                    return jsonify(
                        calls=lead_list
                    )
                else:
                    return api.abort(404, message='No calls found.')
            else:
                return api.abort(404, message='Partnership account not found.')
        else:
            api.abort(401)


@ns.route('/<int:paid>/calls/<int:cid>')
@api.doc(responses={200: 'OK',
                    400: 'Error performing operation.',
                    401: 'Unauthorized request.'},
         params={'paid': 'The partner account Id',
                 'cid': 'The call Id'})
class Call(Resource):
    @requires_auth
    def get(self, paid, cid):
        """
        Retrieves call lead details of a call.

        <p>
        The Calls API GET endpoint should be used to retrieve information on a single call for
        a specific partner account.
        </p>
        <br />
        <p>
        You will require a partner authentication token, a partner account id and a call 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">
           {
              "agent_id": 3,
              "call_count": 0,
              "call_source": "twilio PN",
              "call_type": "outbound",
              "caller_id": "",
              "created_on": "2019-04-04 19:51:21",
              "duration": null,
              "endtime": null,
              "id": 431,
              "my_phone": "+13367394103",
              "phonenumber": "+17732909650",
              "phonenumber_id": 5,
              "progress_status": "new lead",
              "recording_url": "",
              "starttime": "2019-04-04 19:51:21",
              "status": "missed",
              "updated_on": "2019-04-04 19:51:28",
              "widget_guid": "",
              "originating_number": "+17732909650"
            }
     </pre>

        """
        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:
                lead = Lead.query\
                    .filter(and_(Lead.id == cid, Lead.partnership_account_id == paid))\
                    .first()

                if lead is not None:
                    if lead.starttime is not None:
                        result_starttime = lead.starttime.strftime('%Y-%m-%d %H:%M:%S')
                    else:
                        result_starttime = None

                    if lead.endtime is not None:
                        result_stoptime = lead.endtime.strftime('%Y-%m-%d %H:%M:%S')
                    else:
                        result_stoptime = None

                    if lead.status is not None:
                        result_status = lead.status
                    else:
                        result_status = ''

                    if lead.widget_guid is not None:
                        result_widget_guid = lead.widget_guid
                    else:
                        result_widget_guid = ''

                    return jsonify(
                        id=lead.id,
                        created_on=lead.created_datetime,
                        updated_on=lead.updated_datetime,
                        agent_id=lead.agent_id,
                        call_source=lead.source,
                        progress_status=lead.progress_status,
                        caller_id=lead.caller_id,
                        phonenumber_id=lead.inbound_id,
                        phonenumber=lead.phonenumber,
                        my_phone=lead.my_phone,
                        duration=lead.duration,
                        starttime=result_starttime,
                        endtime=result_stoptime,
                        status=result_status,
                        call_type=lead.call_type,
                        recording_url=lead.recording_url,
                        widget_guid=result_widget_guid,
                        call_count=lead.call_count,
                        originating_number=lead.originating_number
                    )
                else:
                    return api.abort(404, message='Call not found.')
            else:
                return api.abort(404, message='Partnership account not found.')
        else:
            api.abort(401)