# Sistema de Sincronizacao ServiceNow <> GLPI Middleware em Node.js para sincronizacao bidirecional de tickets, comentarios e status entre ServiceNow e GLPI, com banco intermediario PostgreSQL e acesso direto ao banco MySQL/MariaDB do GLPI. ## O que o projeto faz hoje - Busca incidentes e requisicoes no ServiceNow por watermark (`sync_control`). - Salva/atualiza tickets no banco intermediario (`tickets_sn`). - Cria tickets no GLPI para registros pendentes (`ticket_sync.glpi_sync_status = 'pending_check'`). - Sincroniza comentarios em duas direcoes: - ServiceNow -> GLPI - GLPI -> ServiceNow - No fluxo ServiceNow -> GLPI: - `comments` viram comentarios (followups) no GLPI. - `work_notes` viram tarefas no GLPI. - Sincroniza status em duas direcoes com controle de origem (`source_last`: `SNOW`/`GLPI`). - Trata regras de negocio especificas de fechamento/reabertura. - Reprocessa tickets em estado de erro no inicio de cada ciclo. - Executa em job agendado (`node-cron`) com protecao contra concorrencia local (`isCronRunning`). ## Arquitetura ### Componentes - `cron.js`: agenda e dispara o ciclo de sincronizacao. - `src/app.js`: orquestra o ciclo principal. - `src/controllers/*`: fluxo de tickets, comentarios, status e recuperacao de erro. - `src/services/*`: integracoes com ServiceNow e GLPI. - `src/models/*`: acesso a dados (PostgreSQL e GLPI MySQL). - `src/data/*`: pools de conexao (`pg` e `mysql2`). - `src/scripts/python/update_location_mapping.py`: atualiza tabela `location_mapping` a partir de CSV. ### Bancos envolvidos - PostgreSQL (`snglpi`): estado da integracao. - MySQL/MariaDB (GLPI): criacao/consulta/atualizacao de tickets e followups. ## Fluxo do ciclo Executado em ordem pelo `main()`: 1. `processErrorController` 2. `processTicketsController` 3. `processCommentsController` 4. `processStatusAndClosureController` ## Regras de negocio importantes - Controle de precedencia por `source_last` para reduzir conflito de atualizacao. - Ao detectar divergencia de status, o bastao nao e invertido para `GLPI` quando a ultima origem valida ja e `SNOW`. - Encerramento/Resolucao vindo do ServiceNow: - Nao fecha ticket no GLPI automaticamente. - Insere nota formatada no GLPI. - Marca sync como `closed/closed` para remover do monitoramento. - Ticket resolvido no GLPI com `solutiontypes_id = GLPI_OOS_SOLUTION_TYPE_ID` (fora do escopo): - Nao resolve no SN. - Adiciona `work_note` no SN. - Marca sincronizacao como encerrada/ignorada. - Se GLPI resolver e SN estiver em `Em Espera` ou `Aguardando Atendimento`, integracao forca `Em Atendimento` antes de resolver no SN. - Comentarios GLPI sao sanitizados (HTML/imagens/metadados) antes de envio ao SN. - Watermark de coleta no ServiceNow usa margem de seguranca de 6 horas para tras (`newWatermark - 6h`). - Motivo: reduzir risco de perda de eventos em casos de atraso de replicacao, diferenca de timezone e clock skew entre sistemas. - Efeito colateral esperado: releitura de uma janela recente e maior chance de reprocessamento controlado (idempotencia pelo banco local). ## Regras de negocio detalhadas 1. Controle de origem (`source_last`) - `SNOW` ou `GLPI` define quem teve a ultima escrita valida para o ticket. - Evita corrida de atualizacao de status/comentario entre os dois sistemas. 2. Status GLPI -> ServiceNow - Solucao no GLPI dispara tentativa de resolucao no SN. - Se SN estiver em status bloqueante (`Em Espera` ou `Aguardando Atendimento`), a integracao seta `Em Atendimento` antes da resolucao. - Regra fora do escopo (`solutiontypes_id = GLPI_OOS_SOLUTION_TYPE_ID`) fecha fluxo local sem resolver no SN e registra `work_note`. 3. Status ServiceNow -> GLPI - Mudancas de estado no SN sao refletidas no GLPI para tickets ativos. - Para `Resolvido`, `Encerrado` e `Encerrado - Omitido` no SN: - GLPI recebe nota de encerramento/resolucao. - Integracao remove ticket do monitoramento (`closed/closed`), sem fechar ticket no GLPI. - Fechamento permanente no GLPI bloqueia reabertura automatica por sincronizacao. 4. Comentarios GLPI -> SN - Fluxo com verificacao de existencia local/remota para evitar duplicatas. - Conteudo passa por sanitizacao para remover HTML, normalizar texto e tratar imagens. 5. Comentarios SN -> GLPI - Comentarios novos detectados no SN sao persistidos no banco intermediario e enviados ao GLPI. - `work_notes` do SN sao persistidas como `update_type = task` e enviadas como tarefa no GLPI. - Campo `author` no banco intermediario usa `sys_created_by` do SN. - Conteudo enviado ao GLPI e formatado com card visual e autor no cabecalho. - IDs de origem/destino ficam registrados em `ticket_updates` para rastreabilidade. 6. Reprocessamento de erro - Inicio de cada ciclo tenta resetar estados de erro para recolocar tickets no fluxo automatico. ## Pre-requisitos - Node.js 18+ - NPM - PostgreSQL - MySQL/MariaDB com base do GLPI acessivel - Python 3.10+ (para o mapeador de localidades) ## Instalacao ```bash npm install ``` ### Dependencias Python ```bash cd src/scripts/python pip install -r requirements.txt ``` ## Configuracao de ambiente Crie `.env.development` e `.env.production` com base em `.env.example` e inclua tambem as variaveis usadas no codigo: ### ServiceNow - `SERVICENOW_USERNAME` - `SERVICENOW_PASSWORD` - `SERVICENOW_ASSIGNMENT_GROUP` - `SERVICENOW_TABLE_INCIDENT_URL` - `SERVICENOW_TABLE_REQUEST_URL` - `SERVICENOW_TABLE_JOURNAL_URL` - `SERVICENOW_SC_ITEM_OPTION_URL` - `SERVICENOW_DEFAULT_USER` - `SERVICENOW_RESOLVED_BY_SYSID` - `SERVICENOW_IGNORE_DEFAULT_USER_JOURNAL` (`true` por padrao; use `false` para testes locais) ### GLPI (MySQL/MariaDB) - `GLPI_DB_HOST` - `GLPI_DB_PORT` - `GLPI_DB_USER` - `GLPI_DB_PASSWORD` - `GLPI_DB_NAME` - `GLPI_DB_CHARSET` - `GLPI_DEFAULT_USER_ID` - `GLPI_DEFAULT_GROUP_ID` (padrao `30`) - `GLPI_DEFAULT_ENTITY_ID` (padrao `127`) - `GLPI_OOS_SOLUTION_TYPE_ID` (padrao `27`) ### Banco intermediario (PostgreSQL) - `SNGLPI_DB_HOST` - `SNGLPI_DB_PORT` - `SNGLPI_DB_NAME` - `SNGLPI_DB_USER` - `SNGLPI_DB_PASSWORD` ### Agendamento e mapeamento - `CRON_SCHEDULE` (ex.: `*/5 * * * *`) - `LOCATION_MAPPING_CSV_PATH` (arquivo CSV para mapeamento SN -> GLPI) ## Execucao ### Desenvolvimento ```bash npm run dev ``` ### Producao ```bash npm run start:prod ``` ## Execucao com PM2 Subir os dois processos (sync + mapeador): ```bash pm2 start ecosystem.config.js --env production ``` Comandos uteis: ```bash pm2 list pm2 logs sn-glpi-sync-cron pm2 logs sn-glpi-location-mapper pm2 restart sn-glpi-sync-cron ``` ## Script de mapeamento de localidades Arquivo: `src/scripts/python/update_location_mapping.py` - Carrega `NODE_ENV` e respectivo `.env.*`. - Monitora alteracoes recentes no CSV (`LOCATION_MAPPING_CSV_PATH`). - Recria os dados da tabela `location_mapping` com base no CSV e IDs validos em ambos os bancos. - Roda em loop continuo (ideal via PM2 como processo separado). ## Como os dados chegam do ServiceNow - Incidentes: consulta na tabela definida por `SERVICENOW_TABLE_INCIDENT_URL`, filtrando por `assignment_group` e `sys_updated_on >= watermark`. - Requisicoes: consulta na tabela definida por `SERVICENOW_TABLE_REQUEST_URL` com o mesmo filtro. - Comentarios: consulta na tabela definida por `SERVICENOW_TABLE_JOURNAL_URL` por `element_id` e `element IN (comments, work_notes)`, com paginacao (`limit/offset`). - Enriquecimento de requisicoes: consulta em `SERVICENOW_SC_ITEM_OPTION_URL` para capturar variaveis como justificativa e telefone. - Campos principais persistidos localmente: - Ticket: `number`, `sys_id`, `short_description`, `state`, `description`, `caller/opened_by`, `location`, `opened_at`, `sys_updated_on`. - Atualizacoes: `sys_id`, `element`, `value`, `sys_created_on`, `sys_created_by`. ## Estrutura do banco intermediario Definicao base em `src/scripts/database/scriptBD.sql`: - `tickets_sn` - `ticket_sync` - `ticket_updates` - `location_mapping` - `sync_control` Arquivo auxiliar de manutencao/reset (com comandos destrutivos): - `src/scripts/database/maintenance_reset.sql` ## Limitacoes conhecidas (estado atual) - Nao ha suite de testes automatizados (`npm test` e placeholder). - Parte do fluxo depende de acesso direto ao banco do GLPI (acoplamento operacional alto). (Utilizar API em nova versão) - Existe logica sensivel de timezone/watermark que merece revisao para evitar reprocesso/perda de evento. ## Proximas melhorias recomendadas - Cobertura de testes (unitario e integracao com mocks de API/DB). - Externalizar IDs e regras hardcoded para variaveis de ambiente. - Revisar estrategia de watermark/timezone e idempotencia. - Criar healthcheck/observabilidade (metricas de ciclo, falhas por etapa, tickets processados). - Adicionar validacoes de configuracao na inicializacao (falha rapida quando faltar env obrigatoria). - Alterar uso de banco do GLPI para a API do GLPI. ## Arquivos principais - `cron.js` - `src/app.js` - `src/controllers/processTicketsController.js` - `src/controllers/processCommentsController.js` - `src/controllers/processStatusController.js` - `src/controllers/processErrorController.js` - `src/services/servicenowService.js` - `src/services/glpiTicketService.js` - `src/services/glpiCommentService.js` - `src/scripts/python/update_location_mapping.py`