Mapa de Apontamentos - GenericMap
O Mapa de Apontamentos tem como objetivo principal exibir Dados de Apontamentos referentes a uma Entidade Principal.
Pré-requisitos
São pré-requisitos para esse módulo:
- Painel para exibir os detalhes dos Apontamentos;
- Tabelas "nfs_mapa_generico" e "nfs_mapa_generico_relatorio" criadas na seguinte estrutura:
CREATE TABLE `nfs_mapa_generico` (
`SEQ_DB` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`EMPRESA` int(11) DEFAULT NULL,
`FILIAL` int(11) DEFAULT NULL,
`LOCAL` int(11) DEFAULT NULL,
`TABLENAME` varchar(100) DEFAULT NULL,
`TITLE` varchar(100) DEFAULT NULL,
`MAIN_TABLE` varchar(200) DEFAULT NULL,
`DISPLAY_FIELDS` varchar(1000) DEFAULT NULL,
`OPTIONS` varchar(500) DEFAULT NULL,
`REPORT_DAYS` varchar(500) DEFAULT NULL,
`REPORT_TYPES` varchar(500) DEFAULT NULL,
`QUERY_STATEMENTS` text,
`SUBQUERY_STATEMENTS` text,
`JORNADA_QUERY` text,
`FILTERS` varchar(1000) DEFAULT NULL,
`LEGENDS` varchar(1000) DEFAULT NULL,
`INDICATORS` varchar(1000) DEFAULT NULL,
`ENABLED` int(1) DEFAULT NULL,
PRIMARY KEY (`SEQ_DB`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `nfs_mapa_generico_relatorio` (
`SEQ_DB` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`EMPRESA` int(11) DEFAULT NULL,
`FILIAL` int(11) DEFAULT NULL,
`LOCAL` int(11) DEFAULT NULL,
`MAPA_GENERICO_SEQ_DB` bigint(20) unsigned DEFAULT NULL,
`TIPO_RELATORIO` varchar(20) DEFAULT NULL,
`QUERY_STATEMENTS` text,
`DISPLAY_FIELDS` varchar(1000) DEFAULT NULL,
`SUBQUERY_STATEMENTS` text,
`ENABLED` int(1) DEFAULT NULL,
PRIMARY KEY (`SEQ_DB`),
KEY `idx_nfs_mapa_generico_relatorio` (`SEQ_DB`),
KEY `fk_nfs_mapa_generico_relatorio_seq_db` (`MAPA_GENERICO_SEQ_DB`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
- Caso não esteja habilitado, habilitar módulo "Rotas Personalizada";
- *Criar rota personalizada para "/custom/mapa/<tablename>";
*devemos passar como tablename o nome que definimos como
TABLENAME
para o mapa genérico na tabela nfs_mapa_generico ; { .is-warning }
Construção da consulta
Todo o processo de construção da consulta para este módulo usou como base a consulta do BoBAgro, que consiste do resultado de 3 subconsultas, sendo:
- A primeira subconsulta obtem os dados dos apontamentos que são iniciados e finalizados no mesmo dia:
-- 1ª Subconsulta
INI_DH = '01/01/2019 08:00:00'
FIM_DH = '01/01/2019 16:59:59'
- A segunda e terceira subconsultas obtem os dados dos apontamentos que são iniciados e terminados em dias diferentes. Assim a segunda subconsulta obtem os dados parciais do apontamento até as 23h59'59 do mesmo dia, e a terceira subconsulta os dados parcias restantes do mesmo apontamento:
DT_INI = '01/01/2019 22:00:00'
DT_FIM = '02/01/2019 06:00:00'
-- 2ª Subconsulta
DT_INI = '01/01/2019 22:00:00' e DT_FIM = '01/01/2019 23:59:59'
-- 3ª Subconsulta
DT_INI = '02/01/2019 00:00:00' e DT_FIM = '02/01/2019 06:00:00'
Tabela nfs_mapa_generico
Possui as definições principais do ambiente, sendo:
1. TABLENAME:
Apelido/Nome da entidade definido para o mapa genérico; (sera usado para acessar o mapa generico como descrito no 4º item dos pré-requisitos desse módulo)
TABLENAME ='EQUIPAMENTO'
2. TITLE:
Título do Mapa exibido no topo do módulo;
TITLE ='Mapa de Apontamento Máquina'
3. MAIN_TABLE:
Nome da tabela principal (usada como link entre para o Painel QIG);
MAIN_TABLE ='EQUIPAMENTO'
4. DISPLAY_FIELDS:
Configuração JSON de exibição dos dados principais;
{
"KEY": "idEquipamento",
"TITLE": "codigoEquipamento",
"FIELD_LINK" : "idEquipamento",
"DATAS": {
"INI": "dataAbertura",
"FIM": "dataFinal"
},
"COLUNAS": {
"descricaoModelo": "Modelo",
"codigoEquipamento": "Equipamento"
},
"INDICADOR": "produtiva",
"TOOLTIP": {
"codigoOperacao": "Código Atividade",
"descOperacao": "Descrição Atividade",
"codigoOperador": "Código Operador",
"nomeOperador": "Nome Operador"
}
}
Onde:
- KEY: chave principal da consulta;
- TITLE: título do gráfico gerado;
- FIELD_LINK: Usado para quando o Detalhes não é o mesmo dados que KEY, no caso se for um Mapa de Apontamentos de Mão de Obra, onde o Boletim é por Encarregado e o Mapa deve ser pelo operador, com isso para não ficar o LINK para o Operador, deve ser passado o SEQ_DB do encarregado para poder abrir seu Detalhes;
- DATAS: alias das colunas INI_DH e FIM_DH das subconsultas;
- COLUNAS: labels exibidas nas tabela de resultados;
- INDICADOR: atividade Produtiva ou Improdutiva;
- TOOLTIP: colunas:labels exibidas no tooltip do gráfico.
- OPTIONS: dados opcionais (por ora, usado apenas um valor de Jornada de Trabalho Padrão);
{
"JORNADA_PADRAO": 12
}
6. REPORT_DAYS:
Configuração JSON para perído de dias processados no relatório (esse valor usa a data fornecida como referência);
{
"5": {
"label": "-5 dias",
"value": 5,
"selected": true
},
"10": {
"label": "-10 dias",
"value": 10,
"selected": false
},
"15": {
"label": "-15 dias",
"value": 15,
"selected": false
}
}
Onde:
- label: label exibida no drop-down;
- value: quantidade de dias;
- selected: se pré-selecionado ou não.
7. REPORT_TYPES:
Configuração JSON para tipos de relatório gerado. Cada tipo especificado requer de um registro na tabela nfs_mapa_generico_relatorio com detalhes do relatório gerado);
{
"tipoPorcentagem": {
"label": "Porcentagem",
"value": "porcentagem",
"selected": true
},
"tipoHoras": {
"label": "Horas",
"value": "horas",
"selected": false
},
"tipoProducao": {
"value": "producao",
"label": "Produção",
"selected": false
}
}
Onde:
- label: label do drop-down;
- value: link com tipo de relatório em nfs_mapa_generico_relatorio;
- selected: se pré-selecionado ou não.
8. QUERY_STATEMENTS:
Statements usados para montar a consulta principal (comentados inline para melhor entendimento);
{
"SELECT": [
"e.SEQ_DB as idEquipamento", // chave principal da consulta
"e.CODIGO as codigoEquipamento", // colunas exibidas nas tabela de resultados
"m.SEQ_DB as idModelo",
"m.DESCRICAO as descricaoModelo", // colunas exibidas nas tabela de resultados
"dados.dataAbertura", // datas de referência
"dados.dataFinal",
"codigoOperacao", // colunas usadas no tooltip e indicador
"descOperacao",
"produtiva",
"codigoOperador",
"nomeOperador"
],
"FROM": [], // consulta baseada em subquery
"SUBQUERY": ["dados", "idEquipamento"], // resultado da subquery com chave
"JOIN": [
"right join app_equipamento e on e.SEQ_DB = dados.idEquipamento",
"inner join app_classe_operacional c on e.CLASSE_OPERACIONAL_SEQ_DB = c.SEQ_DB",
"inner join app_modelo m on e.MODELO_SEQ_DB = m.SEQ_DB"
],
"WHERE": [
"e.ATIVO = 1 and e.DELETED = 0 and e.EMPRESA in (:empresa, 9999) and e.FILIAL in (:filial, 9999) and e.LOCAL in (:local, 9999)",
"c.ATIVO = 1 and c.DELETED = 0 and c.EMPRESA in (:empresa, 9999) and c.FILIAL in (:filial, 9999) and c.LOCAL in (:local, 9999)",
"m.ATIVO = 1 and m.DELETED = 0 and m.EMPRESA in (:empresa, 9999) and m.FILIAL in (:filial, 9999) and m.LOCAL in (:local, 9999)"
],
"ORDER_BY": [
"dados.idModelo",
"dados.codigoEquipamento",
"dados.dataAbertura"
]
}
9. SUBQUERY_STATEMENTS:
Statements usados para montar subconsultas (comentados inline para melhor entendimento);
{
"SELECT": [
// resultado das subquery's
"eq.SEQ_DB as idEquipamento",
"eq.CODIGO as codigoEquipamento",
"cl.SEQ_DB as idClasse",
"mo.SEQ_DB as idModelo",
"mo.DESCRICAO as descricaoModelo",
"se.SEQ_DB as idRegional",
"coalesce(atv.CODIGO, '') as codigoOperacao",
"coalesce(atv.DESCRICAO, '') as descOperacao",
"coalesce(atv.FLAG_PRODUTIVA, 0) as produtiva",
"coalesce(op.CRACHA, '') as codigoOperador",
"coalesce(op.NOME, '') as nomeOperador"
],
"FROM": [
// tabela principal das subquery's
["app_apontamento_maquina", "ap"]
],
"JOIN": [
// relacionamentos de cada subquery
"inner join app_boletim_maquina bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB",
"inner join app_equipamento eq on eq.SEQ_DB = bo.EQUIPAMENTO_SEQ_DB",
"inner join app_modelo mo on mo.SEQ_DB = eq.MODELO_SEQ_DB",
"inner join app_classe_operacional cl on cl.SEQ_DB = eq.CLASSE_OPERACIONAL_SEQ_DB",
"inner join app_setor se on se.SEQ_DB = ap.SETOR_SEQ_DB",
"left join app_atividade atv on atv.SEQ_DB = ap.ATIVIDADE_SEQ_DB",
"left join app_operador op on op.SEQ_DB = bo.OPERADOR_SEQ_DB"
],
"WHERE": [
// filtros (só apontamentos fechados)
"ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (:empresa, 9999) and ap.FILIAL in (:filial, 9999) and ap.LOCAL in (:local, 9999) and ap.FIM_DH is not null"
],
"GROUP_BY": [
"idEquipamento",
"codigoEquipamento",
"idClasse",
"idModelo",
"descricaoModelo",
"ap.FIM_DH",
"ap.INI_DH",
"idRegional",
"codigoOperacao",
"descOperacao",
"produtiva",
"codigoOperador",
"nomeOperador"
],
"UNION": [
{
// diferenças entre as subquery's
"SELECT": [
// subquery 1: apontamentos iniciados e finalizados no mesmo dia
"ap.INI_DH as dataAbertura",
"ap.FIM_DH as dataFinal"
],
"WHERE": [
"ap.INI_DH between concat(:de, ' 00:00:00') and concat(:ate, ' 23:59:59')",
"date(ap.INI_DH) = date(ap.FIM_DH)"
]
},
{
"SELECT": [
// subquery 2: apontamentos iniciados e finalizados no próximo dia (até fim do dia)
"ap.INI_DH as dataAbertura",
"concat(date(ap.INI_DH), ' 23:59:59') as dataFinal"
],
"WHERE": [
"(ap.INI_DH between concat(:de, ' 00:00:00') and concat(:ate, ' 23:59:59') or ap.FIM_DH between concat(:de, ' 00:00:00') and concat(:ate, ' 23:59:59'))",
"ap.INI_DH >= concat(:de, ' 00:00:00')",
"date(ap.INI_DH) < date(ap.FIM_DH)"
]
},
{
"SELECT": [
// subquery 2: apontamentos iniciados e finalizados no próximo dia (0h em diante)
"concat(date_add(date(ap.INI_DH), interval 1 day), ' 00:00:00') as dataAbertura",
"ap.FIM_DH as dataFinal"
],
"WHERE": [
"ap.INI_DH >= concat(:de, ' 00:00:00')",
"ap.FIM_DH <= concat(:ate, ' 23:59:59')",
"date(ap.INI_DH) < date(ap.FIM_DH)"
]
}
]
}
10. JORNADA_QUERY:
QueryBuilder para obter jornada de trabalho da entidade (são retornadas as jornadas de trabalho de todos os dias);
{
"SELECT": ["ej.EQUIPAMENTO_SEQ_DB AS ID", "jor.*"],
"FROM": [["equipamento_jornada", "ej"]],
"JOIN": [["ej", "jornada", "jor", "jor.SEQ_DB = ej.JORNADA_SEQ_DB"]],
"WHERE": [
"ej.EQUIPAMENTO_SEQ_DB in (:lista)",
"ej.INI_VIGENCIA <= :data",
"(ej.FIM_VIGENCIA >= :data or ej.FIM_VIGENCIA is null)"
]
}
IMPORTANTE: As cláusulas (SELECT, FROM etc.) devem está em CAIXA ALTA; em futuras versões esses parâmetros serão normalizados, seguindo as definições do QueryBuilder. {.is-danger}
Caso queira utilizar algum campo em especifico ao invés de utilizar uma tabela de jornadas, podemos especificar esse campo definindo no registro(s) o valor JORNADA_POR_CAMPO igual a 1 e adicionando o alias JORNADA_VALOR no campo a ser usado como o valor de jornada, exemplo:
{
"SELECT": [
"eqp.SEQ_DB AS ID",
"eqp.DISPONIBILIDADE AS JORNADA_VALOR",
"1 as JORNADA_POR_CAMPO"
],
"FROM": [
["eqp", "eqp"]
],
"WHERE": [
"eqp.SEQ_DB in (:lista)"
]
}
11. FILTERS:
Filtros disponíveis para composição do relatório;
{
"classe_operacional": {
"label": "Classe Operacional",
"query_alias": "c",
"subquery_alias": "cl",
"id": "SEQ_DB",
"descricao": "DESCRICAO",
"multiple": true,
"subfilter": "equipamento"
},
"modelo": {
"label": "Modelo",
"query_alias": "m",
"subquery_alias": "mo",
"id": "SEQ_DB",
"descricao": "DESCRICAO",
"multiple": true,
"subfilter": "equipamento"
},
"equipamento": {
"label": "Equipamento",
"query_alias": "e",
"subquery_alias": "eq",
"id": "SEQ_DB",
"descricao": "DESCRICAO",
"multiple": true,
"subfilter": ""
},
"setor": {
"label": "Setor / Regional",
"query_alias": "",
"subquery_alias": "se",
"id": "SEQ_DB",
"descricao": "DESCRICAO",
"multiple": true,
"subfilter": ""
}
}
Onde:
- label: label do formulário de filtro;
- query_alias: alias para consulta principal (preenchido se aplicável);
- subquery_alias: alias para subquery (preenchido se aplicável);
- id: valor para filtro;
- descricao: descrição para filtro;
- multiple: se permite filtrar por mais de um valor;
- subfilter: preenchido se valores filtram outros filtros.
Se as chaves query_alias e subquery_alias forem preenchidas os filtros serão aplicados na consulta principal e/ou na subquery, respectivamente. {.is-danger}
12. LEGENDS:
Legendas principais para apontamentos em relação à jornada de trabalho da entidade;
{
"zero": {
"label": "0%", // label da legenda
"color": "#FF5050", // cor da legenda
"eval": "[percent] == 0" // operção lógica sobre percentual obtido na consulta
},
"insatisfatorio": {
"label": "> 0%",
"color": "#E59400",
"eval": "[percent] > 0 && [percent] < 50"
},
"satisfatorio": {
"label": ">= 50%",
"color": "#ffff00",
"eval": "[percent] >= 50 && [percent] < 90"
},
"otimo": {
"label": ">= 90%",
"color": "#92D050",
"eval": "[percent] >= 90"
}
}
Onde:
- label: label da legenda;
- color: cor da legenda.
- eval: operção lógica sobre percentual obtido na consulta.
- INDICATORS: Indicadores exibidos no gráfico (atividade produtiva ou não, ou demais indicadores).
{
"produtiva": {
"value": 1,
"label": "Produtiva",
"color": "#92D050"
},
"improdutiva": {
"value": 0,
"label": "Produtiva",
"color": "#FF5050"
}
}
Onde:
- value: valor obtido da consulta;
- label: label exibido no legenda;
- color: cor da legenda.
Tabela nfs_mapa_generico_relatorio
Possui as definições de cada tipo de relatório gerado (coluna REPORT_TYPES da nfs_mapa_generico), sendo:
1. MAPA_GENERICO_SEQ_DB:
FK da tabela nfs_mapa_generico;
MAPA_GENERICO_SEQ_DB=1
2. TIPO_RELATORIO:
valor do tipo de relatório selecionado;
TIPO_RELATORIO='porcentagem'
3. QUERY_STATEMENTS:
coluna(s) da consulta principal que será usada na construção do tipo de relatório;
{
"SELECT": [
"timestampdiff(second, cast(dataAbertura as datetime), cast(dataFinal as datetime)) as tempoApontado"
]
}
Ou, para o tipo producao da entidade equipamento da BoBAgro, usa-se os seguintes dados:
{
"SELECT": ["producao as tempoApontado", "divisao"]
}
Observações Normalmente deve-se especificar aqui o campo que será usado como valor de referência para o relatório. Nos exemplos acima temos o campo tempoApontamento que é o valor em segundos usado para determinar o percentual de apontamento por Jornada de Trabalho da entidade. No segundo exemplo temos a coluna divisao, que é usada para criar um agrupamento adicional (além do agrupamento por dia); nesse exemplo, o agrupamento seria o Código da Fazenda e o Código do Talhão descritos no SUBQUERY_STATEMENTS a seguir.
4. DISPLAY_FIELDS:
definições de exibição e/ou agrupamento dos dados de acordo com o tipo de relatório;
{
"MAIN": "tempoApontado",
"TIPO": "absolute",
"DIVISAO": ""
}
DICA
- MAIN: refere-se ao valor de referência para o relatório;
- TIPO: tipo de formatação/exibição do dados. Os valores previstos são "absolute" (valor do campo MAIN convertido em horas, por exemplo, ou producao, no tipo de relatório "producao"*), "percent" (valor exibido em percentual em relação a Jornada de Trabalho da Entidade) ou "html" (este é usando quando existe agrupamento de dados, p.ex., tipo de relatório producao, onde os dados são agrupados por Fazenda/Talhão);
- DIVISAO: especificado quando existe agrupamento de dados além do dia.
5. SUBQUERY_STATEMENTS:
Statements que serão usando nas subconsultas. Caso as subquery's de um determinado tipo de relatório requera mais colunas/relacionamento/agrupamento, estes são especificados aqui;
{
"SELECT": [
"sum(pr.producao) as producao",
"concat(fz.CODIGO, '-', coalesce(tl.CODIGO, '')) as divisao "
],
"JOIN": [
"left join app_apontamento_maquina_producao pr on pr.SEQ_DB_DEVICE_MASTER_SEQ_DB = bo.SEQ_DB and pr.ATIVIDADE_SEQ_DB = atv.SEQ_DB and pr.ATIVO = 1 and pr.DELETED = 0 and pr.EMPRESA in (:empresa, 9999) and pr.FILIAL in (:filial, 9999) and pr.LOCAL in (:local, 9999)",
"left join app_fazenda fz on fz.SEQ_DB = ap.FAZENDA_SEQ_DB and fz.ATIVO = 1 and fz.DELETED = 0 and fz.EMPRESA in (:empresa, 9999) and fz.FILIAL in (:filial, 9999) and fz.LOCAL in (:local, 9999)",
"left join app_talhao tl on tl.SEQ_DB = pr.TALHAO_SEQ_DB and tl.ATIVO = 1 and tl.DELETED = 0 and tl.EMPRESA in (:empresa, 9999) and tl.FILIAL in (:filial, 9999) and tl.LOCAL in (:local, 9999)"
],
"GROUP_BY": ["divisao"]
}
Referências
Como referência, segue duas consultas geradas de acordo com os dados usados nos exemplos:
- Entidade "EQUIPAMENTO" e Tipo de Relatório "porcentagem" no período 23/01/2019 a 27/01/2019
select
e.SEQ_DB as idEquipamento,
e.CODIGO as codigoEquipamento,
m.SEQ_DB as idModelo,
m.DESCRICAO as descricaoModelo,
dados.dataAbertura,
dados.dataFinal,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador,
timestampdiff(second,
cast(dataAbertura as datetime),
cast(dataFinal as datetime)) as tempoApontado
from (
select
eq.SEQ_DB as idEquipamento,
eq.CODIGO as codigoEquipamento,
cl.SEQ_DB as idClasse,
mo.SEQ_DB as idModelo,
mo.DESCRICAO as descricaoModelo,
coalesce(atv.CODIGO, '') as codigoOperacao,
coalesce(atv.DESCRICAO, '') as descOperacao,
coalesce(atv.FLAG_PRODUTIVA, 0) as produtiva,
coalesce(op.CRACHA, '') as codigoOperador,
coalesce(op.NOME, '') as nomeOperador,
se.SEQ_DB as idRegional,
ap.INI_DH as dataAbertura,
ap.FIM_DH as dataFinal
from app_apontamento_maquina as ap
inner join app_boletim_maquina bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_equipamento eq on eq.SEQ_DB = bo.EQUIPAMENTO_SEQ_DB
inner join app_modelo mo on mo.SEQ_DB = eq.MODELO_SEQ_DB
inner join app_classe_operacional cl on cl.SEQ_DB = eq.CLASSE_OPERACIONAL_SEQ_DB
inner join app_setor se on se.SEQ_DB = ap.SETOR_SEQ_DB
left join app_atividade atv on atv.SEQ_DB = ap.ATIVIDADE_SEQ_DB
left join app_operador op on op.SEQ_DB = bo.OPERADOR_SEQ_DB
where
ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (1, 9999) and ap.FILIAL in (1, 9999) and ap.LOCAL in (1, 9999)
and ap.FIM_DH is not null
and ap.INI_DH between '2019-01-23 00:00:00' and '2019-01-27 23:59:59'
and date(ap.INI_DH) = date(ap.FIM_DH)
group by
idEquipamento,
codigoEquipamento,
idClasse,
idModelo,
descricaoModelo,
ap.FIM_DH,
ap.INI_DH,
idRegional,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador
union all
select
eq.SEQ_DB as idEquipamento,
eq.CODIGO as codigoEquipamento,
cl.SEQ_DB as idClasse,
mo.SEQ_DB as idModelo,
mo.DESCRICAO as descricaoModelo,
coalesce(atv.CODIGO, '') as codigoOperacao,
coalesce(atv.DESCRICAO, '') as descOperacao,
coalesce(atv.FLAG_PRODUTIVA, 0) as produtiva,
coalesce(op.CRACHA, '') as codigoOperador,
coalesce(op.NOME, '') as nomeOperador,
se.SEQ_DB as idRegional,
ap.INI_DH as dataAbertura,
concat(date(ap.INI_DH), ' 23:59:59') as dataFinal
from app_apontamento_maquina as ap
inner join app_boletim_maquina bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_equipamento eq on eq.SEQ_DB = bo.EQUIPAMENTO_SEQ_DB
inner join app_modelo mo on mo.SEQ_DB = eq.MODELO_SEQ_DB
inner join app_classe_operacional cl on cl.SEQ_DB = eq.CLASSE_OPERACIONAL_SEQ_DB
inner join app_setor se on se.SEQ_DB = ap.SETOR_SEQ_DB
left join app_atividade atv on atv.SEQ_DB = ap.ATIVIDADE_SEQ_DB
left join app_operador op on op.SEQ_DB = bo.OPERADOR_SEQ_DB
where
ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (1, 9999) and ap.FILIAL in (1, 9999) and ap.LOCAL in (1, 9999)
and ap.FIM_DH is not null
and (ap.INI_DH between '2019-01-23 00:00:00' and '2019-01-27 23:59:59' or ap.FIM_DH between '2019-01-23 00:00:00' and '2019-01-27 23:59:59')
and ap.INI_DH >= '2019-01-23 00:00:00'
and date(ap.INI_DH) < date(ap.FIM_DH)
group by
idEquipamento,
codigoEquipamento,
idClasse,
idModelo,
descricaoModelo,
ap.FIM_DH,
ap.INI_DH,
idRegional,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador
union all
select
eq.SEQ_DB as idEquipamento,
eq.CODIGO as codigoEquipamento,
cl.SEQ_DB as idClasse,
mo.SEQ_DB as idModelo,
mo.DESCRICAO as descricaoModelo,
coalesce(atv.CODIGO, '') as codigoOperacao,
coalesce(atv.DESCRICAO, '') as descOperacao,
coalesce(atv.FLAG_PRODUTIVA, 0) as produtiva,
coalesce(op.CRACHA, '') as codigoOperador,
coalesce(op.NOME, '') as nomeOperador,
se.SEQ_DB as idRegional,
concat(date_add(date(ap.INI_DH), interval 1 day), ' 00:00:00') as dataAbertura,
ap.FIM_DH as dataFinal
from app_apontamento_maquina as ap
inner join app_boletim_maquina bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_equipamento eq on eq.SEQ_DB = bo.EQUIPAMENTO_SEQ_DB
inner join app_modelo mo on mo.SEQ_DB = eq.MODELO_SEQ_DB
inner join app_classe_operacional cl on cl.SEQ_DB = eq.CLASSE_OPERACIONAL_SEQ_DB
inner join app_setor se on se.SEQ_DB = ap.SETOR_SEQ_DB
left join app_atividade atv on atv.SEQ_DB = ap.ATIVIDADE_SEQ_DB
left join app_operador op on op.SEQ_DB = bo.OPERADOR_SEQ_DB
where
ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (1, 9999) and ap.FILIAL in (1, 9999) and ap.LOCAL in (1, 9999)
and ap.FIM_DH is not null
and ap.INI_DH >= '2019-01-23 00:00:00'
and ap.FIM_DH <= '2019-01-27 23:59:59'
and date(ap.INI_DH) < date(ap.FIM_DH)
group by
idEquipamento,
codigoEquipamento,
idClasse,
idModelo,
descricaoModelo,
ap.FIM_DH,
ap.INI_DH,
idRegional,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador
) dados
right join app_equipamento e on e.SEQ_DB = dados.idEquipamento
inner join app_classe_operacional c on e.CLASSE_OPERACIONAL_SEQ_DB = c.SEQ_DB
inner join app_modelo m on e.MODELO_SEQ_DB = m.SEQ_DB
where
e.ATIVO = 1 and e.DELETED = 0 and e.EMPRESA in (1, 9999) and e.FILIAL in (1, 9999) and e.LOCAL in (1, 9999)
and c.ATIVO = 1 and c.DELETED = 0 and c.EMPRESA in (1, 9999) and c.FILIAL in (1, 9999) and c.LOCAL in (1, 9999)
and m.ATIVO = 1 and m.DELETED = 0 and m.EMPRESA in (1, 9999) and m.FILIAL in (1, 9999) and m.LOCAL in (1, 9999)
order by
dados.idModelo,
dados.codigoEquipamento,
dados.dataAbertura;
- Entidade "EQUIPAMENTO" e Tipo de Relatório "producao":
select
e.SEQ_DB as idEquipamento,
e.CODIGO as codigoEquipamento,
m.SEQ_DB as idModelo,
m.DESCRICAO as descricaoModelo,
dados.dataAbertura,
dados.dataFinal,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador,
producao as tempoApontado,
divisao
from (
select
eq.SEQ_DB as idEquipamento,
eq.CODIGO as codigoEquipamento,
cl.SEQ_DB as idClasse,
mo.SEQ_DB as idModelo,
mo.DESCRICAO as descricaoModelo,
coalesce(atv.CODIGO, '') as codigoOperacao,
coalesce(atv.DESCRICAO, '') as descOperacao,
coalesce(atv.FLAG_PRODUTIVA, 0) as produtiva,
coalesce(op.CRACHA, '') as codigoOperador,
coalesce(op.NOME, '') as nomeOperador,
se.SEQ_DB as idRegional,
sum(pr.producao) as producao,
concat(fz.CODIGO, '-', coalesce(tl.CODIGO, '')) as divisao,
ap.INI_DH as dataAbertura,
ap.FIM_DH as dataFinal
from app_apontamento_maquina as ap
inner join app_boletim_maquina bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_equipamento eq on eq.SEQ_DB = bo.EQUIPAMENTO_SEQ_DB
inner join app_modelo mo on mo.SEQ_DB = eq.MODELO_SEQ_DB
inner join app_classe_operacional cl on cl.SEQ_DB = eq.CLASSE_OPERACIONAL_SEQ_DB
inner join app_setor se on se.SEQ_DB = ap.SETOR_SEQ_DB
left join app_atividade atv on atv.SEQ_DB = ap.ATIVIDADE_SEQ_DB
left join app_operador op on op.SEQ_DB = bo.OPERADOR_SEQ_DB
left join app_apontamento_maquina_producao pr on pr.SEQ_DB_DEVICE_MASTER_SEQ_DB = bo.SEQ_DB and pr.ATIVIDADE_SEQ_DB = atv.SEQ_DB
left join app_fazenda fz on fz.SEQ_DB = ap.FAZENDA_SEQ_DB
left join app_talhao tl on tl.SEQ_DB = pr.TALHAO_SEQ_DB
where
ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (1, 9999) and ap.FILIAL in (1, 9999) and ap.LOCAL in (1, 9999)
and ap.FIM_DH is not null
and ap.INI_DH between '2019-01-23 00:00:00' and '2019-01-27 23:59:59'
and date(ap.INI_DH) = date(ap.FIM_DH)
group by
idEquipamento,
codigoEquipamento,
idClasse,
idModelo,
descricaoModelo,
ap.FIM_DH,
ap.INI_DH,
idRegional,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador,
divisao
union all
select
eq.SEQ_DB as idEquipamento,
eq.CODIGO as codigoEquipamento,
cl.SEQ_DB as idClasse,
mo.SEQ_DB as idModelo,
mo.DESCRICAO as descricaoModelo,
coalesce(atv.CODIGO, '') as codigoOperacao,
coalesce(atv.DESCRICAO, '') as descOperacao,
coalesce(atv.FLAG_PRODUTIVA, 0) as produtiva,
coalesce(op.CRACHA, '') as codigoOperador,
coalesce(op.NOME, '') as nomeOperador,
se.SEQ_DB as idRegional,
sum(pr.producao) as producao,
concat(fz.CODIGO, '-', coalesce(tl.CODIGO, '')) as divisao,
ap.INI_DH as dataAbertura,
concat(date(ap.INI_DH), ' 23:59:59') as dataFinal
from app_apontamento_maquina as ap
inner join app_boletim_maquina bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_equipamento eq on eq.SEQ_DB = bo.EQUIPAMENTO_SEQ_DB
inner join app_modelo mo on mo.SEQ_DB = eq.MODELO_SEQ_DB
inner join app_classe_operacional cl on cl.SEQ_DB = eq.CLASSE_OPERACIONAL_SEQ_DB
inner join app_setor se on se.SEQ_DB = ap.SETOR_SEQ_DB
left join app_atividade atv on atv.SEQ_DB = ap.ATIVIDADE_SEQ_DB
left join app_operador op on op.SEQ_DB = bo.OPERADOR_SEQ_DB
left join app_apontamento_maquina_producao pr on pr.SEQ_DB_DEVICE_MASTER_SEQ_DB = bo.SEQ_DB and pr.ATIVIDADE_SEQ_DB = atv.SEQ_DB
left join app_fazenda fz on fz.SEQ_DB = ap.FAZENDA_SEQ_DB
left join app_talhao tl on tl.SEQ_DB = pr.TALHAO_SEQ_DB
where
ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (1, 9999) and ap.FILIAL in (1, 9999) and ap.LOCAL in (1, 9999)
and ap.FIM_DH is not null
and (ap.INI_DH between '2019-01-23 00:00:00' and '2019-01-27 23:59:59' or ap.FIM_DH between '2019-01-23 00:00:00' and '2019-01-27 23:59:59')
and ap.INI_DH >= '2019-01-23 00:00:00'
and date(ap.INI_DH) < date(ap.FIM_DH)
group by
idEquipamento,
codigoEquipamento,
idClasse,
idModelo,
descricaoModelo,
ap.FIM_DH,
ap.INI_DH,
idRegional,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador,
divisao
union all
select
eq.SEQ_DB as idEquipamento,
eq.CODIGO as codigoEquipamento,
cl.SEQ_DB as idClasse,
mo.SEQ_DB as idModelo,
mo.DESCRICAO as descricaoModelo,
coalesce(atv.CODIGO, '') as codigoOperacao,
coalesce(atv.DESCRICAO, '') as descOperacao,
coalesce(atv.FLAG_PRODUTIVA, 0) as produtiva,
coalesce(op.CRACHA, '') as codigoOperador,
coalesce(op.NOME, '') as nomeOperador,
se.SEQ_DB as idRegional,
sum(pr.producao) as producao,
concat(fz.CODIGO, '-', coalesce(tl.CODIGO, '')) as divisao,
concat(date_add(date(ap.INI_DH), interval 1 day), ' 00:00:00') as dataAbertura,
ap.FIM_DH as dataFinal
from app_apontamento_maquina as ap
inner join app_boletim_maquina bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_equipamento eq on eq.SEQ_DB = bo.EQUIPAMENTO_SEQ_DB
inner join app_modelo mo on mo.SEQ_DB = eq.MODELO_SEQ_DB
inner join app_classe_operacional cl on cl.SEQ_DB = eq.CLASSE_OPERACIONAL_SEQ_DB
inner join app_setor se on se.SEQ_DB = ap.SETOR_SEQ_DB
left join app_atividade atv on atv.SEQ_DB = ap.ATIVIDADE_SEQ_DB
left join app_operador op on op.SEQ_DB = bo.OPERADOR_SEQ_DB
left join app_apontamento_maquina_producao pr on pr.SEQ_DB_DEVICE_MASTER_SEQ_DB = bo.SEQ_DB and pr.ATIVIDADE_SEQ_DB = atv.SEQ_DB
left join app_fazenda fz on fz.SEQ_DB = ap.FAZENDA_SEQ_DB
left join app_talhao tl on tl.SEQ_DB = pr.TALHAO_SEQ_DB
where
ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (1, 9999) and ap.FILIAL in (1, 9999) and ap.LOCAL in (1, 9999)
and ap.FIM_DH is not null
and ap.INI_DH >= '2019-01-23 00:00:00'
and ap.FIM_DH <= '2019-01-27 23:59:59'
and date(ap.INI_DH) < date(ap.FIM_DH)
group by
idEquipamento,
codigoEquipamento,
idClasse,
idModelo,
descricaoModelo,
ap.FIM_DH,
ap.INI_DH,
idRegional,
codigoOperacao,
descOperacao,
produtiva,
codigoOperador,
nomeOperador,
divisao
) dados
right join app_equipamento e on e.SEQ_DB = dados.idEquipamento
inner join app_classe_operacional c on e.CLASSE_OPERACIONAL_SEQ_DB = c.SEQ_DB
inner join app_modelo m on e.MODELO_SEQ_DB = m.SEQ_DB
where
e.ATIVO = 1 and e.DELETED = 0 and e.EMPRESA in (1, 9999) and e.FILIAL in (1, 9999) and e.LOCAL in (1, 9999)
and c.ATIVO = 1 and c.DELETED = 0 and c.EMPRESA in (1, 9999) and c.FILIAL in (1, 9999) and c.LOCAL in (1, 9999)
and m.ATIVO = 1 and m.DELETED = 0 and m.EMPRESA in (1, 9999) and m.FILIAL in (1, 9999) and m.LOCAL in (1, 9999)
order by
dados.idModelo,
dados.codigoEquipamento,
dados.dataAbertura;
Exemplo de um Mapa de Apontamento por de Mão de Obra
Caracteriza-se Mão de Obra nesse caso onde tem Encarregado e o mesmo aponta 1 ou mais operadores.
INSERT INTO nfs_mapa_generico_relatorio (SEQ_DB, MAPA_GENERICO_SEQ_DB, TIPO_RELATORIO, QUERY_STATEMENTS, DISPLAY_FIELDS, SUBQUERY_STATEMENTS, ENABLED) VALUES(1, 1, 'porcentagem', '{
"SELECT": [
"timestampdiff(second, cast(dataAbertura as datetime), cast(dataFinal as datetime)) as tempoApontado"
]
}', '{
"MAIN": "tempoApontado",
"TIPO": "percent",
"DIVISAO": ""
}', NULL, 1);
INSERT INTO nfs_mapa_generico_relatorio (SEQ_DB, MAPA_GENERICO_SEQ_DB, TIPO_RELATORIO, QUERY_STATEMENTS, DISPLAY_FIELDS, SUBQUERY_STATEMENTS, ENABLED) VALUES(2, 1, 'horas', '{
"SELECT": [
"timestampdiff(second, cast(dataAbertura as datetime), cast(dataFinal as datetime)) as tempoApontado"
]
}', '{
"MAIN": "tempoApontado",
"TIPO": "absolute",
"DIVISAO": ""
}', NULL, 1);
INSERT INTO nfs_mapa_generico (SEQ_DB, EMPRESA, FILIAL, `LOCAL`, TABLENAME, TITLE, MAIN_TABLE, DISPLAY_FIELDS, `OPTIONS`, REPORT_DAYS, REPORT_TYPES, QUERY_STATEMENTS, SUBQUERY_STATEMENTS, JORNADA_QUERY, FILTERS, LEGENDS, INDICATORS, ENABLED) VALUES(1, 1, 9999, 9999, 'EFETIVO_FUNCIONARIO', 'Mapa de Apontamentos de Mão de Obra', 'EFETIVO_FUNCIONARIO', '{
"KEY": "idFuncionario",
"TITLE": "crachaFuncionario",
"FIELD_LINK": "idEncarregado",
"DATAS": {
"INI": "dataAbertura",
"FIM": "dataFinal"
},
"COLUNAS": {
"nomeFuncionario": "Funcionário",
"cargoFuncionario": "Cargo"
},
"INDICADOR": "produtiva",
"TOOLTIP": {
"crachaFuncionario": "Crachá Funcionário",
"nomeFuncionario": "Nome Funcionário",
"nomeEncarregado": "Encarregado",
"atividade": "Atividade/Perda"
}
}', '{
"JORNADA_PADRAO": 8
}', '{
"5": {
"label": "-5 dias",
"value": 5,
"selected": true
},
"10": {
"label": "-10 dias",
"value": 10,
"selected": false
},
"15": {
"label": "-15 dias",
"value": 15,
"selected": false
}
}', '{
"tipoPorcentagem": {
"value": "porcentagem",
"label": "Porcentagem",
"selected": true
},
"tipoHoras": {
"value": "horas",
"label": "Horas",
"selected": false
}
}', '{
"SELECT": [
"dados.idApontamento",
"car.SEQ_DB as idCargoFuncionario",
"car.DESCRICAO as cargoFuncionario",
"enc.SEQ_DB as idEncarregado",
"ff.SEQ_DB as idFuncionario",
"ff.CRACHA as crachaFuncionario",
"ff.NOME as nomeFuncionario",
"coalesce(enc.CRACHA, '') as crachaEncarregado",
"coalesce(enc.NOME, '') as nomeEncarregado",
"dados.atividade",
"dados.produtiva",
"dados.dataAbertura",
"dados.dataFinal"
],
"FROM": [],
"SUBQUERY": ["dados", "idFuncionario"],
"JOIN": [
"inner join app_efetivo_funcionario ff on ff.SEQ_DB = dados.idFuncionario",
"inner join app_efetivo_funcionario enc on enc.SEQ_DB = dados.idEncarregado",
"left join app_efetivo_funcao car on car.SEQ_DB = dados.idCargoFuncionario"
],
"WHERE": [
"ff.ATIVO = 1 and ff.DELETED = 0 and ff.EMPRESA in (:empresa, 9999) and ff.FILIAL in (:filial, 9999) and ff.LOCAL in (:local, 9999)",
"enc.ATIVO = 1 and enc.DELETED = 0 and enc.EMPRESA in (:empresa, 9999) and enc.FILIAL in (:filial, 9999) and enc.LOCAL in (:local, 9999)",
"car.ATIVO = 1 and car.DELETED = 0 and car.EMPRESA in (:empresa, 9999) and car.FILIAL in (:filial, 9999) and car.LOCAL in (:local, 9999)"
],
"ORDER_BY": [
"dados.dataAbertura",
"nomeFuncionario"
]
}', '{
"SELECT": [
"ap.SEQ_DB as idApontamento",
"f.SEQ_DB as idFuncionario",
"coalesce(f.CRACHA, '') as crachaFuncionario",
"coalesce(f.NOME, '') as nomeFuncionario",
"e.SEQ_DB as idEncarregado",
"coalesce(e.CRACHA, '') as crachaEncarregado",
"coalesce(e.NOME, '') as nomeEncarregado",
"ca.SEQ_DB as idCargoFuncionario",
"coalesce(ca.DESCRICAO, '') as cargoFuncionario",
"if(ap.TIPO_APONTAMENTO = 1, 1, 0) produtiva",
"case when (ap.OPER_SEQ_DB IS NULL) then coalesce(i.DESCRICAO, '') when (ap.OPER_SEQ_DB IS NOT NULL AND ap.INTERFERENCIA_SEQ_DB IS NOT NULL) then coalesce(i.DESCRICAO, '') else coalesce(ati.DESCRICAO, '') end as atividade"
],
"FROM": [
["app_mo_apt", "ap"]
],
"JOIN": [
"inner join app_mo_boletim bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB ",
"inner join app_efetivo_funcionario f ON ap.OPERADOR_SEQ_DB = f.SEQ_DB",
"inner join app_efetivo_funcionario e ON ap.EFETIVO_FUNCIONARIO_SEQ_DB = e.SEQ_DB",
"left join app_oper ati ON ap.OPER_SEQ_DB = ati.SEQ_DB",
"left join app_interferencia i ON ap.INTERFERENCIA_SEQ_DB = i.SEQ_DB",
"left join app_efetivo_funcao ca ON f.EFETIVO_FUNCAO_SEQ_DB = ca.SEQ_DB"
],
"WHERE": [
"ap.ATIVO = 1 and ap.DELETED = 0 and ap.EMPRESA in (:empresa, 9999) and ap.FILIAL in (:filial, 9999) and ap.LOCAL in (:local, 9999) and ap.FIM_DH is not null"
],
"GROUP_BY": [
"idApontamento",
"idFuncionario",
"crachaFuncionario",
"nomeFuncionario",
"idCargoFuncionario",
"cargoFuncionario",
"idEncarregado",
"crachaEncarregado",
"nomeEncarregado",
"atividade",
"ap.TIPO_APONTAMENTO",
"ap.FIM_DH",
"ap.INI_DH"
],
"UNION": [{
"SELECT": [
"ap.INI_DH as dataAbertura",
"ap.FIM_DH as dataFinal"
],
"WHERE": [
"ap.INI_DH between concat(:de, ' 00:00:00') and concat(:ate, ' 23:59:59')",
"date(ap.INI_DH) = date(ap.FIM_DH)"
]
},{
"SELECT": [
"ap.INI_DH as dataAbertura",
"concat(date(ap.INI_DH), ' 23:59:59') as dataFinal"
],
"WHERE": [
"(ap.INI_DH between concat(:de, ' 00:00:00') and concat(:ate, ' 23:59:59') or ap.FIM_DH between concat(:de, ' 00:00:00') and concat(:ate, ' 23:59:59'))",
"ap.INI_DH >= concat(:de, ' 00:00:00')",
"date(ap.INI_DH) < date(ap.FIM_DH)"
]
},{
"SELECT": [
"concat(date_add(date(ap.INI_DH), interval 1 day), '' 00:00:00'') as dataAbertura",
"ap.FIM_DH as dataFinal"
],
"WHERE": [
"ap.INI_DH >= concat(:de, ' 00:00:00')",
"ap.FIM_DH <= concat(:ate, ' 23:59:59')",
"date(ap.INI_DH) < date(ap.FIM_DH)"
]
}]
}', '{}', '{
"efetivo_funcionario": {
"label": "Funcionário",
"query_alias": "ff",
"subquery_alias": "f",
"id": "SEQ_DB",
"descricao": "NOME",
"multiple": true,
"subfilter": ""
},
"efetivo_funcao": {
"label": "Cargo",
"query_alias": "car",
"subquery_alias": "ca",
"id": "SEQ_DB",
"descricao": "DESCRICAO",
"multiple": true,
"subfilter": "funcionario"
}
}', '{
"zero": {
"label": "0%",
"color": "#FF5050",
"eval": "[percent] == 0"
},
"insatisfatorio": {
"label": "> 0%",
"color": "#E59400",
"eval": "[percent] > 0 && [percent] < 50"
},
"satisfatorio": {
"label": ">= 50%",
"color": "#ffff00",
"eval": "[percent] >= 50 && [percent] < 90"
},
"otimo": {
"label": ">= 90%",
"color": "#92D050",
"eval": "[percent] >= 90"
}
}', '{
"produtiva": {
"value": 1,
"label": "Produtiva",
"color": "#92D050"
},
"improdutiva": {
"value": 0,
"label": "Improdutiva",
"color": "#FF5050"
}
}', 1);
Resultado em SQL:
Prestar atenção no WHERE que estão filtras pela empresa, filial, local, período e funcionario (808) da civilmaster-mo;
select
dados.idApontamento,
car.SEQ_DB as idCargoFuncionario,
car.DESCRICAO as cargoFuncionario,
enc.SEQ_DB as idEncarregado,
ff.SEQ_DB as idFuncionario,
ff.CRACHA as crachaFuncionario,
ff.NOME as nomeFuncionario,
coalesce(enc.CRACHA, '') as crachaEncarregado,
coalesce(enc.NOME, '') as nomeEncarregado,
dados.atividade,
dados.dataAbertura,
dados.dataFinal,
timestampdiff(second,
cast(dataAbertura as datetime),
cast(dataFinal as datetime)) as tempoApontado
from
(
select
ap.SEQ_DB as idApontamento,
f.SEQ_DB as idFuncionario,
coalesce(f.CRACHA, '') as crachaFuncionario,
coalesce(f.NOME, '') as nomeFuncionario,
e.SEQ_DB as idEncarregado,
coalesce(e.CRACHA, '') as crachaEncarregado,
coalesce(e.NOME, '') as nomeEncarregado,
ca.SEQ_DB as idCargoFuncionario,
coalesce(ca.DESCRICAO, '') as cargoFuncionario,
case
when (ap.OPER_SEQ_DB is null) then coalesce(i.DESCRICAO, '')
when (ap.OPER_SEQ_DB is not null
and ap.INTERFERENCIA_SEQ_DB is not null) then coalesce(i.DESCRICAO, '')
else coalesce(ati.DESCRICAO, '')
end as atividade,
ap.INI_DH as dataAbertura,
ap.FIM_DH as dataFinal
from app_mo_apt as ap
inner join app_mo_boletim bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_efetivo_funcionario f on ap.OPERADOR_SEQ_DB = f.SEQ_DB
inner join app_efetivo_funcionario e on ap.EFETIVO_FUNCIONARIO_SEQ_DB = e.SEQ_DB
left join app_oper ati on ap.OPER_SEQ_DB = ati.SEQ_DB
left join app_interferencia i on ap.INTERFERENCIA_SEQ_DB = i.SEQ_DB
left join app_efetivo_funcao ca on f.EFETIVO_FUNCAO_SEQ_DB = ca.SEQ_DB
where
ap.ATIVO = 1
and ap.DELETED = 0
and ap.EMPRESA in (1, 9999)
and ap.FILIAL in (1, 9999)
and ap.LOCAL in (9, 9999)
and ap.FIM_DH is not null
and f.SEQ_DB in (880)
and ap.INI_DH between '2023-03-10 00:00:00' and '2023-03-14 23:59:59'
and date(ap.INI_DH) = date(ap.FIM_DH)
group by
idApontamento,
idFuncionario,
crachaFuncionario,
nomeFuncionario,
idCargoFuncionario,
cargoFuncionario,
idEncarregado,
crachaEncarregado,
nomeEncarregado,
atividade,
ap.FIM_DH,
ap.INI_DH
union all
select
ap.SEQ_DB as idApontamento,
f.SEQ_DB as idFuncionario,
coalesce(f.CRACHA, '') as crachaFuncionario,
coalesce(f.NOME, '') as nomeFuncionario,
e.SEQ_DB as idEncarregado,
coalesce(e.CRACHA, '') as crachaEncarregado,
coalesce(e.NOME, '') as nomeEncarregado,
ca.SEQ_DB as idCargoFuncionario,
coalesce(ca.DESCRICAO, '') as cargoFuncionario,
case
when (ap.OPER_SEQ_DB is null) then coalesce(i.DESCRICAO, '')
when (ap.OPER_SEQ_DB is not null
and ap.INTERFERENCIA_SEQ_DB is not null) then coalesce(i.DESCRICAO, '')
else coalesce(ati.DESCRICAO, '')
end as atividade,
ap.INI_DH as dataAbertura,
concat(date(ap.INI_DH), ' 23:59:59') as dataFinal
from app_mo_apt as ap
inner join app_mo_boletim bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_efetivo_funcionario f on ap.OPERADOR_SEQ_DB = f.SEQ_DB
inner join app_efetivo_funcionario e on ap.EFETIVO_FUNCIONARIO_SEQ_DB = e.SEQ_DB
left join app_oper ati on ap.OPER_SEQ_DB = ati.SEQ_DB
left join app_interferencia i on ap.INTERFERENCIA_SEQ_DB = i.SEQ_DB
left join app_efetivo_funcao ca on f.EFETIVO_FUNCAO_SEQ_DB = ca.SEQ_DB
where
ap.ATIVO = 1
and ap.DELETED = 0
and ap.EMPRESA in (1, 9999)
and ap.FILIAL in (1, 9999)
and ap.LOCAL in (9, 9999)
and ap.FIM_DH is not null
and f.SEQ_DB in (880)
and (ap.INI_DH between '2023-03-10 00:00:00' and '2023-03-14 23:59:59'
or ap.FIM_DH between '2023-03-10 00:00:00' and '2023-03-14 23:59:59')
and ap.INI_DH >= '2023-03-10 23:59:59'
and date(ap.INI_DH) < date(ap.FIM_DH)
group by
idApontamento,
idFuncionario,
crachaFuncionario,
nomeFuncionario,
idCargoFuncionario,
cargoFuncionario,
idEncarregado,
crachaEncarregado,
nomeEncarregado,
atividade,
ap.FIM_DH,
ap.INI_DH
union all
select
ap.SEQ_DB as idApontamento,
f.SEQ_DB as idFuncionario,
coalesce(f.CRACHA, '') as crachaFuncionario,
coalesce(f.NOME, '') as nomeFuncionario,
e.SEQ_DB as idEncarregado,
coalesce(e.CRACHA, '') as crachaEncarregado,
coalesce(e.NOME, '') as nomeEncarregado,
ca.SEQ_DB as idCargoFuncionario,
coalesce(ca.DESCRICAO, '') as cargoFuncionario,
case
when (ap.OPER_SEQ_DB is null) then coalesce(i.DESCRICAO, '')
when (ap.OPER_SEQ_DB is not null
and ap.INTERFERENCIA_SEQ_DB is not null) then coalesce(i.DESCRICAO, '')
else coalesce(ati.DESCRICAO, '')
end as atividade,
concat(date_add(date(ap.INI_DH), interval 1 day), ' 00:00:00') as dataAbertura,
ap.FIM_DH as dataFinal
from app_mo_apt as ap
inner join app_mo_boletim bo on bo.SEQ_DB = ap.SEQ_DB_DEVICE_MASTER_SEQ_DB
inner join app_efetivo_funcionario f on ap.OPERADOR_SEQ_DB = f.SEQ_DB
inner join app_efetivo_funcionario e on ap.EFETIVO_FUNCIONARIO_SEQ_DB = e.SEQ_DB
left join app_oper ati on ap.OPER_SEQ_DB = ati.SEQ_DB
left join app_interferencia i on ap.INTERFERENCIA_SEQ_DB = i.SEQ_DB
left join app_efetivo_funcao ca on f.EFETIVO_FUNCAO_SEQ_DB = ca.SEQ_DB
where
ap.ATIVO = 1
and ap.DELETED = 0
and ap.EMPRESA in (1, 9999)
and ap.FILIAL in (1, 9999)
and ap.LOCAL in (9, 9999)
and ap.FIM_DH is not null
and f.SEQ_DB in (880)
and ap.INI_DH >= '2023-03-10 00:00:00'
and ap.FIM_DH <= '2023-03-14 23:59:59'
and date(ap.INI_DH) < date(ap.FIM_DH)
group by
idApontamento,
idFuncionario,
crachaFuncionario,
nomeFuncionario,
idCargoFuncionario,
cargoFuncionario,
idEncarregado,
crachaEncarregado,
nomeEncarregado,
atividade
) dados
inner join app_efetivo_funcionario ff on ff.SEQ_DB = dados.idFuncionario
inner join app_efetivo_funcionario enc on enc.SEQ_DB = dados.idEncarregado
left join app_efetivo_funcao car on car.SEQ_DB = dados.idCargoFuncionario
where
ff.ATIVO = 1
and ff.DELETED = 0
and ff.EMPRESA in (1, 9999)
and ff.FILIAL in (1, 9999)
and ff.LOCAL in (9, 9999)
and enc.ATIVO = 1
and enc.DELETED = 0
and enc.EMPRESA in (1, 9999)
and enc.FILIAL in (1, 9999)
and enc.LOCAL in (9, 9999)
and car.ATIVO = 1
and car.DELETED = 0
and car.EMPRESA in (1, 9999)
and car.FILIAL in (1, 9999)
and car.LOCAL in (9, 9999)
and ((ff.SEQ_DB in (880)) or (dados.idFuncionario in (880)))
order by
dados.dataAbertura,
nomeFuncionario
Definindo cor e texto dos indicadores
Através dos ALIAS indicatorColor e indicatorLegend configurados ao montar o mapa, pode ser especificado qual a cor e texto da legenda:
1. Alterando as SUBQUERY_STATEMENTS

- 1 - Faço o inner join da tabela grupo atividades
- 2 - Retorno no nome do grupo como indicatorLegend e a cor do grupo como indicatorColor
2. Configuração da QUERY_STATEMENTS
Após a definição dos aliases na SUBQUERY_STATEMENTS, basta trazer o resultado na QUERY para que os efeitos sejam aplicados no mapa de apontamentos

Neste caso criei uma coluna da tabela de grupo de atividade onde defino a cor

Resultado:

3. Extras
Criação da coluna de cores no grupo de atividades:
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, CONFIG)
VALUES('GRUPO_ATIVIDADE', 'COR', 4, 0, 1, 1, 1, 'Cor', 'Cor', 'COLOR', NULL, NULL, NULL, NULL, 'IU', '0', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);