Snapshot of the pre-existing, working V1 automation (n8n workflow + SQL query + docker-compose + README) exactly as found on disk, before any V2 changes. .env is intentionally not tracked (gitignored, contains local secrets). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
214 lines
7.4 KiB
SQL
214 lines
7.4 KiB
SQL
-- Top 10 chamados abertos por blocos operacionais.
|
|
-- Blocos:
|
|
-- - 3 chamados com SLA vencido mais criticos
|
|
-- - 3 chamados com maior tempo sem interacao
|
|
-- - 2 chamados sem tecnico atribuido
|
|
-- - 2 chamados de prioridade alta mais recentes
|
|
-- Se faltar item em algum bloco, o complemento vem do ranking geral.
|
|
--
|
|
-- Ajuste os parametros abaixo no workflow n8n:
|
|
-- {DIAS_SEM_INTERACAO_ALERTA}
|
|
-- {HORAS_SLA_RISCO}
|
|
-- {GLPI_BASE_URL}
|
|
|
|
WITH ultima_interacao AS (
|
|
SELECT
|
|
tickets_id,
|
|
MAX(data_interacao) AS ultima_interacao_em
|
|
FROM (
|
|
SELECT tickets_id, MAX(data_interacao) AS data_interacao
|
|
FROM (
|
|
SELECT items_id AS tickets_id, date AS data_interacao
|
|
FROM glpi_itilfollowups
|
|
WHERE itemtype = 'Ticket'
|
|
AND is_private = 0
|
|
|
|
UNION ALL
|
|
|
|
SELECT items_id AS tickets_id, date_mod AS data_interacao
|
|
FROM glpi_itilfollowups
|
|
WHERE itemtype = 'Ticket'
|
|
AND is_private = 0
|
|
|
|
UNION ALL
|
|
|
|
SELECT items_id AS tickets_id, date_creation AS data_interacao
|
|
FROM glpi_itilfollowups
|
|
WHERE itemtype = 'Ticket'
|
|
AND is_private = 0
|
|
) followup_datas
|
|
WHERE data_interacao IS NOT NULL
|
|
GROUP BY tickets_id
|
|
|
|
UNION ALL
|
|
|
|
SELECT tickets_id, MAX(data_interacao) AS data_interacao
|
|
FROM (
|
|
SELECT tickets_id, date AS data_interacao
|
|
FROM glpi_tickettasks
|
|
|
|
UNION ALL
|
|
|
|
SELECT tickets_id, date_mod AS data_interacao
|
|
FROM glpi_tickettasks
|
|
|
|
UNION ALL
|
|
|
|
SELECT tickets_id, date_creation AS data_interacao
|
|
FROM glpi_tickettasks
|
|
) task_datas
|
|
WHERE data_interacao IS NOT NULL
|
|
GROUP BY tickets_id
|
|
) interacoes
|
|
GROUP BY tickets_id
|
|
), tecnicos AS (
|
|
SELECT
|
|
tu.tickets_id,
|
|
GROUP_CONCAT(TRIM(CONCAT(COALESCE(u.firstname, ''), ' ', COALESCE(u.realname, u.name))) SEPARATOR ', ') AS tecnicos
|
|
FROM glpi_tickets_users tu
|
|
LEFT JOIN glpi_users u ON u.id = tu.users_id
|
|
WHERE tu.type = 2
|
|
GROUP BY tu.tickets_id
|
|
), chamados_base AS (
|
|
SELECT
|
|
t.id,
|
|
t.name AS titulo,
|
|
t.status,
|
|
CASE t.status
|
|
WHEN 1 THEN 'Novo'
|
|
WHEN 2 THEN 'Em atendimento'
|
|
WHEN 3 THEN 'Planejado'
|
|
WHEN 4 THEN 'Pendente'
|
|
ELSE CONCAT('Status ', t.status)
|
|
END AS status_nome,
|
|
t.date AS aberto_em,
|
|
t.date_mod AS modificado_em,
|
|
t.time_to_resolve AS sla_resolver_ate,
|
|
t.priority,
|
|
t.urgency,
|
|
t.impact,
|
|
COALESCE(e.completename, e.name, 'Nao informado') AS entidade,
|
|
COALESCE(c.completename, c.name, 'Sem categoria') AS categoria,
|
|
COALESCE(tecnicos.tecnicos, 'Sem tecnico atribuido') AS tecnico_atribuido,
|
|
GREATEST(
|
|
COALESCE(ultima_interacao.ultima_interacao_em, '1970-01-01 00:00:00'),
|
|
COALESCE(t.date_mod, '1970-01-01 00:00:00'),
|
|
COALESCE(t.date, '1970-01-01 00:00:00')
|
|
) AS ultima_interacao_em,
|
|
TIMESTAMPDIFF(DAY, t.date, NOW()) AS dias_aberto,
|
|
GREATEST(TIMESTAMPDIFF(DAY, GREATEST(
|
|
COALESCE(ultima_interacao.ultima_interacao_em, '1970-01-01 00:00:00'),
|
|
COALESCE(t.date_mod, '1970-01-01 00:00:00'),
|
|
COALESCE(t.date, '1970-01-01 00:00:00')
|
|
), NOW()), 0) AS dias_sem_interacao,
|
|
TIMESTAMPDIFF(HOUR, NOW(), t.time_to_resolve) AS horas_ate_sla,
|
|
CASE WHEN t.time_to_resolve IS NOT NULL AND t.time_to_resolve < NOW() THEN 1 ELSE 0 END AS sla_vencido,
|
|
CASE
|
|
WHEN t.time_to_resolve IS NOT NULL
|
|
AND t.time_to_resolve >= NOW()
|
|
AND TIMESTAMPDIFF(HOUR, NOW(), t.time_to_resolve) <= {HORAS_SLA_RISCO} THEN 1
|
|
ELSE 0
|
|
END AS sla_em_risco,
|
|
CASE WHEN tecnicos.tecnicos IS NULL THEN 1 ELSE 0 END AS sem_tecnico,
|
|
CONCAT('{GLPI_BASE_URL}', '/front/ticket.form.php?id=', t.id) AS link_glpi
|
|
FROM glpi_tickets t
|
|
LEFT JOIN glpi_entities e ON e.id = t.entities_id
|
|
LEFT JOIN glpi_itilcategories c ON c.id = t.itilcategories_id
|
|
LEFT JOIN ultima_interacao ON ultima_interacao.tickets_id = t.id
|
|
LEFT JOIN tecnicos ON tecnicos.tickets_id = t.id
|
|
WHERE t.is_deleted = false
|
|
AND t.status NOT IN (5, 6)
|
|
AND COALESCE(c.completename, c.name, '') NOT LIKE 'ADMINISTRATIVO%'
|
|
AND COALESCE(c.completename, c.name, '') NOT LIKE 'DESENVOLVIMENTO%'
|
|
AND COALESCE(c.completename, c.name, '') NOT LIKE 'INFRA%'
|
|
), chamados_ranked AS (
|
|
SELECT
|
|
id,
|
|
titulo,
|
|
status_nome,
|
|
aberto_em,
|
|
modificado_em,
|
|
ultima_interacao_em,
|
|
dias_aberto,
|
|
dias_sem_interacao,
|
|
sla_resolver_ate,
|
|
horas_ate_sla,
|
|
sla_vencido,
|
|
sla_em_risco,
|
|
priority AS prioridade,
|
|
urgency AS urgencia,
|
|
impact AS impacto,
|
|
entidade,
|
|
categoria,
|
|
tecnico_atribuido,
|
|
sem_tecnico,
|
|
link_glpi,
|
|
(
|
|
CASE WHEN sla_vencido = 1 THEN 100 ELSE 0 END
|
|
+ CASE WHEN sla_em_risco = 1 THEN 45 ELSE 0 END
|
|
+ CASE
|
|
WHEN dias_sem_interacao >= 7 THEN 35
|
|
WHEN dias_sem_interacao >= 3 THEN 25
|
|
WHEN dias_sem_interacao >= {DIAS_SEM_INTERACAO_ALERTA} THEN 10
|
|
ELSE 0
|
|
END
|
|
+ LEAST(dias_aberto, 30)
|
|
+ (priority * 8)
|
|
+ (urgency * 5)
|
|
+ (impact * 5)
|
|
+ CASE WHEN sem_tecnico = 1 THEN 25 ELSE 0 END
|
|
) AS score_criticidade
|
|
FROM chamados_base
|
|
), sla_top AS (
|
|
SELECT *, 'SLA vencido' AS bloco_origem, 1 AS bloco_ordem
|
|
FROM chamados_ranked
|
|
WHERE sla_vencido = 1
|
|
ORDER BY score_criticidade DESC, dias_sem_interacao DESC, dias_aberto DESC
|
|
LIMIT 3
|
|
), sem_interacao_top AS (
|
|
SELECT *, 'Sem interacao' AS bloco_origem, 2 AS bloco_ordem
|
|
FROM chamados_ranked
|
|
WHERE id NOT IN (SELECT id FROM sla_top)
|
|
ORDER BY dias_sem_interacao DESC, score_criticidade DESC, dias_aberto DESC
|
|
LIMIT 3
|
|
), sem_tecnico_top AS (
|
|
SELECT *, 'Sem tecnico' AS bloco_origem, 3 AS bloco_ordem
|
|
FROM chamados_ranked
|
|
WHERE sem_tecnico = 1
|
|
AND id NOT IN (SELECT id FROM sla_top)
|
|
AND id NOT IN (SELECT id FROM sem_interacao_top)
|
|
ORDER BY score_criticidade DESC, dias_sem_interacao DESC, dias_aberto DESC
|
|
LIMIT 2
|
|
), prioridade_alta_recente_top AS (
|
|
SELECT *, 'Prioridade alta recente' AS bloco_origem, 4 AS bloco_ordem
|
|
FROM chamados_ranked
|
|
WHERE prioridade >= 4
|
|
AND id NOT IN (SELECT id FROM sla_top)
|
|
AND id NOT IN (SELECT id FROM sem_interacao_top)
|
|
AND id NOT IN (SELECT id FROM sem_tecnico_top)
|
|
ORDER BY aberto_em DESC, score_criticidade DESC
|
|
LIMIT 2
|
|
), selecionados AS (
|
|
SELECT * FROM sla_top
|
|
UNION ALL
|
|
SELECT * FROM sem_interacao_top
|
|
UNION ALL
|
|
SELECT * FROM sem_tecnico_top
|
|
UNION ALL
|
|
SELECT * FROM prioridade_alta_recente_top
|
|
), complemento AS (
|
|
SELECT *, 'Ranking geral' AS bloco_origem, 5 AS bloco_ordem
|
|
FROM chamados_ranked
|
|
WHERE id NOT IN (SELECT id FROM selecionados)
|
|
ORDER BY score_criticidade DESC, sla_vencido DESC, dias_sem_interacao DESC, dias_aberto DESC
|
|
LIMIT 10
|
|
)
|
|
SELECT *
|
|
FROM (
|
|
SELECT * FROM selecionados
|
|
UNION ALL
|
|
SELECT * FROM complemento
|
|
) ranking_final
|
|
ORDER BY bloco_ordem ASC, score_criticidade DESC, dias_sem_interacao DESC, dias_aberto DESC
|
|
LIMIT 10;
|