2026-03-04 16:37:04 -03:00
# Sistema de Integracao ServiceNow <-> GLPI
2025-08-30 19:04:35 -03:00
2026-03-04 16:37:04 -03:00
Middleware Node.js para integrar chamados entre ServiceNow e GLPI, usando PostgreSQL como banco intermediario e acesso ao banco do GLPI.
2025-08-30 19:04:35 -03:00
2026-03-04 16:37:04 -03:00
## Estado atual
2025-08-30 19:04:35 -03:00
2026-03-04 16:37:04 -03:00
1. Coleta de tickets SN por watermark.
FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
2. Criacao/vinculo de tickets no GLPI (grava `external_id` no GLPI com o numero do ticket SN).
2026-03-04 16:37:04 -03:00
3. Sincronizacao de comentarios e tasks em duas direcoes.
4. Preenchimento do campo "Ticket Externo" no SN com o ID GLPI.
FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
5. Motor de regras unico (`processTicketLifecycleController`) para status/fechamento/reabertura:
`status=5` (resolver SN), `status=6` (encerrar definitivamente no SN), nota no GLPI quando o SN
resolve/encerra por conta propria (com aviso e troca de fila no SN), reabertura automatica e
regra de fora de escopo.
2025-11-19 16:01:37 -03:00
2026-02-19 11:21:40 -03:00
## Fluxo do ciclo
2025-11-19 16:01:37 -03:00
2026-03-04 16:37:04 -03:00
Executado pelo `main()` :
2025-11-19 16:01:37 -03:00
2026-02-19 11:21:40 -03:00
1. `processErrorController`
2. `processTicketsController`
FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
3. `processTicketLifecycleController` (quando `ENABLE_GLPI_CLOSE_CRON=true` )
4. `processCommentsController`
2026-02-19 11:21:40 -03:00
2026-03-04 16:37:04 -03:00
## Documentacao detalhada
2026-02-19 11:21:40 -03:00
2026-03-04 16:37:04 -03:00
1. Fluxo tecnico: [docs/fluxo.md ](docs/fluxo.md )
2. Regras de negocio completas: [docs/regrasdenegocio.md ](docs/regrasdenegocio.md )
3. Casos de uso: [docs/casosdeuso.md ](docs/casosdeuso.md )
4. Plano e checklist de rollout: [docs/checklist.md ](docs/checklist.md )
2025-11-19 16:01:37 -03:00
2026-03-04 16:37:04 -03:00
## Variaveis de ambiente importantes
2025-11-19 16:01:37 -03:00
2026-03-04 16:37:04 -03:00
### Feature flags
2025-11-19 16:01:37 -03:00
FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
1. `ENABLE_GLPI_CLOSE_CRON`
- `true` : liga o motor de regras de status/fechamento/reabertura (`processTicketLifecycleController`)
- `false` : desliga o motor inteiro
2025-11-19 16:01:37 -03:00
2026-02-19 11:21:40 -03:00
### ServiceNow
2025-11-19 16:01:37 -03:00
2026-03-04 16:37:04 -03:00
1. `SERVICENOW_TABLE_INCIDENT_URL`
2. `SERVICENOW_TABLE_REQUEST_URL`
3. `SERVICENOW_TABLE_JOURNAL_URL`
4. `SERVICENOW_SC_ITEM_OPTION_URL`
5. `SERVICENOW_DEFAULT_USER`
6. `SERVICENOW_IGNORE_DEFAULT_USER_JOURNAL`
7. `SERVICENOW_EXTERNAL_TICKET_FIELD` (default: `u_external_ticket` )
2026-02-19 11:21:40 -03:00
2026-03-04 16:37:04 -03:00
### GLPI e banco intermediario
2026-02-19 11:21:40 -03:00
2026-03-04 16:37:04 -03:00
1. `GLPI_DB_*`
2. `SNGLPI_DB_*`
3. `GLPI_OOS_SOLUTION_TYPE_ID`
2026-02-19 11:21:40 -03:00
2026-03-04 16:37:04 -03:00
## Desenvolvimento
2025-11-19 16:01:37 -03:00
2026-03-04 16:37:04 -03:00
1. Instalar dependencias:
2025-11-19 16:01:37 -03:00
```bash
2026-03-04 16:37:04 -03:00
npm install
2025-11-19 16:01:37 -03:00
```
2026-03-04 16:37:04 -03:00
2. Criar env:
2025-11-19 16:01:37 -03:00
```bash
2026-03-04 16:37:04 -03:00
copy .env.example .env.development
2025-11-19 16:01:37 -03:00
```
2026-03-04 16:37:04 -03:00
3. Executar:
2025-11-19 16:01:37 -03:00
```bash
2026-03-04 16:37:04 -03:00
npm run dev
2025-11-19 16:01:37 -03:00
```
2026-03-04 16:37:04 -03:00
## Producao
2026-02-19 11:21:40 -03:00
2026-06-26 11:39:57 -03:00
### Deploy manual na VM
2026-02-19 11:21:40 -03:00
```bash
2026-06-26 11:39:57 -03:00
git pull origin master
npm ci --omit=dev
2026-03-04 16:37:04 -03:00
pm2 start ecosystem.config.js --env production
2026-06-26 11:39:57 -03:00
pm2 save
```
Se o processo ja estiver rodando:
```bash
pm2 restart sn-glpi-sync-cron --update-env
```
### Deploy via Gitea Actions
O workflow `.gitea/workflows/deploy-production.yml` roda no runner com rotulo `vm-prod` .
1. Configure a variavel do repositorio `PROD_DEPLOY_PATH` com o caminho da aplicacao na VM de producao. Se nao configurar, o workflow usa `/opt/sn-glpi-sync-new` .
FEAT: Motor de regras único de status/fechamento + mandante configurável
Consolida os dois controladores legados que decidiam status/fechamento de
forma concorrente (processGlpiClosureController + processStatusController)
em um único processTicketLifecycleController, eliminando a dependência do
campo source_last (mantido só como rastro de auditoria) e a flag
ENABLE_STATUS_SYNC (removida). Isso corrige o bug de reabertura: chamados
reabertos no SN voltavam a ser fechados no GLPI porque a regra de
precedência de finalização do fluxo legado forçava o status do GLPI de
volta pro SN.
Correções de bugs encontrados em teste (Frente 1):
- Constraint UNIQUE em ticket_sync.sn_ticket_id + ON CONFLICT DO NOTHING
na criação do registro, prevenindo duplicação de tickets.
- Fechamento no SN agora é confirmado por leitura ao vivo do status antes
de marcar o ticket como solved/closed, em vez de confiar só no HTTP 200
(a API do SN pode retornar sucesso e silenciosamente ignorar um valor de
estado inválido — descoberto e corrigido também no mandante).
- Nota de encerramento do SN pro GLPI agora é idempotente e criada uma
única vez por ticket.
- Erros de sincronização passam a ter um limite de tentativas
(MAX_ERROR_RETRIES) antes de marcar o ticket como error_permanent,
exigindo intervenção manual em vez de tentar para sempre.
- Chamados criados no GLPI passam a gravar o número do ticket do SN no
campo externalid.
Nova funcionalidade (Frente 2): quando o SN resolve/encerra um chamado por
conta própria antes do GLPI, além da nota informativa no GLPI (agora com o
nome de quem encerrou, buscado ao vivo via resolved_by/closed_by/
sys_updated_by), o próprio SN recebe um aviso de que a Sothis não vai mais
atender aquele chamado e ele é transferido pra fila de TI da CAOA.
Nova funcionalidade (Mandante, regras 19-22): espelhamento opcional e
configurável de status intermediário (Aguardando Atendimento/Em
Atendimento/Em Espera) entre os dois sistemas, controlado pela env
MANDANTE=GLPI|SNOW. Sem essa env configurada, mantém o comportamento atual
(nenhum espelhamento de status intermediário). Nunca afeta os status finais
(resolvido/encerrado/fora de escopo), que continuam regidos pelas regras
fixas de fechamento.
Corrigido também o workflow de deploy (.gitea/workflows/deploy-production.yml),
que ainda validava os controladores antigos (já removidos) e exigia
ENABLE_STATUS_SYNC=true, o que quebraria o próximo deploy em produção.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-10 09:45:34 -03:00
2. Garanta que o arquivo `.env.production` exista nesse caminho na VM e contenha `SERVICENOW_CAOA_TI_GROUP_ID` preenchido.
2026-06-26 11:39:57 -03:00
3. Faça push na branch `master` ou execute o workflow manualmente em Actions.
4. Acompanhe pelo Gitea Actions ou na VM:
```bash
pm2 list
pm2 logs sn-glpi-sync-cron
2025-10-29 14:20:21 -03:00
```
2026-02-19 11:21:40 -03:00
2026-03-04 16:37:04 -03:00
## Observacoes
2026-02-19 11:21:40 -03:00
2026-03-04 16:37:04 -03:00
1. O projeto ainda nao tem suite automatizada robusta.
2. O rollout recomendado e por fases com feature flags.
3. Nao remover schema legado antes de estabilizar o fluxo novo.
2026-03-04 16:48:23 -03:00
4. Consulte `docs/checklist.md` antes de cada deploy para validar pre e pos-subida.