Configuração Painel
O Painel com Query Builder tem a função de ter um maior perfomace e flexibilidade na hora de exibir informações importantes.
Primeira Configuração
Exemplo de um Painel do Padrão do SMARTOS:
{
"QUERY_BUILDER": {
"main_table": {
"select": [
"FUNCIONARIO.seq_db SEQ_DB",
"FUNCIONARIO.nome NOME_FUNCIONARIO",
"FUNCIONARIO.cracha CRACHA_FUNCIONARIO",
"FUNCIONARIO.FOTO_SEQ_DB FOTO_SEQ_DB",
"IF(FUNCIONARIO.FLAG_FERIAS = 1, 'Férias',NULL) as VACATION"
],
"from": "FUNCIONARIO FUNCIONARIO",
"where": [
"FUNCIONARIO.QIG_DISPLAY = 1",
"FUNCIONARIO.TIPO_FUNCIONARIO_SEQ_DB = 2"
],
"group_result_by": "SEQ_DB",
"order_by": [["FUNCIONARIO.NOME", "ASC"]]
},
"secondary_table": {
"select": [
"1 as funcionarioApontando",
"BOLETIM.FIM_DH FIM_DH",
"BOLETIM.FUNCIONARIO_SEQ_DB",
"BOLETIM.SEQ_DB BOLETIM_SEQ_DB",
":NFS_NOW AGORA",
"(select sec_to_time(sum(time_to_sec(TIMEDIFF(if(a.FIM_DH is null,:NFS_NOW,a.FIM_DH),a.INI_DH)))) from app_apontamento a inner join app_boletim b on b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB where a.TIPO_APONTAMENTO = 1 and b.FIM_DH is null and a.SEQ_DB_DEVICE_MASTER_SEQ_DB = BOLETIM.SEQ_DB) as WORKING"
],
"from": "BOLETIM",
"left_join": [
[
"BOLETIM",
"FUNCIONARIO",
"FUNCIONARIO",
"BOLETIM.FUNCIONARIO_SEQ_DB = FUNCIONARIO.SEQ_DB"
]
],
"where": [
"BOLETIM.FIM_DH is NULL",
"FUNCIONARIO.SEQ_DB IN (:funcionario)"
],
"group_result_by": "FUNCIONARIO_SEQ_DB"
},
"additional_tables": {
"apontamento": {
"select": [
"( select if( ( ( p / total )* 100 ) is not null, ( p / total )* 100, 0 ) resultado from ( select sum( IMPRODUTIVA ) i, sum( PRODUTIVA ) p, ( sum( IMPRODUTIVA )+ sum( PRODUTIVA ) ) total from ( select ( select sum( ap.INI_FIM_DIFF_SEC ) from app_apontamento ap where ap.SEQ_DB = a.SEQ_DB and ap.TIPO_APONTAMENTO = 2 and ap.FUNCIONARIO_SEQ_DB = ap.AUXILIAR_SEQ_DB ) IMPRODUTIVA, ( select sum( ap.INI_FIM_DIFF_SEC ) from app_apontamento ap where ap.SEQ_DB = a.SEQ_DB and ap.TIPO_APONTAMENTO = 1 and ap.FUNCIONARIO_SEQ_DB = ap.AUXILIAR_SEQ_DB ) PRODUTIVA from app_apontamento a inner join app_boletim b on b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB where b.FIM_DH is null AND a.EMPRESA = :NFS_EMPRESA and a.FILIAL = :NFS_FILIAL and a.`LOCAL` = :NFS_LOCAL) as result) as retorno ) horas",
"APONTAMENTO.SEQ_DB SEQ_DB",
"APONTAMENTO.INI_DH INI_DH_APONTAMENTO",
"APONTAMENTO.CODIGO_OS CODIGO_OS",
"PARADA.DESCRICAO PARADA",
"SERVICO.DESCRICAO SERVICO",
"SERVICO.QII_COLOR QII_COLOR_SERVICO",
"PARADA.QII_COLOR QII_COLOR_PARADA",
"APONTAMENTO.SEQ_DB_DEVICE_MASTER_SEQ_DB BOLETIM_SEQ_DB"
],
"from": "APONTAMENTO APONTAMENTO",
"left_join": [
[
"APONTAMENTO",
"PARADA",
"PARADA",
"PARADA.SEQ_DB = APONTAMENTO.PARADA_SEQ_DB"
],
[
"APONTAMENTO",
"SERVICO",
"SERVICO",
"SERVICO.SEQ_DB = APONTAMENTO.SERVICO_SEQ_DB"
]
],
"where": ["PARADA.SEQ_DB IN (:parada)"],
"group_result_by": "BOLETIM_SEQ_DB"
},
"apontamento_status_os": {
"select": [
"OS.CODIGO OS",
"APONTAMENTO_STATUS_OS.SEQ_DB_DEVICE_MASTER_SEQ_DB BOLETIM_SEQ_DB"
],
"from": "APONTAMENTO_STATUS_OS APONTAMENTO_STATUS_OS",
"left_join": [
[
"APONTAMENTO_STATUS_OS",
"OS",
"OS",
"OS.SEQ_DB = APONTAMENTO_STATUS_OS.OS_SEQ_DB"
]
],
"group_result_by": "BOLETIM_SEQ_DB"
}
}
}
}
Configuração Filtro
Configuração Filtro do Painel:
Inserir no campo FILTERS da tabela nfs_qig_panels, como no modelo abaixo:
{
"funcionario": {
"type": "Table",
"options": {
"label": "Encarregado",
"required": false,
"multiple": "multiple",
"attr": {
"data-filter": "funcionario.SEQ_DB",
"data-where": "funcionario.flag_apontador = 1"
}
}
}
}
ATENÇÃO O "data-filter" é obrigatório, caso não seja inserido será exibido no console do navegador e no Log uma mensagem de erro. ex: "Falha na configuração do painel : esperado elemento 'data-filter'." {.is-warning}
OBS:
Configurações OBRIGATÓRIAS
Group by Result
O group_by_result é um item obrigatória quando for configurar um painel com NFS Query Builder, sendo responsável por realizar a ligação entre as tabelas configuradas na additional_tables com secondary_table e secondary_table com main_table e deve estar em cada um das configurações como é mostrado abaixo.
ATENÇÃO Sem configurar o group group_by_result o painel não vai funcionar corretamente!!! {.is-warning}
DICA As consultas em NFS Query Builder usadas como exemplo estão na Primeira Configuração
- main_table : O SEQ_DB da tabela que está sendo pesquisada, por exemplo, se a main table é FUNCIONARIO então o "group_by_result": "SEQ_DB". Para entender melhor use o "dump" : "result" para ver o seu retorno, exemplo:
{
"615": Array[1][
{
"SEQ_DB": "615",
"NOME_FUNCIONARIO": "ELTON BERNINI",
"CRACHA_FUNCIONARIO": "PM0034",
"FOTO_SEQ_DB": "3",
"VACATION": null,
"last_BOLETIM": "562",
"seq_db": "615"
}
]
}
Como foi possível observar veio agrupado pelo SEQ_DB do ELTON.
- secondary_table: Nessa tabela geralmente é boletim/turno de uma máquina, funcionário, entre outros e também é agrupado por essa informação com isso fazendo a conexão com painel. Por exemplo se for boletim ele tem um funcionário_seq_db que deve ser passado no select e no "group_result_by": "FUNCIONARIO_SEQ_DB", que se realizarmos o "dump " : "result" irá aparecer:
{
"615": Array[1][
{
"funcionarioApontando": "1",
"FIM_DH": null,
"FUNCIONARIO_SEQ_DB": "615",
"BOLETIM_SEQ_DB": "562",
"AGORA": "2018-06-01 14:20:32",
"WORKING": null,
"last_apontamento": "2923",
"last_apontamento_status_os": "1413"
}
]
}
- additional_tables: Último nível do painel onde encontrar-se Apontamento, Apontamento de OS e etc. A configuração group_result_by será o BOLETIM_SEQ_DB que deve estar estar no select para ser comparado depois com o da seconday_table.
Podemos observar o resultado quando feito um "dump" : "result" que o BOLETIM_SEQ_DB é 562 igual da secondary_table no json acima e logo seus apontamento está no segundo bloco:
{
"556": Array[1][
{
"horas": "0.0000",
"SEQ_DB": "2909",
"INI_DH_APONTAMENTO": "2018-02-20 16:56:34",
"CODIGO_OS": null,
"PARADA": "À disposição",
"SERVICO": null,
"QII_COLOR_SERVICO": null,
"QII_COLOR_PARADA": "#f70000",
"BOLETIM_SEQ_DB": "556",
"APONTAMENTO_INI_DH": "2018-02-20 16:56:34"
}
],
"562": Array[1][
{
"horas": "0.0000",
"SEQ_DB": "2923",
"INI_DH_APONTAMENTO": "2018-04-06 13:20:37",
"CODIGO_OS": null,
"PARADA": "À disposição",
"SERVICO": null,
"QII_COLOR_SERVICO": null,
"QII_COLOR_PARADA": "#f70000",
"BOLETIM_SEQ_DB": "562",
"APONTAMENTO_INI_DH": "2018-04-06 13:20:37"
}
],
"590": Array[1][
{
"horas": "0.0000",
"SEQ_DB": "2980",
"INI_DH_APONTAMENTO": "2018-04-06 13:09:43",
"CODIGO_OS": null,
"PARADA": null,
"SERVICO": "REVISAO DE PRE ENTREGA",
"QII_COLOR_SERVICO": null,
"QII_COLOR_PARADA": null,
"BOLETIM_SEQ_DB": "590",
"APONTAMENTO_INI_DH": "2018-04-06 13:09:43"
}
]
}
Legendas (Subtitles)
Configurar uma lengenda é um item obrigatório de certa forma porque se não o painel perde uma boa parte de seu objetivo de exisiter, então para configura-la na coluna SUBTITLES como pode ser observado no json a seguir:
{
"SUBTITLES": {
"secondary_table": {
"DEFAULT_COLOR": "#FFFF00",
"TEXT_COLOR": "#000000",
"DESCRIPTION": "DESCRICAO"
},
"additional_tables": {
"tabela": {
"DESCRICAO_LEGENDA": {
"TABLE_FIELD_COLOR": "COLUNA_COR",
"DEFAULT_COLOR": "#b71c1c"
}
},
"tabela2": {
"DESCRICAO_LEGENDA": {
"TABLE_FIELD_COLOR": "COLUNA_COR",
"DEFAULT_COLOR": "#FFA500"
}
}
}
}
}
Secondary_table
Essa tabela geralmente representa o Boletim.
- DEFAULT_COLOR: A cor padrão quando um boletim quando ainda não.
- DESCRIPTION: Uma descrição para o boletim tem a data final não nula, geralmente descrito como Boletim Aberto, Turno Aberto e etc.
Additional_table
O Additional diferente da Secondary table pode ter uma ou mais tabelas como é nos cliente, quando precisa exibir Apontamento e Apontamento de OS, ambas podem refletir seus estados no painel.
- tabela: Nome da tabela que deseja exibir uma legenda, por exemplo Apontamento;
- DESCRICAO_LEGENDA: Nome da coluna que está no Query Builder com uma descrição, por exemplo, supondo que deve mostrar o Serviço, então na Query Builder terá uma coluna chamada SERVICO, nela deve ser retornado a código e/ou descrição do serviço.
- TABLE_FIELD_COLOR: Na mesma query onde trago o SERVICO vou trazer a cor que deve ser exibida, entao vou criar mais uma coluna chamada QII_SERVICO_COR, que será um hexadecimal.
Modelo de Subtitle
{
"SUBTITLES": {
"additional_tables": {
"apontamento": {
"PARADA": {
"TABLE_FIELD_COLOR": "QII_COLOR_PARADA",
"DEFAULT_COLOR": "#b71c1c"
},
"SERVICO": {
"TABLE_FIELD_COLOR": "",
"DEFAULT_COLOR": "#1b5e20"
}
},
"apontamento_status_os": {
"OS": {
"TABLE_FIELD_COLOR": "",
"DEFAULT_COLOR": "#FFA500"
}
}
},
"secondary_table": {
"DEFAULT_COLOR": "#FFFF00",
"DESCRIPTION": "Boletim Aberto"
}
}
}
Legendas com imagem
Também é possível configurar uma imagem na legenda, mais usado nas tabelas de additional_tables. São necessários os seguintes passos:
-
Na tabela alvo, por exemplo PARADA, é necessário na nfs_core_ds_tabela_campo adicionar a coluna SUBTITLE como IMG_MOBILE.
-
No json de configuração do adicionar a chave TABLE_FIELD_IMG que será o nome da coluna que usado no Query Builder, ex.:
...
"additional_tables": {
"apontamento": {
"PARADA": {
"TABLE_FIELD_IMG": "QII_IMG_PARADA",
"TABLE_FIELD_COLOR": "QII_COLOR_PARADA",
"DEFAULT_COLOR": "#b71c1c"
}
}
...
- Agora no Query Builder não é necessário passar o campo da imagem na coluna QII_IMG_PARADA, mas sim o SEQ_DB porque no painel ela é carregada por ajax usando esse valor, assim não adicionando um base64 que é extenso na query. Também é necessário colocar uma condição porque há casos de não ter imagem e usar a cor
IF(PARADA.SUBTITLE is not null,PARADA.SEQ_DB,'') QII_IMG_PARADA
. Então se tem imagem obtem o seq_db da parada se não passa um valor vazio, assim vai pegar a cor definida. Ex. de uma configuração additional_tables parte do Query Builder:
{
"additional_tables": {
"apontamento": {
"select": [
"(SELECT (SUM(IF(a.TIPO_APONTAMENTO = 1,TIME_TO_SEC(TIMEDIFF(IF(a.FIM_DH IS NULL,:NFS_NOW, a.FIM_DH), a.INI_DH)),0)) / (SUM(TIME_TO_SEC(TIMEDIFF(IF(a.FIM_DH IS NULL,:NFS_NOW, a.FIM_DH), a.INI_DH))) - SUM(IF(p.FLAG_REFEICAO = 1, TIME_TO_SEC(TIMEDIFF(IF(a.FIM_DH IS NULL,:NFS_NOW, a.FIM_DH), a.INI_DH)),0))) *100) AS PRODUTIVIDADE FROM app_apontamento a INNER JOIN app_boletim b ON (b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB AND b.ATIVO = 1 AND b.DELETED = 0) INNER JOIN app_funcionario f ON (f.SEQ_DB = a.AUXILIAR_SEQ_DB AND f.ATIVO = 1 AND f.DELETED = 0) LEFT JOIN app_parada p ON (p.SEQ_DB = a.PARADA_SEQ_DB AND p.ATIVO = 1 AND p.DELETED = 0) WHERE b.FIM_DH IS NULL AND a.ATIVO = 1 AND a.DELETED = 0 AND a.EMPRESA = :NFS_EMPRESA AND a.FILIAL = :NFS_FILIAL AND a.`LOCAL` = :NFS_LOCAL) as horas",
"APONTAMENTO.SEQ_DB SEQ_DB",
"DATE_FORMAT(APONTAMENTO.INI_DH,'%d/%m/%Y %H:%i:%s')INI_DH_APONTAMENTO",
"APONTAMENTO.CODIGO_OS OS",
"PARADA.DESCRICAO PARADA",
"SERVICO.DESCRICAO SERVICO",
"SERVICO.QII_COLOR QII_COLOR_SERVICO",
"PARADA.QII_COLOR QII_COLOR_PARADA",
"IF(PARADA.SUBTITLE is not null,PARADA.SEQ_DB,'') QII_IMG_PARADA",
"APONTAMENTO.SEQ_DB_DEVICE_MASTER_SEQ_DB BOLETIM_SEQ_DB"
],
"from": "APONTAMENTO APONTAMENTO",
"left_join": [
[
"APONTAMENTO",
"PARADA",
"PARADA",
"PARADA.SEQ_DB = APONTAMENTO.PARADA_SEQ_DB"
],
[
"APONTAMENTO",
"SERVICO",
"SERVICO",
"SERVICO.SEQ_DB = APONTAMENTO.SERVICO_SEQ_DB"
],
[
"APONTAMENTO",
"BOLETIM",
"BOLETIM",
"APONTAMENTO.SEQ_DB_DEVICE_MASTER_SEQ_DB = BOLETIM.SEQ_DB"
],
[
"BOLETIM",
"FUNCIONARIO",
"FUNCIONARIO",
"BOLETIM.FUNCIONARIO_SEQ_DB = FUNCIONARIO.SEQ_DB"
]
],
"where": ["PARADA.SEQ_DB IN (:parada)"],
"group_result_by": "BOLETIM_SEQ_DB"
},
"apontamento_status_os": {
"select": [
"OS.CODIGO OS",
"APONTAMENTO_STATUS_OS.SEQ_DB_DEVICE_MASTER_SEQ_DB BOLETIM_SEQ_DB"
],
"from": "APONTAMENTO_STATUS_OS APONTAMENTO_STATUS_OS",
"left_join": [
[
"APONTAMENTO_STATUS_OS",
"OS",
"OS",
"OS.SEQ_DB = APONTAMENTO_STATUS_OS.OS_SEQ_DB"
]
],
"group_result_by": "BOLETIM_SEQ_DB"
}
}
}
Como podemos observar no select do apontamento é feita a verificação descrita acima.
Mensagem
Para aparecer a mensagem no nfs_qig_panels na coluna MESSAGE_TABLE deve estar configurada com a tabela de mensagem.
Localização
Para mostrar a Localização ter o tracking habilitado no entry point e MAIN_TABLE configurada.
Configuração para exibir o painel em modo Kanban
É possível definir em qual modo o painel será aberto inicialmente pela própria interface do NFS:
- Acesse Meus dados/Perfil de Usuário, note que em Opções do Ambiente será exibida a seguinte opção:
Por padrão essa opção virá desabilitada, ao mudar para sim uma alteração será enviada para o banco de dados setando na tabela nfs_acl_usuario_empresa no campo OPTIONS (objeto) um novo indice chamado "PANEL_DISPLAY_DEFAULT" com valor "S" ao mudar para não o indice é mantido mas o valor "N" será setado.
{
"theme":"orange",
"bg-img":"201",
"PANEL_DISPLAY_DEFAULT":"N" // <<<
}
Sim: Ao acessar o painel 2 (painelNew) ele será aberto no modo Kanban. Não: Ao acessar o painel 2 (painelNew) ele será aberto no modo Cards.
O painel 1 (painel old) não possui o modo Kanban.
Criar um Novo Boletim
Para habilar o botão para criar um novo boletim é necessário:
- Usar o Field Action
- Realizar a permissão a um grupo/usuário corretamente no Controle de Acesso.
- Verificar se o campo está sendo exibido no detalhes, para isso tem que chegar o display da nfs_qig_details nas colunas MAIN_TABLE_OPTIONS, SECONDARY_TABLE_OPTIONS e ADDITIONAL_TABLES.
- Verificar se o campo não está como DISABLED igual a 1 no nfs_core_ds_tabela_campo, se tiver tem que mudar para 0, porque do mesma forma que é possível no crud editar deve ser possível inserir.
Foi criado um entry point com valor 50 que é executado antes de carregar a tela, estão da para definir alguns valores como padrão. Temos os seguintes arrays:
$valores['secondaryConfig']
Tabela com os valores configurados na secondary table do detalhes, para acessar o valor MEDICAO_FIM e alterar para OBRIGATORIO = 1, os campos que existem são os mesmos da nfs_core_ds_tabela_campo.
$valores['secondaryConfig']['MEDICAO_FIM']->OBRIGATORIO = 1;
$valores['displayAdditional']
Um array com as tabelas additional, para ver o nome de cada additional utilize o código abaixo
foreach ($valores["additionals"] as $additionalName => $values) {
NfsLogger::error(" Additional [{$additionalName}]", "DETALHES");
}
dentro de cada additional tem os campos da nfs_core_ds_tabela_campo.
Exemplo código em php:
/*
Entry ponint 50
*/
/*
Variaveis importantes
Mostrar os valores
*/
NfsLogger::error(" SecondaryName: {$valores['secondaryName']} ", 'DETALHES');
NfsLogger::error(" SeqDB da MainTable: {$valores['seqDb']} ", 'DETALHES');
NfsLogger::error(" seqQii do Painel: {$valores['seqQii']} ", 'DETALHES');
NfsLogger::error(" seqPanel do Painel: {$valores['seqPanel']} ", 'DETALHES');
NfsLogger::error(" displayNameTables são as tabelas que são usadas na inserção de novos detalhes: {$valores['displayNameTables']} ", 'DETALHES');
NfsLogger::error(" displayAdditional modelo da aditional para quando for inserir um novo apontamento: {$valores['displayAdditional']} ", 'DETALHES');
NfsLogger::error(" secondaryConfig modelo da secondary: {$valores['secondaryConfig']} ", 'DETALHES');
// Exemplo para definir valores padrão quando inicia tela de detalhes
$valores['secondaryConfig']['INI_DH_TIPO']->VALOR_DISPLAY = 'Manual';
$valores['secondaryConfig']['INI_DH_TIPO']->VALOR = 'M';
$valores['secondaryConfig']['MEDICAO_INICIO']->VALOR = '10';
$valores['secondaryConfig']['MEDICAO_FIM']->OBRIGATORIO = 1;
No exemplo do código em php é salvo no log os valores de algumas variáveis e depois atualizado alguns valores como padrão.
Exemplo query entry point:
INSERT INTO nfs_homol_suzanosa_bobagro.nfs_entry_point (SEQ_DB, FILE_OR_DOMAIN, `ACTION`, XMOVA_INSTALLCODE, XMOVA_INSTALLCODE_VERSION, EMPRESA, FILIAL, `LOCAL`, TABELA, ENTRY_NUM, CODE, VERSION, BUILD, ATIVO, CODETYPE, FIELD, DESCRIPTION, INS_DH, UPD_DH) VALUES(156, 'SYSTEM', NULL, NULL, NULL, 9999, 9999, 9999, NULL, 50, '$valores[''secondaryConfig''][''INI_DH_TIPO'']->VALOR_DISPLAY = ''Manual'';
$valores[''secondaryConfig''][''INI_DH_TIPO'']->VALOR = ''M'';
$valores[''secondaryConfig''][''MEDICAO_INICIO'']->VALOR = ''10'';
$valores[''secondaryConfig''][''MEDICAO_FIM'']->OBRIGATORIO = 1;', 0, 0, 1, 'PHP', NULL, NULL, '2018-09-28 11:33:26.000', '2019-04-26 11:17:09.000');
No exemplo de query entry point está definindo alguns valores como padrão.
Outras Configurações
Em construção
Data do Último Apontamento
No Painel com Query Builder é dada a opção caso haja mais de sempre exibir a data do último apontamento feito, basta na coluna DISPLAY_FIELDS da tabela nfs core painels em uma das opções de F1 até F6 na opção FIELD o valor LAST_DATE. Exemplo:
"F3": [
{
"FIELD": "LAST_DATE",
"LABEL": "",
"TOOLTIP": ""
}
],
Ele vai funcionar apenas para todas as tabelas dentro do additional_tables.
Scroll automático
Atenção O scroll automático não está implementado quando o painel está em fullscreen pelo portlet (ícones na tela) {.is-warning}
Existe um ícone de relógio, que ao ser acionado apresenta uma tela para informação de uma escala de tempo de 1 até 90. Esta escala é o "tempo" que o scroll vai levar para deslizar a tela de uma extremidade até a outra.
- Pressione ESC para interromper a rolagem automática
Legenda no Card do QII
Para habilitar a legenda no CARD é necessáro habilitar/adicionar o seguinte parâmetro na nfs_core_par_parametros:
BORDER_QII_OLD_PANEL
Com valor igual a 1 ou true.
Essa funcionalidade usa a cor da legenda e adiciona na borda do card.