Example #1
0
def report_staffid(con, *args):
    global my_queue
    if not args:  # 外联情况
        info = con.getInfo()
    else:
        info = args[0]  # 这里用info命名不太恰当但是历史原因就暂时info(时间上是ev--event)
        return
    caller = info.getHeader('caller-caller-id-number')
    callee = info.getHeader(
        'variable_sip_to_user')  # 或者caller-destination-number
    uuid = info.getHeader('variable_uuid')

    # 获取分机
    member = info.getHeader('variable_MEMBERINTERFACE')
    ccutils.set_variable(con, 'CDR(Exten)', member)

    # 获取工号
    sql = 'select StaffId from' + Conf.R_STAFFIDEXTEN_SHARE + 'where Exten = {}'.format(
        member)
    row = db.get(sql)
    StaffId = row.StaffId if row else 0
    if StaffId:
        ccutils.multiset(con, ['StaffId', StaffId, 'CDR(StaffId)', StaffId])

    # 插入录音记录时会用到
    ccutils.multiset(con, [
        'CDR(DIALSTATUS)', 'ANSWER', 'QUEUETIME_START',
        ccutils.microtime(True)
    ])

    return (StaffId, member)
Example #2
0
def queue_answer(con, *args):
    # IsForeCSave = GLOBALS['IsForeCSave']
    info = args[0]
    callee = info.getHeader('variable_sip_from_user')
    uuid = info.getHeader('variable_uuid')
    CustomId = info.getHeader('variable_CDR(customerid)')  #获取客户ID
    CustomId = CustomId if CustomId else 0
    QueueName = info.getHeader('variable_QueueName')
    '''
        这里要通过MEMBERINTERFACE获取坐席分机,但是在呼入情况下info是针对客户那一端的channel的不是针对坐席这一端的
        所以通过info.getHeader()来获取是'牛头不对马尾',呼出应该没问题
        '''
    member = info.getHeader('variable_MEMBERINTERFACE')  #获取分机
    starttime = ccutils.microtime(True)
    # 获取工号
    sql = 'select StaffId from' + Conf.R_STAFFIDEXTEN_SHARE + 'where Exten = {}'.format(
        member)
    row = db.get(sql)
    StaffId = row.StaffId if row else 0
    vars = [
        'CDR(Exten)', member, 'IsAnswer', 1, 'QUEUETIME_START',
        ccutils.microtime(True)
    ]
    ccutils.multiset(con, vars)
    isIvrLogin = '******'
    if not StaffId:
        # 如果staffid为空有可能是座席F5刷新导致的,临时的解决为从登录日志表中获取最新的一次登录绑定
        sql = "select UserName from {} where exten={} and IsSuccess=1 order by id desc limit 1;".format(
            Conf.l_CRM_LOGIN, member)
        row = db.get(sql)
        StaffId = row.StaffId if row else 0
        if StaffId:
            ccutils.set_variable(con, 'StaffId', 0)
    online_time = 0
    if StaffId:
        ccutils.multiset(con, ['StaffId', StaffId, 'CDR(StaffId)', StaffId])
        sql = 'select UpdateTime from' + Conf.R_STAFFIDEXTEN_SHARE + 'where StaffId={} limit 1'.format(
            StaffId)
        row = db.get(sql)
        online_time = row.UpdateTime if row else 0
        if online_time == 1:
            # 如果是语音登录则记录最后一次接通的被叫号码
            isIvrLogin = 1
            sql = "update {} set lastnum={} where queue_name='{}' and staffid={};".format(
                Conf.FORECAST_QUEUE, callee, QueueName, StaffId)
            db.execute(sql)
    # 摘机标识
    if isIvrLogin and online_time == 1:
        ccutils.set_variable(con, 'SHARED(SRC_IsSave, {})', member, isIvrLogin)
        # 参数字符串
        ccutils.set_variable(con, 'SHARED(SHARE_STRING, {})', member,
                             int(CustomId) * int(StaffId))
    ccutils.set_variable(con, 'CDR(customerid)', CustomId)
    # 号码呼叫状态置为通话中
    sql = "update" + Conf.FORECAST_DATA_TEMP + "set calloutStatus=2,updatetime='{}' where id={};".format(
        now(), CustomId)
    db.execute(sql)
    return (StaffId, )
