Contexto
O SFN atende a Secretaria de Infraestrutura e Obras de Francisco Morato/SP. Substitui blocos de papel e planilhas por um pipeline auditável que conecta solicitações externas, vistorias em campo e a cadeia formal de procedimentos fiscais.
A plataforma é PWA tablet-first: o fiscal cria a notificação no local, anexa fotos da vistoria, imprime no Zebra portátil e entrega o documento físico ao autuado — tudo offline-capable.
Cadeia de procedimentos
Cada item é registro independente — dados são copiados no momento da criação, alterações posteriores não afetam os demais. A navegação bidirecional mostra origem e gerados.
Solicitação → Notificação → Embargo → Multa
- Solicitações chegam de Ouvidoria, Protocolo, MP, Guarda Municipal, georreferenciamento ou app do cidadão (via API externa).
- Notificação é criada da solicitação (com banner verde/âmbar conforme imóvel está ou não no cadastro Intertec).
- Embargo é gerado a partir de notificação, herdando rastreabilidade.
- Multa segue fluxo de status
PEND_ENTREGA → AG_RECURSO → RECURSO_EXPIRADO → RECURSO_ACEITO / MULTA_FINALcom janela de recurso configurável (default 30 dias).
Recursos principais
- Wizard de notificação em 4 passos: busca de imóvel, dados do imóvel, dados do proprietário, dados da notificação.
- Busca composta: “Marfim 111” filtra logradouro
Marfim+ número exato111. - Fotos de vistoria em Notificações, Embargos e Multas — captura via câmera, edição de descrição, navegação na visualização expandida.
- Impressão térmica Zebra ZQ220 (72mm) + templates A4 oficiais com assinatura dupla (fiscal + notificado).
- Auto-transições de status — AR “Recebido” em
PEND_ENTREGAmove paraAG_RECURSO; ao abrir detalhe com prazo expirado, vai paraRECURSO_EXPIRADO. - Importação Intertec — UI com parser CSV resiliente (cabeçalho com reordenação/renomeação) + upsert por inscrição.
- Valores em U.F.M — Unidade Fiscal Municipal, substituindo UFIR/R$ em todo o projeto.
- Offline: banner persistente de status de conexão, Service Worker + Manifest configurados.
API de Integração Externa
Permite que sistemas externos (georreferenciamento, ouvidoria, MP, app cidadão) criem solicitações sem login LDAP. Autenticação via header X-API-Key.
POST /api/v1/external/solicitacoes— idempotente viasistema_origem+id_externo(UNIQUE INDEX parcial). Reenvio devolve200comreenvio: true.GET /api/v1/external/solicitacoes/:id/status— retorna status e procedimentos gerados (notificação, embargo, multa).- Validação Zod estrita: campos desconhecidos retornam
400; para dados imprevisíveis, usar o campo JSONBmetadata_externa.
Stack
| Camada | Tecnologia |
|---|---|
| Frontend | React 19, TypeScript 5.9, Vite 8, TailwindCSS 4.2 |
| Backend | Express 5, TypeScript, Node.js 22 |
| Banco | PostgreSQL 17 (migrations SQL sequenciais) |
| Auth | LDAP/AD + JWT |
| Infra | Docker Compose, Nginx |
| Impressão | Zebra ZQ220 Plus (ZPL / jsPDF fallback) |
Desafios resolvidos
- Bug de fuso horário em datas locais (
parseDateParts,addDays) corrigido com split por-em vez denew Date(). - Idempotência da API externa com
UNIQUE INDEXparcial por origem + ID externo — protege reenvios. - Importação SIRF de ~52k imóveis em lotes de 1000 via API, reaproveitando o mesmo endpoint da UI.
- Cadeia de renotificações preservada quando multa é gerada a partir de embargo (herda
renotificacaoIds).