# 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 - 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. - Ticket resolvido no GLPI com `solutiontypes_id = 27` (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 = 27`) fecha fluxo local sem resolver no SN e registra `work_note`. 3. Status ServiceNow -> GLPI - Mudancas de estado no SN sao refletidas no GLPI respeitando o estado final de fechado. - 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. - 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` ### 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` ### 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). ## Estrutura do banco intermediario Definicao base em `src/scripts/database/scriptBD.sql`: - `tickets_sn` - `ticket_sync` - `ticket_updates` - `location_mapping` - `sync_control` ## Limitacoes conhecidas (estado atual) - Nao ha suite de testes automatizados (`npm test` e placeholder). - Ha regras hardcoded que deveriam vir de configuracao (ex.: `resolved_by` em fechamento no SN). - Parte do fluxo depende de acesso direto ao banco do GLPI (acoplamento operacional alto). - 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). ## 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`