def queue_groupcall_answer(con, *args):
    if not args:  # 外联情况
        ev = con.getInfo()
    else:
        ev = args[0]  # 这里用info命名不太恰当但是历史原因就暂时info(时间上是ev--event)
        return

    # $IsForeCSave = & $GLOBALS['IsForeCSave'];  #todo 不知道这个变量何用??
    callee = ev.getHeader(
        'variable_sip_to_user')  # 或者caller-destination-number
    CustomId = ev.getHeader('variable_CustomId')
    QueueName = ev.getHeader('QueueName')
    memberinterface = ev.getHeader('variable_MEMBERINTERFACE')  #获取分机
    member = memberinterface[:4]
    start_time = ccutils.microtime(True)
    # 获取工号
    sql = 'select StaffId from {} where Exten={} limit 1'.format(
        Conf.R_STAFFIDEXTEN_SHARE, member)
    row = db.get(sql)
    StaffId = row.StaffId if row else 0
    ccutils.multiset(con, ['CDR(Exten)', member, 'IsAnswer', 1])
    isIvrLogin = '******'
    if not StaffId:
        # 如果staffid为空 有可能 是座席F5刷新导致的,临时的解决为从登录日志表中获取最新的一次登录绑定
        sql = "select UserName from {} where exten='{}' and IsSuccess=1 order by id desc limit 1;".format(
            Conf.l_CRM_LOGIN, member)
        row = db.get(sql)
        StaffId = row.StaffId if row else 0
        if not StaffId:
            ccutils.set_variable(con, 'StaffId', 0)

    if StaffId:
        ccutils.multiset(con, ['StaffId', StaffId, 'CDR(StaffId)', StaffId])
        sql = 'select UpdateTime from {} where StaffId={} limit 1'.format(
            Conf.R_STAFFIDEXTEN_SHARE, StaffId)
        row = db.get(sql)
        online_time = row.UpdateTime if row else 0
    ccutils.set_variable(con, 'CDR(customerid)', CustomId)
    return True
Example #4
0
def call_transfer(con, *args):
    if not args:  # 外联情况
        info = con.getInfo()
    else:
        info = args[0]  # 这里用info命名不太恰当但是历史原因就暂时info(时间上是ev--event)
        return

    # print('info.serialize() is {}'.format(info.serialize()))
    caller = info.getHeader('caller-caller-id-number')
    callee = info.getHeader(
        'variable_sip_to_user')  # 或者caller-destination-number
    uuid = info.getHeader('variable_uuid')
    domain_name = info.getHeader('variable_domain_name')
    if not domain_name:
        domain_name = info.getHeader('variable_sip_to_host')
    elif not domain_name:
        domain_name = info.getHeader('channel-network-addr')
    ccutils.multiset(con, ['CDR(calltype)', 1, 'CALLTYPE', 1])
    sql = 'select StaffId from ' + Conf.R_STAFFIDEXTEN_SHARE + 'where Exten = {}'.format(
        callee)
    row = db.get(sql)
    trans_staffid = row.StaffId if row else 0
    if trans_staffid:
        ccutils.multiset(
            con, ['StaffId', trans_staffid, 'CDR(StaffId)', trans_staffid])

        sql = "select a.Id ,a.ClassifId from {} a join crm_department b on a.DepartmentId=b.Id " \
              "join {} c on b.Id=c.DepartmentId where a.`Status`=1 and c.StaffId={};".format(Conf.K_PROJECTINFO, Conf.CRM_USERINFO, trans_staffid)
        row = db.get(sql)
        # 此外线号码没有绑定项目
        if row:
            # 归属分类Id
            ClassifId = row.ClassifId
            # 归属项目Id
            ProjectId = row.Id
            ccutils.multiset(con, [
                'CDR(ClassifId)', ClassifId, 'CDR(projectid)', ProjectId,
                'PROID', ProjectId, 'ClassifId', ClassifId
            ])
    ccutils.set_variable(con, 'CDR(DIALSTATUS)', 'answered')
    con.executeAsync('bridge',
                     'sofia/internal/${}%${}/'.format(callee,
                                                      domain_name), uuid)

    # $agi->agi_exec('Dial', "SIP/$callee,30");

    return True
