A quem interessar possa...
Aqui na Prefeitura de São José dos Campos conseguimos integrar a botoeira http://paineleletronico.net/opiniao/ com o NovoSGA versão 1.5.1, coletando a opinião e associando corretamente à senha sendo atendida no guichê.
O desenvolvedor da botoeira (Ericson) é super atencioso e acessível, e o equipamento funcionou corretamente.
Desta forma, os órgãos públicos que usam o NovoSGA podem atender ao artigo 23 da Lei Federal 13460/2017 de Qualidade nos serviços da administração pública:
"Os órgãos e entidades públicos abrangidos por esta Lei deverão avaliar os serviços prestados, nos seguintes aspectos:
I - satisfação do usuário com o serviço prestado; [...].
§ 1º A avaliação será realizada por pesquisa de satisfação feita, no mínimo, a cada um ano, ou por qualquer outro meio que garanta significância estatística aos resultados."
http://www.planalto.gov.br/ccivil_03/_ato2015-2018/2017/lei/l13460.htm
O atendente deve solicitar que a pessoa faça a avaliação ANTES de encerrar o atendimento no sistema NovoSGA.
Se a pessoa concordar em avaliar, aguardar aparecer na tela mensagem da botoeira confirmando a gravação e só então encerrar o atendimento.
Se o atendimento for encerrado antes da avaliação, a opinião será gravada no banco de dados, mas não será associada à senha correta.
...... SEGUE O PASSO A PASSO ......
1) Criada tabela avaliacao_botoeira
2) Criado arquivo coletaropiniaobotoeira.php gravado em SGA/PUBLIC
3) Criada view_atendimentos_un_protocolo para uso no QLikview (BI com relatórios detalhados).
4) Criados usuários no banco de dados
botoeira - permissão de select na tabela atendimentos e de insert na tabela avaliacao_botoeira (usado no PHP)
protocolo - permissão de select na view_atendimentos_un_protocolo (usado no BI)
5) Instalado o programa da botoeira e conectada uma botoeira na porta USB do micro
6) Na configuração da botoeira, no campo URL, foi colocada a chamada ao PHP com a passagem dos dados coletados pela botoeira. Adaptar a URL para os dados do seu ambiente, altere o IPdoservidor (coloque o mesmo do NovoSGA 1.5.1 do seu ambiente), unidade e guichê.
http://IPdoservidor/sga/public/coletaropiniaobotoeira.php?dia=<dia>&mes=<mes>&ano=<ano>&hora=<hora>&minuto=<minuto>&segundo=<segundo>&operador=<operador>&opiniao=<opiniao>&servidor=IPdoservidor&unidade=1&guiche=1
7) Depois de tudo configurado, se ainda não tem a botoeira e quiser testar se o PHP e o banco de dados estão OK, em um browser acesse o link:
http://IPdoservidor/sga/public/coletaropiniaobotoeira.php?dia=1&mes=1&ano=1&hora=1&minuto=1&segundo=1&operador=1&opiniao=1&servidor=IPdoservidor&unidade=1&guiche=100
Se for apresentado o texto abaixo o NovoSGA e o banco de dados estão configurados corretamente.
SELECT a.id from atendimentos a where a.unidade_id=1 and a.num_local=100 and a.dt_fim is null
Senhas localizadas: 0
ID Senha: 0
insert into avaliacao_botoeira values ( null, '1-1-1 1:1:1','1', '1', 1, 100, 0, now() )
Atenção: sempre que este teste é feito, é gravado um registro na tabela avaliacao_botoeira
com data igual a '0001-01-01 01:01:01', unidade 1 e guichê = 100. Estes registros não
interferem nas avaliações das senhas reais e podem ser apagados.
-- criação da tabela para registrar as avaliações
-- um registro é criado pelo coletaropiniaobotoeira.php sempre que um botão da botoeira é acionado dentro do intervalo de tempo válido para a coleta
-- o registro é gravado mesmo que não seja localizada a senha correspondente
-- registros sem nº de senha indicam que:
-- atendente fechou o atendimento antes da pessoa fazer a avaliação OU
-- a URL na configuração da botoeira daquele micro está com Unidade ou Guichê errado
CREATE TABLE avaliacao_botoeira
(
id
BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT 'Id da avaliação - sequencial',
data_avaliacao
DATETIME NOT NULL COMMENT 'Data e hora da avaliação (enviado pela botoeira)',
usuario_avaliado
VARCHAR(30) NOT NULL COMMENT 'Usuario de rede (enviado pela botoeira)',
resposta
VARCHAR(10) NOT NULL COMMENT 'Avaliacao (enviado pela botoeira)',
unidade_id
INT(11) NOT NULL COMMENT 'Código da unidade no SGA (fixo na URL da configuração da botoeira)',
num_local
SMALLINT(6) NOT NULL COMMENT 'Número do guichê (fixo na URL da configuração da botoeira)',
atendimento_id
BIGINT(20) NULL DEFAULT NULL COMMENT 'ID da senha avaliada, se = 0 atendente encerrou antes
da avaliação ou botoeira foi acionada sem atendimento.',
data_gravacao
DATETIME NOT NULL COMMENT 'Data e hora da gravação no banco de dados, se for diferente da
data_avaliacao indica que há tráfego na rede',
PRIMARY KEY (id
)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
-- criar usuário botoeira para acessar a tabela atendimentos e gravar dados na tabela avaliacao_botoeira
CREATE USER 'botoeira'@'%' IDENTIFIED BY 'SENHA';
-- direito de insert na tabela avaliacao_botoeira e de select na tabela atendimentos
GRANT insert ON sga.avaliacao_botoeira TO botoeira;
GRANT select ON sga.atendimentos TO botoeira;
FLUSH PRIVILEGES;
SHOW GRANTS FOR botoeira;
-- Código do arquivo coletaropiniaobotoeira.php - gravado na pasta /SGA/PUBLIC
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
// conectar com banco de dados - usuário com acesso apenas às tabelas atendimentos e avaliacao_botoeira
$servidor = $GET['servidor'];
$banco = mysqli_connect($servidor, "botoeira", "SENHA", "sga");
if (!$banco) {
echo " Erro ao conectar ao MySQL. servidor = $servidor" . PHP_EOL;
echo " Número do Erro: " . mysqli_connect_errno() . PHP_EOL;
echo " Erro: " . mysqli_connect_error() . PHP_EOL;
exit;
}
// conectou corretamente com o banco de dados sga
// colocar parametros da URL em variáveis
$dia = $GET['dia'];
$mes = $GET['mes'];
$ano = $GET['ano'];
$hora = $GET['hora'];
$minuto = $GET['minuto'];
$segundo = $GET['segundo'];
$operador = $GET['operador'];
$opiniao = $GET['opiniao'];
$unidade = $GET['unidade'];
$guiche = $_GET['guiche'];
// montar SQL que procura o id da senha daquela unidade e guiche, na tabela atendimentos, com data fim vazia
$query_procura = "SELECT a.id from atendimentos a where a.unidade_id=$unidade and a.num_local=$guiche ";
$query_procura.= "and a.dt_fim is null ";
// executar a query e localizar o ID do atendimento para a unidade e guichê avaliados
$resposta = mysqli_query($banco,$query_procura);
$registro = mysqli_fetch_array($resposta);
$senhas_localizadas = mysqli_num_rows($resposta);
$id_senha = 0;
if ($senhas_localizadas > 0) { $id_senha = $registro['id']; }
echo " $query_procura ";
echo "<br> Senhas localizadas: " . $senhas_localizadas;
echo "<br> ID Senha: $id_senha <br>";
// montar SQL para incluir um registro na tabela avaliacao_botoeira
// campos $ano $mes $dia $hora $minuto $segundo $operador $opiniao $unidade $guiche foram recebidos na URL
// campo $id_senha é a identificação da senha sendo avaliada
// $id_senha é igual a zero quando não foi localizada senha em atendimento,
// isso ocorre se botoeira é acionada quando não tem nenhum atendimento sendo feito, por exemplo:
// - ao limpar a botoeira
// - atendente encerra o atendimento antes do cliente gravar a opinião
// se na configuração da botoeira os parâmetros 'Próxima coleta' e 'Temporização da leitura' não forem
// corretamente configurados, e o cliente apertar mais de um botão, pode acontecer de gravar mais de uma
// avaliação para a mesma senha
$query_grava = "insert into avaliacao_botoeira values ( null, ";
$query_grava.= "'$ano-$mes-$dia $hora:$minuto:$segundo',";
$query_grava.= "'$operador', '$opiniao', $unidade, $guiche," ;
$query_grava.= " $id_senha, now() )";
// incluir o registro no banco de dados
$resposta=mysqli_query($banco,$query_grava);
echo " <br> $query_grava";
mysqli_close($banco);
?>
-- Criar view para mostrar atendimentos junto com a avaliação
-- ajustar no final do código para colocar a unidade desejada (aqui na nossa instalação unidade = 1) e para a quantidade de dias que a view deve coletar (aqui coloquei os últimos 35 dias)
-- Se uma senha não teve avaliação os 3 últimos campos = NULL
-- Se uma senha foi avaliada mais de uma vez, são apresentadas todas as avaliações
CREATE VIEW sga
.view_atendimentos_un_protocolo
as
select a
.unidade_id
AS CodUnidade
, un
.nome
AS Unidade
,
a
.id
AS idSenha
, a
.atendimento_id
AS idAnterior
,
a
.sigla_senha
AS Letra
, a
.num_senha
AS NumSenha
,
p
.nome
AS Prioridade
, a
.num_local
AS Guiche
,
(case weekday(date_format(a
.dt_cheg
,'%Y/%m/%d'))
when 0 then '2a'
when 1 then '3a'
when 2 then '4a'
when 3 then '5a'
when 4 then '6a'
when 5 then 'Sab'
when 6 then 'Dom' end) AS Dia
,
a
.dt_cheg
AS Chegada
,
a
.dt_cha
AS Chamada
,
a
.dt_ini
AS Inicio
,
a
.dt_fim
AS Fim
,
(case
when ((a
.status
= 6) or ((a
.status
= 1) and (timediff(now(),a
.dt_cheg
) > '24:00:00'))) then ''
when isnull(a
.dt_cha
) then timediff(now(),a
.dt_cheg
)
else timediff(a
.dt_cha
,a
.dt_cheg
) end) AS Espera
,
(case when isnull(a
.dt_ini
)
then '' else timediff(a
.dt_ini
,a
.dt_cha
) end) AS Deslocamento
,
(case when ((a
.status
= 6) or isnull(a
.dt_ini
))
then '' else timediff(a
.dt_fim
,a
.dt_ini
) end) AS Atendimento
,
(case when ((a
.status
= 6) or isnull(a
.dt_ini
))
then '' else timediff(a
.dt_fim
,a
.dt_cheg
) end) AS TempoTotal
,
a
.status
AS CodigoStatus
,
(case
when (a
.status
= 1) then 'Senha emitida/Aguardando chamar'
when (a
.status
= 2) then 'Chamado pela mesa'
when (a
.status
= 3) then 'Atendimento iniciado'
when (a
.status
= 4) then 'Atendimento encerrado'
when (a
.status
= 5) then 'Não compareceu'
when (a
.status
= 6) then 'Senha cancelada'
when (a
.status
= 7) then 'Erro triagem'
when (a
.status
= 8) then 'Atendimento encerrado e codificado'
else 'Erro' end) AS Status
,
a
.nm_cli
AS Cliente
, a
.ident_cli
AS Documento
,
s
.nome
AS Serviço Triagem
, sa
.nome
AS ServicoAtendido
,
concat(u
.nome
,' ', u
.sobrenome
) AS AtendidoPor
,
concat(ut
.nome
, ' ', ut
.sobrenome
) AS TriadoPor
,
u
.login
AS CPFatendente
, ut
.login
AS CPFtriagem
,
bo
.usuario_avaliado
AS LoginRede
,
bo
.data_avaliacao
AS DataAvaliacao
,
bo
.resposta
AS Avaliacao
from ((((((((view_historico_atendimentos
a
left join historico_atend_codif
ha
on((a
.id
= ha
.atendimento_id
)))
left join usuarios
u
on((a
.usuario_id
= u
.id
)))
left join usuarios
ut
on((a
.usuario_tri_id
= ut
.id
)))
left join prioridades
p
on((a
.prioridade_id
= p
.id
)))
left join servicos
s
on((a
.servico_id
= s
.id
)))
left join unidades
un
on((a
.unidade_id
= un
.id
)))
left join servicos
sa
on((ha
.servico_id
= sa
.id
)))
left join avaliacao_botoeira
bo
on((a
.id
= bo
.atendimento_id
)))
where ((a
.unidade_id
= 1)
and (a
.dt_cheg
>= (curdate() - interval 35 day)));