#!/usr/bin/php -q Retorna uma conexão para o banco de dados. * -sGravaLog -> Grava log de erros gerados pelo serviço. * -sCreateMemory -> Aloca memoria para sincronização de dados. * ***************************************************************************************** */ error_reporting(E_ALL); ini_set('display_errors', 1); ini_set("memory_limit", "512M"); /* * Inclui funçoes genéricas. */ include("util/util.php"); include("util/sharedMem.php"); include("util/funcoesSsupervisor.php"); /* * Para rodar como um processo normal é preciso passar "N" como primeiro parametro. */ $notDaemon = isset($argv[1]) && (strtoupper($argv[1]) === 'N'); /* * Mostra o help quando passodo --help no primeiro argumento. */ GetSupervisorHelp(); /* * Inicializa o daemom quando N não for informado. */ GetDaemon($notDaemon); /* * Conexão com o banco de dados. */ $conn = false; /* * Log do sistema */ $patLog = "/var/log/asterisk/ssupervisor.log"; /* * Informações para controle */ $arDadosControle = array(); /* * Indica que uma transação foi iniciada; */ $inTransaction = 0; /* * Armazena o número de ciclos, para controlar a consulta a * chamdas abanconadas sem retorno, devera ser na ordem de * 1 para 10 ou seja a cada 10 atualizações od supervisor * faz uma para chamadas abandonadas sem retorno. */ $numCiclos = 0; try { declare(ticks=1); $statusSignal = 0; if (!$notDaemon) { pcntl_signal(SIGTERM, "sig_handler"); pcntl_signal(SIGHUP, "sig_handler"); pcntl_signal(SIGUSR1, "sig_handler"); pcntl_signal(SIGINT, "sig_handler"); } sGravaLog(sprintf("Server Start: %s [ok]\n", date("Y-m-d H:i:s"))); /* * Armazena dados da ultima consulta. */ $gOldAgt = array(); $gOlDac = array(); $gOldAbdsr = array(); /* * Informações de erro ou outras mensagens. */ $gNumErros = 0; $gArMsg = array(); $gUltMsg = ''; $idMsg = 0; /* * Cria segmento de memoria compartilhada. * Controle -> Guarda a posição de escrita de um agente ou dac. * O tamanho da memosia é calculado com base no espaco para mensagens(102400) e o restante * o espaço necessario para as informações dos agentes pelos dacs. */ //$shmKeyCtrl = sCreateMemory(SHM_IPC_FILE_CONTROLE, array(102400,NUM_MAX_AGENTES_ON + NUM_MAX_DACS_ON, TAM_SEGMENTO_CONTROLE)); $shmKeyCtrl = sCreateMemory(SHM_IPC_FILE_CONTROLE, array(TAM_SEGMENTO_CONTROLE, 0, 0)); /* * Cria segmento de memoria compartilhada. * Dac -> Dados das filas de atendimento. */ $shmKeyDac = sCreateMemory(SHM_IPC_FILE_DAC, array(0, NUM_MAX_DACS_ON, TAM_SEGMENTO_DAC)); /* * Cria segmento de memoria compartilhada. * Agente -> Informaçoes sobre os PAs conectados. */ $shmKeyAgt = sCreateMemory(SHM_IPC_FILE_AGENTE, array(0, NUM_MAX_AGENTES_ON, TAM_SEGMENTO_AGENTE)); while (true) { try { /* * Estabelece uma conexão com o banco de dados. */ if (!$conn) { $conn = sGetConnection(); } /* * Basicamente copia os dados da tabela supervisor agentes, e informações d * as filas para memoria */ $gOlDac = SetDadosDac($conn, $shmKeyDac, $gOlDac); /* * Basicamente copia os dados da tabela supervisor agentes, e informações d * as filas para memoria */ $gOldAgt = SetDadosAgente($conn, $shmKeyAgt, $gOldAgt); /* * Encerra a conexao com banco de dados. */ // pg_close($conn); $conn = null; } catch (Exception $ex) { /* * Garante que a conexao ao banco seja reiniciada. */ //pg_close($conn); $conn = false; /** * Registra a mensagem para o monitor. */ SeTinfoControle(TIPO_DADOS_MSG, $gUltMsg, true); sGravaLog($ex->getMessage()); } /* * Verifica se o processo deve ser encerrado */ if (!$notDaemon && sig_status()) break; /* * Tempo do ciclo de atualizações. */ usleep(TEMPO_CICLO); /* * O numero de cliclose é zerado para cada consulta * das chamadas abandonadas sem retorno. */ $numCiclos++; } /* * Fecha os blocos de memória. */ ShmClose($shmKeyCtrl); ShmClose($shmKeyDac); ShmClose($shmKeyAgt); sGravaLog(sprintf("Server Stop: %s [ok]\n", date("Y-m-d H:i:s"))); } catch (Exception $ex) { sGravaLog($ex->getMessage()); } function sGravaLog($log) { global $gUltMsg, $patLog, $shmKeyCtrl; /* * Controle para evitar que o log cresça rapidamente, * levando em conta que o cliclo de atualizações é muito * rápido, poderia gerar uma série de gravções desnecessários * por exemplo perda de conexao. */ if ($log != $gUltMsg) { $gUltMsg = $log; /* * Registra no arquivo de log do sistema. */ WriteLog(trim($log) . "\n", $patLog); } } function GetDaemon($notDaemon) { /* * Se o script não for chamado com daemon sai sem executar nada. */ if ($notDaemon) { return 0; } $pid = pcntl_fork(); if ($pid) { exit(0); //success } /* PIDFile SYSTEMD * SYSTEMD irá monitorar esse pid para verificar se ainda ativo */ $PIDFile = fopen("/var/lock/subsys/supervisor.pid", "w+"); $pid = getmypid(); if ($pid == false) { exit(1); } fwrite($PIDFile, $pid); fclose($PIDFile); // posix_setsid(); } function GetSupervisorHelp() { global $argc, $argv; $arg = isset($argv[1]) ? $argv[1] : ''; if ($argc && ((stripos($arg, '--h') !== false) || (stripos($arg, '-h') !== false) || (stripos($arg, '/h') !== false))) { return displayUsage(); } } function displayUsage() { echo "-------------------------------------------------------------------------------------------------------\n"; echo "- Servico de sincronizacao de dados para o supervisor! -\n"; echo "-------------------------------------------------------------------------------------------------------\n"; echo "- Para rodar como um processo normal passe \"N\" como primeiro argumento:\"./ssupervisor.php N\"! -\n"; echo "- Para rodar como Daemon nao passe nenhum argumemento argumento:\"./ssupervisor.php \"! -\n"; echo "-------------------------------------------------------------------------------------------------------\n"; echo "\n"; exit(0); } //end displayUsage() function sGetConnection() { /* * Se precisar de uma conexão diferente da padrão, espcifique sua propria connection string. * $connStr = sprintf("host='%s' port='%s' dbname='%s' user='%s' password='%s'", '127.0.0.1', '5432', 'pbx', 'contacte', 'ctepgSQL'); * $connStr = sprintf("host='%s' port='%s' dbname='%s' user='%s' password='%s'", '192.168.115.64', '5432', 'pbx', 'contacte', 'ctepgSQL'); */ $connStr = ''; $connStr = !$connStr ? GetDefStrDb() : $connStr; $conn = pg_connect($connStr); if (!$conn) { GeraExcept("Não foi possível estabelecer uma conexão com o banco de dados!"); } return $conn; } function sSetTransaction($conn, $isolation = 'READ UNCOMMITTED') { /* * Muda o isolamento da transação. */ return true; $query = "SET TRANSACTION ISOLATION LEVEL $isolation"; $result = pg_query($conn, $query); if (!$result) { GeraExcept("Não foi possível definir o isolamento da transação!"); } } function sBeginTransaction($conn) { global $inTransaction; /* * Define o isolamento padrão para as transações. */ sSetTransaction($conn); /* * Inicia a Transacao */ $result = pg_query($conn, 'begin'); if (!$result) { GeraExcept("Não foi possível iniciar uma transação!"); } $inTransaction = 1; } function sCommitTransaction($conn) { global $inTransaction; /* * Fianaliza a Transacao corrente. */ $result = pg_query($conn, 'commit'); if (!$result) { GeraExcept("Não foi possível finalizar a transação!"); } $inTransaction = 0; } function sRollbackTransaction($conn) { global $inTransaction; /* * Cancela a transasação corrente. */ if ($inTransaction) { pg_query($conn, 'rollback'); } } function SetDadosDac($conn, $shmKeyDac, $oldDac = array()) { try { /* * Inicia uma transação com o banco de dados. */ sBeginTransaction($conn); /* * Pesquisa as ligacoes abandonadas sem retorno. */ $abdsr = GetAbdsr($conn); $arDadosDac = []; $query = GetQueryDac(); $result = pg_query($conn, $query); if (!$result) { GeraExcept("Não foi possível consultar os dados do supervisor!"); } /* * Finaliza a transação. */ sCommitTransaction($conn); while ($dados = pg_fetch_array($result, null, PGSQL_ASSOC)) { $dac = $dados['dac']; /* * Pega as chamadas abandonada para fila que não tiveram retorno no dac. */ if (array_key_exists($dac, $abdsr)) { $dados['abdsr'] = $abdsr[$dac]; } else { $dados['abdsr'] = 0; } /* * Armazena os dados por dac. */ $arDadosDac[$dac] = $dados; } /* * Grava dados na memoria. */ ShmClear($shmKeyDac, 0, Malloc(array(0, NUM_MAX_DACS_ON, TAM_SEGMENTO_DAC))); $sizeDac = ShmWriteVar($shmKeyDac, $arDadosDac, 0); SeTinfoControle(TIPO_DADOS_DAC, $sizeDac); if (!$sizeDac) { GeraExcept("Não foi possível gravar os dados do supervisor!"); } return $arDadosDac; } catch (Exception $ex) { /* * Cancela a transação no banco de dados. */ sRollbackTransaction($conn); /* * Regera a excessao para o controle da aplidação. */ GeraExcept($ex->getMessage()); } } function GetDataSize($tipoDados) { global $arDadosControle; return $arDadosControle[$tipoDados]; } function GetAbdsr($conn) { global $gOldAbdsr, $numCiclos; /* * Faz a consulta a abandonadas sem retorno * a cada n ciclos(CICLOS_ABSR) da consulta * a informações para dac e agente. */ if (($numCiclos < CICLOS_ABSR) && (count($gOldAbdsr))) { return $gOldAbdsr; } $numCiclos = 0; $diasAbandon = GetDiasAbandonada($conn); $abdsr = array(); $query = "SELECT b.fila, count(DISTINCT a.abdsr_uniqueid) AS qtde_fila FROM pbx_abandonadas_semretorno a INNER JOIN ast_eventos_dacs b ON b.uid2 = a.abdsr_uniqueid AND b.fila = a.abdsr_fila AND b.evento = 'ABANDON' INNER JOIN ast_bilhetes c ON c.uniqueid = b.uid2 WHERE a.abdsr_data_hora_retorno IS NULL AND a.abdsr_data >= (now()::date - $diasAbandon) GROUP BY b.fila ORDER BY 1"; $result = pg_query($conn, $query); if (!$result) { return array(); } while ($dados = pg_fetch_array($result, null, PGSQL_ASSOC)) { $fila = trim($dados['fila']); $abdsr[$fila] = $dados['qtde_fila']; } $gOldAbdsr = $abdsr; return $abdsr; } function SetDadosAgente($conn, $shmKeyAgt, $oldAgt = array()) { global $gOlDac; try { /* * Esta variavel devera conter informações para atualizar o agente. */ $dadosMonitor = array( "dac" => "", "qtde_fila" => 0, "duracao" => '00:00:00', "fone" => '-', "abandonadas" => '0', "tme" => '0', "tma" => '0', "atendidas_pa" => '0', "num_protocolo" => '-', "ramal_monitor" => '', "dac_logado" => '-', "status_agente" => 'OFF', "tempo_logado" => '-', "uniqueid2" => 0, "tempo_atualiza" => 0, "pausa_motivo_rt" => '-', "pausa_motivo_ausente" => 0, "uniqueid" => 0, 'matricula' => '-', "disponivel_atendimento" => 1, "uf_origem" => '', "mun_origem" => '', "mun_id" => '0', "prefixo_fone" => '', "disponivelFila" => '1', "originadas_pa" => '0', "agente_anota_key" => "", "txt_cliente" => "", "chamada_classificado" => '2', "chamada_classificado_txt" => '...', "chamada_classificado_exige" => '0', "prm_obs_pausaprod" => '0', "exibePesquisa" => '0', 'canal_transfer' => '', "abandonadasRet" => '0', "tipo_ligacao" => '', "cont_identificador" => "", "status_discador" => 0, 'media' => 0, 'pa_fixo' => 0 ); $arDadosAgente = array(); /* * Inicia a transacao no banco de dados. */ sBeginTransaction($conn); /* * Informações dos agentes obtidos da tabela pbx_supervisor_agentes. * "tempo_logado";"fone";"status_agente";"duracao";"num_protocolo";"ramal_monitor";"uniqueid2";"tempo_atualiza";"pausa_motivo_rt";"uniqueid";"disponivel_atendimento";"chamada_classificado";"canal_transfer" */ $query = GetQueryAgenteRt(); $result = pg_query($conn, $query); if (!$result) { GeraExcept("Não foi possível consultar os dados do agente!"); } /* * Finaliza a transação. */ sCommitTransaction($conn); while ($dados = pg_fetch_array($result, null, PGSQL_ASSOC)) { $agente = $dados["matricula"]; $arDadosMonitor = $dadosMonitor; foreach ($dados as $key => $value) { $arDadosMonitor[$key] = $value; } $chamadaAgt = $dados["originadas_pa"] + $dados["atendidas_pa"]; $arDadosMonitor['tma'] = SecondToStrTime($chamadaAgt ? round(($dados["tempo_atendimento"] / $chamadaAgt), 0) : 0); $arDadosAgente[$agente] = $arDadosMonitor; } /* * Informações sobre a fila de atendimento que o agente esta logado. * campos constantes em $gOlDac: sel, dac, originadas, atendidas, abandonadas, espera, tempo_espera, tempo_nivel_servico, tipo, transbordando, * transbordada, nao_classificado, id_dac, num_agente, ord */ $arInfoDac = array("atendidas" => "atendidas_pa", "originadas" => "originadas_pa", "tme" => "tme", "tma" => "tma", "abdsr" => "abandonadasRet", "abandonadas" => "abandonadas", "espera" => "qtde_fila"); $arInfoDac = array("tme" => "tme", "abdsr" => "abandonadasRet", "abandonadas" => "abandonadas", "espera" => "qtde_fila"); foreach ($arDadosAgente as $key => $infoAgt) { $dac = $infoAgt["dac"]; if (!empty($gOlDac[$dac])) { $arDac = $gOlDac[$dac]; foreach ($arInfoDac as $keyParam => $valParam) { $infoAgt[$valParam] = $arDac[$keyParam]; } $arDadosAgente[$key] = $infoAgt; } } /* * Grava os dados na memoria */ ShmClear($shmKeyAgt, 0, Malloc(array(0, NUM_MAX_AGENTES_ON, TAM_SEGMENTO_AGENTE))); $sizeAgt = ShmWriteVar($shmKeyAgt, $arDadosAgente, 0); SeTinfoControle(TIPO_DADOS_AGENTE, $sizeAgt); if (!$sizeAgt) { GeraExcept("Não foi possível gravar os dados dos agentes!"); } return $arDadosAgente; } catch (Exception $ex) { /* * Se ocorrerem erros no banco de dados cancela a transação. */ sRollbackTransaction($conn); /* * Devolve o controle de erros para a aplicação. */ GeraExcept($ex->getMessage()); } } function GetQueryAgenteRt() { return "SELECT a.dac, a.ramal AS ramal_monitor, a.matricula, a.nome, a.monitorar AS statusmonitorar, a.intercalar AS statusintercalar, ( (EXTRACT(EPOCH FROM (now() - a.duracao)) / 60)) AS status_time, a.disponivel_atendimento, chamada_classificado, (LOCALTIMESTAMP(0) - a.tempo_login) AS tempo_logado, a.modo_atendimento, a.origem_destino AS fone, trim(status) AS status_agente, CASE WHEN((a.status = 'PAUSA') AND (coalesce(a.motivo_pausa, '') <> ''))THEN a.status || '-' || upper(a.motivo_pausa) ELSE a.status END AS status, (LOCALTIMESTAMP(0) - a.duracao) AS duracao, protocolo AS num_protocolo, uniqueid2, extract(epoch FROM (NOW() - logado))::int AS tempo_atualiza, trim(motivo_pausa) AS pausa_motivo_rt, trim(uniqueid) AS uniqueid, disponivel_atendimento, chamada_classificado, coalesce(canal_transfer, '') AS canal_transfer, org_id, tipo_ligacao, cont_identificador, status_discador, (SELECT COUNT(*) FROM ast_bilhetes x, ast_eventos_dacs y WHERE y.uid2 = x.uniqueid AND x.data_bilhete IN(a.tempo_login::date, NOW()::date) AND y.fila = a.dac AND y.agente = ('Agent/' || a.matricula) AND y.evento IN('COMPLETAAGENT','COMPLETACALLER','TRANSFERORIG','BUSYS','NOANSWERS') AND x.lastapp <> 'Transferred Call' ) AS originadas_pa, (SELECT COUNT(*) FROM ast_bilhetes x, ast_eventos_dacs y, ast_bilhetes_complemento z WHERE y.uid2 = x.uniqueid AND x.uniqueid = z.uniqueid2 AND z.direcao = 'fila-ramal' AND x.data_bilhete IN(a.tempo_login::date, NOW()::date) AND y.fila = a.dac AND y.agente = ('Agent/' || a.matricula) AND y.evento IN('COMPLETEAGENT','COMPLETECALLER', 'TRANSFER','COMPLETEAGENTRAMAL','COMPLETECALLERRAMAL') AND x.lastapp <> 'Transferred Call' ) AS atendidas_pa, (SELECT SUM(CASE WHEN ((y.evento = 'TRANSFER') OR (y.evento = 'TRANSFERORIG')) THEN strtoint(y.param4) ELSE strtoint(y.param2) END) FROM ast_bilhetes x, ast_eventos_dacs y WHERE y.uid2 = x.uniqueid AND x.data_bilhete IN(a.tempo_login::date, NOW()::date) AND y.fila = a.dac AND y.agente = ('Agent/' || a.matricula) AND y.evento IN('COMPLETEAGENT','COMPLETECALLER', 'TRANSFER','COMPLETEAGENTRAMAL','COMPLETECALLERRAMAL', 'COMPLETAAGENT','COMPLETACALLER','TRANSFERORIG') AND x.lastapp <> 'Transferred Call') AS tempo_atendimento, (SELECT coalesce(pa_fixo, 0) FROM pbx_usuarios WHERE matricula = a.matricula) AS pa_fixo FROM pbx_supervisor_agentes a WHERE 1=1 ORDER BY a.dac, a.nome"; } function SeTinfoControle($tipoDados, $dados, $silent = false) { global $shmKeyCtrl, $arDadosControle, $gNumErros, $gArMsg, $idMsg; if ($tipoDados != TIPO_DADOS_MSG) { $arDadosControle[$tipoDados] = $dados; $arDadosControle["ultAtulizacao"] = time(); } else { $arDadosControle["numErros"] = ++$gNumErros; $arDadosControle["ultMsg"] = $gArMsg[$idMsg++] = substr($dados, 0, 1024); $arDadosControle["ultRegMsg"] = date("Y-m-d H:i:s"); } $arDadosControle["dataHora"] = date("Y-m-d H:i:s"); /* * armazena até 100 mensagens. */ if ($idMsg > 99) { $idMsg = 0; } /* * Grava os dados na memoria. */ ShmClear($shmKeyCtrl, 0, Malloc(array(TAM_SEGMENTO_CONTROLE, 0, 0))); if (!ShmWriteVar($shmKeyCtrl, $arDadosControle, 0)) { if (!$silent) { GeraExcept("Não foi possível gravar os dados do controle!"); } } } function GetQueryDac() { return "SELECT DISTINCT coalesce(sel, 0) AS sel, e.dac, coalesce(originadas_pa,0) AS originadas, coalesce(a.atendidas, 0) AS atendidas, coalesce(a.abandonadas::int, 0) AS abandonadas, coalesce(e.espera::int, 0) AS espera, ( coalesce(e.tempo_espera::int, 0) * INTERVAL '1 SECOND') AS tempo_espera, coalesce(e.tempo_espera::int, 0) AS tempo_espera_int, ( round(coalesce(a.inb,0),0)::text || '%') AS tempo_nivel_servico, 'D' AS tipo, transbordando, transbordada, tme, tma, nao_classificado, id_dac, (SELECT count(*) FROM pbx_supervisor_agentes WHERE dac = e.dac) AS num_agente, 1 AS ord, org_id FROM pbx_supervisor_dacs e LEFT JOIN ( SELECT 0 as sel, DAC, ID_DAC, DATA, ABANDONADAS ,ATENDIDAS_PA AS ATENDIDAS ,ORIGINADAS_PA ,ESPERA ,round( CASE WHEN(ESPERA = 0)THEN 0 ELSE (TEMPO_ESPERA / ESPERA) END ) * INTERVAL '1 SECOND' AS TME ,round( CASE WHEN(ATENDIDAS_PA = 0)THEN 0 ELSE (TEMPO_ATENDIMENTO / (ATENDIDAS_PA + ORIGINADAS_PA))END) * INTERVAL '1 SECOND' AS TMA ,round(CASE WHEN(ABANDONADAS = 0)THEN 0 ELSE (TEMPO_ABANDONO / ABANDONADAS) END) * INTERVAL '1 SECOND' AS TMAB ,(CASE WHEN((ATENDIDAS_PA::FLOAT + ABANDONADAS::FLOAT) = 0)THEN 0 ELSE ATENDIDAS_30::FLOAT / (ATENDIDAS_PA::FLOAT + ABANDONADAS::FLOAT) END * 100)::numeric(5,2) as INB ,(CASE WHEN(OFERECIDAS::FLOAT = 0)THEN 0 ELSE (ABANDONADAS::FLOAT / OFERECIDAS::FLOAT) END * 100)::numeric(5,2) as IAB ,TEMPO_ESPERA ,TEMPO_ATENDIMENTO ,TEMPO_ABANDONO ,TRANSBORDANDO ,TRANSBORDADA ,NAO_CLASSIFICADO FROM ( SELECT DATA, DAC, ID_DAC, org_id ,SUM (CASE WHEN EVENTO = 'ENTERQUEUE' THEN 1 ELSE 0 END) AS OFERECIDAS ,SUM (CASE WHEN EVENTO = 'ENTERQUEUE' THEN 1 ELSE 0 END) AS ATENDIDAS_URA ,SUM (CASE WHEN EVENTO = 'ABANDON' THEN 1 ELSE 0 END) AS ABANDONADAS ,SUM (CASE WHEN EVENTO IN ('COMPLETEAGENT','COMPLETECALLER', 'TRANSFER','COMPLETEAGENTRAMAL','COMPLETECALLERRAMAL') THEN 1 ELSE 0 END) AS ATENDIDAS_PA ,SUM (CASE WHEN EVENTO IN ('COMPLETAAGENT','COMPLETACALLER','TRANSFERORIG','BUSYS','NOANSWERS') THEN 1 ELSE 0 END) AS ORIGINADAS_PA ,SUM (CASE WHEN EVENTO IN ('COMPLETEAGENT','COMPLETECALLER', 'TRANSFER','COMPLETEAGENTRAMAL','COMPLETECALLERRAMAL') AND strtoint(param1) <= (SELECT a.tempo_nivel_servico FROM pbx_supervisor_dacs a WHERE a.dac = fila)::FLOAT THEN 1 ELSE 0 END) AS ATENDIDAS_30 ,SUM (CASE WHEN EVENTO IN ('TRANSFER') THEN 1 ELSE 0 END) AS TRANSFERIDAS ,SUM (CASE WHEN EVENTO IN ('CONNECT') AND strtoint(param1) > '3' THEN 1 ELSE 0 END) AS ESPERA ,SUM (CASE WHEN (EVENTO IN ('CONNECT') AND strtoint(param1) > '3') THEN strtoint(param1) ELSE 0 END) AS TEMPO_ESPERA ,SUM (CASE WHEN EVENTO IN ('COMPLETEAGENT','COMPLETECALLER','TRANSFER','COMPLETEAGENTRAMAL','COMPLETECALLERRAMAL') AND strtoint((case when(param2 = '')then '0' else param2 end)) > '1' THEN strtoint((case when(param2 = '')then '0' else param2 end)) ELSE 0 END) AS TEMPO_ATENDIMENTO ,SUM (CASE WHEN EVENTO IN ('ABANDON') THEN strtoint(param3) ELSE 0 END) AS TEMPO_ABANDONO ,SUM (CASE WHEN EVENTO IN('TRANSBORDANDO') THEN 1 ELSE 0 END) AS TRANSBORDANDO ,SUM (transbordada) AS TRANSBORDADA ,SUM (CASE WHEN EVENTO IN ('COMPLETEAGENT','COMPLETECALLER', 'TRANSFER','COMPLETEAGENTRAMAL','COMPLETECALLERRAMAL') THEN nao_classificado ELSE 0 END) AS nao_classificado FROM ( SELECT a.data_bilhete as data, b.fila as dac, d.id as id_dac, b.fila,b.evento,b.param1,b.param2,b.param3,b.param4, case when(evento = 'TRANSBORDADO')then 1 else 0 end as transbordada, case when( exists( select '' from pbx_classifica_reg WHERE id_bilhetes = a.uniqueid) )then 0 else 1 end as nao_classificado, d.org_id FROM (select data_bilhete, uniqueid from ast_bilhetes where data_bilhete = now()::date and lastapp <> 'Transferred Call') a INNER JOIN ast_eventos_dacs b on a.uniqueid = b.uid2 INNER JOIN pbx_queues_grupos d on d.nome = b.fila and d.status = 'A' WHERE b.evento in ('ABANDON','COMPLETEAGENT','COMPLETECALLER', 'CONNECT','ENTERQUEUE','TRANSFER', 'COMPLETAAGENT','COMPLETACALLER', 'TRANSFERORIG', 'TRANSBORDANDO', 'TRANSBORDADO','COMPLETEAGENTRAMAL','COMPLETECALLERRAMAL','BUSYS','NOANSWERS') ) AS DADOS GROUP BY DATA, DAC, ID_DAC, org_id ) AS DADOS ORDER BY 1 ) a ON e.dac = a.dac ORDER BY 2"; } function sig_handler($signo) { global $statusSignal; $statusSignal = 1; } function sig_status() { global $statusSignal; pcntl_signal_dispatch(); return $statusSignal; } ?>