Example #5
0
def call_in(con, *args):
    '''
	:param info:
	:return:
	此函数对应于agi_call_in.php
	'''
    if not args:  #外联情况
        info = con.getInfo()
    else:
        info = args[0]  #这里用info命名不太恰当但是历史原因就暂时info(时间上是ev--event)
        return
    caller = info.getHeader('variable_sip_from_user')
    callee = info.getHeader('channel-destination-number')
    if 'gw+' in callee: callee = callee[3:]
    uuid = info.getHeader('variable_uuid')
    domain_name = info.getHeader('variable_domain_hame')
    if not domain_name: domain_name = info.getHeader('variable_sip_to_host')
    elif not domain_name: domain_name = info.getHeader('channel-network-addr')
    dial_str = None
    # 通过外线号码获得其所属的项目(正常进行的项目)
    sql = 'select b.id as ClassifId, a.CompanyId, a.Type from {} a join {} b on a.CompanyId = b.CompanyId ' \
          'where a.Num = "{}" order by b.Id limit 1'.format(Conf.K_NUMINFO_SHARE, Conf.K_PROJECT_CLASSIFICATION, callee)
    row = db.get(sql)
    if not row:
        print('#########未绑定项目#############')
        return dial_str
    # 判断是否为语音识别的呼入号码
    # row.Type = 3
    if row.Type == 3:
        sql = 'select asrnumber, CompanyId from' + Conf.ASRCALL_CONFIG + 'where CallerID = "{}"'.format(
            callee)
        asrrow = db.get(sql)
        if asrrow:
            CustomerId = 0  #todo 原来php里直接出现此变量,python会报错如果没有实现定义的话,所以这里添加个定义,具体php为何这样有待进一步理解
            vars = [
                'asrnumber', asrrow.asrnumber, 'CompanyId', asrrow.CompanyId,
                'CDR(CompanyId)', asrrow.CompanyId, 'CDR(calltype)', 6,
                'CUSID', CustomerId, 'CustomId', CustomerId, 'CDR(customerid)',
                CustomerId
            ]
            ccutils.multiset(con, vars)
            # ###todo:transfer好像执行完不会返回,这里似乎应该调用execute_extension更合适,待确认...
            con.executeAsync('transfer', 'from-asrcall', uuid)
            return dial_str
    # 归属分类id
    ClassifId = row.ClassifId
    # 队列名称:队列到名字和呼入到外线一致
    QueueName = callee

    CompanyId = row.CompanyId
    vars = [
        'CompanyId', CompanyId, 'ClassifId', ClassifId, 'CDR(calltype)', 1,
        'CDR(ClassifId)', ClassifId, 'CDR(CompanyId)', CompanyId
    ]
    ccutils.multiset(con, vars)
    # 黑名单
    sql = 'select id from' + Conf.K_BLACKLIST_SHARE + 'where Num = "{}" and CompanyId = {} limit 1'.format(
        caller, CompanyId)
    blacklist = db.get(sql).id if db.get(sql) else None
    if blacklist:
        print('已经加入黑名单')
        return dial_str
    sql = "select IVR_IsStaffFirst,IsRecord from {} where Enabled=1 and Id={} ;".format(
        Conf.CRM_COMPANYINFO, CompanyId)
    row = db.get(sql)
    if not row:
        # 公司账户已经禁用
        con.execute('playback', 'ccos_company_disabled')
        return dial_str

    staff_first = row.IVR_IsStaffFirst
    #  $agi->set_variable('ISRECORD',$row['IsRecord']);
    # 检查应该客户是否为服务客户  如果是   则获取其相应资料
    sql = "select Id,StaffId,ProjectId from" + Conf.CUSTOMER_BASEINFO + "where CompanyId={} and  DelBatchId=0  and  phone='{}' limit 1;".format(
        CompanyId, caller)

    row = db.get(sql)
    CustomerId = row.Id if row else 0
    StaffId = row.StaffId if row else 0

    ###
    if not CustomerId and staff_first:
        sql = "select id, StaffId,customerid from {} where ClassifId={} and  dst={} and StaffId>0 union all select id,  " \
              "StaffId,customerid from {} where ClassifId={} and  src ={} and StaffId>0 order by id  desc limit 1;".format(Conf.CDR, ClassifId, caller, Conf.CDR, ClassifId, caller)
        row = db.get(sql)
        CustomerId = row.customerid if row else 0
        StaffId = row.StaffId if row else 0

    ###
    if not CustomerId:
        CustomerId = ccutils.get_generator_id(0, caller)

    vars = ['CUSID', CustomerId, 'CDR(customerid)', CustomerId]
    ccutils.multiset(con, vars)
    # 语音导航
    ivr_exec(con, callee)
    # 直属号码
    if not staff_first or not StaffId:
        sql = "select StaffId,count(*) as CountNum  from" + Conf.R_STAFFIDNUM_SHARE + "where num='{}' and type=1 ;".format(
            callee)
        row = db.get(sql)
        # 如果没有呼入绑定 则挂机
        if row and not row.CountNum:
            return None

        # 如果有呼入绑定 且只有一个座席
        if row.CountNum == 1:
            StaffId = row.StaffId
            staff_first = 1

    # 呼叫归属客服
    if staff_first and StaffId:
        sql = 'select Exten from' + Conf.R_STAFFIDEXTEN_SHARE + 'where StaffId = "{}"'.format(
            StaffId)
        row = db.get(sql)
        Exten = row.Exten if row else ''
        vars = [
            'StaffId', StaffId, 'CDR(Exten)', Exten, 'CDR(StaffId)', StaffId
        ]
        ccutils.multiset(con, vars)
        ExtenStatus = -4
        if Exten: ExtenStatus = get_extension_state(Exten)  #取当前分机状态
        # 分机空闲时进行呼叫
        if not ExtenStatus:
            sql = "select c.id,b.IsHiddenNum from" + Conf.CRM_USERINFO + "a  join crm_role b on a.RoleId=b.Id join " \
                  "k_projectinfo c on a.DepartmentId=c.DepartmentId and c.`Status`=1 where a.StaffId='{}';".format(StaffId)
            row = db.get(sql)
            isHiddenNum = row.IsHiddenNum
            if not isHiddenNum:
                ccutils.set_variable(con, 'CALLERID(num-pres)', 'prohib')

            # ccutils.set_variable(con,'CALL_STR','SIP/{}'.format(Exten))
            # con.executeAsync('set', 'CALL_STR=SIP/{}'.format(Exten), uuid)
            # con.executeAsync('Goto', 'transfer', uuid)
            dial_str = 'sofia/internal/{}%{}'.format(Exten, domain_name)
        elif staff_first == 1:
            con.execute('playback',
                        Conf.SOUND_PATH + 'Ivr_021.wav')  # 坐席正忙请稍后再拨
            return dial_str

        if not QueueName:
            return dial_str
        # 如果列队中有部门经理 且号码显示 没全部为可显示
        sql = "select a.Id from" + Conf.R_STAFFIDNUM_SHARE + "a join {} b  on a.StaffId=b.StaffId join {} c on b.RoleId=c.Id and c.`Type`=3 and c.IsHiddenNum=1 where  a.Num ='{}' limit 1 ;".format(
            Conf.CRM_USERINFO, Conf.CRM_ROLE, callee)
        row = db.get(sql)
        isHiddenNum = row.Id if row else 0
        if not isHiddenNum:
            # 查看座席权限是否 是隐藏
            sql = "select Id  from" + Conf.CRM_ROLE + "where CompanyId={} and type=4 and  ISHiddenNum=0 limit 1;".format(
                CompanyId)
            row = db.get(sql)
            isHiddenNum = row.Id if row else 0
            if isHiddenNum:
                ccutils.set_variable(con, 'CALLERID(num-pres)', 'prohib')
        ccutils.set_variable(con, 'U_QUEUE', QueueName)
        return (dial_str, QueueName)
