Procedimento Operacional Padrão das Atividades da Saúde Digital
A Saúde Digital atua como área de apoio técnico à Secretaria da Saúde, com foco na qualidade e consistência dos dados em saúde, garantindo que as informações dos sistemas assistenciais sejam corretamente transmitidas e utilizadas para fins de gestão.
Entre suas atividades está a transmissão de dados para o eSUS APS, com análise e correção de inconsistências identificadas pelo sistema, incluindo ajustes em cadastros de estabelecimentos de saúde quando necessário. A equipe também atua na transmissão de registros de vacinação para a RNDS, realizando correções cadastrais que viabilizam a conclusão dos envios.
No apoio à gestão, são utilizadas ferramentas como o Metabase e a solução interna upFiles, permitindo a análise de bases de dados e a identificação antecipada de inconsistências cadastrais. Além disso, a Saúde Digital realiza a atualização de painéis e gráficos, apoiando outros setores no acompanhamento da qualidade das informações.
- Análise de Dados e Ferramentas de Apoio
- Contexto da Análise de Dados na Saúde Digital
- Ferramentas de Apoio à Análise de Dados
- upFiles - finalidade e papel no processo de dados
- Metabase: análise e visualização de dados
- Fluxo de Atualização dos Painéis de Dados
- Transmissão de Vacinas a RNDS
- Transmissão de Fichas para o ESUSAPS
- Cadastro de Endereçamento no SIS
Análise de Dados e Ferramentas de Apoio
Este capítulo apresenta o papel da Análise de Dados no contexto das atividades da Saúde Digital, descrevendo como informações oriundas dos sistemas de saúde são organizadas, qualificadas e transformadas em bases estruturadas para apoio à gestão, ao monitoramento e à tomada de decisão.
A Saúde Digital atua como área de suporte técnico responsável por viabilizar o uso estratégico dos dados, garantindo que relatórios e registros produzidos nos sistemas assistenciais possam ser tratados de forma padronizada e utilizados em ferramentas analíticas. Esse processo contribui para a identificação de inconsistências, o acompanhamento da qualidade da informação e a prevenção de problemas relacionados a faturamento e monitoramento de indicadores.
Neste capítulo são contextualizadas as principais ferramentas de apoio à análise de dados mantidas pela Saúde Digital, com destaque para aplicações que permitem a conversão de relatórios em estruturas compatíveis com banco de dados e sua integração com plataformas de visualização, como o Metabase. Também é apresentado o papel do upFiles nesse fluxo, enquanto solução utilizada para organizar e disponibilizar dados de forma estruturada.
Contexto da Análise de Dados na Saúde Digital
A Análise de Dados é uma atividade central no apoio técnico prestado pela Saúde Digital à Secretaria da Saúde. Seu objetivo é possibilitar que informações registradas nos sistemas assistenciais sejam compreendidas, avaliadas e utilizadas de forma qualificada para fins de gestão, monitoramento e apoio à tomada de decisão.
Os dados em saúde são produzidos em diferentes sistemas, com estruturas, regras e níveis de maturidade distintos. Por esse motivo, a simples existência de relatórios não garante, por si só, que a informação esteja pronta para uso analítico. Antes de serem utilizados em painéis e gráficos, os dados passam por etapas de verificação, organização e validação, buscando identificar inconsistências, limitações e possíveis impactos na interpretação dos resultados.
Nesse contexto, a Saúde Digital atua como área de apoio técnico, promovendo a transformação de dados brutos em bases mais estruturadas e analisáveis. Esse trabalho envolve análise crítica das fontes de dados, realização de testes de mesa e avaliação contínua da confiabilidade das informações, reconhecendo que nem todo dado disponível é, necessariamente, adequado para geração de indicadores ou visualizações gerenciais.
Também é importante destacar que os sistemas utilizados pela Secretaria da Saúde apresentam diferentes estágios de desenvolvimento no que se refere à geração e ao uso de dados. Enquanto alguns já permitem análises mais consolidadas, outros ainda exigem cuidados adicionais, uso indireto de relatórios ou validações mais extensas antes de qualquer aplicação analítica.
Este capítulo tem como finalidade contextualizar esse processo, apresentando a lógica da análise de dados adotada pela Saúde Digital e as ferramentas de apoio utilizadas. As páginas seguintes detalham o papel de cada ferramenta e os cuidados necessários para o uso responsável das informações, especialmente no apoio às atividades desenvolvidas por estagiários, técnicos e gestores que acessam painéis de dados.
Ferramentas de Apoio à Análise de Dados
A Análise de Dados na Saúde Digital é viabilizada por um conjunto de ferramentas que atuam de forma complementar, cada uma com um papel específico dentro do processo de organização, validação e uso das informações em saúde. Essas ferramentas oferecem suporte técnico para que os dados possam ser trabalhados de forma estruturada e analisável, respeitando as características e limitações de cada sistema de origem.
upFiles
O upFiles é uma ferramenta desenvolvida internamente pela Saúde Digital, criada para apoiar o tratamento e a padronização de dados provenientes de planilhas e relatórios. Seu principal objetivo é permitir que arquivos nos formatos CSV e XLS/XLSX sejam transformados em estruturas compatíveis com banco de dados, armazenadas em ambiente PostgreSQL.
Por meio do upFiles, é possível criar novas tabelas e inserir dados de forma controlada, permitindo tanto a sobrescrita quanto a manutenção e o acréscimo de registros, conforme a necessidade da análise. Essa funcionalidade possibilita maior reaproveitamento das bases de dados e padronização das informações ao longo do tempo.
Metabase
O Metabase é a ferramenta utilizada pela Saúde Digital para análise e visualização de dados. A partir das bases estruturadas, sejam elas oriundas do upFiles ou de conexões diretas a bancos de dados, o Metabase permite a criação de painéis, gráficos e consultas que apoiam o monitoramento e a tomada de decisão.
Os painéis disponibilizados refletem diretamente a qualidade e a estrutura das bases utilizadas, sendo fundamental compreender que a ferramenta apresenta os dados conforme estão armazenados, não substituindo a análise crítica nem os processos de validação realizados previamente.
Conexões diretas a bancos de dados
Além do uso de arquivos e bases intermediárias, a Saúde Digital também realiza conexões diretas a bancos de dados de aplicações sobre as quais possui maior controle técnico. Esse tipo de acesso permite análises mais consistentes e atualizadas, reduzindo etapas intermediárias de tratamento de dados.
Esse cenário é adotado, por exemplo, em sistemas que utilizam bancos de dados como SQL Server e PostgreSQL, associados a aplicações acompanhadas diretamente pela equipe da Saúde Digital, como o ESUSSAMU e, de forma mais limitada, o eSUS APS, sempre considerando o nível de maturidade e confiabilidade das informações disponíveis.
É importante ressaltar que, independentemente da ferramenta ou forma de acesso utilizada, a qualidade dos dados permanece como elemento central do processo de análise. A existência de ferramentas tecnológicas não elimina a necessidade de validação, testes e avaliação crítica das informações, reconhecendo que nem todo dado disponível resulta, necessariamente, em painéis ou indicadores confiáveis.
As páginas seguintes deste capítulo detalham, de forma mais aprofundada, a finalidade e o funcionamento de cada ferramenta, bem como os cuidados necessários para seu uso no apoio às atividades desenvolvidas por estagiários, técnicos e gestores.
upFiles - finalidade e papel no processo de dados
Criação de tabelas e estruturação de dados
O upFiles <https://saudedigital.sorocaba.sp.gov.br/upFiles/> é uma ferramenta desenvolvida internamente pela Saúde Digital para suprir limitações identificadas em soluções de upload de dados utilizadas de forma nativa por ferramentas de análise. Seu principal objetivo é permitir a criação de tabelas em banco de dados PostgreSQL a partir de planilhas, de forma padronizada, controlada e reutilizável, viabilizando análises posteriores no Metabase.
Diferentemente de soluções mais simples de upload, o upFiles foi concebido para trabalhar com grandes volumes de dados, sem limitação prática de tamanho de arquivo, e para permitir maior controle sobre a estrutura das tabelas criadas. Essa abordagem se mostrou necessária especialmente diante das limitações dos relatórios extraídos de sistemas como o Sistema de Gestão Pública de Saúde, que, em sua versão web, apresenta restrições significativas na organização e padronização dos dados.
Preparação prévia dos dados
Antes de iniciar qualquer processo no upFiles, é fundamental que os dados estejam organizados em formato de planilha padrão, com informações separadas por colunas, cada coluna representando um único tipo de dado. Essa organização é essencial para que o sistema consiga interpretar corretamente a estrutura do arquivo.
Em situações em que o relatório não apresenta cabeçalho adequado, o upFiles possui uma tratativa básica para identificar colunas a partir das primeiras linhas de dados. Nesses casos, colunas sem nome são criadas automaticamente e devem ser revisadas e renomeadas durante a etapa de configuração. Ainda assim, recomenda-se que os dados já sejam preparados previamente de forma estruturada, sempre que possível.
Etapa 1 – Envio do arquivo para início do processamento
O processo de criação de tabela no upFiles começa com o upload do arquivo, momento em que o sistema passa a analisar a estrutura da planilha.
Após o envio, o sistema realiza a leitura do arquivo e apresenta um preview com as primeiras 20 linhas, permitindo verificar como os dados foram interpretados antes de avançar para a configuração da tabela.
Etapa 2 – Configuração da tabela
Na etapa de configuração, o usuário define como a tabela será criada no banco de dados. Quando o objetivo é criar uma nova base, deve ser mantida a opção Criar nova tabela.
A definição do nome da tabela é obrigatória. O próprio sistema aplica automaticamente um prefixo identificador às tabelas criadas pelo upFiles, permitindo que elas sejam facilmente reconhecidas no banco de dados e listadas separadamente de outras tabelas que não se originam da ferramenta.
Chave Primária (PK)
Nesta etapa também é possível definir uma chave primária, conhecida como PK. A chave primária é um campo que identifica unicamente cada registro da tabela, sendo utilizada para evitar duplicidades e permitir atualizações controladas dos dados.
Quando o relatório não possui um identificador único confiável, o upFiles permite a criação de uma chave hash automática, solução especialmente útil em cenários em que os sistemas de origem não fornecem uma chave primária adequada.
Configuração das colunas
O upFiles utiliza, inicialmente, os nomes das colunas presentes na planilha, mas permite que esses nomes sejam editados para facilitar o uso futuro no Metabase. Para cada coluna, o sistema apresenta exemplos de valores, auxiliando na escolha do tipo de dado mais adequado.
Os tipos disponíveis incluem:
-
Texto
-
Inteiro
-
Inteiro grande
-
Decimal
-
Data, com conversão ou já estruturada
-
Hora
-
Data e hora, com conversão ou já estruturada
Também existe a opção de anonimização de colunas, recurso importante para atendimento à LGPD, especialmente em casos em que os dados possam ser utilizados em painéis com acesso ampliado.
Adicionalmente, é possível criar colunas customizadas com valor fixo, utilizadas em situações específicas para facilitar a integração futura entre bases distintas no Metabase.
Confirmação da estrutura da tabela
Ao final da configuração, a estrutura definida é confirmada. Nesta primeira execução, o sistema apenas cria a tabela no banco de dados, sem inserir os dados da planilha. Essa separação entre criação da tabela e carga de dados foi adotada como medida de segurança, garantindo maior controle sobre a estrutura antes da inserção efetiva das informações.
É importante destacar que a criação de tabelas no upFiles envolve conceitos de banco de dados e, por esse motivo, recomenda-se que essa etapa seja realizada por profissionais com maior familiaridade técnica ou sob orientação adequada.
As informações inseridas no sistema são registradas com identificação do responsável pelo envio e carimbo de data e hora, permitindo rastreabilidade e facilitando eventuais manutenções no banco de dados. Algumas ações, como a exclusão de tabelas, não são realizadas pela interface do upFiles e dependem de procedimentos técnicos diretos no banco de dados.
A próxima página deste capítulo apresenta a etapa de upload de dados, que consiste na inserção efetiva das informações na tabela já criada, processo consideravelmente mais simples e operacional.
Upload de Dados em tabelas estruturadas
Após a criação e validação da estrutura de uma tabela no upFiles, a próxima etapa consiste no upload dos dados propriamente ditos. Essa fase é operacionalmente mais simples do que a criação da tabela, pois utiliza uma estrutura já definida previamente, reduzindo o risco de inconsistências estruturais.
Assim como na etapa inicial de criação, o processo começa com o upload do arquivo, seguido da visualização de um preview com as primeiras linhas, permitindo uma conferência visual para garantir que os dados foram interpretados corretamente pelo sistema.
Seleção da tabela de destino
Com os dados validados visualmente, a etapa seguinte consiste em alterar a opção de configuração para Upload de Dados. Nesse momento, a interface passa a apresentar uma lista de tabelas já existentes, criadas anteriormente por meio do próprio upFiles.
Validação de compatibilidade entre planilha e tabela
Durante a etapa de configuração do upload, o upFiles realiza uma verificação automática de compatibilidade entre a estrutura da planilha enviada e a estrutura da tabela selecionada como destino. Essa validação considera, principalmente, a quantidade e a ordem das colunas, uma vez que o mapeamento dos dados ocorre por posição.
A lista exibida contempla apenas tabelas originadas pelo upFiles, facilitando a identificação correta da base que receberá os novos dados. A seleção da tabela correta é essencial para garantir a integridade das informações e a continuidade das análises futuras no Metabase.
Definição do comportamento do upload
Após selecionar a tabela de destino, o usuário deve definir como os novos dados serão tratados em relação aos registros já existentes. Existem duas possibilidades principais:
-
Substituir tudo (limpa e reinsere): remove os dados atuais da tabela e insere apenas os dados do novo arquivo.
-
Adicionar aos dados existentes: mantém os registros atuais e insere os novos dados na mesma tabela.
Quando a opção de adicionar aos dados existentes é selecionada, torna-se necessário definir o comportamento em caso de registros duplicados, com base na chave primária previamente configurada.
Tratamento de duplicidades
Nos casos em que um registro do novo arquivo possui a mesma chave primária de um registro já existente na tabela, o sistema permite duas abordagens:
-
Ignorar e manter os dados antigos: os registros existentes são preservados e os novos são descartados quando ocorre duplicidade.
-
Atualizar (sobrescrever com novos): os registros existentes são substituídos pelos dados mais recentes do arquivo enviado.
Essa escolha deve considerar o objetivo da base de dados e a forma como os relatórios são atualizados ao longo do tempo.
Identificação e auditoria do upload
Antes da execução do upload, o sistema solicita a identificação do responsável pelo envio, por meio do CPF. Essa informação é utilizada exclusivamente para fins de rastreabilidade e auditoria, permitindo identificar quando e por quem determinado conjunto de dados foi inserido.
Após a confirmação, o processo de upload é iniciado e os dados passam a integrar a tabela selecionada, ficando disponíveis para análise no Metabase.
Uso dos dados no Metabase
Concluído o upload, o trabalho de estruturação no upFiles é finalizado. A partir desse ponto, a exploração, análise e visualização dos dados passam a ser realizadas diretamente no Metabase, por meio da criação ou atualização de painéis, gráficos e consultas.
Essa separação entre estruturação de dados e análise visual reforça a lógica adotada pela Saúde Digital, garantindo maior controle sobre as bases de dados e mais segurança no uso das informações.
Metabase: análise e visualização de dados
A análise de dados na Saúde Digital tem como objetivo transformar bases estruturadas em informações compreensíveis, capazes de apoiar o monitoramento de processos, a avaliação de resultados e a tomada de decisão. Essa análise ocorre a partir de dados previamente organizados e validados, sendo a visualização uma etapa final desse processo.
Ferramentas de Business Intelligence, conhecidas como ferramentas de BI, são utilizadas para representar dados por meio de gráficos, tabelas e painéis interativos. Essas ferramentas não produzem nem corrigem dados, mas permitem explorar informações já existentes, facilitando sua leitura por diferentes perfis de usuários, como gestores, técnicos e equipes de apoio.
Entre as ferramentas de BI mais conhecidas estão soluções amplamente difundidas no mercado, como o Power BI, além de alternativas open source. Todas compartilham o mesmo princípio, transformar dados estruturados em visualizações que auxiliam a compreensão da informação.
O Metabase no contexto da Saúde Digital
No âmbito da Saúde Digital, o Metabase é a ferramenta adotada para análise e visualização de dados. Um dos fatores que motivaram sua escolha é o fato de se tratar de uma ferramenta open source, sem custo de licenciamento para a administração pública, além de permitir integração direta com bancos de dados utilizados pelo setor.
O Metabase é utilizado para criar gráficos e painéis a partir de bases estruturadas, seja por meio de tabelas preparadas no upFiles ou por conexões diretas a bancos de dados. Ele deve ser compreendido como uma ferramenta de apoio à análise, refletindo exatamente os dados disponíveis nas bases acessadas.
Organização das informações no Metabase
Antes de criar ou acessar visualizações no Metabase, é importante entender como a ferramenta organiza os conteúdos. Essa organização facilita a navegação, a interpretação das informações e o controle de acesso.
-
Coleções
Funcionam como pastas. Servem para organizar painéis e gráficos por tema ou finalidade, como gestão, monitoramento ou apoio técnico.
As coleções também ajudam no controle de acesso, pois os perfis de usuários podem ser configurados para acessar apenas determinadas coleções, garantindo que cada público visualize apenas as informações adequadas.
-
Painéis
São telas que reúnem vários gráficos sobre um mesmo assunto. Um painel permite acompanhar diferentes informações relacionadas a um processo em um único local, facilitando a análise e o acompanhamento. -
Gráficos
São as visualizações dos dados, como tabelas ou gráficos de barras. Cada gráfico apresenta um recorte específico da base de dados, definido por critérios como período, unidade de saúde ou situação do registro.
Essa estrutura permite que o Metabase apresente informações de forma organizada e segura, desde análises simples até painéis mais completos, respeitando o perfil de acesso e a qualidade dos dados disponíveis.
Atenção à escolha da coleção ao criar painéis
Antes de criar um painel no Metabase, é importante definir em qual coleção ele será armazenado, pois essa escolha influencia diretamente a organização das análises e o controle de acesso às informações.
No Metabase, os perfis de acesso são organizados por setor, e cada perfil visualiza apenas as coleções que lhe foram atribuídas. Dessa forma, manter os painéis nas coleções corretas facilita a configuração dos acessos e garante que cada setor veja apenas as informações pertinentes.
A coleção Saúde Digital é destinada, em geral, a painéis de uso interno do setor, como análises técnicas, correções de cadastro, validações de dados e painéis em fase de teste, que não são voltados à divulgação ampla.
Já a coleção Gestão SES concentra painéis consolidados e compartilhados, utilizados por mais de um setor da Secretaria da Saúde. Nela ficam análises que atendem simultaneamente áreas como Atenção Primária, Atenção Especializada e Vigilância, como painéis de absenteísmo ou de transmissão de vacinas à RNDS.
Sempre que um painel tiver uso transversal ou interesse de múltiplos setores, a orientação é que ele seja criado ou organizado na coleção Gestão SES, facilitando o gerenciamento dos perfis de acesso e promovendo o uso seguro e consistente das informações.
Exemplo prático: criação de gráficos no Metabase a partir do zero
Embora já existam painéis consolidados sobre a transmissão de dados de vacinas para a RNDS, este exemplo parte da criação de um novo painel do zero, na coleção Gestão SES, com finalidade exclusivamente didática. O objetivo é ilustrar conceitos básicos do Metabase e a lógica de construção de gráficos, sem aprofundar em análises complexas.
É importante destacar que o Metabase, assim como outras ferramentas de Business Intelligence, não depende apenas da ferramenta em si, mas principalmente de testes, validações e análise crítica dos dados. Muitas dessas validações se assemelham ao chamado teste de mesa, amplamente utilizado na formação em Tecnologia da Informação, no qual o comportamento dos dados é analisado antes de qualquer conclusão.
O Metabase oferece diversos tipos de gráficos e visualizações, além de recursos como filtros, sumarizações, ordenações e junções entre tabelas. Neste exemplo, no entanto, será utilizada uma estrutura simples, baseada em uma única tabela, sem junções, apenas para demonstrar o funcionamento básico da ferramenta.
Estratégia de construção dos gráficos
Uma prática comum na construção de painéis é iniciar pela criação de um gráfico base, considerando todos os dados e filtros que poderão ser utilizados posteriormente. Esse gráfico inicial serve como modelo e pode ser duplicado, facilitando a criação de novas visualizações sem a necessidade de repetir configurações.
Neste exemplo, serão criados dois gráficos, ambos a partir da mesma tabela de transmissão de dados:
-
o primeiro gráfico apresentará o total de registros existentes na tabela, independentemente do status da transmissão
-
o segundo gráfico será criado a partir da duplicação do primeiro, ajustando apenas a forma de apresentação da informação
Essa abordagem torna o processo mais ágil e reduz a chance de inconsistências entre os gráficos do mesmo painel.
Gráfico 1: total de registros por status de integração
O primeiro gráfico tem como objetivo oferecer uma visão geral da base de dados, apresentando o total de registros existentes e sua distribuição por status de integração, como enviados, com erro ou outros estados disponíveis na tabela.
Para iniciar a construção desse gráfico, acesse o painel previamente criado e inclua um novo conteúdo. Isso pode ser feito tanto pela opção de criar uma nova pergunta quanto pela opção de adicionar um gráfico, pois ambas conduzem ao mesmo ambiente de construção de análises do Metabase.
Ao iniciar esse processo, o primeiro passo é selecionar a tabela que será utilizada como base da análise. É a partir dessa tabela que o Metabase irá explorar os dados, aplicar as sumarizações definidas e transformar as informações em visualizações gráficas.
Neste momento, você estará visualizando a tela de montagem visual de gráficos do Metabase, que utiliza uma interface intuitiva e não exige conhecimento de codificação. Essa abordagem permite que a análise seja construída de forma guiada, facilitando o uso mesmo por usuários com menor familiaridade técnica.
Nessa tela, já é possível identificar, na seção Dados, qual é a tabela que está sendo utilizada como base para a análise. Essa conferência é importante para garantir que a visualização está sendo construída a partir da fonte correta antes de avançar para as demais configurações.
Para este exemplo, os outros botões de ação disponíveis na interface podem ser ignorados neste primeiro momento. Funcionalidades como unir dados, criar colunas personalizadas, adicionar filtros para limitar os resultados, ordenar informações ou definir limite de linhas serão exploradas posteriormente, conforme o usuário se familiarizar com a ferramenta e passar a trabalhar com outros conjuntos de dados.
Prosseguindo com a criação do gráfico, ao clicar no botão Resumir, o Metabase passa a trabalhar os dados de forma agregada, ou seja, deixa de exibir os registros linha a linha e passa a resumir a informação com base em funções e agrupamentos. Essa etapa é fundamental para a construção de gráficos e indicadores, pois é nela que definimos “o que queremos contar, somar ou analisar” e “como esses dados devem ser agrupados”.
Dentro do Resumir, o primeiro passo é escolher uma função ou métrica, que define qual tipo de cálculo será aplicado sobre os dados. Entre as opções disponíveis, estão, por exemplo:
-
Contagem de linhas, que contabiliza quantos registros existem na tabela ou em determinado recorte dos dados. É útil quando cada linha representa um evento, atendimento ou registro individual.
-
Número de valores distintos, que conta quantos valores únicos existem em uma coluna, como quantidade de pacientes diferentes ou unidades distintas.
-
Contagem cumulativa de linhas, que soma os registros de forma progressiva, normalmente utilizada em análises temporais.
-
Mínimo de e Máximo de, que identificam o menor ou maior valor de uma coluna numérica ou de data, ajudando a entender limites dos dados.
-
Expressão personalizada, que permite criar cálculos mais específicos, combinando campos ou aplicando regras customizadas, sendo mais utilizada em análises avançadas.
Para este exemplo, será utilizada a função Contagem de linhas, pois cada linha da tabela representa um registro de transmissão.
Após escolher a função, o Metabase permite definir por qual campo os dados serão agrupados, criando as chamadas “quebras” da análise. É nesse ponto que informamos, por exemplo, que a contagem deve ser separada por status, unidade de saúde, período ou qualquer outra categoria relevante. Essa combinação entre função e agrupamento é o que dá sentido à visualização final.
Ao combinar essa contagem com o campo Status, o Metabase passa a apresentar quantos registros existem em cada situação, como enviados, com erro ou em outros estados possíveis, oferecendo uma visão geral simples e objetiva do cenário de transmissão.
Nesse ponto, as configurações necessárias para o gráfico já estão definidas. Ainda assim, é importante destacar que, a qualquer momento, é possível clicar em Visualizar para acompanhar como o gráfico está sendo montado e verificar se o resultado corresponde ao esperado.
Antes de salvar a análise, é necessário ajustar a forma de visualização do gráfico. Para isso, clique em Visualizar e, na tela seguinte, utilize novamente a opção Visualizar para escolher o tipo de gráfico mais adequado para representar os dados, como barras, rosca ou tabela, conforme o objetivo da análise.
É recomendável utilizar o ícone de engrenagem para ajustar a forma como os dados são exibidos no gráfico. Nessa área, é possível configurar elementos visuais que facilitam a leitura e a interpretação da informação apresentada.
Com o gráfico finalizado, basta clicar em Salvar para definir um nome e, se necessário, incluir uma descrição, facilitando a identificação e o entendimento do gráfico dentro do painel e da coleção em que ele será armazenado.
Após salvar o gráfico, você será redirecionado automaticamente ao painel, onde já será possível visualizar o gráfico inserido. Observe que, na parte superior da página, o painel se encontra em modo de edição, o que faz com que os botões de ação relacionados à edição estejam visíveis.
Nesse modo, já é possível redimensionar e reposicionar os gráficos na tela, bem como adicionar filtros ao painel, que poderão ser utilizados posteriormente para refinar as visualizações. Essas funcionalidades permitem personalizar a apresentação das informações de acordo com a necessidade da análise.
As configurações de layout e de filtros do painel não serão detalhadas neste material. A proposta é que você explore essas possibilidades diretamente na ferramenta, de forma gradual, à medida que se familiariza com o uso do Metabase.
Gráfico 2: duplicação e reaproveitamento do gráfico base
Agora que o primeiro gráfico já foi criado e salvo, o próximo passo é sair do modo de edição do painel. Essa etapa é necessária porque a criação de um novo gráfico a partir de um existente ocorre por meio da edição do gráfico já criado, e não diretamente dentro do painel em modo de edição.
Com o painel em modo de visualização, selecione o gráfico já existente e acesse a opção de edição. A partir desse ponto, o Metabase permite alterar as configurações do gráfico conforme necessário, como ajustes de agrupamento, filtros ou tipo de visualização, reutilizando toda a estrutura já definida anteriormente.
Após realizar as alterações desejadas, ao clicar em Salvar, escolha a opção Salvar como novo gráfico. Dessa forma, o gráfico original é preservado, e uma nova visualização é criada a partir dele, reaproveitando a base de dados e as configurações iniciais, o que facilita a criação de novos gráficos de forma mais rápida e consistente.
Essa abordagem permite trabalhar com um gráfico base, a partir do qual novas análises podem ser geradas, mantendo padronização e reduzindo retrabalho na construção dos painéis.
Considerações sobre validação e interpretação
Este exemplo demonstra apenas o uso básico do Metabase para a criação de gráficos simples. Na prática, análises mais robustas exigem testes contínuos, avaliação cuidadosa dos resultados, possíveis uniões entre tabelas e, sempre que necessário, a comparação com outras fontes de informação, garantindo que os dados apresentados sejam consistentes e úteis para a gestão.
O Metabase deve ser compreendido como uma ferramenta de apoio à análise, e não como uma fonte automática de verdade. A qualidade das visualizações produzidas está diretamente relacionada à qualidade da base de dados utilizada e ao cuidado na definição das métricas, filtros e critérios de agrupamento adotados durante a análise.
Por esse motivo, a interpretação dos gráficos e painéis deve ser feita de forma crítica e contextualizada, considerando as limitações dos dados e o objetivo da análise. Visualizações bem construídas auxiliam a tomada de decisão, mas não substituem a análise técnica nem o conhecimento dos processos que originaram os dados.
Para aprofundamento técnico sobre o uso da ferramenta, além da realização de testes práticos pelo próprio usuário, recomenda-se a consulta ao manual oficial do Metabase, especialmente o material introdutório sobre dashboards e visualizações.
Introdução aos Dashboards do Metabase.
Fluxo de Atualização dos Painéis de Dados
Nas páginas anteriores, foram apresentados os conceitos básicos de análise de dados e o uso do Metabase como ferramenta de visualização. A partir deste ponto, o foco passa a ser a manutenção e atualização dos painéis já existentes, garantindo que as informações exibidas continuem refletindo, de forma adequada, a realidade dos dados disponíveis.
Para acessar os conteúdos específicos, utilize o menu lateral esquerdo da Estante SES, onde estão organizados, em estrutura de árvore, os painéis cuja atualização mínima é de responsabilidade da equipe da Saúde Digital. Cada painel possui sua própria página, com orientações direcionadas ao seu contexto.
A atualização dos painéis não consiste na recriação dos gráficos, mas sim na atualização das bases de dados que os alimentam. Esse processo é essencial para que gestores e equipes que utilizam os painéis tenham acesso a informações atuais, consistentes e úteis para o acompanhamento das atividades e apoio à tomada de decisão.
Em cada página, serão apresentados exemplos de painéis já existentes, indicando a origem dos dados, qual tabela deve ser atualizada no upFiles e como verificar, no Metabase, se a atualização foi realizada com sucesso. O objetivo é orientar a equipe quanto ao fluxo de atualização, sem aprofundar em decisões técnicas que podem variar conforme o tipo de dado ou sistema de origem.
É importante destacar que nem todos os painéis possuem a mesma periodicidade ou utilizam as mesmas fontes de dados. Por esse motivo, cada painel é tratado individualmente, respeitando as particularidades do sistema de origem, do formato do relatório e da finalidade da informação apresentada.
Integração de Vacinas à RNDS
| Onde encontrar o painel no Metabase | Metabase > Gestão SES > Integração de Vacinas à RNDS |
| Sistema utilizado para coleta dos dados | Sistema de Gestão Pública de Saúde - SIS <https://sisweb.sorocaba.sp.gov.br> |
| Módulo/Local do relatório no Sistema | Integração > RNDS > Integração RIA (Vacinas) |
| Período que deve ser atualizado | Semanal, com upload realizado uma vez por semana, considerando sempre os dados da semana anterior. A atualização deve ocorrer às segundas-feiras, após a finalização da transmissão e correção das vacinas registradas na sexta-feira e no sábado. |
| Tabela utilizada no upFile | uf_ria_rnds_vacinas |
| Tipo de atualização no upFile | Upload de Dados > Adicionar aos dados existentes > Atualizar (sobrescrever com novos) |
| Como validar a atualização no Metabase |
Conferir se o volume total de registros do painel aumentou de forma compatível com a quantidade de imunizações transmitidas no período analisado e, principalmente, se a distribuição por status apresenta apenas os valores esperados (É importante considerar que a exportação do SIS pode conter registros duplicados da chave primária (Código), e que esse comportamento é tratado no upFiles de acordo com o tipo de atualização selecionado durante o upload.).
O gráfico de Status de Integração deve concentrar os registros nos status Enviado e Erro. A presença de status como Lote não gerado ou Lote gerado indica inconsistências no processo de preparação ou envio dos dados e deve ser tratada no sistema de origem antes de novas atualizações. |
Ao acessar a tela de Integração RIA (Vacinas), limpe o campo de unidade de saúde, garantindo que os dados sejam consultados de forma consolidada. Em seguida, selecione o período correspondente à semana anterior, preferencialmente utilizando o calendário do sistema para marcar o primeiro dia da semana (domingo) até o último dia (sábado).
Após definir o período, marque a opção “Exibir Enviados” e execute a busca para obter os dados de transmissão.
Essa etapa pode levar, em média, entre 5 e 10 minutos para que o sistema conclua o processamento e retorne a lista de imunizações.
Assim que os dados forem exibidos no sistema, clique no botão de exportação de dados e selecione a opção MS Excel para realizar o download do arquivo.
Após realizar o upload dos dados no upFiles, acompanhe principalmente o gráfico de Status de Integração ao longo do tempo no Metabase. Nesse gráfico, espera-se que sejam apresentados apenas registros com os status “Enviado” e “Erro”, que representam o fluxo regular de transmissão das informações.
Caso sejam identificados outros status, isso caracteriza um ponto de atenção no processo. Nessas situações, pode ser necessário realizar a correção dos dados dos pacientes, proceder com o reenvio das informações, reemitir o relatório no sistema de origem e, posteriormente, efetuar novamente o upload no upFiles, mantendo a mesma configuração já estabelecida para este painel.
É importante destacar que a extração e o upload dos dados devem ser realizados sempre considerando períodos de até uma semana. A utilização de intervalos maiores aumenta significativamente a demanda de recursos do servidor, podendo impactar o desempenho do sistema e comprometer o funcionamento de outros serviços. O uso de períodos semanais contribui para a estabilidade do ambiente e para a continuidade das operações.
O gráfico de Status de Integração ao longo do tempo tem como finalidade acompanhar o comportamento das transmissões de imunizações para a RNDS, permitindo identificar rapidamente tanto as situações esperadas quanto os pontos que demandam atenção no processo.
Status apresentados no gráfico:
-
Enviado
-
Indica que a imunização foi devidamente registrada na RNDS.
-
Representa o fluxo correto e esperado do sistema.
-
-
Erro
-
Sinaliza falhas na transmissão das informações.
-
Deve ser acompanhado com atenção, pois permite:
-
identificar unidades ou profissionais com maior recorrência de problemas,
-
analisar os motivos dos erros,
-
avaliar a necessidade de orientações, capacitações adicionais ou ajustes de parametrização no sistema.
-
-
-
Lote não gerado
-
Indica imunizações que permaneceram no sistema sem preparo para envio à RNDS.
-
Representa uma falha anterior à etapa de transmissão.
-
-
Lote gerado
-
Corresponde a lotes que foram preparados, mas ainda não transmitidos à RNDS.
-
Indica interrupção do fluxo após a preparação do envio.
-
Observações importantes:
-
Os status Lote não gerado e Lote gerado não devem aparecer no gráfico ao longo do tempo.
-
A presença desses status caracteriza um desvio significativo do fluxo esperado, indicando falhas no processo de preparação ou envio dos dados.
-
Nesses casos, é necessário revisar o procedimento no sistema de origem antes de realizar qualquer nova atualização no upFiles.
Dessa forma, o comportamento esperado do gráfico é a concentração dos registros apenas nos status Enviado e Erro, sendo este último utilizado como insumo para monitoramento, análise crítica e ações de melhoria contínua no processo de registro e transmissão de imunizações.
Relatório de Agendas de Serviço
| Onde encontrar o painel no Metabase |
Metabase > Gestão SES > Relatório de Agendas de Serviço > Alta com Continuidade do Cuidado Metabase > Gestão SES > Relatório de Agendas de Serviço > Atenção Primária à Saúde Metabase > Gestão SES > Relatório de Agendas de Serviço > Policlínica Municipal Dr. Edward Maluf
|
| Sistema utilizado para coleta dos dados | Sistema de Gestão Pública de Saúde - SIS <https://sisweb.sorocaba.sp.gov.br> |
| Módulo/Local do relatório no Sistema | Regulação > Relatórios > Relatório de pacientes agendados |
| Período que deve ser atualizado | Semanal, com upload realizado uma vez por semana, considerando sempre os dados da semana anterior. A atualização deve ocorrer após o fechamento automático das faltas no sistema (preferencialmente as terças-feiras), que acontece com um intervalo de dois dias, garantindo que os registros de comparecimento e ausência estejam consolidados no momento da extração. |
| Tabela utilizada no upFile | uf_agenda_de_servicos |
| Tipo de atualização no upFile | Upload de Dados > Adicionar aos dados existentes > Atualizar (sobrescrever com novos) |
| Como validar a atualização no Metabase |
A validação dos dados de agenda é realizada de forma comparativa, considerando as limitações do relatório disponível no sistema de origem. Para cada período, os dados precisam ser extraídos separadamente em dois conjuntos, pacientes recepcionados e pacientes faltosos, que juntos compõem a base utilizada para o controle de absenteísmo. A extração e o upload dos dados devem ocorrer preferencialmente às terças-feiras, garantindo que o sistema já tenha aplicado o fechamento automático das faltas.
Após o upload no upFiles, a validação consiste em verificar se os valores apresentados no Metabase estão coerentes com a quantidade aproximada de registros observada durante o upload, especialmente por meio do gráfico que apresenta a proporção entre atendidos e faltosos. O painel considera exclusivamente esses dois tipos de agendamento, não contemplando análises de vagas abertas ou outros estados. |
Ao acessar a tela de Relatório de Pacientes Agendados, selecione o período correspondente à semana anterior, preferencialmente utilizando o calendário do sistema para marcar o primeiro dia da semana (domingo) até o último dia (sábado). Em seguida, no campo Situação, selecione a opção Recepcionado e clique em Gerar CSV para realizar o download dos dados.
Após a conclusão do primeiro download, reaproveite os demais campos já preenchidos, alterando apenas o campo Situação, selecionando a opção Faltou, e clique novamente em Gerar CSV para obter o segundo arquivo necessário à composição da análise de absenteísmo.
O sistema, por padrão, salva o arquivo com o nome ram_rel_pacientes_agendados_[data_atual]. Recomenda-se renomear os arquivos antes do upload, substituindo o termo agendados por recepcionado ou faltou, conforme o conteúdo de cada arquivo, a fim de evitar confusão durante o processo de envio ao upFiles.
É importante destacar que a extração e o upload dos dados devem ser realizados sempre considerando períodos de até uma semana. A utilização de intervalos maiores aumenta significativamente a demanda de recursos do servidor, podendo impactar o desempenho do sistema e comprometer o funcionamento de outros serviços. O uso de períodos semanais contribui para a estabilidade do ambiente e para a continuidade das operações.
É importante lembrar que o processo de obtenção dos dados para este painel ocorre em duas etapas distintas: uma extração considerando a Situação – Recepcionado e outra considerando a Situação – Faltou, sendo ambas necessárias para a composição da análise de absenteísmo.
Após o download dos arquivos, lembre-se de realizar o upload duas vezes no upFiles, uma para cada arquivo, respeitando a situação correspondente a cada conjunto de dados.
Transmissão de Vacinas a RNDS
Este capítulo apresenta o processo de transmissão de vacinas à Rede Nacional de Dados em Saúde (RNDS), no contexto das atividades da Saúde Digital, abordando conceitos gerais da integração RIA, orientações para a transmissão no sistema, correção de registros e tratamento dos erros mais comuns identificados no envio das informações de imunização.
Contextualização
Este material tem como objetivo orientar o usuário sobre como realizar a transmissão de vacinas no SIS, especificamente:
-
Onde localizar a funcionalidade no sistema;
-
Como selecionar o período correto;
-
Como preparar e enviar o lote de vacinas para a RNDS.
Além do passo a passo da transmissão, são apresentadas orientações gerais sobre erros, pendências e correções que podem ocorrer durante esse processo.
O que é a transmissão de vacinas
A transmissão de vacinas é o processo pelo qual os registros de vacinação realizados no sistema municipal (SIS) são enviados para a Rede Nacional de Dados em Saúde (RNDS), por meio da Integração RIA (Vacinas).
Na prática, isso significa que todas as vacinas aplicadas nas unidades de saúde precisam ser comunicadas aos sistemas nacionais, garantindo que a informação esteja disponível de forma unificada no âmbito do SUS.
Esse envio não acontece automaticamente no momento do registro da vacina. Ele depende da execução do processo de transmissão, que reúne os registros em lotes e os envia para a RNDS.
O que é a RNDS
A Rede Nacional de Dados em Saúde (RNDS) é a plataforma do Ministério da Saúde responsável por integrar e centralizar informações de saúde de todo o país.
No contexto da imunização, a RNDS permite que:
-
As vacinas aplicadas sejam visualizadas em nível nacional;
-
O histórico vacinal do paciente fique disponível em outros sistemas;
-
Os dados subsidiem ações de vigilância, planejamento e políticas públicas;
-
Haja maior confiabilidade e rastreabilidade das informações.
Por isso, manter a transmissão de vacinas em dia e sem erros é fundamental para a qualidade da informação em saúde.
O papel do SIS na transmissão de vacinas
O SIS é o sistema onde ocorre:
-
O registro da aplicação da vacina no atendimento ao paciente;
-
A organização desses registros para envio;
-
A transmissão dos dados para a RNDS por meio da Integração RIA (Vacinas).
Ou seja, o SIS funciona como o elo entre a aplicação da vacina na unidade de saúde e a base nacional de dados.
Somente os registros corretamente preenchidos e devidamente transmitidos são aceitos pela RNDS.
O que é a Integração RIA (Vacinas)
A Integração RIA (Vacinas) é o mecanismo utilizado pelo SIS para enviar os dados de vacinação à RNDS.
Por meio dessa integração, o sistema:
-
Seleciona os registros de vacinação de um determinado período;
-
Prepara um lote de envio;
-
Transmite esse lote para a RNDS;
-
Recebe o retorno com o status da transmissão (sucesso ou erro).
Todo esse processo é realizado em uma tela específica do sistema e exige atenção, pois falhas no preenchimento dos dados podem gerar erros na transmissão.
Por que a transmissão de vacinas é importante
A realização correta da transmissão de vacinas é essencial porque:
-
Garante que as vacinas aplicadas sejam reconhecidas oficialmente;
-
Evita divergências entre dados locais e nacionais;
-
Contribui para a segurança do histórico vacinal do paciente;
-
Atende às exigências do Ministério da Saúde quanto ao envio de informações;
-
Reduz retrabalho e correções futuras.
A ausência de transmissão ou a transmissão com erros pode resultar em pendências, inconsistências de dados e necessidade de ajustes posteriores.
Envio de Lote (RIA / RNDS)
A transmissão de vacinas no SIS é o processo responsável por enviar os registros de vacinação do sistema municipal para a RNDS, por meio da Integração RIA (Vacinas).
Esse procedimento garante que as vacinas aplicadas sejam devidamente comunicadas aos sistemas nacionais.
Este manual orienta exclusivamente o passo a passo da transmissão, desde a seleção do período até o envio do lote.
As orientações sobre erros, pendências ou falhas na transmissão estão descritas em outro capítulo e não fazem parte deste material.
Onde realizar a transmissão no sistema
No SIS, a transmissão de vacinas é realizada no seguinte caminho de menu:
Integração → RNDS → Integração RIA (Vacinas)
Passo a passo para transmissão de vacinas
Para acessar a tela de Integração RIA (Vacinas)
-
Acesse o SIS com seu usuário e senha.
-
No menu superior, clique em Integração.
-
Em seguida, clique em RNDS.
-
Selecione a opção Integração RIA (Vacinas).
Limpar a unidade pré-selecionada
Ao abrir a tela, o sistema apresenta automaticamente uma unidade pré-definida.
-
Localize o campo Unidade.
-
Apague a unidade que vem preenchida automaticamente, deixando o campo em branco.
Atenção:A transmissão só deve ser realizada após a remoção da unidade pré-setada, conforme o fluxo definido pelo município.
Definir o período da transmissão
-
Preencha o campo Data Inicial com a data de início do período que será transmitido.
-
Preencha o campo Data Final com a data final do período.
-
Após preencher as datas, clique em Buscar.
Aguarde o carregamento das informações.
Selecionar os registros e preparar o lote
Após a busca, o sistema exibirá a lista de registros de vacinação.
-
Clique na opção Marcar todos para selecionar todos os registros listados.
-
Em seguida, clique no botão Preparar Lote.
O sistema iniciará o preparo do lote. Esse processo pode levar alguns minutos.
Enviar o lote de vacinas
Após o preparo do lote ser concluído:
-
Selecione novamente todos os registros (caso o sistema desmarque automaticamente).
-
Clique no botão Enviar Lote.
-
Aguarde a finalização do envio.
O processo de transmissão pode demorar cerca de 45 minutos.
Durante esse período:
-
Não feche a tela
-
Não atualize o navegador
-
Não realize novas transmissões simultaneamente
Aguardar a conclusão da transmissão
-
Aguarde até que o sistema finalize o envio do lote.
-
Após a conclusão, o status será atualizado conforme o retorno da RNDS.
-
Caso ocorram erros ou pendências, consulte o capítulo específico de erros e correções.
Considerações finais
-
Sempre confira o período selecionado antes de preparar o lote.
-
Realize a transmissão em horários com menor uso do sistema, sempre que possível.
-
Em caso de erro, não refaça o processo sem antes consultar o manual de erros.
Problemas e Correções
É indicado que as transmissões sejam realizadas com intervalo de dois dias anteriores a data da transmissão, para que haja tempo hábil da transmissão por parte de todas as unidades de saúde.
Sempre que transmitido, o transmissor deve verificar os logs de erro para realizar as correções e realizar nova transmissão. Há disponibilização de um documento específico para Mensagens de Erro no Portal de Serviços - RIA.
Também foi criado, baseado nesse documento, um GPT específico que pode orientar quanto aos erros demonstrados em log (clique aqui para acessar o GPT "Assistente de Erros RNDS - Por DIEGO BISPO FERNANDES").
Dos erros mais comuns encontrados nas transmissões, até o presente momento (28/05/2025), as soluções são dadas a partir de:
- Erro de código do Fabricante (0) - Erro de parametrização do Fornecedor do Imunobiológico, para isso, é indicado a visualização da aplicação no paciente em Imunização > Registro no cartão, dessa maneira você será capaz de identificar qual é o fornecedor do imunobiológico e, assim, deve ser localizado o Fornecedor em Almoxarifado > Cadastro de Fabricante e corrigido o código RNDS, de acordo com a tabela Simplifier do RNDS.
- Erros de registro
- Erros de dados Cadastrais
- Erro de CNS do Paciente - Para corrigir, basta corrigir o CNS no cadastro do paciente, de acordo com o CNS encontrado CADSUS Web oficial. A Integração não corrige na totalidade os cadastros por algum problema do webservice, portanto, indica-se sempre atualizar de acordo com o oficial (ATENÇÃO: Cadastros novos são validados em 01 dia, portanto, a retransmissão de cadastros novos deve ocorrer 01 dia após a correção).
- Erro "Attribute value must not be empty" - Esse erro representa falha no cadastro do paciente, onde um ou mais campos responsáveis pela integração estão vazios. Via de regra, CPF e CNS constam vazios e impossibilitam a integração.
Para os erros de dados Cadastrais, encontramos uma solução que apoia a retransmissão. Trata-se de um script Python que realiza login no sistema com as credenciais de quem estiver atarefado a realizar as correções, verifica a lista de prontuários indicada pelo corretor e que, ao executar, entra prontuário a prontuário consultando os dados na integração ao CADSUS para capturar o CPF do Paciente, Apagar o CNS e corrigir a informação de Município de Nascimento do Paciente.
Antes de fazer download do Script, é importante garantir que o seu computador tenha os recursos necessários para a execução do mesmo, para isso, preparamos os materiais abaixo:
Preparando ambiente Python para Windows
Execute no PowerShell o script abaixo
# Instalar Python 3.12
winget install --id Python.Python.3.12 -e --accept-package-agreements --accept-source-agreements
# Recarregar variáveis de ambiente
$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" +
[System.Environment]::GetEnvironmentVariable("Path","User")
# Criar ambiente virtual
python -m venv venv
# Ativar ambiente virtual
.\venv\Scripts\Activate
# Atualizar pip
python -m pip install --upgrade pip
# Instalar dependências necessárias
pip install requests beautifulsoup4
# Teste de imports
python - << EOF
import requests
from bs4 import BeautifulSoup
from datetime import datetime
import time
import re
print("Ambiente Python pronto para execução do script.")
EOF
Preparando ambiente Python para Zorin (Linux)
Execute no Terminal o script abaixo:
#!/bin/bash
# Atualizar repositórios
sudo apt update -y
# Instalar Python 3, pip, venv e dependências de compilação
sudo apt install -y python3 python3-pip python3-venv build-essential
# Criar ambiente virtual
python3 -m venv venv
# Ativar ambiente virtual
source venv/bin/activate
# Atualizar pip
pip install --upgrade pip
# Instalar dependências necessárias
pip install requests beautifulsoup4
# Teste de imports
python - << 'EOF'
import requests
from bs4 import BeautifulSoup
from datetime import datetime
import time
import re
print("Ambiente Python pronto para execução do script.")
EOF
Agora, com o ambiente preparado, você pode baixar o script no link a seguir: wsCorrigeCadastroSIS.py
import requests
from bs4 import BeautifulSoup
from datetime import datetime
import time
import re
# 🔐 CONFIGURAÇÃO DE USUÁRIO E SENHA - EDITE AQUI 🔐
# ═══════════════════════════════════════════════════════════════════════════════════════
USUARIO_SIS = "[INFORME SEU SMS]" # ⬅️ EDITE AQUI: Informe seu SMS
SENHA_SIS = "[INFORME SUA SENHA]" # ⬅️ EDITE AQUI: Coloque a senha do sistema
# ═══════════════════════════════════════════════════════════════════════════════════════
# 📋 LISTA DE PRONTUÁRIOS - COLE AQUI 📋
# ═══════════════════════════════════════════════════════════════════════════════════════
# IMPORTANTE: Cole a lista de prontuários abaixo, um por linha
#
# REGRAS DE FORMATAÇÃO:
# - Cada prontuário deve estar em uma linha separada
# - Separe os prontuários por VÍRGULA
# - O ÚLTIMO prontuário NÃO deve ter vírgula no final
# ═══════════════════════════════════════════════════════════════════════════════════════
PRONTUARIOS = [
1035375,
459159,
760375,
995608,
1136393
]
# ═══════════════════════════════════════════════════════════════════════════════════════
# FIM DA LISTA DE PRONTUÁRIOS
# ═══════════════════════════════════════════════════════════════════════════════════════
# === CONFIGURAÇÕES GERAIS ===
# O sistema adiciona automaticamente o domínio ao usuário
USUARIO_PADRAO = f"{USUARIO_SIS}@sisweb.sorocaba.sp.gov.br"
SENHA_PADRAO = SENHA_SIS
URL_BASE = "https://sisweb.sorocaba.sp.gov.br"
# Valores padrão usados quando campos obrigatórios estão vazios
COD_MUNICIPIO_PADRAO = "3552205"
UF_PADRAO = "SP"
COD_PAIS_NASC_PADRAO = "10" # Brasil (igual exemplo do formulário)
# Lista para registrar prontuários pulados por falta de CPF
PRONTUARIOS_SEM_CPF = []
# Lista para registrar prontuários processados com sucesso (melhor visibilidade em integrações)
PRONTUARIOS_CORRIGIDOS = []
# Lista para armazenar registros detalhados das atualizações (para CSV)
REGISTROS_ATUALIZACAO = []
def fazer_login(usuario=None, senha=None):
"""
Realiza login no SISWEB e retorna (session, csrf_token).
Se usuário/senha não forem informados, usa os padrões.
Adiciona automaticamente @sisweb.sorocaba.sp.gov.br se o usuário não tiver domínio.
"""
if not usuario:
usuario = USUARIO_PADRAO
if not senha:
senha = SENHA_PADRAO
# Adiciona o domínio automaticamente se o usuário não tiver @
if "@" not in usuario:
usuario = f"{usuario}@sisweb.sorocaba.sp.gov.br"
print(f"🔐 Fazendo login no SISWEB com o usuário {usuario}...")
session = requests.Session()
session.headers.update({
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36",
"Accept-Language": "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6",
"Connection": "keep-alive",
"X-Requested-With": "XMLHttpRequest",
})
# Página de login para obter o CSRF
res_login = session.get(f"{URL_BASE}/login")
res_login.raise_for_status()
try:
csrf_token = res_login.text.split('meta name="csrf-token" content="')[1].split('"')[0]
except Exception:
raise RuntimeError("Não foi possível localizar o CSRF token na tela de login.")
# A "conta" é a parte antes do @
conta = usuario.split("@")[0] if "@" in usuario else usuario
payload = {
"utf8": "✓",
"page": "",
"page_query": "",
"conta": conta,
"password": senha,
"commit": "Entrar",
}
resp = session.post(
f"{URL_BASE}/login/create",
data=payload,
headers={
"Referer": f"{URL_BASE}/login",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-CSRF-Token": csrf_token,
},
)
resp.raise_for_status()
print("✅ Login realizado.\n")
return session, csrf_token
def buscar_paciente_id_por_prontuario(session, csrf_token, numprontuario):
"""
Usa o endpoint amb/paciente.json para encontrar o ID interno do paciente (DT_RowId)
a partir do número de prontuário.
"""
params = {
"draw": "1",
"order[0][column]": "1",
"order[0][dir]": "asc",
"start": "0",
"length": "1",
"search[value]": "",
"search[regex]": "false",
"search_operator": "",
"amb_paciente[numprontuario]": str(numprontuario),
# datas podem ser vazias; o filtro principal é o prontuário
"amb_paciente[datcadastro]": "",
"amb_paciente[datalteracao]": "",
"workMode": "wmSearchResult",
"oldWorkMode": "wmSearch",
"_": str(int(time.time() * 1000)), # timestamp em ms, igual ao navegador
}
resp = session.get(
f"{URL_BASE}/amb/paciente.json",
params=params,
headers={
"Accept": "application/json, text/javascript, */*; q=0.01",
"X-CSRF-Token": csrf_token,
"X-Requested-With": "XMLHttpRequest",
"Referer": f"{URL_BASE}/amb/paciente",
},
)
resp.raise_for_status()
try:
data = resp.json()
except Exception as e:
print(f" ❌ Erro ao decodificar JSON de amb/paciente.json (prontuário {numprontuario}): {e}")
print(f" 📄 Resposta bruta: {resp.text[:500]}")
return None
registros = data.get("data", [])
if not registros:
print(f" ❌ Nenhum registro encontrado em amb/paciente.json para o prontuário {numprontuario}.")
return None
primeiro = registros[0]
paciente_id = primeiro.get("DT_RowId")
if not paciente_id:
print(f" ❌ Campo DT_RowId não encontrado no retorno de amb/paciente.json para o prontuário {numprontuario}.")
return None
print(f" 🔎 Paciente encontrado em amb/paciente.json: ID interno {paciente_id}.")
return paciente_id
def carregar_form_edicao(session, paciente_id):
"""
Carrega a tela de edição do paciente e devolve (soup, authenticity_token_form).
"""
url_edit = f"{URL_BASE}/amb/paciente/{paciente_id}/edit"
params = {
"workMode": "wmEdit",
"oldWorkMode": "wmBrowse",
}
resp = session.get(
url_edit,
params=params,
headers={
"Accept": "text/html, */*; q=0.01",
"Referer": f"{URL_BASE}/amb/paciente",
},
)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
# authenticity_token do formulário (hidden field)
token_input = soup.find("input", {"name": "authenticity_token"})
if not token_input or not token_input.get("value"):
raise RuntimeError("Não foi possível localizar authenticity_token no formulário de edição.")
authenticity_token = token_input["value"]
return soup, authenticity_token
def extrair_payload_form(soup):
"""
Lê todos os campos do formulário principal de paciente e devolve um dict
pronto para ser usado no POST (patch).
"""
form = soup.find("form")
if not form:
raise RuntimeError("Formulário de paciente não encontrado na página de edição.")
payload = {}
# Inputs
for inp in form.find_all("input"):
name = inp.get("name")
if not name:
continue
input_type = (inp.get("type") or "").lower()
if input_type in ["checkbox", "radio"]:
if inp.has_attr("checked"):
value = inp.get("value", "1")
else:
# Não envia checkbox/radio não marcados
continue
else:
value = inp.get("value", "")
payload[name] = value
# Textareas
for ta in form.find_all("textarea"):
name = ta.get("name")
if not name:
continue
payload[name] = ta.text or ""
# Selects
for sel in form.find_all("select"):
name = sel.get("name")
if not name:
continue
option_sel = sel.find("option", selected=True)
if option_sel is not None:
value = option_sel.get("value", "")
else:
# fallback: primeira opção
first_opt = sel.find("option")
value = first_opt.get("value", "") if first_opt else ""
payload[name] = value
return payload
def buscar_cpf_cadsus(session, csrf_token, payload, numprontuario):
"""
Tenta buscar o CPF na integração CADSUS usando nome do paciente e nome da mãe.
Retorna o CPF (string) ou None se não encontrar.
"""
nome = payload.get("amb_paciente[nompaciente]", "").strip()
mae = payload.get("amb_paciente[nommae]", "").strip()
if not nome or not mae:
print(" ⚠️ Não há nome e/ou nome da mãe suficientes para pesquisar no CADSUS.")
return None
params = {
"amb_paciente[nome_completo_cadsus]": nome,
"amb_paciente[nome_mae_cadsus]": mae,
"amb_paciente[nome_pai_cadsus]": "",
"amb_paciente[data_nascimento_cadsus]": "",
"amb_paciente[cpf_cadsus]": "",
"amb_paciente[cns_cadsus]": "",
"amb_paciente[tela]": "paciente",
"_": str(int(time.time() * 1000)),
}
try:
resp = session.get(
f"{URL_BASE}/int/data_sus/cad_sus/pesquisar",
params=params,
headers={
"Accept": "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01",
"X-CSRF-Token": csrf_token,
"X-Requested-With": "XMLHttpRequest",
"Referer": f"{URL_BASE}/amb/paciente",
},
timeout=30,
)
resp.raise_for_status()
except Exception as e:
print(f" ❌ Erro ao consultar CADSUS para prontuário {numprontuario}: {e}")
return None
# A resposta é um JavaScript que injeta uma tabela HTML. Procuramos os atributos data-cpf no botão.
# O HTML vem escapado dentro de string JS, então primeiro "desescapamos" aspas.
texto = resp.text.replace('\\"', '"')
# Primeiro data-cpf encontrado será usado
m = re.search(r'data-cpf="([^"]+)"', texto)
if not m:
print(f" ⚠️ Nenhum CPF encontrado no CADSUS para prontuário {numprontuario}.")
return None
cpf = m.group(1).strip()
print(f" 🔄 CPF obtido via CADSUS para prontuário {numprontuario}: {cpf}")
return cpf
def adicionar_mensagem_observacao(payload, mensagem, usuario=None):
"""
Adiciona uma mensagem no campo de observação (infoadicional), preservando o conteúdo existente.
Se usuario não for informado, usa o padrão.
"""
if not usuario:
usuario = USUARIO_PADRAO
# Extrai o operador (parte antes do @)
operador = usuario.split("@")[0] if "@" in usuario else usuario
# Data e hora atual
agora = datetime.now()
data_hora = agora.strftime("%d/%m/%Y %H:%M")
# Monta a mensagem completa
mensagem_completa = f"{data_hora} - Atualizado com Script pelo(a) Operador(a) {operador}, resultado: {mensagem}"
# Pega o conteúdo atual do campo de observação
campo_obs = "amb_paciente[infoadicional]"
conteudo_atual = payload.get(campo_obs, "").strip()
# Se já tem conteúdo, adiciona nova linha antes da nova mensagem
if conteudo_atual:
novo_conteudo = f"{conteudo_atual}\n{mensagem_completa}"
else:
novo_conteudo = mensagem_completa
payload[campo_obs] = novo_conteudo
return mensagem_completa
def ajustar_campos_obrigatorios(payload, numprontuario):
"""
Ajusta/valida campos obrigatórios:
- CPF não pode ficar vazio (retorna False se faltar)
- Município de nascimento não pode ficar vazio (preenche com padrão se necessário)
- Endereço estruturado não pode ficar vazio (CEP + logradouro + bairro)
Retorna:
- True: todos os campos obrigatórios estão OK
- False: faltam dados obrigatórios (CPF ou endereço)
"""
global PRONTUARIOS_SEM_CPF
# Município de nascimento - sempre preenche se vazio
codmun_nasc = payload.get("amb_paciente[codmunicipionasc]", "").strip()
if not codmun_nasc:
print(f" ℹ️ Município de nascimento vazio, preenchendo com padrão {COD_MUNICIPIO_PADRAO}/{UF_PADRAO}.")
payload["amb_paciente[codmunicipionasc]"] = COD_MUNICIPIO_PADRAO
if "amb_paciente[sglufnasc]" in payload and not payload.get("amb_paciente[sglufnasc]", "").strip():
payload["amb_paciente[sglufnasc]"] = UF_PADRAO
# País de nascimento (mantém se já tiver; se não tiver, preenche Brasil padrão)
if "amb_paciente[codpaisnasc]" in payload and not payload.get("amb_paciente[codpaisnasc]", "").strip():
payload["amb_paciente[codpaisnasc]"] = COD_PAIS_NASC_PADRAO
cpf = payload.get("amb_paciente[numcpf]", "").strip()
if not cpf:
print(f" ⚠️ CPF vazio no prontuário {numprontuario}.")
PRONTUARIOS_SEM_CPF.append(numprontuario)
return False
# Endereço estruturado: município de residência, CEP, logradouro e bairro
campos_endereco = {
"amb_paciente[codmunicipiores]": "município de residência",
"amb_paciente[codcep]": "CEP",
"amb_paciente[codlogradouro]": "código do logradouro",
"amb_paciente[codbairro]": "código do bairro",
}
for campo, desc in campos_endereco.items():
if campo not in payload or not str(payload.get(campo, "")).strip():
print(
f" ⚠️ Campo de endereço '{desc}' ({campo}) está vazio no prontuário {numprontuario}."
)
return False
return True
def tem_cns(payload):
"""
Verifica se o payload tem algum campo de CNS preenchido.
Retorna True se encontrar algum campo de CNS/cartão SUS com valor não vazio.
"""
for chave in payload.keys():
nome_lower = chave.lower()
# pega qualquer campo de CNS e qualquer variação de numcartao/numccartao
if "cns" in nome_lower or "numcartao" in nome_lower:
valor = str(payload.get(chave, "")).strip()
if valor: # Se tem algum valor, retorna True
return True
return False
def obter_cns_antes(payload):
"""
Retorna o primeiro valor de CNS encontrado no payload (antes de limpar).
Usado para registrar no CSV.
"""
for chave in payload.keys():
nome_lower = chave.lower()
if "cns" in nome_lower or "numcartao" in nome_lower:
valor = str(payload.get(chave, "")).strip()
if valor:
return valor
return ""
def limpar_cns(payload):
"""
Zera todos os campos relacionados a CNS:
- Qualquer campo cujo nome contenha 'cns'
- Campos de cartão SUS usados como CNS (ex: numcartao / numccartao)
"""
chaves_apagadas = []
for chave in list(payload.keys()):
nome_lower = chave.lower()
# pega qualquer campo de CNS e qualquer variação de numcartao/numccartao
if "cns" in nome_lower or "numcartao" in nome_lower:
payload[chave] = ""
chaves_apagadas.append(chave)
return chaves_apagadas
def salvar_paciente(session, csrf_token, paciente_id, payload):
"""
Envia o PATCH para salvar o paciente com CNS apagado.
"""
url_save = f"{URL_BASE}/amb/paciente/{paciente_id}"
# Garante parâmetros de modo de trabalho e método PATCH
payload.setdefault("utf8", "✓")
payload["_method"] = "patch"
payload.setdefault("workMode", "wmEdit")
payload.setdefault("oldWorkMode", "wmBrowse")
resp = session.post(
url_save,
data=payload,
headers={
"Accept": "text/html, */*; q=0.01",
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-CSRF-Token": csrf_token,
"X-Requested-With": "XMLHttpRequest",
"Referer": f"{URL_BASE}/amb/paciente",
"Origin": URL_BASE,
},
)
if resp.status_code not in (200, 302):
print(f" ❌ Erro ao salvar (HTTP {resp.status_code}).")
return False
return True
def processar_prontuario(session, csrf_token, numprontuario, indice=None, total=None, usuario=None):
global REGISTROS_ATUALIZACAO
# Mostra progresso se indice e total foram fornecidos
if indice is not None and total is not None:
print(f"\n📋 Prontuário {indice}/{total} - Processando prontuário {numprontuario}...")
else:
print(f"\n📋 Processando prontuário {numprontuario}...")
# Inicializa registro para CSV
registro = {
"prontuario": numprontuario,
"cpf_antes": "",
"cns_antes": "",
"municipio_antes": "",
"estado_antes": "",
"cpf_depois": "",
"cns_apagado": "Não",
"sucesso": "Não",
"mensagem": "",
"data_hora": datetime.now().strftime("%d/%m/%Y %H:%M:%S"),
"operador": ""
}
try:
paciente_id = buscar_paciente_id_por_prontuario(session, csrf_token, numprontuario)
if not paciente_id:
registro["mensagem"] = "Paciente não encontrado"
registro["operador"] = usuario.split("@")[0] if usuario and "@" in usuario else (USUARIO_PADRAO.split("@")[0] if "@" in USUARIO_PADRAO else USUARIO_PADRAO)
REGISTROS_ATUALIZACAO.append(registro)
return
soup, authenticity_token = carregar_form_edicao(session, paciente_id)
payload = extrair_payload_form(soup)
# Garante que o authenticity_token correto vá no payload
payload["authenticity_token"] = authenticity_token
# === CAPTURA DADOS ANTES DAS ALTERAÇÕES ===
cpf_antes = payload.get("amb_paciente[numcpf]", "").strip()
cns_antes = obter_cns_antes(payload)
municipio_antes = payload.get("amb_paciente[codmunicipionasc]", "").strip()
estado_antes = payload.get("amb_paciente[sglufnasc]", "").strip()
registro["cpf_antes"] = cpf_antes
registro["cns_antes"] = cns_antes
registro["municipio_antes"] = municipio_antes
registro["estado_antes"] = estado_antes
# Verifica CPF atual (antes de buscar no CADSUS)
cpf_atual = cpf_antes
cpf_capturado_cadsus = None # Rastreia se o CPF foi capturado do CADSUS
# Se já tem CPF e não tem CNS, pode pular para acelerar o processo
if cpf_atual:
if not tem_cns(payload):
print(f" ⏭️ Prontuário já tem CPF e não tem CNS. Pulando para acelerar o processo.")
registro["mensagem"] = "Prontuário já estava correto (tem CPF e não tem CNS)"
registro["operador"] = usuario.split("@")[0] if usuario and "@" in usuario else (USUARIO_PADRAO.split("@")[0] if "@" in USUARIO_PADRAO else USUARIO_PADRAO)
REGISTROS_ATUALIZACAO.append(registro)
return
# Se CPF estiver vazio, tenta buscar via integração CADSUS
if not cpf_atual:
print(" 🔎 CPF vazio no cadastro, tentando buscar via integração CADSUS...")
cpf_cadsus = buscar_cpf_cadsus(session, csrf_token, payload, numprontuario)
if cpf_cadsus:
payload["amb_paciente[numcpf]"] = cpf_cadsus
cpf_capturado_cadsus = cpf_cadsus # Marca que foi capturado do CADSUS
# === LOGA DADOS IMPORTANTES DO CADASTRO ANTES DE QUALQUER ALTERAÇÃO ===
def pega(nome):
return payload.get(nome, "")
print(" 🔍 Dados atuais no cadastro:")
print(f" - Prontuário...............: {pega('amb_paciente[numprontuario]')}")
print(f" - Nome paciente............: {pega('amb_paciente[nompaciente]')}")
print(f" - Data nascimento..........: {pega('amb_paciente[datnascimento]')}")
print(f" - Nome mãe.................: {pega('amb_paciente[nommae]')}")
print(f" - CPF......................: {pega('amb_paciente[numcpf]')}")
print(f" - Cartão SUS (numcartao)...: {pega('amb_paciente[numcartao]')}")
print(f" - Cod logradouro...........: {pega('amb_paciente[codlogradouro]')}")
print(f" - Cod bairro...............: {pega('amb_paciente[codbairro]')}")
print(f" - CEP......................: {pega('amb_paciente[codcep]')}")
print(f" - Cod munic. nascimento....: {pega('amb_paciente[codmunicipionasc]')}")
print(f" - UF nascimento............: {pega('amb_paciente[sglufnasc]')}")
# Ajusta campos obrigatórios (sempre preenche município de nascimento se vazio)
campos_ok = ajustar_campos_obrigatorios(payload, numprontuario)
# Se faltar CPF ou endereço, ainda tenta salvar pelo menos o município de nascimento
if not campos_ok:
cpf = payload.get("amb_paciente[numcpf]", "").strip()
tem_endereco_completo = all([
payload.get("amb_paciente[codmunicipiores]", "").strip(),
payload.get("amb_paciente[codcep]", "").strip(),
payload.get("amb_paciente[codlogradouro]", "").strip(),
payload.get("amb_paciente[codbairro]", "").strip(),
])
if not cpf:
# Falta CPF - adiciona mensagem e tenta salvar pelo menos município de nascimento
usuario_para_msg = usuario if usuario else USUARIO_PADRAO
mensagem = adicionar_mensagem_observacao(
payload,
"sem sucesso por dados insuficientes para coleta de CPF via integracao",
usuario=usuario_para_msg
)
print(f" 📝 Mensagem adicionada no campo de observacao: {mensagem}")
print(" ⚠️ Tentando salvar pelo menos municipio de nascimento...")
# Tenta salvar mesmo sem CPF completo (só município de nascimento)
ok = salvar_paciente(session, csrf_token, paciente_id, payload)
registro["cpf_depois"] = ""
registro["cns_apagado"] = "Sim" if cns_antes else "Não"
registro["sucesso"] = "Parcial" if ok else "Não"
registro["mensagem"] = "sem sucesso por dados insuficientes para coleta de CPF via integracao"
registro["operador"] = usuario_para_msg.split("@")[0] if "@" in usuario_para_msg else usuario_para_msg
REGISTROS_ATUALIZACAO.append(registro)
if ok:
print(f" ✅ Municipio de nascimento salvo com sucesso para o prontuario {numprontuario}.")
else:
print(f" ❌ Falha ao salvar prontuario {numprontuario}.")
return
elif not tem_endereco_completo:
# Falta endereço - não salva para não quebrar o cadastro
print(" ⏭️ Prontuario pulado por falta de informacao de endereco obrigatoria.")
registro["mensagem"] = "Pulado por falta de informação de endereço obrigatória"
registro["operador"] = usuario.split("@")[0] if usuario and "@" in usuario else (USUARIO_PADRAO.split("@")[0] if "@" in USUARIO_PADRAO else USUARIO_PADRAO)
REGISTROS_ATUALIZACAO.append(registro)
return
# Limpa CNS (inclui numcartao)
chaves_cns = limpar_cns(payload)
cns_foi_apagado = len(chaves_cns) > 0
if not chaves_cns:
print(" ℹ️ Nenhum campo de CNS/cartao SUS encontrado para limpar (talvez ja esteja vazio).")
else:
print(f" ✂️ Campos CNS/cartao SUS apagados: {', '.join(chaves_cns)}")
# Salva
ok = salvar_paciente(session, csrf_token, paciente_id, payload)
if ok:
# Adiciona mensagem de sucesso no campo de observação
usuario_para_msg = usuario if usuario else USUARIO_PADRAO
cpf_final = payload.get("amb_paciente[numcpf]", "").strip()
# Monta a mensagem de sucesso
if cpf_capturado_cadsus:
# CPF foi capturado do CADSUS
mensagem_texto = f"atualizacao realizada com sucesso, CNS apagado e inserido CPF {cpf_capturado_cadsus} capturado pela integração CADSUS"
else:
# CPF já existia no cadastro
mensagem_texto = f"atualizacao realizada com sucesso, CNS apagado. CPF {cpf_final} já estava no prontuário"
mensagem = adicionar_mensagem_observacao(
payload,
mensagem_texto,
usuario=usuario_para_msg
)
print(f" 📝 Mensagem de sucesso adicionada no campo de observacao: {mensagem}")
# Salva novamente com a mensagem de sucesso
salvar_paciente(session, csrf_token, paciente_id, payload)
print(f" ✅ Salvamento reportado como sucesso pelo servidor para o prontuario {numprontuario}.")
# Marca como corrigido (para consumo por integracoes / API)
global PRONTUARIOS_CORRIGIDOS
PRONTUARIOS_CORRIGIDOS.append(numprontuario)
# Atualiza registro para CSV
registro["cpf_depois"] = cpf_final
registro["cns_apagado"] = "Sim" if cns_foi_apagado else "Não"
registro["sucesso"] = "Sim"
registro["mensagem"] = mensagem_texto
registro["operador"] = usuario_para_msg.split("@")[0] if "@" in usuario_para_msg else usuario_para_msg
else:
print(f" ❌ Falha ao salvar prontuario {numprontuario} (HTTP diferente de 200/302).")
# Atualiza registro para CSV
registro["cpf_depois"] = payload.get("amb_paciente[numcpf]", "").strip()
registro["cns_apagado"] = "Sim" if cns_foi_apagado else "Não"
registro["sucesso"] = "Não"
registro["mensagem"] = "Falha ao salvar (erro HTTP)"
registro["operador"] = usuario.split("@")[0] if usuario and "@" in usuario else (USUARIO_PADRAO.split("@")[0] if "@" in USUARIO_PADRAO else USUARIO_PADRAO)
# Adiciona registro ao CSV
REGISTROS_ATUALIZACAO.append(registro)
# Pequena pausa entre pacientes
time.sleep(1)
except Exception as e:
print(f" ❌ Erro ao processar prontuário {numprontuario}: {e}")
registro["mensagem"] = f"Erro ao processar: {str(e)}"
registro["operador"] = usuario.split("@")[0] if usuario and "@" in usuario else (USUARIO_PADRAO.split("@")[0] if "@" in USUARIO_PADRAO else USUARIO_PADRAO)
REGISTROS_ATUALIZACAO.append(registro)
def gerar_txt_relatorio(nome_arquivo=None, operador=None):
"""
Gera um arquivo TXT simples com o relatório de atualizações.
Formato do nome: YYYY-MM-DD HHMM ws Corrige CPF SIS [operador].txt
Conteúdo: Prontuário e status de sucesso (similar ao terminal)
"""
if not REGISTROS_ATUALIZACAO:
print("\n⚠️ Nenhum registro para gerar relatório.")
return
if not nome_arquivo:
agora = datetime.now()
# Formato: YYYY-MM-DD HHMM (data ao contrário + hora sem dois pontos)
data_hora = agora.strftime("%Y-%m-%d %H%M")
# Extrai o operador (parte antes do @) se não foi informado
if not operador:
# Tenta pegar do primeiro registro ou usa padrão
if REGISTROS_ATUALIZACAO and REGISTROS_ATUALIZACAO[0].get('operador'):
operador = REGISTROS_ATUALIZACAO[0]['operador']
else:
operador = USUARIO_SIS
nome_arquivo = f"{data_hora} ws Corrige CPF SIS {operador}.txt"
try:
with open(nome_arquivo, 'w', encoding='utf-8') as txtfile:
# Escreve cabeçalho
txtfile.write("=" * 60 + "\n")
txtfile.write("RELATÓRIO DE ATUALIZAÇÕES\n")
txtfile.write(f"Operador: {operador}\n")
txtfile.write(f"Data/Hora: {datetime.now().strftime('%d/%m/%Y %H:%M:%S')}\n")
txtfile.write("=" * 60 + "\n\n")
# Agrupa por status
sucesso = []
falha = []
outros = []
for registro in REGISTROS_ATUALIZACAO:
prontuario = registro['prontuario']
status = registro['sucesso']
if status == "Sim":
sucesso.append(prontuario)
elif status == "Não":
falha.append(prontuario)
else:
outros.append((prontuario, status))
# Escreve prontuários com sucesso
if sucesso:
txtfile.write("✅ PRONTUÁRIOS ATUALIZADOS COM SUCESSO:\n")
for p in sucesso:
txtfile.write(f" - {p}\n")
txtfile.write(f"\nTotal: {len(sucesso)} prontuário(s)\n\n")
# Escreve prontuários com falha
if falha:
txtfile.write("❌ PRONTUÁRIOS NÃO ATUALIZADOS:\n")
for p in falha:
txtfile.write(f" - {p}\n")
txtfile.write(f"\nTotal: {len(falha)} prontuário(s)\n\n")
# Escreve outros status (parcial, pulado, etc)
if outros:
txtfile.write("⚠️ OUTROS STATUS:\n")
for p, status in outros:
txtfile.write(f" - {p} ({status})\n")
txtfile.write(f"\nTotal: {len(outros)} prontuário(s)\n\n")
# Resumo final
txtfile.write("=" * 60 + "\n")
txtfile.write(f"RESUMO:\n")
txtfile.write(f" Total processado: {len(REGISTROS_ATUALIZACAO)}\n")
txtfile.write(f" Sucesso: {len(sucesso)}\n")
txtfile.write(f" Falha: {len(falha)}\n")
if outros:
txtfile.write(f" Outros: {len(outros)}\n")
txtfile.write("=" * 60 + "\n")
print(f"\n📄 Relatório TXT gerado com sucesso: {nome_arquivo}")
print(f" Total de registros: {len(REGISTROS_ATUALIZACAO)}")
return nome_arquivo
except Exception as e:
print(f"\n❌ Erro ao gerar relatório TXT: {e}")
return None
def main():
global REGISTROS_ATUALIZACAO
REGISTROS_ATUALIZACAO = [] # Limpa registros anteriores
inicio = datetime.now()
print(f"🚀 Início da execução: {inicio.strftime('%d/%m/%Y %H:%M:%S')}")
session, csrf_token = fazer_login()
# Acessa uma vez a tela de cadastro (como no uso manual)
try:
session.get(
f"{URL_BASE}/amb/paciente",
headers={
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Referer": f"{URL_BASE}/desktop",
},
)
except Exception:
# Não é crítico, segue o fluxo mesmo assim
pass
total_prontuarios = len(PRONTUARIOS)
for indice, num in enumerate(PRONTUARIOS, start=1):
processar_prontuario(session, csrf_token, num, indice=indice, total=total_prontuarios, usuario=USUARIO_PADRAO)
# Resumo de prontuários não alterados por falta de CPF
if PRONTUARIOS_SEM_CPF:
print("\n⚠️ Prontuários NÃO alterados por estarem sem CPF:")
for p in PRONTUARIOS_SEM_CPF:
print(f" - {p}")
else:
print("\n✅ Nenhum prontuário foi pulado por falta de CPF.")
# Gera relatório TXT
operador_txt = USUARIO_SIS # Usa o operador configurado
gerar_txt_relatorio(operador=operador_txt)
fim = datetime.now()
duracao = (fim - inicio).total_seconds()
print(f"\n🏁 Fim da execução em {duracao:.1f} segundos.")
def run_batch(prontuarios, usuario=None, senha=None):
"""
Executa a correção para uma lista de prontuários e retorna um resumo em dict.
Pensado para uso via API / interface web.
"""
global PRONTUARIOS_SEM_CPF, PRONTUARIOS_CORRIGIDOS, REGISTROS_ATUALIZACAO
PRONTUARIOS_SEM_CPF = []
PRONTUARIOS_CORRIGIDOS = []
REGISTROS_ATUALIZACAO = []
inicio = datetime.now()
session, csrf_token = fazer_login(usuario=usuario, senha=senha)
# Acessa uma vez a tela de cadastro (como no uso manual)
try:
session.get(
f"{URL_BASE}/amb/paciente",
headers={
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Referer": f"{URL_BASE}/desktop",
},
)
except Exception:
pass
total_prontuarios = len(prontuarios)
usuario_para_processar = usuario if usuario else USUARIO_PADRAO
for indice, num in enumerate(prontuarios, start=1):
processar_prontuario(session, csrf_token, num, indice=indice, total=total_prontuarios, usuario=usuario_para_processar)
fim = datetime.now()
duracao = (fim - inicio).total_seconds()
return {
"total": len(prontuarios),
"corrigidos": PRONTUARIOS_CORRIGIDOS,
"nao_alterados_sem_cpf": PRONTUARIOS_SEM_CPF,
"duracao": duracao,
}
if __name__ == "__main__":
main()
Transmissão de Fichas para o ESUSAPS
Como Transmitir as Fichas do ESUS
Este manual tem como objetivo orientar, de forma simples e clara, o processo inicial de transmissão de fichas no e-SUS APS, especificamente a etapa de exportação dos dados a partir do SISWEB.
Nesse procedimento, os dados registrados no SISWEB são exportados em arquivos, obedecendo os padrões LEDI estabelecidos pelo Ministério da Saúde, que posteriormente serão importados no e-SUS APS, permitindo a consolidação da produção do período selecionado.
A correta realização dessa etapa é fundamental para garantir que as informações sejam organizadas e preparadas adequadamente para envio. As orientações sobre erros, inconsistências ou falhas no processo serão abordadas em outro capítulo deste material.
Onde será realizado o processo no SIS
Após entrar no sistema, na aba de pesquisa, pesquise pelo módulo ESUS e nele você irá encontrar Exportar dados para o e-SUS.
Antes de começar o passo a passo, é importante lembrar que você terá que selecionar qual ficha você irá exportar. Elas ficarão do lado esquerdo na tela em uma espécie de "menu":
Vale lembrar também que, TODAS as fichas devem ser exportadas.
Passo a Passo para exportar as fichas
Ao abrir a tela de exportação, localize e preencha os campos:
-
Data inicial
-
Data final
A Exportação deve ser realizada sempre considerando como data incial o primeiro dia do ano e a data final como 01 dia útil anterior ao dia da extração.
Clique no ícone de pesquisa. Em seguida, o sistema exibirá os arquivos referentes ao período selecionado. Verifique se os resultados correspondem às datas informadas.
Importante: Cuidado ao colocar a data, pois dependendo do intervalo de tempo, o sistema pode demorar tanto para procurar como para exportar, tendo risco de dar erro ao exportar, procure colocar um baixo intervalo de tempo, a não ser que você faça exportações de forma recorrente, neste caso dificilmente dará problema.
Após isso clique no botão de download que está como Gerar Arquivo, assim será feita a exportação das fichas.
Agora vamos para o passo a passo das importações.
Passo a Passo para importar as fichas
Após a exportação dos dados no SISWEB, é necessário realizar a importação dos arquivos no e-SUS APS <https://esusaps.sorocaba.sp.gov.br/>.
Essa etapa permite que as fichas exportadas sejam recebidas pelo sistema, possibilitando a consolidação da produção e a verificação de registros válidos ou com inconsistências.
O passo a passo a seguir orienta como acessar o módulo correto e importar os arquivos gerados anteriormente.
Tela para Login:
Conferência das fichas importadas
A conferência deve ser feita sempre após cada importação, garantindo a qualidade das informações transmitidas.
Logo após fazer o login, certifique que está no módulo Transmissão de Dados, se não estiver basta abrir o menu da esquerda e mudar.
Na Transmissão de dados, selecione a aba de Recebimento e selecione para importar os arquivos.
Relatório de Inconsistências
Após a importação, o sistema exibirá os arquivos recebidos, apresentando a quantidade de fichas em cada situação:
-
Fichas válidas: registros importados com sucesso.
-
Fichas inválidas: registros que apresentam inconsistências e não foram aceitos pelo sistema.
Essa separação permite identificar rapidamente se há necessidade de correção.
Após a importação dos arquivos, é indispensável realizar a conferência final das fichas recebidas.
Verifique se o total de registros importados corresponde ao volume esperado para o período transmitido e se não houve importação duplicada do mesmo arquivo.
O sistema apresentará a separação entre fichas válidas e fichas inválidas. Quando houver fichas inválidas, isso indica a presença de inconsistências que impedem a aceitação dos registros. Nesses casos, estará disponível a opção de gerar o Relatório de Inconsistências, que detalha os motivos pelos quais as fichas não foram importadas corretamente.
A análise desse relatório é fundamental para a correção dos registros e posterior retransmissão dos dados. O processo de correção das inconsistências será abordado em um capítulo específico deste manual.
O processo de transmissão não deve ser considerado finalizado sem a conferência das fichas importadas. A ausência dessa verificação pode resultar em perda de produção ou no envio de dados incompletos ou inconsistentes.
Ao clicar no ícone localizado à direita da linha do arquivo importado, é possível gerar o relatório contendo apenas as fichas inválidas, facilitando a análise e a correção dos registros.
A geração desses relatórios é uma etapa fundamental do processo de transmissão, pois garante que todas as informações enviadas estejam corretas e aptas para consolidação da produção.
No próximo capítulo, será apresentado o passo a passo para analisar os Relatórios de Inconsistências, corrigir as informações no sistema e realizar um novo envio das fichas corrigidas.
Correção de Erros e Inconsistências
Este manual tem como objetivo orientar, de forma simples e clara, o processo de identificação e correção de erros e inconsistências encontrados após a transmissão das fichas do e-SUS APS.
Durante a transmissão, algumas fichas podem ser consideradas inválidas. Nesses casos, o sistema disponibiliza um relatório de erros que deve ser analisado para que as correções sejam realizadas corretamente no SISWEB, garantindo a integridade das informações enviadas ao Ministério da Saúde.
Onde realizar o processo no sistema
-
e-SUS APS: para identificar fichas válidas e inválidas e baixar o relatório de inconsistências.
-
SISWEB: para liberar fichas para edição e realizar as correções necessárias.
Passo a passo para correção de erros e inconsistências
1. Identificar fichas inválidas no e-SUS APS
Após realizar a transmissão das fichas no e-SUS APS, verifique a coluna “Fichas válidas/inválidas”.
-
Quando houver fichas inválidas, o botão de download (
) do relatório de erros ficará habilitado.
2. Baixar o relatório de inconsistências
-
Clique no botão de download (
) disponível na linha da transmissão.
-
Será gerado um arquivo de relatório contendo as inconsistências encontradas.
3. Organizar os relatórios
Para facilitar a visualização e o controle, recomenda-se organizar os arquivos em pastas no Google Drive.
-
Acesse o Google Drive.
-
Utilize o padrão de nomeação: Ano.Mês.Dia (exemplo: 2026.01.05).
-
Dentro da pasta criada:
-
Salve as fichas baixadas do SISWEB.
-
Crie uma subpasta chamada Relatórios.
-
Armazene nela todos os relatórios de inconsistências do e-SUS APS. Para saber mais sobre como transmitir as fichas, acesse: Como transmitir as fichas do ESUS.
-
4. Abrir e analisar o relatório
-
Localize o arquivo do relatório.
-
Clique com o botão direito e selecione Abrir com > Planilhas Google.
Ao abrir a planilha, concentre-se apenas nas seguintes colunas:
-
Coluna E – Tipo da ficha (ex.: Atendimento Individual, Procedimentos, etc.).
-
Coluna G – UUID da ficha (usado para localizar a ficha no SISWEB).
-
Coluna J – Descrição do erro encontrado.
Essas informações são suficientes para identificar o que precisa ser corrigido.
5. Liberar fichas para edição no SISWEB
-
Acesse o SISWEB.
-
Pesquise pela opção “Liberar Fichas para Edição”.
⚠️ Atenção: esse processo pode levar alguns minutos, dependendo da quantidade de UUIDs informados.
6. Localizar a ficha para correção
-
No SISWEB, pesquise por “e-SUS Ficha”.
-
Selecione o tipo de ficha correspondente ao erro (ex.: Ficha de Procedimentos, Atendimento Individual, etc.).
-
Na tela da ficha:
-
Clique em Limpar (
).
-
Informe o UUID dado serializado.
-
Clique em Pesquisar (
).
-
7. Correção de erro de CNS do profissional (exemplo comum)
Quando o erro estiver relacionado ao CNS do profissional:
-
Identifique o CNS informado na ficha.
-
Consulte o cadastro do profissional no CNES.
Caso o profissional não seja encontrado, solicite por e-mail:
-
Confirmação de cadastro no CNES;
-
CNS correto;
-
CBO;
-
Conselho profissional;
-
Conselho Regional.
⚠️ Se o profissional não possuir cadastro no CNES, a unidade deverá solicitar o cadastramento oficial.
8. Ajustar os dados e salvar
-
Após corrigir as informações necessárias na ficha:
-
Revise todos os campos obrigatórios.
-
Clique em Salvar.
-
-
Repita o procedimento para todos os UUIDs listados no relatório.
Considerações finais
A correção das inconsistências é fundamental para garantir a qualidade das informações enviadas ao Ministério da Saúde. Sempre que houver fichas inválidas, siga este procedimento antes de realizar uma nova transmissão.
Em caso de dúvidas ou erros não previstos neste manual, entre em contato com a equipe de suporte da Saúde Digital.
Cadastro de Endereçamento no SIS
Contextualização
Este manual foi elaborado para orientar o uso da funcionalidade de Endereçamento do Sistema SIS, responsável pelo cadastro e manutenção de informações como bairros, logradouros, vínculo entre bairro e logradouro e CEP.
O correto preenchimento desses dados é essencial para garantir a padronização dos endereços utilizados no sistema, impactando diretamente a qualidade dos cadastros, atendimentos e consultas realizadas pelas unidades de saúde.
Introdução
Este manual tem como objetivo orientar o cadastro de endereçamento no sistema SIS, abrangendo as seguintes informações:
-
Bairro
-
Logradouro
-
Logradouro do Bairro
-
CEP
Para facilitar, siga a ordem: Bairro -> Logradouro -> Logradouro do Bairro -> CEP
Esse cadastro é utilizado tanto para a cidade de Sorocaba quanto para outros municípios da região, como Alumínio, e é fundamental para garantir o correto registro de endereços nos atendimentos e cadastros do sistema.
O procedimento é geralmente realizado pela equipe de TI ou administrativa, e este material foi elaborado pensando em usuários sem familiaridade prévia com o SIS.
Onde encontrar o cadastro no sistema
Após acessar o sistema SIS com seu usuário e senha, os cadastros de endereçamento ficam disponíveis no seguinte caminho:
Dentro da área de Endereçamento, você encontrará as seguintes abas:
-
Bairro
-
Logradouro
-
Logradouro do Bairro
- CEP
Antes de começar os cadastros, siga a ordem sugerida anteriormente, verifique se o bairro ou logradouro já existe no sistema antes de criar um novo cadastro, evitando duplicidades. E verifique se a cidade está correta.
Na maioria dos cadastros, a cidade utilizada será Sorocaba, podendo variar conforme a necessidade.
Cadastro de Bairro
Nesta página, você aprenderá como realizar o cadastro de bairro no SISWEB.
Esse é o primeiro passo do processo de endereçamento e deve sempre ser realizado antes dos demais cadastros, pois o bairro será utilizado nas etapas seguintes, como cadastro de endereço, atendimentos e consultas.
O preenchimento correto dessas informações garante a padronização dos endereços no sistema, evita inconsistências e reduz problemas em registros futuros.
O procedimento é simples e pode ser realizado mesmo por usuários que não possuem familiaridade com o SIS, desde que sigam o passo a passo descrito abaixo.
Atenção – Validação obrigatória antes de cadastrar
Antes de criar um novo bairro, é obrigatório verificar se ele já não está cadastrado no sistema.
Essa validação evita:
• Cadastro de bairros duplicados
• Diferenças de grafia para o mesmo bairro
• Problemas na padronização dos endereços
Para realizar essa verificação:
• Utilize sempre o botão Localizar (ícone de lupa)
• Pesquise pelo nome do bairro antes de clicar em Adicionar
Somente prossiga com o cadastro se tiver certeza de que o bairro ainda não existe no sistema.
Etapa inicial
Esta etapa serve para criar o bairro que será utilizado nos cadastros de endereço.
Na maioria dos casos, o município será Sorocaba, mas o cadastro também pode ser utilizado para bairros de outros municípios da região, quando necessário.
Passo a passo
Vamos iniciar o cadastro acessando o módulo Endereçamento e a tela “Bairro”.
Conforme recomendação anterior, antes de iniciar o cadastro, clique no botão Localizar (ícone de lupa) e, na lista que for carregada, verifique se o bairro já está cadastrado, para evitar cadastros duplicados.
Caso seja confirmado que não há cadastro do bairro, clique em Adicionar.
O cadastro de bairros é relativamente simples, sendo necessário apenas garantir o preenchimento dos dados mínimos, que são Município e Bairro.
Os demais parametros podem ser mantidos como estão.
Pronto, você acabou de cadastrar um bairro e pode prosseguir a proxima etapa.
Cadastro de Logradouro
Após a conclusão do cadastro de bairro, o próximo passo do processo de endereçamento no sistema SIS é o cadastro de logradouro.
Nesta etapa, são registrados os nomes das ruas, avenidas, travessas, alamedas, entre outros tipos de vias, que posteriormente poderão ser vinculados aos bairros cadastrados.
Esse cadastro é essencial para a correta composição dos endereços utilizados no sistema.
O procedimento é simples e deve ser realizado com atenção, garantindo que o nome do logradouro esteja correto e padronizado, evitando duplicidades e inconsistências nos cadastros.
Cadastro de Logradouro
O logradouro corresponde ao nome da rua, avenida, alameda, travessa, entre outros.
Na maioria dos casos, o município será Sorocaba, mas também pode ser usado para outras cidades da região.
Passo a passo
-
Acesse a aba Logradouro.
-
Clique em Novo ou Adicionar.
-
Preencha os campos obrigatórios:
-
Cidade: cidade desejada.
-
Tipo de logradouro: Rua, Avenida, Travessa, etc.
-
Nome do logradouro: nome completo da via.
-
-
Verifique se os dados estão corretos.
-
Clique em Salvar.
O código do "Tipo" muda de acordo se é rua, avenida, travessa. Em seguida uma lista com os tipos e seus respectivos códigos.
- RUA - 081
- RODOVIA - 090
- ESTRADA - 31
- TRAVESSA - 100
- VIELA - 105
- AVENIDA - 08
- 1A TRAVESSA DA RUA - 507
- 2A TRAVESSA DA RUA - 508
- ALAMEDA - 04
- PRAÇA - 065
- CONDOMÍNIO - 485
- ENTRADA - 081
Cadastro de Logradouro do Bairro
Após o cadastro do logradouro, o próximo passo no processo de endereçamento no sistema SIS é o vínculo entre o bairro e o logradouro, realizado por meio do cadastro de Logradouro do Bairro.
Nesta etapa, o sistema associa o logradouro previamente cadastrado ao bairro correspondente, permitindo que essa relação seja utilizada corretamente nos cadastros de endereço.
Normalmente, esse vínculo é feito entre o bairro e o logradouro recém-criados, mas também pode ser utilizado para associações já existentes no sistema.
A realização correta desse procedimento é essencial para garantir que os endereços fiquem completos, organizados e disponíveis para uso nas demais funcionalidades do sistema.
Cadastro de Logradouro do Bairro
Nesta tela, o sistema faz o vínculo entre o logradouro e o bairro.
Normalmente, será vinculado o logradouro recém-criado ao bairro recém-criado.
Passo a passo
-
Acesse a aba Logradouro do Bairro.
-
Clique em Novo ou Adicionar.
-
Preencha os campos:
-
Cidade: selecione a cidade.
-
Bairro: selecione o bairro desejado.
-
Logradouro: selecione o logradouro correspondente.
-
-
Confira se o vínculo está correto.
-
Clique em Salvar.
O número inicial e final deve ser colocado caso o logradouro seja "Avenida". Em caso de dúvida perguntar para seu superior.
Cadastro de CEP
Após a realização do vínculo entre bairro e logradouro, o último passo do processo de endereçamento no sistema SIS é o cadastro de CEP.
Nesta etapa, o CEP é associado à cidade, ao bairro e ao logradouro, garantindo que o endereço fique completo e corretamente padronizado para utilização nos cadastros e atendimentos do sistema.
Além do cadastro, essa funcionalidade também permite a consulta de CEPs já registrados, facilitando a verificação de informações e evitando duplicidades.
O correto preenchimento desses dados é essencial para assegurar a consistência e a confiabilidade das informações de endereço no SIS.
Cadastro de CEP
O cadastro de CEP serve para vincular o CEP à cidade, bairro e logradouro, garantindo que o endereço fique completo e padronizado no sistema.
Além do cadastro, essa aba também pode ser utilizada para consulta de CEPs já existentes.
Passo a passo para cadastro
-
Acesse a aba CEP.
-
Clique em Novo ou Adicionar.
-
Preencha os campos:
-
CEP: informe o número do CEP.
-
Cidade: normalmente Sorocaba.
-
Bairro: selecione o bairro (geralmente o recém-criado).
-
Logradouro: selecione o logradouro correspondente.
-
-
Verifique se todas as informações estão corretas.
-
Clique em Salvar.
Consulta de CEP
A aba CEP também pode ser utilizada para consultar endereços já cadastrados. Basta apenas filtrar de acordo com a pesquisa que você deseja.
Pode filtrar apenas por bairro para ver os logradouros que possuem cadastrados e o respectivos CEPs ou filtra por bairro e logradouro para ver qual CEP está cadastro sem ter que ver a lista inteira de logradouros
Com a conclusão dessas etapas, o cadastro de endereçamento estará disponível para uso em todo o sistema SIS, garantindo maior padronização e qualidade das informações.