-- 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;