Example #6
0
def queue_hangup(con, ev):
        sys_mode = ccutils.read_configuration('sys_mode')
        caller = ev.getHeader('caller-caller-id-number')
        callee = ev.getHeader('channel-caller-id-number')
        uuid = ev.getHeader('Unique-ID')
        channel = ev.getHeader('Other-Leg-Channel-Name')
        # CustomId = ev.getHeader('variable_CustomId)') #todo 这是原来的php对应的但是获取不到这个变量所以用下面一句代替
        CustomId = ev.getHeader('variable_CDR(customerid)')
        # 如果客户ID不存在 直接退出
        if not CustomId: return True
        ClassifId = ev.getHeader('variable_ClassifId')
        StaffId = ev.getHeader('variable_StaffId')
        REASON = ev.getHeader('variable_REASON')
        REASON = REASON if REASON else ''
        CompanyId = ev.getHeader('variable_CompanyId')
        IsAnswer = ev.getHeader('variable_IsAnswer')
        calltype = ev.getHeader('variable_CALLTYPE')
        PROID = ev.getHeader('variable_PROID')
        recordfile = ev.getHeader('variable_record_file')
        now = datetime.datetime.now()
        endtime = now.strftime('%Y-%m-%d %H:%M:%S')
        if StaffId and not PROID:
                result = ccutils.getInfoByStaffId(StaffId)
                if result:
                        CompanyId = result['CompanyId']
                        ClassifId = result['ClassifId']
                        PROID = result['ProjectId']
                        ccutils.multiset(con, ['CDR(CompanyId)',CompanyId,'CDR(ClassifId)',ClassifId,'CDR(projectid)', PROID])

        if IsAnswer == 1 or not len(REASON):
        # 排队的
                if not  IsAnswer and not len(REASON):
                        REASON = '100'
                        ccutils.set_variable(con, 'CDR(customerid)', CustomId)
                # 呼叫记录插入
                cdrs = ccutils.gen_cdrs(ev)
                ccutils.cdr_insert(ev, *cdrs)
                # 获取通话时常
                answeredtime = 0
                queue_start_time = int(float(ev.getHeader('variable_QUEUETIME_START')))
                if queue_start_time:
                        answeredtime = ccutils.microtime(True) - queue_start_time
                else:
                        answeredtime = ev.getHeader('variable_CDR(billsec)')
                if not answeredtime:
                        answeredtime = '0000-00-00 00:00:00'
                # 接通
                # 号码呼叫状态置为通话结束
                # 关机、停机、拒接、无效号码、无应答插入到回收池
                sql = 'insert ignore into' + Conf.FORECAST_DATA_SHARE_LOG + '(Id,ClassifId,ProjectId,CompanyId,BatchId,StaffId,Name,Phone,Address,Sex,Email,CallOutStatus,CallResult,AnswerTime,UpdateTime,CreateTime)'
                sql += "select Id, ClassifId,ProjectId,CompanyId,BatchId,'{}',Name,Phone,Address,Sex,Email,3,'{}','{}','{}',CreateTime from {} where id='{}' ;".format(StaffId, REASON, answeredtime, endtime, Conf.FORECAST_DATA_TEMP, CustomId)
                db.execute(sql)
                # 从预测池中删除
                sql = "delete from {} where id='{}';".format(Conf.FORECAST_DATA_TEMP, CustomId)
                db.execute(sql)
                if recordfile:
                        extenNum = ev.getHeader('variable_CDR(Exten)')
                        ast_recodefile = recordfile
                        sql = 'insert into' + Conf.L_RECORD + '(Type,StaffId,CustomerId,ProjectId,ClassifId,CallType,CallerNum,CalleeNum,Uniqueid,FileName,Path,HoldSec,CreateTime,CompanyId,exten)values'
                        sql += "(0,'{}','{}','{}','{}',{},'{}','{}',{},'','{}','{}','{}','{}','{}');".format(StaffId, CustomId, PROID, ClassifId, calltype, caller, callee, uuid, ast_recodefile, answeredtime, endtime, CompanyId, extenNum)
                        db.execute(sql)

        else:
                sql = "select  Id, ClassifId,ProjectId,CompanyId,BatchId,Name,Phone,Address,Sex,Email,CreateTime from"+Conf.FORECAST_DATA_TEMP + "where id={} ;".format(CustomId)
                row = db.get(sql)
                if not row:
                        return True
                Id = row.Id
                ClassifId = row.ClassifId
                CompanyId = row.CompanyId
                ProjectId = row.ProjectId
                BatchId = row.BatchId
                Name = row.Name
                Phone = row.Phone
                Address = row.Address
                Sex = row.Sex
                Email = row.Email
                CreateTime = row.CreateTime
                # 关机。停机。拒接。无效号码。无应答 插入 到回收池
                sql = 'insert ignore into'+Conf.FORECAST_DATA_SHARE_LOG + '( Id,ClassifId,ProjectId,CompanyId,BatchId,StaffId,Name,Phone,Address,Sex,Email,CallOutStatus,CallResult,AnswerTime,UpdateTime,CreateTime)values'
                sql += "({}, '{}','{}','{}','{}',0,'{}','{}','{}','{}','{}',0,'{}',0,'{}','{}');".format(Id, ClassifId, ProjectId, CompanyId, BatchId, Name, Phone, Address, Sex, Email, REASON, endtime, CreateTime)
                db.execute(sql)
                # 插入cdr
                # 呼叫发起时间戳
                orig_time = ev.getHeader('variable_Origtime')
                duration = time.time() - orig_time
                call_date = orig_time.strftime('%Y-%m-%d %H:%M:%S')
                duration_int = math.ceil(duration)
                disposition = 'NO ANSWER'
                # 托管用户预测未接通不计话单
                if not sys_mode:
                        sql = 'INSERT INTO'+Conf.CDR+ '(`clid`, `src`, `dst`, `calldate`, `answertime`, `endtime`, `duration`, `billsec`,`duration_int`,`billsec_int`, `dcontext`, `disposition`, `uniqueid`, `linkedid`, `projectid`, `StaffId`, `customerid`, `ClassifId`, `calltype`,`channel`,`dstchannel`,CompanyId)values'
                        sql += "('{}', '{}','{}','{}', '0000-00-00 00:00:00','{}', {}, 0,{},0, 'from-autocall', '{}', '{}', '{}','{}', 0, '{}', '{}', 3,'{}','','$CompanyId');".format(caller, caller, Phone, call_date, endtime, duration, duration_int, disposition, uuid, uuid, ProjectId, CustomId, ClassifId, channel)
                        db.execute(sql)

        return True