snglpi/README.md

207 lines
12 KiB
Markdown
Raw Normal View History

# Sistema de Sincronização ServiceNow <> GLPI
2025-08-30 19:04:35 -03:00
## Visão Geral
2025-08-30 19:04:35 -03:00
Esta aplicação Node.js é um middleware projetado para realizar a sincronização bidirecional de tickets entre uma instância do **ServiceNow (SNOW)** e uma do **GLPI**. O objetivo é manter os tickets, seus status e comentários consistentes entre as duas plataformas, automatizando o fluxo de trabalho para as equipes de suporte.
2025-08-30 19:04:35 -03:00
A aplicação funciona como um job agendado (por exemplo, via cron) que executa um ciclo completo de sincronização.
2025-08-30 19:04:35 -03:00
---
2025-08-30 19:04:35 -03:00
## Como Executar a Aplicação
Esta seção contém as instruções essenciais para configurar e rodar a aplicação em diferentes ambientes.
### 1. Pré-requisitos
- **Node.js**: Certifique-se de ter o Node.js (versão 18 ou superior) instalado.
- **Dependências**: Na raiz do projeto, execute o comando abaixo para instalar todas as dependências necessárias:
```bash
npm install
```
- **Arquivos de Ambiente**: Crie os arquivos `.env.development` e `.env.production` na raiz do projeto, baseando-se no exemplo `.env.example` (se houver) e preenchendo com as credenciais e URLs corretas para cada ambiente.
### 2. Executando com Scripts NPM
### 2. Configuração do Ambiente Python
A aplicação utiliza um script Python para sincronizar o mapeamento de localidades.
#### a) Dependências Python
Navegue até a pasta do script e instale as dependências listadas no `requirements.txt`:
```bash
cd src/scripts/python
pip install -r requirements.txt
```
#### b) Montagem do Compartilhamento de Arquivos (CIFS/Samba)
O script Python lê um arquivo `.csv` de um compartilhamento de rede. No servidor de produção, é necessário montar este compartilhamento para que o caminho definido em `LOCATION_MAPPING_CSV_PATH` seja acessível.
Adicione a seguinte linha ao seu arquivo `/etc/fstab` para montar o compartilhamento automaticamente durante o boot do sistema. **Ajuste o IP, credenciais e caminhos conforme necessário.**
```fstab
//10.0.121.40/Tecnica/Controle\040CAOA/ENTIDADE\040SERVICE\040NOW /mnt/csv_share cifs username=<seu_usuario>,password=<sua_senha>,uid=1000,gid=1000,iocharset=utf8 0 0
```
Após editar o `/etc/fstab`, execute `sudo mount -a` para montar o compartilhamento imediatamente.
Os comandos abaixo utilizam a variável `NODE_ENV` para carregar o arquivo de ambiente (`.env`) correto.
#### Ambiente de Desenvolvimento
Para rodar em modo de desenvolvimento com reinício automático a cada alteração de arquivo (usando `nodemon`):
```bash
npm run dev
```
#### Ambiente de Produção
Para rodar a aplicação em modo de produção (usando `node`):
```bash
npm start
```
ou o comando explícito:
```bash
npm run start:prod
```
### 3. Executando com PM2
O PM2 é o gerenciador de processos recomendado para ambientes de produção. Ele garante que a aplicação reinicie automaticamente em caso de falhas e facilita o gerenciamento.
- **Para iniciar em modo de produção:**
```bash
pm2 start ecosystem.config.js --env production
```
- **Para iniciar em modo de desenvolvimento:**
```bash
pm2 start ecosystem.config.js --env development
```
- **Comandos úteis do PM2:**
```bash
pm2 list # Lista todos os processos
pm2 logs sn-glpi-sync-cron # Exibe os logs em tempo real
pm2 restart sn-glpi-sync-cron # Reinicia a aplicação
pm2 stop sn-glpi-sync-cron # Para a aplicação
```
## Fluxo de Execução
2025-08-30 19:04:35 -03:00
A aplicação segue uma ordem de execução estrita para garantir a consistência dos dados. O ponto de entrada é o arquivo `src/app.js`, que orquestra a chamada dos seguintes controladores:
2025-08-30 19:04:35 -03:00
1. **`processErrorController` - Limpeza de Erros**
- **Objetivo**: Aumentar a resiliência do sistema.
- **Ação**: Busca por tickets que falharam em execuções anteriores (marcados com status de `error`). Ele reseta o status desses tickets para um estado anterior válido (ex: `pending_check` ou `synced`), permitindo que eles sejam reprocessados no ciclo atual.
2025-08-30 19:04:35 -03:00
2. **`processTicketsController` - Criação de Tickets**
- **Objetivo**: Trazer novos tickets do ServiceNow para o GLPI.
- **Ação**:
- **Busca no SNOW**: Invoca o `processSyncController` para buscar incidentes e requisições novas ou atualizadas no ServiceNow, utilizando uma "marca d'água" (timestamp) para otimização.
- **Criação no GLPI**: Para cada novo ticket coletado, o `glpiTicketService` é chamado para:
- Verificar se o ticket já existe no GLPI para evitar duplicatas.
- Formatar os dados (título, descrição, categoria, etc.).
- Criar o ticket correspondente no banco de dados do GLPI.
2025-08-30 19:04:35 -03:00
3. **`processCommentsController` - Sincronização de Comentários**
- **Objetivo**: Manter as conversas dos tickets sincronizadas.
- **Ação**: Para cada ticket ativo, realiza uma sincronização bidirecional de comentários (notas/follow-ups):
- **SNOW -> GLPI**: Busca novos comentários no ServiceNow, os salva no banco intermediário e os insere como follow-ups no GLPI.
- **GLPI -> SNOW**: Busca novos follow-ups no GLPI, os sanitiza (remove HTML, trata imagens) e os envia como `work_notes` para o ServiceNow.
2025-08-30 19:04:35 -03:00
4. **`processStatusAndClosureController` - Sincronização de Status e Fechamento**
- **Objetivo**: Manter os status dos tickets alinhados e gerenciar o ciclo de vida (resolução e fechamento).
- **Ação**: Realiza uma sincronização bidirecional de status, tratando reaberturas, pausas, resoluções e fechamentos em ambas as direções.
2025-08-30 19:04:35 -03:00
---
2025-08-30 19:04:35 -03:00
## Regras de Negócio Principais
2025-08-30 19:04:35 -03:00
A aplicação implementa várias regras de negócio para gerenciar a complexidade da sincronização:
2025-08-30 19:04:35 -03:00
### Controle de Fluxo com "Bastão" (`source_last`)
- Para evitar conflitos de atualização (race conditions), o sistema utiliza um campo `source_last` na tabela `ticket_sync`.
- Este campo funciona como um "bastão da palavra": o sistema que realiza a última atualização (SNOW ou GLPI) "segura o bastão".
- O sistema oposto só pode atualizar o ticket se ele estiver com o bastão. Isso garante que as atualizações de status e comentários ocorram de forma ordenada.
2025-08-30 19:04:35 -03:00
### Criação e Enriquecimento de Tickets
- **Mapeamento**: Tickets do ServiceNow são mapeados para o GLPI com base em regras de categoria, prioridade e SLA definidas no `ticketGlpiModel.js`.
- **Título**: O título do ticket no GLPI é padronizado como `[TIPO] - [ENTIDADE] - [TÍTULO ORIGINAL]`.
- **Enriquecimento de Descrição**: Se uma requisição do ServiceNow chega com a descrição vazia, o sistema busca automaticamente o conteúdo de variáveis de catálogo (como `justificativa` e `telefone`) e as utiliza para preencher a descrição e os dados do ticket no GLPI.
2025-08-30 19:04:35 -03:00
### Sincronização de Comentários
- **Lógica de 4 Casos (GLPI -> SNOW)**: Para evitar duplicatas, a sincronização de comentários do GLPI para o SNOW verifica 4 cenários:
1. **Já Sincronizado**: O comentário existe em ambos os locais. Nenhuma ação.
2. **Existe no SN, Falta no BD Local**: O registro local é criado para corrigir o estado.
3. **Existe no BD Local, Falta no SN**: O comentário é reenviado para o ServiceNow.
4. **Novo Comentário**: O comentário é enviado para o SNOW e registrado localmente.
- **Sanitização**: Comentários do GLPI passam por um processo de limpeza (`commentSanitizer.js`) que remove tags HTML e substitui imagens por um texto placeholder, garantindo que o conteúdo seja legível no ServiceNow.
2025-08-30 19:04:35 -03:00
### Sincronização de Status
- **Fechamento de Ticket em Espera**: Se um ticket é resolvido no GLPI, mas seu correspondente no ServiceNow está com o status "Em Espera" ou "Aguardando Atendimento", o sistema primeiro altera o status no ServiceNow para "Em Atendimento" e só então prossegue com a resolução. Isso automatiza o fluxo e evita falhas.
- **Regra "Fora do Escopo"**: Se um ticket no GLPI é solucionado com o tipo de solução "Fora do Escopo", o sistema não o resolve no ServiceNow. Em vez disso, ele adiciona uma nota de trabalho (`work_note`) explicando o motivo e fecha o registro de sincronização, tratando-o como um caso especial.
- **Reabertura**: O sistema permite a reabertura de tickets em ambas as direções, desde que o ticket não esteja permanentemente fechado.
2025-08-30 19:04:35 -03:00
### Ambientes (`.env`)
- A aplicação suporta múltiplos ambientes através de arquivos `.env`.
- Se a variável de ambiente `NODE_ENV` for definida como `production`, o arquivo `.env.production` será carregado.
- Caso contrário (ou se `NODE_ENV` for `development`), o arquivo `.env.development` será utilizado.
2025-08-30 19:04:35 -03:00
### Atualização do Mapeamento de Localidades (`update_location.py`)
- A aplicação conta com um script Python (`src/scripts/python/update_location.py`) para manter o mapeamento entre as localidades do ServiceNow e as entidades do GLPI.
- **Fonte da Verdade**: Um arquivo `.csv` localizado em um servidor de arquivos (`LOCATION_MAPPING_CSV_PATH` no `.env`) é a fonte da verdade para este mapeamento.
- **Processo**:
1. Um usuário (`sothis`) atualiza o arquivo `.csv` com as correspondências corretas entre os nomes das localidades (SNOW) e os nomes das entidades (GLPI).
2. Um `cron job` no servidor executa o script `update_location.py` periodicamente.
3. O script lê o `.csv`, busca os IDs correspondentes nos bancos de dados de ambos os sistemas e recria a tabela `location_mapping` no banco de dados intermediário (PostgreSQL).
- **Resultado**: Garante que os tickets criados no GLPI sejam sempre associados à entidade correta, com base em um mapeamento centralizado e de fácil manutenção.
---
2025-08-30 19:04:35 -03:00
## Estrutura do Banco de Dados Intermediário (PostgreSQL)
2025-08-30 19:04:35 -03:00
- **`tickets_sn`**: Armazena uma cópia local dos dados dos tickets do ServiceNow para otimizar consultas.
- **`ticket_sync`**: Tabela central que controla o estado da sincronização de cada ticket, incluindo os IDs de ambos os sistemas e o campo `source_last`.
- **`ticket_updates`**: Log de todas as atualizações (comentários, etc.), usado para evitar duplicidade e rastrear o histórico.
- **`location_mapping`**: Tabela de mapeamento entre as localizações do ServiceNow e as entidades do GLPI.
- **`sync_control`**: Armazena metadados do processo, como a marca d'água (timestamp) da última sincronização bem-sucedida.
2025-08-30 19:04:35 -03:00
---
2025-08-30 19:04:35 -03:00
## Diagrama de Fluxo (Exemplo)
2025-08-30 19:04:35 -03:00
### Sincronização de Resolução: GLPI -> ServiceNow
2025-08-30 19:04:35 -03:00
O diagrama abaixo ilustra como o sistema lida com um ticket que foi marcado como "Solucionado" no GLPI.
2025-08-30 19:04:35 -03:00
```mermaid
sequenceDiagram
participant App as app.js
participant StatusCtrl as processStatusAndClosureController
participant GlpiModel as TicketGlpiModel
participant SyncModel as TicketSyncModel
participant SnowService as servicenowService
participant ServiceNow as ServiceNow API
App->>StatusCtrl: Iniciar ciclo de status
StatusCtrl->>SyncModel: getTicketsToMonitor()
SyncModel-->>StatusCtrl: Lista de tickets ativos
loop Para cada ticket monitorado
StatusCtrl->>GlpiModel: getTicketStatus(glpi_id)
GlpiModel-->>StatusCtrl: Status 'Solucionado' (5)
alt Status mudou para 'Solucionado'
StatusCtrl->>GlpiModel: getTicketSolution(glpi_id)
GlpiModel-->>StatusCtrl: Detalhes da solução
StatusCtrl->>SnowService: closeTicketInServiceNow(sn_id, solucao)
SnowService->>ServiceNow: PATCH /api/now/table/incident/{sys_id} (state: 'Resolved')
ServiceNow-->>SnowService: 200 OK
SnowService-->>StatusCtrl: Sucesso
StatusCtrl->>SyncModel: updateStatus(sn_id, 'solved', 'solved')
SyncModel-->>StatusCtrl: OK
end
end
```