A classe Usuario foi projetada para representar os usuários que interagem com a plataforma. Ela encapsula informações e comportamentos relacionados aos indivíduos que utilizam o sistema, oferecendo recursos e funcionalidades personalizadas para atender às suas necessidades.
Usuário Terceiro (Third Party)
No NFS tem a possíbilidade de vincular um usuário a uma tabela app, onde chamamos ela de terceiro, com isso o cliente tem a possibilidade liberar um usuário externo para consultar relatórios e paineis.
Com isso nas funcionalidade que usam o Nfs Query Builder vai ter o parâmetro :NFS_THIRD_PARTY que vai conter o SEQ_DB da tabela de Terceiro
Configuração
A primeira coisa a ser realizada é ativar o parâmetros
THIRD_PARTY_ENABLED
com valor igual a 1.
Controle de Acesso - Usuário
No Controle de Acesso a o criar um novo usuário vai ter a opção Terceiro. Todas os usuário marcados com esse flag serão exibidos para serem vínculados a um terceiro.
Sempre lembre-se de vincular o usuário a uma empresa se não você não vai conseguir acessar o sistema. {.is-danger}
INSERT INTO nfs_acl_usuario_empresa
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, USUARIO_SEQ_DB, EMPRESA_SEQ_DB, INS_DH, INS_USUARIO_SEQ_DB, ATIVO, DELETED, `OPTIONS`)
VALUES(NULL, 1, 1, 1, 141, 1, '2020-05-27 12:20:32.0', 100, 1, 0, '{"theme":"default"}');
INSERT INTO nfs_acl_usuario_empresa
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, USUARIO_SEQ_DB, EMPRESA_SEQ_DB, INS_DH, INS_USUARIO_SEQ_DB, ATIVO, DELETED, `OPTIONS`)
VALUES(NULL, 1, 1, 2, 141, 1, '2020-05-27 12:20:32.0', 100, 1, 0, '{"theme":"default"}');
INSERT INTO nfs_acl_usuario_empresa
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, USUARIO_SEQ_DB, EMPRESA_SEQ_DB, INS_DH, INS_USUARIO_SEQ_DB, ATIVO, DELETED, `OPTIONS`)
VALUES(NULL, 1, 1, 3, 141, 1, '2020-05-27 12:20:32.0', 100, 1, 0, '{"theme":"default"}');
INSERT INTO nfs_acl_usuario_empresa
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, USUARIO_SEQ_DB, EMPRESA_SEQ_DB, INS_DH, INS_USUARIO_SEQ_DB, ATIVO, DELETED, `OPTIONS`)
VALUES(NULL, 1, 1, 4, 141, 1, '2020-05-27 12:20:32.0', 100, 1, 0, '{"theme":"default"}');
Controle de Acesso - Grupo
Crie um Grupo e depois vincule esse usuário a esse grupo.
Insert para cria um grupo:
INSERT INTO nfs_acl_grupo
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, NOME, RESTRICTED, INS_DH, ATIVO, DELETED, HOMEPAGE)
VALUES(NULL, 1, 1, 1, 'GRUPO TERCEIRO', 0, '2015-11-04 13:48:20.0', 1, 0, NULL);
CRUD - Tabela de Relacionamento como Usuário
Nesse caso vou adotar que o seu sistema tenha uma tabela chamada app_terceiro, vamos fazer um vínculo entre o terceiro e o usuário, exemplo:
INSERT INTO nfs_core_ds_tabela
(NOME, TABELA_REAL, DESCRICAO, UNQ, DISPLAY, TIPO, MOBILE_TABLE, MOBILE_MESSAGE, MOBILE_MESSAGE_FK, FILTRO_USER, MAX_ROWS_WO_FILTER, `OPTIONS`, ORDER_BY, INDICATORS)
VALUES('TERCEIRO_USUARIO', 'APP_TERCEIRO_USUARIO', 'Terceiro x Usuário', NULL, 'ID', 1, 0, 0, NULL, 0, 100, NULL, NULL, NULL);
INSERT INTO nfs_core_ds_tabela_campo
(TABELA_NOME, NOME, SEQ, SYS, SEND_XMOVA, GRID, GRID_MOBILE, DESCRICAO, DESCRICAO_RESUMIDA, TIPO, OBRIGATORIO, TAMANHO, TAMANHO_DECIMAL, MASCARA, INSERT_UPDATE, DISABLED, HINT, LINK, VALIDACAO, OPCOES, VALOR_DEFAULT, VALIDACAO_VIEW, FILTRO_VIEW, TOOLTIP_MESSAGE, PROPERTIES)
VALUES('TERCEIRO_USUARIO', 'TERCEIRO', 2, 0, 1, 1, 1, 'Terceiro', 'Terceiro', 'FK', NULL, NULL, NULL, NULL, 'IU', '0', NULL, 'TERCEIRO', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
INSERT INTO nfs_core_ds_tabela_campo
(TABELA_NOME, NOME, SEQ, SYS, SEND_XMOVA, GRID, GRID_MOBILE, DESCRICAO, DESCRICAO_RESUMIDA, TIPO, OBRIGATORIO, TAMANHO, TAMANHO_DECIMAL, MASCARA, INSERT_UPDATE, DISABLED, HINT, LINK, VALIDACAO, OPCOES, VALOR_DEFAULT, VALIDACAO_VIEW, FILTRO_VIEW, TOOLTIP_MESSAGE, PROPERTIES)
VALUES('TERCEIRO_USUARIO', 'USUARIO', 2, 0, 1, 1, 1, 'Usuário', 'Usuário', 'USER', NULL, NULL, NULL, NULL, 'IU', '0', NULL, 'NFS_ACL_USUARIO', NULL, NULL, NULL, NULL, NULL, NULL, NULL);
Ponto a observar:
- Ao criar o registro na nfs_core_ds_tabela_campo o tipo deve ser USER e o LINK é NFS_ACL_USUARIO.
Essa tabela NFS_ACL_USUARIO meio que cria uma copia da nfs_acl_usuario para usar algumas informações, como o SEQ_DB, nome, sobrenome, email.
O resultado vai ser:
No caso já adicionei o usuário que eu criei a um terceiro.
Ao realizar a associação e salvar, quando o usuário Dalton logar no sistema ele vai ter o SEQ_DB do terceiro na imagem no seu campo, recomendo por enquanto usar em relatório, painels entre outros componentes que usam Nfs Query Builder
Como usar
Sugiro que você dê acesso para esse grupo somente o necessário que ele vai usar, por exemplo, no caso somente dei permissão para acessar o menu relatórios, submenus de terceiros, assim como o relatório de terceiro.
Insert do grupo permissão e rota. (Sugiro que olhe no menu o seq_db os seus itens a serem dispobilizados)
INSERT INTO nfs_acl_grupo_permissao
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, MENU_SEQ_DB, TABELA_NOME, SIUD, GRUPO_SEQ_DB, CAMPOS_PERMITIDOS, INS_DH, ATIVO, DELETED)
VALUES(NULL, 1, 9999, 9999, 600, NULL, '1000', 8, '', '2017-08-15 12:45:03.0', 1, 0);
INSERT INTO nfs_acl_grupo_permissao
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, MENU_SEQ_DB, TABELA_NOME, SIUD, GRUPO_SEQ_DB, CAMPOS_PERMITIDOS, INS_DH, ATIVO, DELETED)
VALUES(NULL, 1, 9999, 9999, 601, NULL, '1000', 8, '', '2017-08-15 12:45:03.0', 1, 0);
INSERT INTO nfs_acl_grupo_permissao
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, MENU_SEQ_DB, TABELA_NOME, SIUD, GRUPO_SEQ_DB, CAMPOS_PERMITIDOS, INS_DH, ATIVO, DELETED)
VALUES(NULL, 1, 9999, 9999, 6600, NULL, '1000', 8, '', '2017-08-15 12:45:03.0', 1, 0);
INSERT INTO nfs_acl_grupo_permissao
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, MENU_SEQ_DB, TABELA_NOME, SIUD, GRUPO_SEQ_DB, CAMPOS_PERMITIDOS, INS_DH, ATIVO, DELETED)
VALUES(NULL, 1, 9999, 9999, 6601, NULL, '1000', 8, '', '2017-08-15 12:45:03.0', 1, 0);
INSERT INTO nfs_acl_grupo_permissao
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, MENU_SEQ_DB, TABELA_NOME, SIUD, GRUPO_SEQ_DB, CAMPOS_PERMITIDOS, INS_DH, ATIVO, DELETED)
VALUES(NULL, 1, 9999, 9999, 6602, NULL, '1000', 8, '', '2017-08-15 12:45:03.0', 1, 0);
INSERT INTO nfs_acl_grupo_permissao_rota
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, TIPO, ROTA, GRUPO_SEQ_DB, INS_DH, ATIVO, DELETED)
VALUES(NULL, 1, 1, 1, 'ALLOW', '/acl/*', 1, '2019-03-27 14:16:01.0', 1, 0);
INSERT INTO nfs_acl_grupo_permissao_rota
(SEQ_DB, EMPRESA, FILIAL, `LOCAL`, TIPO, ROTA, GRUPO_SEQ_DB, INS_DH, ATIVO, DELETED)
VALUES(NULL, 1, 1, 2, 'ALLOW', '/acl/*', 2, '2018-02-06 12:27:07.0', 1, 0);
Relatório - NFS_THIRD_PARTY
Para ser usado no relatório no WHERE do NFS Query Builder adicione o parâmetro :NFS_THIRD_PARTY.
Exemplo:
Relatório de Resumo do Terceiro no modelo Excel
UPDATE nfs_reports set enabled = 0 where DISPLAY_NAME ='relatorio_resumo_terceiro';
INSERT INTO nfs_reports (SEQ_DB, NAME, DISPLAY_NAME, FILTERS, QUERIES, TEMPLATE, ENABLED, EXPORT_OPTIONS) VALUES(NULL, 'relatorio_resumo_terceiro', 'Resumo dos Terceiros(.pdf)', '{
"inicio": {
"type": "Date",
"options": {
"label": "De",
"required": true
}
},
"fim": {
"type": "Date",
"options": {
"label": "Até",
"required": true
}
},
"terceiro": {
"type": "Table",
"options": {
"label": "Terceiro",
"multiple": false,
"required": false
}
}
}
', '{
"filial": {
"dump": "",
"main": true,
"select": [
"f.LOCAL",
"f.DESCRICAO",
"f.ENDERECO",
"f.CEP",
"f.ESTADO",
"f.TELEFONE",
"f.FAX",
"f.SITE",
"concat(DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%d/%m/%Y''), '' - '', DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%d/%m/%Y'')) PERIODO"
],
"from": "endereco_filial f"
},
"total": {
"dump": "",
"main": true,
"select": [
"SUM(SEC_TO_TIME(TIMESTAMPDIFF(second,a.INI_DH,a.FIM_DH))) HORAS_ATIVIDADE",
"SUM(a.PRODUCAO) PRODUCAO"
],
"from": "apontamento_mo_terceiro a",
"inner_join": [
["a", "boletim_mo", "b", "b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB"],
["a", "terceiro", "t", "t.SEQ_DB = a.TERCEIRO_SEQ_DB"],
["a", "divisao_6", "d6", "d6.SEQ_DB = a.DIVISAO_6_SEQ_DB"],
["a", "divisao_5", "d5", "d5.SEQ_DB = a.DIVISAO_5_SEQ_DB"],
["a", "divisao_4", "d4", "d4.SEQ_DB = a.DIVISAO_4_SEQ_DB"],
["a", "divisao_3", "d3", "d3.SEQ_DB = a.DIVISAO_3_SEQ_DB"],
["a", "divisao_2", "d2", "d2.SEQ_DB = a.DIVISAO_2_SEQ_DB"],
["a", "divisao_1", "d1", "d1.SEQ_DB = a.DIVISAO_1_SEQ_DB"]
],
"where": [
"DATE(a.INI_DH) >= DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"DATE(a.INI_DH) <= DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"a.TERCEIRO_SEQ_DB in (:NFS_THIRD_PARTY)",
"a.PRODUCAO IS NOT NULL"
],
"having": ["HORAS_ATIVIDADE > 0"]
},
"por_nivel": {
"dump": "",
"main": true,
"select": [
"a.DIVISAO_5_SEQ_DB",
"CONCAT(d1.CODIGO, '' - '', d1.DESCRICAO) NIVEL_1",
"CONCAT(d2.CODIGO, '' - '', d2.DESCRICAO) NIVEL_2",
"CONCAT(d3.CODIGO, '' - '', d3.DESCRICAO) NIVEL_3",
"CONCAT(d4.CODIGO, '' - '', d4.DESCRICAO) NIVEL_4",
"CONCAT(d5.CODIGO, '' - '', d5.DESCRICAO) NIVEL_5",
"SUM(SEC_TO_TIME(TIMESTAMPDIFF(second,a.INI_DH,a.FIM_DH))) HORAS_ATIVIDADE",
"SUM(a.PRODUCAO) PRODUCAO"
],
"from": "apontamento_mo_terceiro a",
"inner_join": [
["a", "boletim_mo", "b", "b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB"],
["a", "terceiro", "t", "t.SEQ_DB = a.TERCEIRO_SEQ_DB"],
["a", "divisao_6", "d6", "d6.SEQ_DB = a.DIVISAO_6_SEQ_DB"],
["a", "divisao_5", "d5", "d5.SEQ_DB = a.DIVISAO_5_SEQ_DB"],
["a", "divisao_4", "d4", "d4.SEQ_DB = a.DIVISAO_4_SEQ_DB"],
["a", "divisao_3", "d3", "d3.SEQ_DB = a.DIVISAO_3_SEQ_DB"],
["a", "divisao_2", "d2", "d2.SEQ_DB = a.DIVISAO_2_SEQ_DB"],
["a", "divisao_1", "d1", "d1.SEQ_DB = a.DIVISAO_1_SEQ_DB"]
],
"where": [
"DATE(a.INI_DH) >= DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"DATE(a.INI_DH) <= DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"a.TERCEIRO_SEQ_DB in (:NFS_THIRD_PARTY)",
"a.PRODUCAO IS NOT NULL"
],
"group_by":[
"a.DIVISAO_5_SEQ_DB"
],
"order_by":[
["d1.CODIGO","ASC"],
["d2.CODIGO","ASC"],
["d3.CODIGO","ASC"],
["d4.CODIGO","ASC"],
["d5.CODIGO","ASC"]
]
},
"por_apontamento": {
"dump": "",
"main": true,
"select": [
"a.DIVISAO_5_SEQ_DB",
"CONCAT(t.CODIGO, '' - '', t.DESCRICAO) TERCEIRO",
"CONCAT(d6.CODIGO, '' - '', d6.DESCRICAO) ATIVIDADE",
"a.QTD_FUNCIONARIO",
"a.INI_DH",
"a.FIM_DH",
"SEC_TO_TIME(TIMESTAMPDIFF(second,a.INI_DH,a.FIM_DH)) HORAS_ATIVIDADE",
"a.PRODUCAO"
],
"from": "apontamento_mo_terceiro a",
"inner_join": [
["a", "boletim_mo", "b", "b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB"],
["a", "terceiro", "t", "t.SEQ_DB = a.TERCEIRO_SEQ_DB"],
["a", "divisao_6", "d6", "d6.SEQ_DB = a.DIVISAO_6_SEQ_DB"],
["a", "divisao_5", "d5", "d5.SEQ_DB = a.DIVISAO_5_SEQ_DB"],
["a", "divisao_4", "d4", "d4.SEQ_DB = a.DIVISAO_4_SEQ_DB"],
["a", "divisao_3", "d3", "d3.SEQ_DB = a.DIVISAO_3_SEQ_DB"],
["a", "divisao_2", "d2", "d2.SEQ_DB = a.DIVISAO_2_SEQ_DB"],
["a", "divisao_1", "d1", "d1.SEQ_DB = a.DIVISAO_1_SEQ_DB"]
],
"where": [
"DATE(a.INI_DH) >= DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"DATE(a.INI_DH) <= DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"a.TERCEIRO_SEQ_DB in (:NFS_THIRD_PARTY)",
"a.PRODUCAO IS NOT NULL"
],
"order_by":[
["d1.CODIGO","ASC"],
["d2.CODIGO","ASC"],
["d3.CODIGO","ASC"],
["d4.CODIGO","ASC"],
["d5.CODIGO","ASC"],
["a.INI_DH","ASC"]
],
"group_result_by":"DIVISAO_5_SEQ_DB"
}
}', '{% extends ''reports/base.twig'' %}
{% macro header(images, filial, filters, parameters) %}
{% from ''reports/macros.twig'' import img64 %}
<div class="row space-before highlight" >
<div class="col-xs-12 text-center" style="border: 1px solid">
<h3><strong>RELATÓRIO DE RESUMO DOS TERCEIROS</strong></h3>
</div>
</div>
<div class="row space-before" style="border: 1px solid">
<div class="col-xs-2" style="padding-top:5px; padding-bottom:5px">
{% if filial.LOCAL == 2 %}
{{ img64(images[''agis_sacyr''].image_base64,''100px'') }}
{% elseif filial.LOCAL == 3 %}
{{ img64(images[''agis_busnello''].image_base64,''100px'') }}
{% else %}
{{ img64(images[''agis''].image_base64,''100px'') }}
{% endif %}
</div>
<div class="col-xs-6 text-right" style="border-right: 1px solid">
<h3>{{filial.DESCRICAO}}</h3>
<p>{{filial.ENDERECO}} - CEP: {{filial.CEP}}
{% if filial.ESTADO is not null %}
- {{filial.ESTADO}}
{% endif %}
</p>
<p>Tel: {{filial.TELEFONE}}
{% if filial.FAX is not null %}
- Fax: {{filial.FAX}}
{% endif %}
</p>
<p>{{filial.SITE}}</p>
</div>
<div class="col-xs-4">
<p>Período: <strong>{{ filial.PERIODO }}</strong></p>
<p>Data/Hora Emissão: <strong>{{ ''now''|date(''d/m/Y H:i:s'') }}</strong></p>
</div>
</div>
{% endmacro %}
{% block content %}
{% set filial = filial[0]%}
{% set total = total[0]%}
{{ _self.header(images, filial) }}
<div class="row space-before highlight" style="border: 1px solid">
<div class="col-xs-12 ">
<strong>RESUMO </strong>
</div>
</div>
<div class="row" style="border: 1px solid">
<div class="col-xs-12">
<strong>Terceiros</strong>
</div>
</div>
{% for n in por_nivel %}
<div class="row" style="border: 1px solid">
<div class="col-xs-12">
<table class="table table-condensed">
<thead>
<tr>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Nível 1</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Nível 2</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Nível 3</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Nível 4</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Nível 5</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle;width: 30%"></th>
</tr>
</thead>
<tbody>
<tr>
<td class="text-center" style="font-size: 12px">{{ n.NIVEL_1 }}</td>
<td class="text-center" style="font-size: 12px">{{ n.NIVEL_2 }}</td>
<td class="text-center" style="font-size: 12px">{{ n.NIVEL_3 }}</td>
<td class="text-center" style="font-size: 12px">{{ n.NIVEL_4 }}</td>
<td class="text-center" style="font-size: 12px">{{ n.NIVEL_5 }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row" style="border: 1px solid">
<div class="col-xs-12">
<table class="table table-condensed">
<thead>
<tr>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Terceiro</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Atividade</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Início</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Fim</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Horas da Atividade</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Quantidade de Funcionários</th>
<th class="text-center" style="font-size: 12px;vertical-align:middle">Produção</th>
</tr>
</thead>
<tbody>
{% for a in por_apontamento[n.DIVISAO_5_SEQ_DB] %}
<tr>
<td class="text-center" style="font-size: 12px;width: 25%">{{ a.TERCEIRO }}</td>
<td class="text-center" style="font-size: 12px;width: 25%">{{ a.ATIVIDADE }}</td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ a.INI_DH|date(''d/m/Y H:i:s'') }}</td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ a.FIM_DH|date(''d/m/Y H:i:s'') }}</td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ a.HORAS_ATIVIDADE|nfs_type(''HORA'') }}</td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ a.QTD_FUNCIONARIO }}</td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ a.PRODUCAO }}</td>
</tr>
{% endfor %}
<tr>
<td colspan=''4'' class="text-left" style="font-size: 12px;width: 70%"><strong><i>Total por Nível</i></strong></td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ n.HORAS_ATIVIDADE|nfs_type(''HORA'') }}</td>
<td class="text-center" style="font-size: 12px;width: 10%"></td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ n.PRODUCAO }}</td>
</tr>
</tbody>
</table>
</div>
</div>
{% endfor %}
<div class="row" style="border: 1px solid">
<div class="col-xs-12">
<table class="table table-condensed">
<tbody>
<tr>
<td colspan=''4'' class="text-left" style="font-size: 12px;width: 70%"><strong><i>Total Geral</i></strong></td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ total.HORAS_ATIVIDADE|nfs_type(''HORA'') }}</td>
<td class="text-center" style="font-size: 12px;width: 10%"></td>
<td class="text-center" style="font-size: 12px;width: 10%">{{ total.PRODUCAO }}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="break-after">
</div>
{% endblock %}', 1, '{
"pdf": {
"orientation": "Landscape",
"footer-right": "[title] - [page]/[topage]"
},
"images": [
"agis",
"agis_sacyr",
"agis_busnello"
]
}');
Relatório de Resumo do Terceiro no modelo Excel
UPDATE nfs_reports set enabled = 0 where DISPLAY_NAME ='relatorio_resumo_terceiro_excel';
INSERT INTO nfs_reports (SEQ_DB, NAME, DISPLAY_NAME, FILTERS, QUERIES, TEMPLATE, ENABLED, EXPORT_OPTIONS) VALUES(129, 'relatorio_resumo_terceiro_excel', 'Resumo dos Terceiros(.xls)', '{
"inicio": {
"type": "Date",
"options": {
"label": "De",
"required": true
}
},
"fim": {
"type": "Date",
"options": {
"label": "Até",
"required": true
}
},
"terceiro": {
"type": "Table",
"options": {
"label": "Terceiro",
"multiple": false,
"required": false
}
}
}
', '{
"filial": {
"dump": "",
"main": true,
"select": [
"f.DESCRICAO",
"f.ENDERECO",
"f.CEP",
"f.ESTADO",
"f.TELEFONE",
"f.FAX",
"f.SITE",
"concat(DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%d/%m/%Y''), '' - '', DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%d/%m/%Y'')) PERIODO"
],
"from": "endereco_filial f"
},
"total": {
"dump": "",
"main": true,
"select": [
"SUM(SEC_TO_TIME(TIMESTAMPDIFF(second,a.INI_DH,a.FIM_DH))) HORAS_ATIVIDADE",
"SUM(a.PRODUCAO) PRODUCAO"
],
"from": "apontamento_mo_terceiro a",
"inner_join": [
["a", "boletim_mo", "b", "b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB"],
["a", "terceiro", "t", "t.SEQ_DB = a.TERCEIRO_SEQ_DB"],
["a", "divisao_6", "d6", "d6.SEQ_DB = a.DIVISAO_6_SEQ_DB"],
["a", "divisao_5", "d5", "d5.SEQ_DB = a.DIVISAO_5_SEQ_DB"],
["a", "divisao_4", "d4", "d4.SEQ_DB = a.DIVISAO_4_SEQ_DB"],
["a", "divisao_3", "d3", "d3.SEQ_DB = a.DIVISAO_3_SEQ_DB"],
["a", "divisao_2", "d2", "d2.SEQ_DB = a.DIVISAO_2_SEQ_DB"],
["a", "divisao_1", "d1", "d1.SEQ_DB = a.DIVISAO_1_SEQ_DB"]
],
"where": [
"DATE(a.INI_DH) >= DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"DATE(a.INI_DH) <= DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"a.TERCEIRO_SEQ_DB in (:NFS_THIRD_PARTY)",
"a.PRODUCAO IS NOT NULL"
],
"having": ["HORAS_ATIVIDADE > 0"]
},
"por_nivel": {
"dump": "",
"main": true,
"select": [
"a.DIVISAO_5_SEQ_DB",
"CONCAT(d1.CODIGO, '' - '', d1.DESCRICAO) NIVEL_1",
"CONCAT(d2.CODIGO, '' - '', d2.DESCRICAO) NIVEL_2",
"CONCAT(d3.CODIGO, '' - '', d3.DESCRICAO) NIVEL_3",
"CONCAT(d4.CODIGO, '' - '', d4.DESCRICAO) NIVEL_4",
"CONCAT(d5.CODIGO, '' - '', d5.DESCRICAO) NIVEL_5",
"SUM(SEC_TO_TIME(TIMESTAMPDIFF(second,a.INI_DH,a.FIM_DH))) HORAS_ATIVIDADE",
"SUM(a.PRODUCAO) PRODUCAO"
],
"from": "apontamento_mo_terceiro a",
"inner_join": [
["a", "boletim_mo", "b", "b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB"],
["a", "terceiro", "t", "t.SEQ_DB = a.TERCEIRO_SEQ_DB"],
["a", "divisao_6", "d6", "d6.SEQ_DB = a.DIVISAO_6_SEQ_DB"],
["a", "divisao_5", "d5", "d5.SEQ_DB = a.DIVISAO_5_SEQ_DB"],
["a", "divisao_4", "d4", "d4.SEQ_DB = a.DIVISAO_4_SEQ_DB"],
["a", "divisao_3", "d3", "d3.SEQ_DB = a.DIVISAO_3_SEQ_DB"],
["a", "divisao_2", "d2", "d2.SEQ_DB = a.DIVISAO_2_SEQ_DB"],
["a", "divisao_1", "d1", "d1.SEQ_DB = a.DIVISAO_1_SEQ_DB"]
],
"where": [
"DATE(a.INI_DH) >= DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"DATE(a.INI_DH) <= DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"a.TERCEIRO_SEQ_DB in (:NFS_THIRD_PARTY)",
"a.PRODUCAO IS NOT NULL"
],
"group_by":[
"a.DIVISAO_5_SEQ_DB"
],
"order_by":[
["d1.CODIGO","ASC"],
["d2.CODIGO","ASC"],
["d3.CODIGO","ASC"],
["d4.CODIGO","ASC"],
["d5.CODIGO","ASC"]
]
},
"por_apontamento": {
"dump": "",
"main": true,
"select": [
"a.DIVISAO_5_SEQ_DB",
"CONCAT(t.CODIGO, '' - '', t.DESCRICAO) TERCEIRO",
"CONCAT(d6.CODIGO, '' - '', d6.DESCRICAO) ATIVIDADE",
"a.QTD_FUNCIONARIO",
"a.INI_DH",
"a.FIM_DH",
"SEC_TO_TIME(TIMESTAMPDIFF(second,a.INI_DH,a.FIM_DH)) HORAS_ATIVIDADE",
"a.PRODUCAO"
],
"from": "apontamento_mo_terceiro a",
"inner_join": [
["a", "boletim_mo", "b", "b.SEQ_DB = a.SEQ_DB_DEVICE_MASTER_SEQ_DB"],
["a", "terceiro", "t", "t.SEQ_DB = a.TERCEIRO_SEQ_DB"],
["a", "divisao_6", "d6", "d6.SEQ_DB = a.DIVISAO_6_SEQ_DB"],
["a", "divisao_5", "d5", "d5.SEQ_DB = a.DIVISAO_5_SEQ_DB"],
["a", "divisao_4", "d4", "d4.SEQ_DB = a.DIVISAO_4_SEQ_DB"],
["a", "divisao_3", "d3", "d3.SEQ_DB = a.DIVISAO_3_SEQ_DB"],
["a", "divisao_2", "d2", "d2.SEQ_DB = a.DIVISAO_2_SEQ_DB"],
["a", "divisao_1", "d1", "d1.SEQ_DB = a.DIVISAO_1_SEQ_DB"]
],
"where": [
"DATE(a.INI_DH) >= DATE_FORMAT(STR_TO_DATE(:inicio, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"DATE(a.INI_DH) <= DATE_FORMAT(STR_TO_DATE(:fim, ''%d/%m/%Y''), ''%Y-%m-%d'')",
"a.TERCEIRO_SEQ_DB in (:NFS_THIRD_PARTY)",
"a.PRODUCAO IS NOT NULL"
],
"order_by":[
["d1.CODIGO","ASC"],
["d2.CODIGO","ASC"],
["d3.CODIGO","ASC"],
["d4.CODIGO","ASC"],
["d5.CODIGO","ASC"],
["a.INI_DH","ASC"]
],
"group_result_by":"DIVISAO_5_SEQ_DB"
}
}', '$objPHPExcel = new \\PHPExcel();
$sheet = $objPHPExcel->getActiveSheet();
$row = 1;
$styleItalic = [
''font'' => array(
''bold'' => true,
''italic'' => true,
''color'' => array(''rgb'' => ''000000'')
),
''fill'' => [
''type'' => \\PHPExcel_Style_Fill::FILL_SOLID,
''color'' => [''rgb'' => ''FFFFFF'']
],
''alignment'' => array(
''horizontal'' => PHPExcel_Style_Alignment::HORIZONTAL_LEFT,
)
];
$styleCenter = [
''fill'' => [
''type'' => \\PHPExcel_Style_Fill::FILL_SOLID,
''color'' => [''rgb'' => ''FFFFFF'']
],
''alignment'' => array(
''horizontal'' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
)
];
$styleBold = [
''font'' => array(
''bold'' => true,
''color'' => array(''rgb'' => ''000000'')
),
''fill'' => [
''type'' => \\PHPExcel_Style_Fill::FILL_SOLID,
''color'' => [''rgb'' => ''FFFFFF'']
],
''alignment'' => array(
''horizontal'' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
),
''borders'' => array(
''outline'' => array(
''style'' => PHPExcel_Style_Border::BORDER_THICK,
''color'' => array(''rgb'' => ''F0F0F0''),
),
)
];
$styleTitleWhite = [
''font'' => array(
''bold'' => true,
''color'' => array(''rgb'' => ''000000'')
),
''fill'' => [
''type'' => \\PHPExcel_Style_Fill::FILL_SOLID,
''color'' => [''rgb'' => ''FFFFFF'']
],
''alignment'' => array(
''horizontal'' => PHPExcel_Style_Alignment::HORIZONTAL_LEFT,
),
''borders'' => array(
''outline'' => array(
''style'' => PHPExcel_Style_Border::BORDER_THICK,
''color'' => array(''rgb'' => ''F0F0F0''),
),
)
];
$styleTitleGrey = [
''font'' => array(
''bold'' => true,
''color'' => array(''rgb'' => ''000000'')
),
''fill'' => [
''type'' => \\PHPExcel_Style_Fill::FILL_SOLID,
''color'' => [''rgb'' => ''F0F0F0'']
],
''alignment'' => array(
''horizontal'' => PHPExcel_Style_Alignment::HORIZONTAL_LEFT,
),
''borders'' => array(
''outline'' => array(
''style'' => PHPExcel_Style_Border::BORDER_THICK,
''color'' => array(''rgb'' => ''F0F0F0''),
),
)
];
$styleTitleBlue = [
''font'' => array(
''bold'' => true,
''color'' => array(''rgb'' => ''FFFFFF'')
),
''fill'' => [
''type'' => \\PHPExcel_Style_Fill::FILL_SOLID,
''color'' => [''rgb'' => ''2d5f8b'']
],
''alignment'' => array(
''horizontal'' => PHPExcel_Style_Alignment::HORIZONTAL_LEFT,
),
''borders'' => array(
''outline'' => array(
''style'' => PHPExcel_Style_Border::BORDER_THICK,
''color'' => array(''rgb'' => ''FFFFFF''),
),
)
];
$styleTitle = [
''font'' => array(
''size'' => 24,
''bold'' => true,
''color'' => array(''rgb'' => ''000000'')
),
''fill'' => [
''type'' => \\PHPExcel_Style_Fill::FILL_SOLID,
''color'' => [''rgb'' => ''F0F0F0'']
],
''alignment'' => array(
''horizontal'' => PHPExcel_Style_Alignment::HORIZONTAL_CENTER,
),
''borders'' => array(
''outline'' => array(
''style'' => PHPExcel_Style_Border::BORDER_THICK,
''color'' => array(''rgb'' => ''FFFFFF''),
)
)
];
foreach (range(''A'',''G'') as $column) {
$sheet->getColumnDimension($column)->setAutoSize(true);
}
$sheet->getStyle("A{$row}:G{$row}")->applyFromArray($styleTitle);
$sheet->mergeCells("A{$row}:G{$row}");
$sheet->SetCellValue("A{$row}", "RELATÓRIO DE RESUMO DOS TERCEIROS");
$sheet->getRowDimension(''1'')->setRowHeight(40);
$sheet->getColumnDimension(''A'')->setWidth(100);
$row++;
$filial = $templateData[''filial''][0];
$sheet->SetCellValue("A{$row}", $filial[''DESCRICAO'']);
$sheet->SetCellValue("B{$row}", "PERÍODO: ".$filial[''PERIODO'']);
$row++;
$endereco = $filial[''ENDERECO''] .'' - ''. $filial[''CEP''];
if ($filial[''ESTADO''] != null) {
$endereco = $endereco.'' - ''. $filial[''ESTADO''];
}
$sheet->SetCellValue("A{$row}", $endereco );
$sheet->SetCellValue("B{$row}", "Data/Hora Emissão:".date(''d/m/Y H:i:s''));
$row++;
$tel = $filial[''TELEFONE''];
if ($filial[''FAX''] != null) {
$tel = $tel.'' - ''. $filial[''FAX''];
}
$sheet->SetCellValue("A{$row}", $tel);
$row++;
$sheet->SetCellValue("A{$row}", $filial[''SITE'']);
$row++;
$total = $templateData[''total''][0];
$row ++;
$sheet->getStyle("A{$row}:G{$row}")->applyFromArray($styleTitleGrey);
$sheet->mergeCells("A{$row}:G{$row}");
$sheet->SetCellValue("A{$row}", "RESUMO");
$row ++;
$sheet->getStyle("A{$row}:G{$row}")->applyFromArray($styleTitleWhite);
$sheet->mergeCells("A{$row}:G{$row}");
$sheet->SetCellValue("A{$row}", "Terceiros");
foreach ($templateData[''por_nivel''] as $n) {
$row ++;
$sheet->getStyle("A{$row}:G{$row}")->applyFromArray($styleBold);
$sheet->SetCellValue("A{$row}", "Nível 1");
$sheet->SetCellValue("B{$row}", "Nível 2");
$sheet->SetCellValue("C{$row}", "Nível 3");
$sheet->SetCellValue("D{$row}", "Nível 4");
$sheet->SetCellValue("E{$row}", "Nível 5");
$row ++;
$sheet->getStyle("A{$row}:G{$row}")->applyFromArray($styleCenter);
$sheet->SetCellValue("A{$row}", $n[''NIVEL_1'']);
$sheet->SetCellValue("B{$row}", $n[''NIVEL_2'']);
$sheet->SetCellValue("C{$row}", $n[''NIVEL_3'']);
$sheet->SetCellValue("D{$row}", $n[''NIVEL_4'']);
$sheet->SetCellValue("E{$row}", $n[''NIVEL_5'']);
$row ++;
$sheet->getStyle("A{$row}:G{$row}")->applyFromArray($styleBold);
$sheet->SetCellValue("A{$row}", "Terceiro");
$sheet->SetCellValue("B{$row}", "Atividade");
$sheet->SetCellValue("C{$row}", "Início");
$sheet->SetCellValue("D{$row}", "Fim");
$sheet->SetCellValue("E{$row}", "Horas da Atividade");
$sheet->SetCellValue("F{$row}", "Quantidade de Funcionários");
$sheet->SetCellValue("G{$row}", "Produção");
foreach ($templateData[''por_apontamento''][$n[''DIVISAO_5_SEQ_DB'']] as $a) {
$row ++;
$sheet->getStyle("A{$row}:G{$row}")->applyFromArray($styleCenter);
$sheet->SetCellValue("A{$row}", $a[''TERCEIRO'']);
$sheet->SetCellValue("B{$row}", $a[''ATIVIDADE'']);
$sheet->SetCellValue("C{$row}", date("d/m/Y H:m:s", strtotime($a[''INI_DH''])));
$sheet->SetCellValue("D{$row}", date("d/m/Y H:m:s", strtotime($a[''FIM_DH''])));
$sheet->SetCellValue("E{$row}", \\core\\Utils::converteSegundos($a[''HORAS_ATIVIDADE'']));
$sheet->SetCellValue("F{$row}", $a[''QTD_FUNCIONARIO'']);
$sheet->SetCellValue("G{$row}", $a[''PRODUCAO'']);
}
$row ++;
$sheet->getStyle("A{$row}:D{$row}")->applyFromArray($styleItalic);
$sheet->getStyle("E{$row}:G{$row}")->applyFromArray($styleCenter);
$sheet->mergeCells("A{$row}:D{$row}");
$sheet->SetCellValue("A{$row}", "Total por Nível");
$sheet->SetCellValue("E{$row}", \\core\\Utils::converteSegundos($n[''HORAS_ATIVIDADE'']));
$sheet->SetCellValue("F{$row}", '''');
$sheet->SetCellValue("G{$row}", $n[''PRODUCAO'']);
}
$row ++;
$sheet->getStyle("A{$row}:D{$row}")->applyFromArray($styleItalic);
$sheet->getStyle("E{$row}:G{$row}")->applyFromArray($styleCenter);
$sheet->mergeCells("A{$row}:D{$row}");
$sheet->SetCellValue("A{$row}", "Total Geral");
$sheet->SetCellValue("E{$row}", \\core\\Utils::converteSegundos($total[''HORAS_ATIVIDADE'']));
$sheet->SetCellValue("F{$row}", '''');
$sheet->SetCellValue("G{$row}", $total[''PRODUCAO'']);
$sheet->setTitle(substr($templateData[''display_name''], 0, 30));
', 1, '{
"excel": {
"template": ""
}
}');
Private User
Private User é uma nova funcionalidade do NFS que permite usar a tabela NFS_ACL_USUARIO para:
- Usar em apontamentos
- Exibir só os dados relacionados a esse usuário por default
- Relatórios somente para esse tipo de usuário
- Vincular o usuário logado com o registro de efetivo_funcionário ( por exemplo)
A primeira configuração é definir quais usuários serão private user, depois é só ir na nfs_acl_usuario e na coluna TIPO_USUARIO_SEQ_DB e difinir igual a 5, também é possível realizar isso pelo Controle de Acesso.
Private User - CRUD
Vamos supor que você tem a tarefa de configurar para que no apontamento_ponto tenha o nfs_acl_usuario. Para isso é necessário o seguinte:
- NOME deve ser igual a NFS_ACL_USUARIO, hoje só vemos a necessidade de um usuário por tabela.
- TIPO deve ser igual USER
- LINK deve ser igual a NFS_ACL_USUARIO
- PROPERTIES deve ser a seguinte configuração,
{"users": "privateUsers"}
, importantíssimo para no combo no CRUD mostrar os usuários. - Esse item não deve ser configurado, mas por padrão o DISPLAY_FIELDS é NOME :: SOBRENOME
Para no caso de adicinar na Apontamento Ponto.
INSERT INTO nfs_core_ds_tabela_campo (TABELA_NOME, NOME, SEQ, SYS, SEND_XMOVA, GRID, GRID_MOBILE, DESCRICAO, DESCRICAO_RESUMIDA, TIPO, OBRIGATORIO, TAMANHO, TAMANHO_DECIMAL, MASCARA, INSERT_UPDATE, DISABLED, HINT, LINK, VALIDACAO, OPCOES, VALOR_DEFAULT, VALIDACAO_VIEW, FILTRO_VIEW, TOOLTIP_MESSAGE, PROPERTIES) VALUES('APONTAMENTO_PONTO', 'NFS_ACL_USUARIO', 5, 0, 1, 1, 1, 'Funcionário', 'Funcionário', 'USER', 1, NULL, NULL, NULL, 'IU', '0', NULL, 'NFS_ACL_USUARIO', NULL, NULL, NULL, NULL, NULL, NULL, '{ "users": "privateUsers"}');
Usuário com mais informações
Outra caso comum é ter uma tarefa para ter mais informações relacionado ao nosso Usuário, no caso NÃO É PARA SER CRIADA NENHUM COLUNA NOVA NA NFS_ACL_USUARIO e sim no NFS criar uma app_ para ser relacionado ao usuário, podemos fazer isso hoje com a nossa tabela de Funcionário ficando:
INSERT INTO nfs_core_ds_tabela_campo (TABELA_NOME, NOME, SEQ, SYS, SEND_XMOVA, GRID, GRID_MOBILE, DESCRICAO, DESCRICAO_RESUMIDA, TIPO, OBRIGATORIO, TAMANHO, TAMANHO_DECIMAL, MASCARA, INSERT_UPDATE, DISABLED, HINT, LINK, VALIDACAO, OPCOES, VALOR_DEFAULT, VALIDACAO_VIEW, FILTRO_VIEW, TOOLTIP_MESSAGE, PROPERTIES) VALUES('FUNCIONARIO', 'NFS_ACL_USUARIO', 7, 0, 1, 1, 1, 'Usuário', 'Usuário', 'USER', 1, NULL, NULL, NULL, 'IU', '0', NULL, 'NFS_ACL_USUARIO', NULL, NULL, NULL, NULL, NULL, NULL, '{ "users": "privateUsers"}');
Por exemplo nessa tabela de Funcionário você pode relacionar um funcionário x usuário e adicionar mais informações como:
- PIS
- Endereço
- Apelido (Não no sentido prejorativo)
- Conta Bancaria
Entre outras que seja necessário e não tenha na NFS_ACL_USUARIO.
Private User - Relatórios
Quando o usuário for desse tipo terá disponível para ser usado no NFS Query Builder o parâmetro :NFS_ACL_USUARIO_SEQ_DB, onde vai ser disponível filtrar pelo o usuário logado. Então supondo que tenha 5 usuários private user e esteja logado com um, então colocando o where abaixo será filtrado somente pelos meus dados.
Atenção na montagem da query para não realizar algum left join e exibir dados não necessários
{
"filiais": {
"dump": "",
"main": true,
"select": [
"distinct fi.SEQ_DB SEQ_DB"
],
"from": "filial_banco fi",
"inner_join": [
["fi", "apontamento_ponto", "a", "a.filial = fi.SEQ_DB"],
["a", "nfs_acl_usuario", "nfs", "nfs.seq_db = a.nfs_acl_usuario_seq_db "]
],
"where": [
"a.nfs_acl_usuario_seq_db in (:NFS_ACL_USUARIO_SEQ_DB)",
"DATE(a.INI_DH) >= DATE_FORMAT(STR_TO_DATE(:inicio, '%d/%m/%Y'), '%Y-%m-%d')",
"DATE(a.INI_DH) <= DATE_FORMAT(STR_TO_DATE(:fim, '%d/%m/%Y'), '%Y-%m-%d')",
"fi.CNPJ is not null",
"fi.DESCRICAO is not null"
]
}
}
Caso o relatorio esteja sendo feito utilizando Entry Point, podemos filtrar os dados pegando o usuario atual da sessão e caso seja um usuario PRIVATE, aplicar as tratativas, exemplo:
$user = xDS::getUser();
$apontamentos = Dao::table('APT');
if ($user->isPrivateUser()) {
$apontamenos->where(['NFS_ACL_USUARIO_SEQ_DB' => $user->SEQ_DB]);
}
$apontamentos->get();
Buscar Dados de Outro Usuário
Existe casos onde é necessário buscar dados de outro usuário num entry point quando o mesmo é um terceiro.
Para resolver esse problema foi criado um parâmetro AllowAnyPrivateUserSearch para tirar a limitação com a busca pelo usuário de terceiro e poder encontrar qualquer dados.
Um exemplo, é o usuário Luis aprovar um boletim e no entry point vai mandar para o usuário Dalton que também ao modificar o boletim envia de voltar para o Luis e ambos usuário são terceiros, com isso precisa usar a flag AllowAnyPrivateUserSearch. Esse parâmetro é usado somente no update.
Como usar
$params['AllowAnyPrivateUserSearch'] = true; // vai permitir buscar e alterar os dados
$seqDb = 1;
$updatedValues = []; // seus valores para serem alterados
$tableBo->updateRow('MY_UPDATED_TABLE', $seqDb, $updatedValues, $params);