Inclusão do modelo de operadora Bradesco - Importação plano de saúde.
This commit is contained in:
parent
3541917a0b
commit
4f5c5a17f1
@ -41,7 +41,7 @@ Não há suíte de testes, lint ou build configurados neste projeto.
|
|||||||
|
|
||||||
### Ambiente de desenvolvimento assistido
|
### Ambiente de desenvolvimento assistido
|
||||||
|
|
||||||
O `.venv` do projeto já tem Python 3.13 + Django 6.0 + DRF + psycopg + python-dotenv + Pillow + nh3 + reportlab + openpyxl + holidays instalados, e há um Postgres local acessível via `.env` — dá pra rodar `makemigrations`/`migrate`/`seed_portal`/`runserver` normalmente por aqui usando `.venv\Scripts\python.exe manage.py ...` (ou ativando o venv primeiro). Isso deixou de ser uma limitação a partir da rodada em que o ambiente ganhou essas ferramentas (ver `plano.md`) — não assumir mais que só é possível revisar o backend estaticamente.
|
O `.venv` do projeto já tem Python 3.13 + Django 6.0 + DRF + psycopg + python-dotenv + Pillow + nh3 + reportlab + openpyxl + holidays + docling instalados, e há um Postgres local acessível via `.env` — dá pra rodar `makemigrations`/`migrate`/`seed_portal`/`runserver` normalmente por aqui usando `.venv\Scripts\python.exe manage.py ...` (ou ativando o venv primeiro). Isso deixou de ser uma limitação a partir da rodada em que o ambiente ganhou essas ferramentas (ver `plano.md`) — não assumir mais que só é possível revisar o backend estaticamente.
|
||||||
|
|
||||||
## Arquitetura
|
## Arquitetura
|
||||||
|
|
||||||
@ -502,11 +502,14 @@ portal_api/planos_saude/
|
|||||||
├── unimed/saude.py Unimed (CSV, mensalidade+coparticipação, casamento por nome)
|
├── unimed/saude.py Unimed (CSV, mensalidade+coparticipação, casamento por nome)
|
||||||
├── itamed/saude.py Itamed Saúde (PDF via pdfplumber, mensalidade+coparticipação, casamento por nome)
|
├── itamed/saude.py Itamed Saúde (PDF via pdfplumber, mensalidade+coparticipação, casamento por nome)
|
||||||
├── dental_uni/odonto_mensalidade.py Dental Uni Odonto (PDF via pdfplumber, só mensalidade, casamento por nome)
|
├── dental_uni/odonto_mensalidade.py Dental Uni Odonto (PDF via pdfplumber, só mensalidade, casamento por nome)
|
||||||
└── unimed_oeste_pr/saude.py Unimed Oeste do Paraná (PDF via pdfplumber, mensalidade+coparticipação por texto da descrição, casamento por nome)
|
├── unimed_oeste_pr/saude.py Unimed Oeste do Paraná (PDF via pdfplumber, mensalidade+coparticipação por texto da descrição, casamento por nome)
|
||||||
|
└── bradesco/saude.py Bradesco Saúde (PDF **sem texto selecionável** — OCR via `docling`, mensalidade+coparticipação, casamento por nome)
|
||||||
```
|
```
|
||||||
|
|
||||||
Pra adicionar uma operadora nova: criar `operadoras/<nome>/<arquivo>.py` implementando `OperadoraParser.extrai()` (devolve `(List[Individuo], List[ItemAuditoria])`) e registrar em `pipeline.OPERADORAS`. **Antes de escrever o parser, ler `projects/importacao-planos-saude.skill`** — documenta decisões de negócio já validadas com o cliente (ex.: nome divergente nunca é resolvido por aproximação, valor final negativo vai pra auditoria, um mesmo beneficiário pode aparecer em várias linhas/rubricas e precisa ser somado) que não devem ser reinterpretadas sem confirmar de novo.
|
Pra adicionar uma operadora nova: criar `operadoras/<nome>/<arquivo>.py` implementando `OperadoraParser.extrai()` (devolve `(List[Individuo], List[ItemAuditoria])`) e registrar em `pipeline.OPERADORAS`. **Antes de escrever o parser, ler `projects/importacao-planos-saude.skill`** — documenta decisões de negócio já validadas com o cliente (ex.: nome divergente nunca é resolvido por aproximação, valor final negativo vai pra auditoria, um mesmo beneficiário pode aparecer em várias linhas/rubricas e precisa ser somado) que não devem ser reinterpretadas sem confirmar de novo.
|
||||||
|
|
||||||
|
**PDF sem texto selecionável (ex.: Bradesco Saúde) precisa de OCR, não de `pdfplumber`**: confirmado rodando `pdfplumber` contra o arquivo real da Bradesco — `page.chars`/`page.extract_text()` vêm vazios em toda página, porque o documento é uma composição de imagens raster (cada linha da tabela é literalmente um bitmap), sem nenhuma camada de texto. Nesse caso o parser usa `docling` (biblioteca de OCR + reconstrução de estrutura de tabela, adicionada ao `requirements.txt` — pesada: traz `torch`/`transformers`/`opencv-python` como dependência transitiva, então o primeiro `pip install` baixa bem mais do que os parsers em `pdfplumber` exigiam) em vez de `pdfplumber`. Ver o docstring de `operadoras/bradesco/saude.py` para o motivo de usar reconstrução de tabela (`DocumentConverter().convert(...).document.tables`, cabeçalho identificado por texto normalizado via `_classifica_coluna`, não por posição fixa) e o contorno de um bug real de fronteira de célula do modelo de tabela (TableFormer) nas colunas numéricas estreitas — valor de uma linha "vazando" pra célula da linha vizinha, contornado extraindo todos os valores monetários da área em ordem de leitura e redistribuindo 1 por linha, em vez de confiar em qual célula específica o modelo atribuiu cada valor. Ao adicionar outra operadora nesse mesmo caso (PDF sem texto selecionável), reaproveitar essa técnica em vez de assumir que `pdfplumber` vai funcionar — testar primeiro com `page.chars`/`extract_text()` contra o arquivo real antes de escolher qual dos dois usar.
|
||||||
|
|
||||||
**Diferença deliberada em relação ao pipeline original**: lá, o valor do mês sempre gravava na coluna `VALOR` (desconto do empregado), nunca em `VALOREMPRESA` — regra fixa. Aqui, o usuário escolhe na tela de nova importação, **por tipo de lançamento (mensalidade/coparticipação) e por tipo de beneficiário (titular/dependente)** — quatro combinações independentes, ex.: mensalidade do titular custeada pela empresa e mensalidade do dependente descontada do empregado —, uma de três regras de custeio: "Custeado pela empresa" (`{"modo": "empresa"}`), "Descontado do empregado" (`{"modo": "empregado"}`, o comportamento antigo — nomenclatura "empregado", não "funcionário", pra não confundir com `NOMEFUNC`/`CPFFUNC` do leiaute do Questor, que é outra coisa) ou "Regra específica" (`{"modo": "especifica", "limite_valor": float|None, "percentual": float|None}`). Na regra específica, `limite_valor` é um teto de quanto a empresa cobre (o excedente vira desconto do empregado) e `percentual` é a fração do valor do mês custeada pela empresa (o resto vira desconto) — o usuário pode preencher só um dos dois ou os dois juntos; quando os dois vêm preenchidos, prevalece o que resultar no **menor** valor custeado pela empresa (mais restritivo), decisão explícita do usuário. Essa divisão é calculada por `matcher._calcula_valores(valor_total, regra)` (chamada por `_aplica_regra_custeio`, que grava `valor_empresa`/`valor` **os dois juntos** a partir do mesmo `valor_total`) — note que `valor_empresa` é arredondado primeiro e `valor` é derivado como o complemento exato (`valor_total - valor_empresa`, também arredondado), nunca os dois arredondados de forma independente, senão a soma dos dois podia ficar 1 centavo a mais/menos que o valor original (ex.: 50% de 51,69 tem que fechar em 25,84 + 25,85 = 51,69, não 25,85 + 25,85). Qual das duas regras (titular ou dependente) usar em cada `Individuo`/`LinhaSistema` é resolvido por `matcher._regra_para_pessoa(regra_por_pessoa, tipo_pessoa)` — `tipo_pessoa` 'T' cai em "titular", 'D'/'A' caem em "dependente" (mesmo critério de "D e A tratados igual" já usado no resto do leiaute) — chamada nos dois pontos de aplicação de `_casa_por_cpf`/`_casa_por_nome` antes de `_aplica_regra_custeio`.
|
**Diferença deliberada em relação ao pipeline original**: lá, o valor do mês sempre gravava na coluna `VALOR` (desconto do empregado), nunca em `VALOREMPRESA` — regra fixa. Aqui, o usuário escolhe na tela de nova importação, **por tipo de lançamento (mensalidade/coparticipação) e por tipo de beneficiário (titular/dependente)** — quatro combinações independentes, ex.: mensalidade do titular custeada pela empresa e mensalidade do dependente descontada do empregado —, uma de três regras de custeio: "Custeado pela empresa" (`{"modo": "empresa"}`), "Descontado do empregado" (`{"modo": "empregado"}`, o comportamento antigo — nomenclatura "empregado", não "funcionário", pra não confundir com `NOMEFUNC`/`CPFFUNC` do leiaute do Questor, que é outra coisa) ou "Regra específica" (`{"modo": "especifica", "limite_valor": float|None, "percentual": float|None}`). Na regra específica, `limite_valor` é um teto de quanto a empresa cobre (o excedente vira desconto do empregado) e `percentual` é a fração do valor do mês custeada pela empresa (o resto vira desconto) — o usuário pode preencher só um dos dois ou os dois juntos; quando os dois vêm preenchidos, prevalece o que resultar no **menor** valor custeado pela empresa (mais restritivo), decisão explícita do usuário. Essa divisão é calculada por `matcher._calcula_valores(valor_total, regra)` (chamada por `_aplica_regra_custeio`, que grava `valor_empresa`/`valor` **os dois juntos** a partir do mesmo `valor_total`) — note que `valor_empresa` é arredondado primeiro e `valor` é derivado como o complemento exato (`valor_total - valor_empresa`, também arredondado), nunca os dois arredondados de forma independente, senão a soma dos dois podia ficar 1 centavo a mais/menos que o valor original (ex.: 50% de 51,69 tem que fechar em 25,84 + 25,85 = 51,69, não 25,85 + 25,85). Qual das duas regras (titular ou dependente) usar em cada `Individuo`/`LinhaSistema` é resolvido por `matcher._regra_para_pessoa(regra_por_pessoa, tipo_pessoa)` — `tipo_pessoa` 'T' cai em "titular", 'D'/'A' caem em "dependente" (mesmo critério de "D e A tratados igual" já usado no resto do leiaute) — chamada nos dois pontos de aplicação de `_casa_por_cpf`/`_casa_por_nome` antes de `_aplica_regra_custeio`.
|
||||||
|
|
||||||
### Modelos (`portal_api/models.py`)
|
### Modelos (`portal_api/models.py`)
|
||||||
|
|||||||
BIN
media/planos_saude/operadora/197_-_COPARTICIPAÇÃO.pdf
Normal file
BIN
media/planos_saude/operadora/197_-_COPARTICIPAÇÃO.pdf
Normal file
Binary file not shown.
BIN
media/planos_saude/operadora/221_-_RELATÓRIO_BRADESCO_082026.pdf
Normal file
BIN
media/planos_saude/operadora/221_-_RELATÓRIO_BRADESCO_082026.pdf
Normal file
Binary file not shown.
BIN
media/planos_saude/operadora/221_-_RELATÓRIO_ITAMED_082026.pdf
Normal file
BIN
media/planos_saude/operadora/221_-_RELATÓRIO_ITAMED_082026.pdf
Normal file
Binary file not shown.
@ -0,0 +1,66 @@
|
|||||||
|
Cód. Contr/Contrat. Pagador;Id. Título;Número Título;Valor Bruto;Valor Líquido;Situação Título;Contratante;Id. Titular;Família;Id. Benef.;Cód.Beneficiário;Nome Beneficiário;Tipo Benef.;Grau Depend.;Código Combinação;Reservado;Valor;Competência;Tipo;Tipo Ato Médico;Cód. Serviço;Descrição Serviço;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;756165;TABATA CAROLINE GOES DA SILVA - 835199;756165;'9750167003613895;TABATA CAROLINE GOES DA SILVA;1;0 - TITULAR;10215;;272,77;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;756165;TABATA CAROLINE GOES DA SILVA - 835199;754971;'9750167003821633;WENDY MANOEL MIGUEL MELO DA SILVA;2;1 - CONJUGE;10008;;231,78;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;756165;TABATA CAROLINE GOES DA SILVA - 835199;756166;'9750167003613909;LUISA VALENTINA GOES DE MELO;2;10 - FILHO(A);10008;;130,13;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;762483;ADRIANA JARDIM DE CARVALHO - 835478;762483;'9750167003631320;ADRIANA JARDIM DE CARVALHO;1;0 - TITULAR;10008;;706,01;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;761760;TAWANY THYESKA DE PIERRI MARQUES - 835910;761760;'9750167003658732;TAWANY THYESKA DE PIERRI MARQUES;1;0 - TITULAR;10215;;238,92;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;761760;TAWANY THYESKA DE PIERRI MARQUES - 835910;761761;'9750167003658740;THAEMY LOHAYNE DE PIERRE BORGES;2;10 - FILHO(A);10008;;130,13;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;766974;EDSON AUGUSTO DOS SANTOS - 838034;766974;'9750167003785599;EDSON AUGUSTO DOS SANTOS;1;0 - TITULAR;10008;;351,21;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;766974;EDSON AUGUSTO DOS SANTOS - 838034;766974;'9750167003785599;EDSON AUGUSTO DOS SANTOS;1;0 - TITULAR;10008;;110;08/2026;Serviços ;Consulta;10101012;Consulta em consultorio no horario normal ou preestabelecido;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;766974;EDSON AUGUSTO DOS SANTOS - 838034;766974;'9750167003785599;EDSON AUGUSTO DOS SANTOS;1;0 - TITULAR;10008;;45,65;08/2026;Serviços ;Exame;41301080;Ceratoscopia computadorizada - monocular;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;766974;EDSON AUGUSTO DOS SANTOS - 838034;766974;'9750167003785599;EDSON AUGUSTO DOS SANTOS;1;0 - TITULAR;10008;;4,26;08/2026;Serviços ;Exame;41301323;Tonometria - binocular;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;766974;EDSON AUGUSTO DOS SANTOS - 838034;766974;'9750167003785599;EDSON AUGUSTO DOS SANTOS;1;0 - TITULAR;10008;;51,08;08/2026;Serviços ;Exame;41501128;Paquimetria ultrassonica - monocular;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;766974;EDSON AUGUSTO DOS SANTOS - 838034;766974;'9750167003785599;EDSON AUGUSTO DOS SANTOS;1;0 - TITULAR;10008;;28,98;08/2026;Serviços ;Outros;50000560;Consulta ambulatorial por nutricionista com diretriz definida pela ANS - n 103;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;757635;JOICE GABRIELLY CONRADO - 840123;757635;'9750167003885879;JOICE GABRIELLY CONRADO;1;0 - TITULAR;10215;;199,65;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;272,8;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;74,25;08/2026;Serviços ;Consulta;10101039;Consulta em pronto socorro;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;3,72;08/2026;Serviços ;Exame;40301583;Colesterol HDL - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;4,96;08/2026;Serviços ;Exame;40301591;Colesterol LDL - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;1,74;08/2026;Serviços ;Exame;40301605;Colesterol total - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;1,74;08/2026;Serviços ;Exame;40301630;Creatinina - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;1,74;08/2026;Serviços ;Exame;40302040;Glicose - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;1,74;08/2026;Serviços ;Exame;40302504;Transaminase oxalacetica amino transferase aspartato - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;1,74;08/2026;Serviços ;Exame;40302512;Transaminase piruvica amino transferase de alanina - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;2,48;08/2026;Serviços ;Exame;40302547;Triglicerideos - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;1,74;08/2026;Serviços ;Exame;40302580;Ureia - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;5,58;08/2026;Serviços ;Exame;40302733;Hemoglobina glicada Fracao A1c - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;8,28;08/2026;Serviços ;Exame;40302830;Vitamina D 25 HIDROXI, pesquisa e/ou dosagem Vitamina D3;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;3,72;08/2026;Serviços ;Exame;40304361;Hemograma com contagem de plaquetas ou fracoes eritrograma, leucograma, plaquet;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;1,86;08/2026;Serviços ;Exame;40310060;Bacterioscopia Gram, Ziehl, Albert etc, por lamina;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;6,19;08/2026;Serviços ;Exame;40310213;Cultura, urina com contagem de colonias;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;11,15;08/2026;Serviços ;Exame;40310426;Antibiograma automatizado;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;2,48;08/2026;Serviços ;Exame;40311210;Rotina de urina caracteres fisicos, elementos anormais e sedimentoscopia;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;9,29;08/2026;Serviços ;Exame;40316190;Cortisol - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;12,39;08/2026;Serviços ;Exame;40316246;Estradiol - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;15,48;08/2026;Serviços ;Exame;40316270;Ferritina - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;8,05;08/2026;Serviços ;Exame;40316289;Foliculo estimulante, hormonio FSH - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;7,8;08/2026;Serviços ;Exame;40316335;Hormonio luteinizante LH - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;13,01;08/2026;Serviços ;Exame;40316408;Progesterona - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;10,53;08/2026;Serviços ;Exame;40316416;Prolactina - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;10,53;08/2026;Serviços ;Exame;40316491;T4 livre - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;10,53;08/2026;Serviços ;Exame;40316521;Tireoestimulante, hormonio TSH - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;10,53;08/2026;Serviços ;Exame;40316572;Vitamina B12 - pesquisa e/ou dosagem;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;143,99;08/2026;Serviços ;Exame;40601200;Procedimento diagnostico em peca anatomica ou cirurgica simples;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;74,25;08/2026;Serviços ;Exame;40808041;Mamografia digital bilateral com diretriz definida pela ANS - n 52;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;59,76;08/2026;Serviços ;Exame;40808130;Densitometria ossea - rotina: coluna e femur ou dois segmentos;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;38,52;08/2026;Serviços ;Exame;40901114;US - Mamas;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;755807;'9750167003885950;LUCIANA CARDOSO FERNANDES;1;0 - TITULAR;10008;;44,36;08/2026;Serviços ;Exame;40901300;US - Transvaginal utero, ovario, anexos e vagina;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;755807;LUCIANA CARDOSO FERNANDES - 840127;857049;'9750167018903290;JOEL MARCONCINI;2;1 - CONJUGE;10008;;490,29;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;780352;EVELYN CHRISTINE CURCINO - 847272;780352;'9750167013066030;EVELYN CHRISTINE CURCINO;1;0 - TITULAR;10215;;210,38;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;781791;TAILLANY TAMYRISS DE PIERRI MARQUES - 848274;781791;'9750167013085115;TAILLANY TAMYRISS DE PIERRI MARQUES;1;0 - TITULAR;10215;;199,65;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;781791;TAILLANY TAMYRISS DE PIERRI MARQUES - 848274;781791;'9750167013085115;TAILLANY TAMYRISS DE PIERRI MARQUES;1;0 - TITULAR;10215;;74,25;08/2026;Serviços ;Exame;40901122;US - Abdome total abdome superior, rins, bexiga, aorta, veia cava inferior e ad;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;781791;TAILLANY TAMYRISS DE PIERRI MARQUES - 848274;781791;'9750167013085115;TAILLANY TAMYRISS DE PIERRI MARQUES;1;0 - TITULAR;10215;;39,43;08/2026;Serviços ;Exame;40901211;US - Estruturas superficiais cervical ou axila ou musculo ou tendao;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;781791;TAILLANY TAMYRISS DE PIERRI MARQUES - 848274;781791;'9750167013085115;TAILLANY TAMYRISS DE PIERRI MARQUES;1;0 - TITULAR;10215;;44,36;08/2026;Serviços ;Exame;40901300;US - Transvaginal utero, ovario, anexos e vagina;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;795128;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG - 858372;795128;'9750167013261614;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG;1;0 - TITULAR;10215;;210,38;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;795128;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG - 858372;795128;'9750167013261614;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG;1;0 - TITULAR;10215;;74,25;08/2026;Serviços ;Consulta;10101039;Consulta em pronto socorro;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;795128;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG - 858372;798055;'9750167014716674;MARIA JULIA MERTIG FAGUNDES;2;10 - FILHO(A);10215;;151,51;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;795128;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG - 858372;798339;'9750167015073823;ROBERTO CARLOS CHINAIDER FAGUNDES;2;1 - CONJUGE;10215;;238,92;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;819205;FRANCISCO AQUINO CHAPARRO - 874116;819205;'9750167018482406;FRANCISCO AQUINO CHAPARRO;1;0 - TITULAR;10008;;272,8;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;819205;FRANCISCO AQUINO CHAPARRO - 874116;822752;'9750167018523960;CAMILA CASSIA MORAES COSTA;2;1 - CONJUGE;10008;;272,8;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;844618;FRANCIELLI SOUZA DE JESUS - 886633;844618;'9750167018752799;FRANCIELLI SOUZA DE JESUS;1;0 - TITULAR;10215;;290,61;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;844618;FRANCIELLI SOUZA DE JESUS - 886633;849666;'9750167018811701;ELOIZA DE SOUZA;2;10 - FILHO(A);10008;;130,13;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;844618;FRANCIELLI SOUZA DE JESUS - 886633;849667;'9750167018811710;ELENA DE SOUZA;2;10 - FILHO(A);10008;;130,13;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;853105;KESSY KOHNLEIN - 892339;853105;'9750167018854672;KESSY KOHNLEIN;1;0 - TITULAR;10220;;137,23;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;854462;DAIANE DA LUZ GUEIROS DA SILVA - 893274;854462;'9750167018871135;DAIANE DA LUZ GUEIROS DA SILVA;1;0 - TITULAR;10008;;213,95;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;854462;DAIANE DA LUZ GUEIROS DA SILVA - 893274;856557;'9750167018897436;RENAN GABRIEL DA LUZ DOMINGOS;2;10 - FILHO(A);10008;;130,13;08/2026;Mensalidade;;;;
|
||||||
|
5884128-0;3187862;201960424;6818,83;6818,83;Aberto;ROSSONI PIOTTO CIA LTDA - 00384013000454;854462;DAIANE DA LUZ GUEIROS DA SILVA - 893274;869895;'9750167019048971;LUCCA GABRIEL DA LUZ DE JESUS;2;10 - FILHO(A);10008;;130,13;08/2026;Mensalidade;;;;
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
CODIGOEMPRESA;NOMEFUNC;CPFFUNC;CODIGOOUTEMP;DATAINICIAL;NOMEDEPENDENTE;CPFDEPENDENTE;VALOREMPRESA;VALOR;DESCRICAO
|
||||||
|
197;IVANILDE HOFFELDER EMILIANO;028.592.429-02;3755;01/04/2026;;;0;0;
|
||||||
|
197;GLEISON BARBOSA EMILIANO;931.417.349-68;3755;01/04/2026;;;0;0;
|
||||||
|
197;GLEISON BARBOSA EMILIANO;931.417.349-68;3755;01/04/2026;FELIPE HOFFELDER EMILIANO;156.691.569-43;0;0;
|
||||||
|
197;GLEISON BARBOSA EMILIANO;931.417.349-68;3755;01/04/2026;GUSTAVO HOFFELDER EMILIANO;156.691.629-19;0;0;
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
CODIGOEMPRESA;NOMEFUNC;CPFFUNC;CODIGOOUTEMP;DATAINICIAL;NOMEDEPENDENTE;CPFDEPENDENTE;VALOREMPRESA;VALOR;DESCRICAO
|
||||||
|
221;PEDRO LEONARDO CABRAL FERNANDES;578.158.871-04;1386;01/06/2026;;;0;0;
|
||||||
|
221;LUIZ CARLOS PIOTTO;713.828.289-34;1386;01/06/2026;;;0;0;
|
||||||
|
221;ALEXSANDRO RODRIGUES DE OLIVEIRA;963.420.136-91;1386;01/06/2026;;;0;0;
|
||||||
|
221;ALEXSANDRO RODRIGUES DE OLIVEIRA;963.420.136-91;1386;01/06/2026;GABRIELA BOFF DE OLIVEIRA;149.302.519-82;0;0;
|
||||||
|
221;ALEXSANDRO RODRIGUES DE OLIVEIRA;963.420.136-91;1386;01/06/2026;MILENA BOFF DE OLIVEIRA;036.970.509-23;0;0;
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
CODIGOEMPRESA;NOMEFUNC;CPFFUNC;CODIGOOUTEMP;DATAINICIAL;NOMEDEPENDENTE;CPFDEPENDENTE;VALOREMPRESA;VALOR;DESCRICAO
|
||||||
|
221;DIEGO RODRIGO DA FONSECA;007.377.729-30;3755;01/12/2023;;;0;0;
|
||||||
|
221;ZAIRA DAVID BARBOSA;007.396.889-79;3755;01/12/2023;;;0;0;
|
||||||
|
221;ADRIANA OLIVEIRA DOS SANTOS CODO;022.366.869-94;3755;01/12/2023;;;0;0;
|
||||||
|
221;ADRIANA OLIVEIRA DOS SANTOS CODO;022.366.869-94;3755;01/12/2023;RAFHAEL HENRIQUE CODO;133.710.699-23;0;0;
|
||||||
|
221;LEANDRA SPEROTTO;022.795.359-20;3755;01/12/2023;;;0;0;
|
||||||
|
221;LEANDRA SPEROTTO;022.795.359-20;3755;01/12/2023;LUCAS SPEROTTO SCHIRMANN;125.709.619-22;0;0;
|
||||||
|
221;JANE MARILIA BEKER;025.273.319-39;3755;01/12/2023;;;0;0;
|
||||||
|
221;ANELISA CLAUDIA TOLEDO;028.627.449-30;3755;01/12/2023;;;0;0;
|
||||||
|
221;ANELISA CLAUDIA TOLEDO;028.627.449-30;3755;01/12/2023;MURILO AUGUSTO TOLEDO SILVA;140.796.419-40;0;0;
|
||||||
|
221;VANESSA JUIF TRINDADE;032.476.309-37;3755;01/12/2023;;;0;0;
|
||||||
|
221;FERNANDO BERLATTO;040.875.749-38;3755;01/12/2023;;;0;0;
|
||||||
|
221;JOAO VICTOR DE OLIVEIRA EGIDIO;051.271.009-08;3755;01/12/2023;;;0;0;
|
||||||
|
221;MARCOS PAULO GOBBO;057.539.659-89;3755;01/12/2023;;;0;0;
|
||||||
|
221;ELIANA KARPSAK LOPES;064.896.469-86;3755;01/12/2023;;;0;0;
|
||||||
|
221;ELIANA KARPSAK LOPES;064.896.469-86;3755;01/12/2023;LUCAS ANTONIO DE OLIVEIRA;066.200.469-83;0;0;
|
||||||
|
221;PAULA MICHELLI DA SILVA;073.516.259-05;3755;01/12/2023;;;0;0;
|
||||||
|
221;PAULA MICHELLI DA SILVA;073.516.259-05;3755;01/12/2023;EMANUELLY FERREIRA DA SILVA;152.794.939-70;0;0;
|
||||||
|
221;JESSICA DE FATIMA CATTANI DE PAULA;092.879.749-00;3755;01/12/2023;;;0;0;
|
||||||
|
221;LUCAS DE SOUZA;093.861.469-08;3755;01/12/2023;;;0;0;
|
||||||
|
221;APARECIDA DOBNER;389.259.312-49;3755;01/12/2023;;;0;0;
|
||||||
|
221;APARECIDA DOBNER;389.259.312-49;3755;01/12/2023;ANNA CAROLINA DOBNER WILLMBRINK;097.280.639-38;0;0;
|
||||||
|
221;MARIZA KARPSAK LOPES;726.088.899-72;3755;01/12/2023;EDUARDO KARPSAK LOPES;096.771.579-22;0;0;
|
||||||
|
221;MARIZA KARPSAK LOPES;726.088.899-72;3755;01/12/2023;;;0;0;
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
CODIGOEMPRESA;NOMEFUNC;CPFFUNC;CODIGOOUTEMP;DATAINICIAL;NOMEDEPENDENTE;CPFDEPENDENTE;VALOREMPRESA;VALOR;DESCRICAO
|
||||||
|
221;JOICE GABRIELLY CONRADO;013.817.749-03;5060;01/06/2025;;;0;0;
|
||||||
|
221;EDSON AUGUSTO DOS SANTOS;033.535.459-99;5060;01/06/2025;;;0;0;
|
||||||
|
221;FRANCISCO AQUINO CHAPARRO;043.273.629-80;5060;01/11/2025;CAMILA CASSIA MORAES COSTA;042.355.369-07;0;0;
|
||||||
|
221;FRANCISCO AQUINO CHAPARRO;043.273.629-80;5060;01/11/2025;;;0;0;
|
||||||
|
221;LUCIANA CARDOSO FERNANDES;044.214.069-02;5060;01/04/2026;JOEL MARCONCINI;969.398.939-20;0;0;
|
||||||
|
221;LUCIANA CARDOSO FERNANDES;044.214.069-02;5060;01/04/2026;;;0;0;
|
||||||
|
221;FRANCIELLI SOUZA DE JESUS;056.918.579-32;5060;01/02/2026;ELENA DE SOUZA;158.076.209-33;0;0;
|
||||||
|
221;FRANCIELLI SOUZA DE JESUS;056.918.579-32;5060;01/02/2026;ELOIZA DE SOUZA;142.759.789-86;0;0;
|
||||||
|
221;FRANCIELLI SOUZA DE JESUS;056.918.579-32;5060;01/02/2026;;;0;0;
|
||||||
|
221;TABATA CAROLINE GOES DA SILVA;072.082.879-10;5060;01/06/2025;;;0;0;
|
||||||
|
221;TABATA CAROLINE GOES DA SILVA;072.082.879-10;5060;01/06/2025;WENDY MANOEL MIGUEL MELO DA SILVA;080.701.949-60;0;0;
|
||||||
|
221;TABATA CAROLINE GOES DA SILVA;072.082.879-10;5060;01/06/2025;LUISA VALENTINA GOES MELO;107.096.349-60;0;0;
|
||||||
|
221;DAIANE DA LUZ GUEIROS DA SILVA;080.947.869-22;5060;01/07/2026;;;0;0;
|
||||||
|
221;DAIANE DA LUZ GUEIROS DA SILVA;080.947.869-22;5060;01/07/2026;RENAN GABRIEL DA LUZ DOMINGOS;800.859.409-84;0;0;
|
||||||
|
221;DAIANE DA LUZ GUEIROS DA SILVA;080.947.869-22;5060;01/07/2026;LUCCA GABRIEL DA LUZ DE JESUS;002.261.929-11;0;0;
|
||||||
|
221;EVELYN CHRISTINE CURCINO;102.022.109-79;5060;01/06/2025;;;0;0;
|
||||||
|
221;KESSY KOHNLEIN;107.820.969-30;5060;01/03/2026;;;0;0;
|
||||||
|
221;TAILLANY TAMYRISS DE PIERRI MARQUES;120.239.569-43;5060;01/06/2025;;;0;0;
|
||||||
|
221;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG;121.074.169-58;5060;01/06/2025;ROBERTO CARLOS CHINAIDER FAGUNDES;078.468.529-06;0;0;
|
||||||
|
221;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG;121.074.169-58;5060;01/06/2025;MARIA JULIA MERTIG FAGUNDES;156.306.539-89;0;0;
|
||||||
|
221;KETLIN RAYANI SILVA DE OLIVEIRA MERTIG;121.074.169-58;5060;01/06/2025;;;0;0;
|
||||||
|
221;ADRIANA JARDIM DE CARVALHO;569.433.180-04;5060;01/02/2025;;;0;0;
|
||||||
|
14
plano.md
14
plano.md
@ -910,6 +910,20 @@ Usuário testou uma importação (código 1601, "1601 - Unimed Oeste PR", regra
|
|||||||
|
|
||||||
O mesmo bloco `#ips-review-regra-empresa-obs` (rodada 62) foi reaproveitado: se não há observação de regra empresa mas há `regra_custeio_salva_observacoes` (novo campo em `ImportacaoPlanoSaudeDetailSerializer`, lendo `RegraCusteioPlanoSaude.observacoes` de verdade via FK), o bloco mostra essa observação com o rótulo "Observações da regra de custeio salva — `<nome>`".
|
O mesmo bloco `#ips-review-regra-empresa-obs` (rodada 62) foi reaproveitado: se não há observação de regra empresa mas há `regra_custeio_salva_observacoes` (novo campo em `ImportacaoPlanoSaudeDetailSerializer`, lendo `RegraCusteioPlanoSaude.observacoes` de verdade via FK), o bloco mostra essa observação com o rótulo "Observações da regra de custeio salva — `<nome>`".
|
||||||
|
|
||||||
|
### 64. Nova operadora: Bradesco Saúde (1386) — primeiro PDF sem texto selecionável, extração via OCR (`docling`)
|
||||||
|
|
||||||
|
Usuário trouxe um modelo novo de fatura (Bradesco Saúde, empresa 221 - Rossoni Piotto) e perguntou se dava pra ler/converter pra parametrizar a importação, já que o PDF é "formato de imagem, sem texto selecionável". Confirmado empiricamente rodando `pdfplumber` contra o arquivo real baixado (`Downloads/221 -BRADESCO SAUDE.pdf`): `page.chars`/`page.extract_text()` vêm vazios nas 3 páginas — o documento é uma composição de dezenas de imagens raster por página (cada faixa da tabela é um bitmap próprio), sem nenhuma camada de texto. É o primeiro caso desse tipo entre as operadoras do módulo; todas as outras (Amil/Itamed/Unimed/Dental Uni/Unimed Oeste PR) têm texto selecionável e usam `pdfplumber`.
|
||||||
|
|
||||||
|
Depois de comparar duas ferramentas de conversão (MarkItDown vs. Docling — MarkItDown não tem OCR/reconstrução de tabela embutidos, feito pra documento já estruturado; Docling tem OCR local + modelo dedicado de estrutura de tabela, TableFormer), a escolha foi Docling — adicionado ao `requirements.txt` (pesado: traz `torch`/`transformers`/`opencv-python`/`pandas` como dependência transitiva, ~90 pacotes novos no freeze).
|
||||||
|
|
||||||
|
**Bug real encontrado testando contra o arquivo de verdade** (por isso vale sempre testar contra o arquivo real antes de confiar, não só contra o texto que o próprio Docling "acha" que extraiu): nas colunas estreitas "Mês/Ano"/"Valor" (sob o cabeçalho mesclado "Lançamento"), o TableFormer às vezes junta as duas numa célula só, e às vezes o valor de uma pessoa "vaza" pra célula da linha anterior (visto de fato: o valor da GABRIELA saiu dentro da célula "Valor" da MILENA, deixando a própria célula da GABRIELA vazia). Subir a resolução de renderização (`images_scale=4`) não mudou nada — não é falta de resolução, é erro de fronteira de célula do modelo mesmo. Contorno implementado em `operadoras/bradesco/saude.py` (`_extrai_valores_area`): em vez de confiar em qual célula/linha especificamente carrega o valor, concatena-se todo o texto da área "Mês/Ano+Valor" de cada linha (de cima para baixo) e extrai-se TODOS os valores monetários encontrados, preservando a ordem de leitura — depois redistribui 1 valor por linha de beneficiário, na mesma ordem (a ordem de leitura continua certa mesmo quando a fronteira de célula erra). Se a contagem final não bater 1:1 com o número de linhas, levanta erro em vez de arriscar lançar o valor errado em alguém.
|
||||||
|
|
||||||
|
Titular x dependente é decidido pela coluna "Certif." (formato `<família>/<sufixo>`, sufixo `"00"` = titular, qualquer outro = dependente daquela família — confirmado pelo usuário), não por uma coluna "Tipo" dedicada como as outras operadoras. Casamento com a planilha padrão é por nome (`chave_casamento = "nome"`, igual Itamed/Unimed/Dental Uni/Unimed Oeste PR — este arquivo também não traz CPF). Coparticipação ("Part. Seg.") ainda não foi validada com nenhum arquivo real com valor diferente de zero — o usuário disse "acreditamos que ficariam" ali; o parser já está pronto pra gerar lançamento de coparticipação quando isso acontecer (mesmo padrão "ausência de valor = zero, não gera Individuo" da Itamed), mas isso é uma suposição a confirmar, não um fato validado.
|
||||||
|
|
||||||
|
Validado rodando o parser (`BradescoSaude.extrai`) e o pipeline completo (`processa_importacao`) direto contra o arquivo real de 08/2026 + a planilha padrão de exemplo fornecida pelo usuário (empresa 221): os 4 valores de mensalidade saíram exatamente certos (incluindo o caso MILENA/GABRIELA acima) e o casamento por nome bateu certo para os 4 beneficiários presentes na planilha (mais um, LUIZ CARLOS PIOTTO, corretamente ficou sem lançamento por não aparecer na fatura daquele mês).
|
||||||
|
|
||||||
|
Registrado em `pipeline.OPERADORAS` como `"bradesco_saude": {"label": "1386 - Bradesco Saúde", ...}`.
|
||||||
|
|
||||||
## Roadmap / próximos passos
|
## Roadmap / próximos passos
|
||||||
|
|
||||||
Nenhuma pendência explícita em aberto no momento, exceto a limitação conhecida
|
Nenhuma pendência explícita em aberto no momento, exceto a limitação conhecida
|
||||||
|
|||||||
294
portal_api/planos_saude/operadoras/bradesco/saude.py
Normal file
294
portal_api/planos_saude/operadoras/bradesco/saude.py
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
"""
|
||||||
|
Bradesco Saúde (1386) - Fatura Técnica. Mensalidade + Coparticipação
|
||||||
|
(coparticipação ainda não validada com dado real, ver nota 5 abaixo).
|
||||||
|
|
||||||
|
Formato recebido: PDF "SPG/Grupos Especiais - Bradesco Saúde - Fatura
|
||||||
|
Técnica". DIFERENTE de Amil/Itamed/Unimed/Dental Uni: este PDF não tem
|
||||||
|
NENHUM texto selecionável (confirmado rodando pdfplumber contra o
|
||||||
|
arquivo real: `page.chars`/`page.extract_text()` vêm vazios em todas as
|
||||||
|
páginas — o "texto" é uma composição de dezenas de imagens raster por
|
||||||
|
página, sem camada de texto nenhuma). Por isso a extração usa OCR com
|
||||||
|
reconstrução de estrutura de tabela (`docling`, ver requirements.txt),
|
||||||
|
em vez do `pdfplumber` usado pelos outros parsers em PDF.
|
||||||
|
|
||||||
|
Layout: a única tabela de beneficiários fica na página 1 (as páginas
|
||||||
|
seguintes são só o texto legal "MENSAGENS", sem beneficiário nenhum —
|
||||||
|
ignoradas naturalmente porque não têm coluna "Certif."). Colunas:
|
||||||
|
Certif. | Nome Segurado | Subfatura Nº | Data Nascimento | Sexo |
|
||||||
|
Est. Civil | Paren. | Plano | Data Início | Mês/Ano | Valor | Part. Seg.
|
||||||
|
— as três últimas vêm sob um cabeçalho mesclado "Lançamento".
|
||||||
|
|
||||||
|
Particularidades identificadas rodando o Docling de verdade contra um
|
||||||
|
arquivo real (competência 08/2026, empresa 221 - Rossoni Piotto):
|
||||||
|
|
||||||
|
1. NÃO HÁ CPF NESTE ARQUIVO. Casamento com a planilha padrão é por NOME
|
||||||
|
(chave_casamento = "nome"), igual Itamed/Unimed/Dental Uni/Unimed
|
||||||
|
Oeste PR.
|
||||||
|
|
||||||
|
2. Titular x dependente é decidido pela coluna "Certif.", não por uma
|
||||||
|
coluna "Tipo" dedicada: o valor vem no formato "<família>/<sufixo>"
|
||||||
|
(ex.: "0000001/00", "0000001/01", "0000001/02") — sufixo "00" é
|
||||||
|
sempre o titular, qualquer outro sufixo é dependente da mesma
|
||||||
|
família (confirmado pelo usuário). `numero_beneficiario` é o
|
||||||
|
"Certif." completo (já é único por pessoa); `numero_titular` de um
|
||||||
|
dependente é deduzido (não lido de nenhuma coluna própria) como
|
||||||
|
"<família>/00" — o Certif. que o titular daquela família teria.
|
||||||
|
|
||||||
|
3. BUG DE RECONHECIMENTO DE TABELA (TableFormer) nas colunas "Mês/Ano"/
|
||||||
|
"Valor": em algumas linhas as duas colunas saem uma célula só
|
||||||
|
("08/2026 1.456,24"); em outras, o valor de uma pessoa "vaza" para a
|
||||||
|
célula da linha ANTERIOR (ex.: visto de fato no arquivo real: a
|
||||||
|
célula "Valor" da linha da MILENA saiu como "1.238,09 505,45" —
|
||||||
|
505,45 é o valor da GABRIELA, a linha seguinte, cuja própria célula
|
||||||
|
"Valor" saiu vazia). Testado subir a resolução de renderização
|
||||||
|
(`images_scale=4`) e o resultado não mudou — não é falta de
|
||||||
|
resolução, é um erro de fronteira de célula do próprio modelo nessas
|
||||||
|
colunas estreitas.
|
||||||
|
|
||||||
|
Contorno usado (`_extrai_valores_area`): em vez de confiar em qual
|
||||||
|
CÉLULA/LINHA especificamente carrega cada valor, agrupamos todo o
|
||||||
|
texto da área "Mês/Ano + Valor" de cada linha (nessa ordem, de cima
|
||||||
|
para baixo) e extraímos TODOS os valores monetários encontrados,
|
||||||
|
preservando a ordem de leitura — depois redistribuímos 1 valor por
|
||||||
|
linha de beneficiário, na mesma ordem. Isso reconstrói a linha certa
|
||||||
|
mesmo quando o valor "vazou" para a célula vizinha, porque a ordem de
|
||||||
|
leitura (de cima para baixo) continua correta mesmo que a fronteira
|
||||||
|
de célula esteja errada. Se a contagem final de valores não bater
|
||||||
|
exatamente com o número de linhas de beneficiário, é sinal de que
|
||||||
|
algo saiu MUITO errado (não só uma célula deslocada) — nesse caso
|
||||||
|
levantamos erro em vez de arriscar lançar valor errado para alguém.
|
||||||
|
|
||||||
|
A mesma técnica é aplicada à coluna "Part. Seg." isoladamente (nela,
|
||||||
|
no arquivo testado, cada linha já veio com sua própria célula
|
||||||
|
correta — mas como é a mesma classe de coluna estreita, aplicamos o
|
||||||
|
mesmo contorno por precaução, sem custo nenhum quando não há bug).
|
||||||
|
|
||||||
|
4. Cabeçalho da tabela não é identificado por posição fixa (linha X,
|
||||||
|
coluna Y) — é identificado pelo TEXTO de cada coluna (normalizado,
|
||||||
|
sem acento) via `_classifica_colunas`, porque o Docling pode
|
||||||
|
devolver a tabela de beneficiários paginada em mais de um objeto
|
||||||
|
`table` quando o PDF tiver muitas linhas (fatura de empresa grande) —
|
||||||
|
`extrai()` já concatena todas as tabelas cujo cabeçalho tem "CERTIF".
|
||||||
|
|
||||||
|
5. "Part. Seg." SEMPRE veio "0,00" nos dois arquivos de exemplo (não há
|
||||||
|
coparticipação neste plano até o momento) — por isso, na prática,
|
||||||
|
nenhum `Individuo` de `tipo_lancamento="coparticipacao"` é gerado
|
||||||
|
ainda (mesmo espírito de "ausência de valor = zero daquele tipo, não
|
||||||
|
gera Individuo" já usado pela Itamed). Fica pronto para o dia em que
|
||||||
|
aparecer um valor real ali, mas ISSO NÃO FOI VALIDADO com nenhum
|
||||||
|
arquivo real com coparticipação — confirmar de novo se/quando a
|
||||||
|
Bradesco mandar um mês com valor diferente de zero nessa coluna.
|
||||||
|
|
||||||
|
IMPORTANTE: como os outros parsers de PDF, este foi escrito e testado
|
||||||
|
contra um único arquivo real (competência 08/2026) — revalidar pelo
|
||||||
|
botão "Selecionar arquivo" (que já roda este mesmo parser) antes de
|
||||||
|
confiar de olhos fechados num mês com um layout diferente (ex.: uma
|
||||||
|
família muito maior, ou mais de uma tabela por página).
|
||||||
|
"""
|
||||||
|
import re
|
||||||
|
from typing import Dict, List, Tuple
|
||||||
|
|
||||||
|
from docling.datamodel.base_models import InputFormat
|
||||||
|
from docling.document_converter import DocumentConverter, PdfFormatOption
|
||||||
|
from docling.datamodel.pipeline_options import PdfPipelineOptions
|
||||||
|
from docling_core.types.doc.items.table.table import TableItem
|
||||||
|
|
||||||
|
from portal_api.planos_saude.modelos import Individuo, ItemAuditoria, Lancamento, normaliza_nome
|
||||||
|
from portal_api.planos_saude.operadoras.base import OperadoraParser
|
||||||
|
|
||||||
|
_CERTIF_RE = re.compile(r"^(?P<familia>\d+)/(?P<sufixo>\d{2})$")
|
||||||
|
_MONEY_RE = re.compile(r"\d{1,3}(?:\.\d{3})*,\d{2}")
|
||||||
|
|
||||||
|
_BUCKET_CERTIF = "certif"
|
||||||
|
_BUCKET_NOME = "nome"
|
||||||
|
_BUCKET_VALOR_AREA = "valor_area" # "Mês/Ano" + "Valor" juntas, ver particularidade 3
|
||||||
|
_BUCKET_PART_SEG = "part_seg"
|
||||||
|
_BUCKET_IGNORAR = "ignorar"
|
||||||
|
|
||||||
|
_converter_singleton: DocumentConverter | None = None
|
||||||
|
|
||||||
|
|
||||||
|
def _converter() -> DocumentConverter:
|
||||||
|
"""Instância única do conversor Docling, reaproveitada entre importações
|
||||||
|
(carregar os modelos de OCR/layout é o custo fixo mais caro — ver nota de
|
||||||
|
performance em CLAUDE.md)."""
|
||||||
|
global _converter_singleton
|
||||||
|
if _converter_singleton is None:
|
||||||
|
opts = PdfPipelineOptions()
|
||||||
|
_converter_singleton = DocumentConverter(
|
||||||
|
format_options={InputFormat.PDF: PdfFormatOption(pipeline_options=opts)}
|
||||||
|
)
|
||||||
|
return _converter_singleton
|
||||||
|
|
||||||
|
|
||||||
|
def _valor_para_float(texto: str) -> float:
|
||||||
|
"""'1.456,24' -> 1456.24"""
|
||||||
|
texto = texto.strip().replace(".", "").replace(",", ".")
|
||||||
|
return float(texto) if texto else 0.0
|
||||||
|
|
||||||
|
|
||||||
|
def _classifica_coluna(texto_cabecalho: str) -> str:
|
||||||
|
t = normaliza_nome(texto_cabecalho)
|
||||||
|
if "CERTIF" in t:
|
||||||
|
return _BUCKET_CERTIF
|
||||||
|
if "NOME" in t and "SEGURADO" in t:
|
||||||
|
return _BUCKET_NOME
|
||||||
|
if "PART" in t and "SEG" in t:
|
||||||
|
return _BUCKET_PART_SEG
|
||||||
|
if "VALOR" in t or "MES" in t:
|
||||||
|
return _BUCKET_VALOR_AREA
|
||||||
|
return _BUCKET_IGNORAR
|
||||||
|
|
||||||
|
|
||||||
|
def _tabela_eh_de_beneficiarios(table: TableItem) -> bool:
|
||||||
|
"""Identifica a tabela certa pelo TEXTO do cabeçalho (não por posição),
|
||||||
|
porque uma fatura de empresa grande pode paginar a tabela de
|
||||||
|
beneficiários em mais de um objeto `table` do Docling."""
|
||||||
|
return any(
|
||||||
|
cell.column_header and "CERTIF" in normaliza_nome(cell.text)
|
||||||
|
for cell in table.data.table_cells
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _agrupa_por_linha(table: TableItem) -> Tuple[List[int], Dict[int, Dict[str, List[str]]]]:
|
||||||
|
"""Classifica cada coluna pelo texto do cabeçalho e agrupa o texto de
|
||||||
|
cada célula de dado por (linha, categoria) — ver particularidade 4."""
|
||||||
|
colunas: Dict[int, str] = {}
|
||||||
|
for cell in table.data.table_cells:
|
||||||
|
if not cell.column_header:
|
||||||
|
continue
|
||||||
|
bucket = _classifica_coluna(cell.text)
|
||||||
|
for col in range(cell.start_col_offset_idx, cell.end_col_offset_idx):
|
||||||
|
if colunas.get(col) in (None, _BUCKET_IGNORAR):
|
||||||
|
colunas[col] = bucket
|
||||||
|
|
||||||
|
linhas: Dict[int, Dict[str, List[str]]] = {}
|
||||||
|
for cell in table.data.table_cells:
|
||||||
|
if cell.column_header:
|
||||||
|
continue
|
||||||
|
bucket = colunas.get(cell.start_col_offset_idx, _BUCKET_IGNORAR)
|
||||||
|
if bucket == _BUCKET_IGNORAR or not cell.text.strip():
|
||||||
|
continue
|
||||||
|
linhas.setdefault(cell.start_row_offset_idx, {}).setdefault(bucket, []).append(cell.text)
|
||||||
|
|
||||||
|
return sorted(linhas.keys()), linhas
|
||||||
|
|
||||||
|
|
||||||
|
def _extrai_valores_area(
|
||||||
|
linhas_ordenadas: List[int], linhas: Dict[int, Dict[str, List[str]]], bucket: str
|
||||||
|
) -> List[float]:
|
||||||
|
"""Concatena o texto do `bucket` de cada linha (na ordem de leitura, de
|
||||||
|
cima para baixo) e extrai TODOS os valores monetários encontrados,
|
||||||
|
preservando essa ordem — ver particularidade 3 do módulo. Levanta
|
||||||
|
ValueError se a contagem final não bater 1:1 com o número de linhas
|
||||||
|
(melhor falhar alto do que lançar um valor na pessoa errada)."""
|
||||||
|
tokens: List[float] = []
|
||||||
|
for idx in linhas_ordenadas:
|
||||||
|
texto = " ".join(linhas[idx].get(bucket, []))
|
||||||
|
tokens.extend(_valor_para_float(v) for v in _MONEY_RE.findall(texto))
|
||||||
|
|
||||||
|
if len(tokens) != len(linhas_ordenadas):
|
||||||
|
raise ValueError(
|
||||||
|
f"Bradesco Saúde: esperava 1 valor de '{bucket}' por linha de beneficiário "
|
||||||
|
f"({len(linhas_ordenadas)} linhas), encontrei {len(tokens)} — layout "
|
||||||
|
f"inesperado, revisar manualmente antes de confiar no resultado."
|
||||||
|
)
|
||||||
|
return tokens
|
||||||
|
|
||||||
|
|
||||||
|
class BradescoSaude(OperadoraParser):
|
||||||
|
nome_operadora = "BRADESCO SAÚDE"
|
||||||
|
chave_casamento = "nome" # PDF não traz CPF, só "Certif." por pessoa
|
||||||
|
|
||||||
|
def _extrai_linhas_beneficiarios(self, caminho_pdf: str) -> List[Dict[str, object]]:
|
||||||
|
resultado = _converter().convert(caminho_pdf)
|
||||||
|
beneficiarios: List[Dict[str, object]] = []
|
||||||
|
|
||||||
|
for table in resultado.document.tables:
|
||||||
|
if not _tabela_eh_de_beneficiarios(table):
|
||||||
|
continue
|
||||||
|
|
||||||
|
linhas_ordenadas, linhas = _agrupa_por_linha(table)
|
||||||
|
if not linhas_ordenadas:
|
||||||
|
continue
|
||||||
|
|
||||||
|
valores = _extrai_valores_area(linhas_ordenadas, linhas, _BUCKET_VALOR_AREA)
|
||||||
|
part_segs = _extrai_valores_area(linhas_ordenadas, linhas, _BUCKET_PART_SEG)
|
||||||
|
|
||||||
|
for posicao, idx in enumerate(linhas_ordenadas):
|
||||||
|
certif_texto = " ".join(linhas[idx].get(_BUCKET_CERTIF, [])).strip()
|
||||||
|
nome_texto = " ".join(linhas[idx].get(_BUCKET_NOME, [])).strip()
|
||||||
|
m_certif = _CERTIF_RE.match(certif_texto)
|
||||||
|
if not m_certif or not nome_texto:
|
||||||
|
raise ValueError(
|
||||||
|
f"Bradesco Saúde: linha com 'Certif.'/'Nome Segurado' em formato "
|
||||||
|
f"inesperado (Certif.={certif_texto!r}, Nome={nome_texto!r}) — "
|
||||||
|
f"revisar manualmente antes de confiar no resultado."
|
||||||
|
)
|
||||||
|
|
||||||
|
familia = m_certif.group("familia")
|
||||||
|
titular = m_certif.group("sufixo") == "00"
|
||||||
|
beneficiarios.append({
|
||||||
|
"numero_beneficiario": certif_texto,
|
||||||
|
"nome": nome_texto,
|
||||||
|
"tipo": "T" if titular else "D",
|
||||||
|
"numero_titular": None if titular else f"{familia}/00",
|
||||||
|
"valor": valores[posicao],
|
||||||
|
"part_seg": part_segs[posicao],
|
||||||
|
})
|
||||||
|
|
||||||
|
return beneficiarios
|
||||||
|
|
||||||
|
def _monta_lancamentos(self, beneficiarios: List[Dict[str, object]]) -> List[Lancamento]:
|
||||||
|
lancamentos: List[Lancamento] = []
|
||||||
|
for b in beneficiarios:
|
||||||
|
lancamentos.append(Lancamento(
|
||||||
|
numero_beneficiario=b["numero_beneficiario"],
|
||||||
|
nome=b["nome"],
|
||||||
|
cpf="",
|
||||||
|
tipo=b["tipo"],
|
||||||
|
rubrica="Mensalidade",
|
||||||
|
valor=b["valor"],
|
||||||
|
tipo_lancamento="mensalidade",
|
||||||
|
numero_titular=b["numero_titular"],
|
||||||
|
))
|
||||||
|
# ver particularidade 5: sem lançamento quando o valor é zero,
|
||||||
|
# mesmo padrão já usado pela Itamed para ausência de coparticipação.
|
||||||
|
if b["part_seg"] != 0.0:
|
||||||
|
lancamentos.append(Lancamento(
|
||||||
|
numero_beneficiario=b["numero_beneficiario"],
|
||||||
|
nome=b["nome"],
|
||||||
|
cpf="",
|
||||||
|
tipo=b["tipo"],
|
||||||
|
rubrica="Coparticipação",
|
||||||
|
valor=b["part_seg"],
|
||||||
|
tipo_lancamento="coparticipacao",
|
||||||
|
numero_titular=b["numero_titular"],
|
||||||
|
))
|
||||||
|
return lancamentos
|
||||||
|
|
||||||
|
def _agrega_por_individuo_e_tipo(self, lancamentos: List[Lancamento]) -> List[Individuo]:
|
||||||
|
"""Agrupa por (indivíduo, tipo_lancamento) — mesmo padrão dos demais parsers."""
|
||||||
|
individuos: Dict[Tuple[str, str], Individuo] = {}
|
||||||
|
ordem = []
|
||||||
|
for lc in lancamentos:
|
||||||
|
chave = (lc.numero_beneficiario, lc.tipo_lancamento)
|
||||||
|
if chave not in individuos:
|
||||||
|
individuos[chave] = Individuo(
|
||||||
|
numero_beneficiario=lc.numero_beneficiario,
|
||||||
|
nome=lc.nome,
|
||||||
|
cpf=lc.cpf,
|
||||||
|
tipo=lc.tipo,
|
||||||
|
tipo_lancamento=lc.tipo_lancamento,
|
||||||
|
numero_titular=lc.numero_titular,
|
||||||
|
)
|
||||||
|
ordem.append(chave)
|
||||||
|
individuos[chave].valor_total += lc.valor
|
||||||
|
individuos[chave].rubricas.append(f"{lc.rubrica}: {lc.valor:+.2f}")
|
||||||
|
return [individuos[c] for c in ordem]
|
||||||
|
|
||||||
|
def extrai(self, caminho_arquivo: str) -> Tuple[List[Individuo], List[ItemAuditoria]]:
|
||||||
|
beneficiarios = self._extrai_linhas_beneficiarios(caminho_arquivo)
|
||||||
|
lancamentos = self._monta_lancamentos(beneficiarios)
|
||||||
|
individuos = self._agrega_por_individuo_e_tipo(lancamentos)
|
||||||
|
return individuos, [] # Bradesco não gera itens de auditoria na extração
|
||||||
@ -16,6 +16,7 @@ from portal_api.planos_saude.matcher import casa_individuos_com_planilha
|
|||||||
from portal_api.planos_saude.modelos import ItemAuditoria, LinhaSistema
|
from portal_api.planos_saude.modelos import ItemAuditoria, LinhaSistema
|
||||||
from portal_api.planos_saude.regras_empresa import valida_regra_empresa
|
from portal_api.planos_saude.regras_empresa import valida_regra_empresa
|
||||||
from portal_api.planos_saude.operadoras.amil.odonto_mensalidade import AmilOdontoMensalidade
|
from portal_api.planos_saude.operadoras.amil.odonto_mensalidade import AmilOdontoMensalidade
|
||||||
|
from portal_api.planos_saude.operadoras.bradesco.saude import BradescoSaude
|
||||||
from portal_api.planos_saude.operadoras.dental_uni.odonto_mensalidade import DentalUniOdontoMensalidade
|
from portal_api.planos_saude.operadoras.dental_uni.odonto_mensalidade import DentalUniOdontoMensalidade
|
||||||
from portal_api.planos_saude.operadoras.itamed.saude import ItamedSaude
|
from portal_api.planos_saude.operadoras.itamed.saude import ItamedSaude
|
||||||
from portal_api.planos_saude.operadoras.unimed.saude import UnimedSaude
|
from portal_api.planos_saude.operadoras.unimed.saude import UnimedSaude
|
||||||
@ -46,8 +47,10 @@ OPERADORAS = {
|
|||||||
"label": "4709 - Unimed Oeste do Paraná",
|
"label": "4709 - Unimed Oeste do Paraná",
|
||||||
"parser": UnimedOestePrSaude,
|
"parser": UnimedOestePrSaude,
|
||||||
},
|
},
|
||||||
# próximas operadoras entram aqui, ex:
|
"bradesco_saude": {
|
||||||
# "bradesco_saude": {"label": "<código> - Bradesco Saúde", "parser": BradescoSaude},
|
"label": "1386 - Bradesco Saúde",
|
||||||
|
"parser": BradescoSaude,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
@ -18,6 +18,36 @@
|
|||||||
gap: var(--space-3);
|
gap: var(--space-3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Filtro de status (Ativos/Inativos/Todos) da lista de usuários — mesmo
|
||||||
|
espírito visual de .ind-departamento-chip (indicador-desempenho.css). */
|
||||||
|
.ua-status-filtros {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: var(--space-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ua-status-chip {
|
||||||
|
padding: var(--space-2) var(--space-4);
|
||||||
|
border-radius: var(--radius-pill);
|
||||||
|
border: 1px solid var(--border-subtle);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 600;
|
||||||
|
color: var(--text-secondary);
|
||||||
|
background: var(--bg-surface);
|
||||||
|
transition: border-color var(--transition-fast), color var(--transition-fast), background var(--transition-fast);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ua-status-chip:hover {
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ua-status-chip.is-active {
|
||||||
|
background: var(--accent);
|
||||||
|
border-color: var(--accent);
|
||||||
|
color: var(--accent-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
.pa-search {
|
.pa-search {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 260px;
|
width: 260px;
|
||||||
|
|||||||
@ -28,6 +28,8 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
const tableBody = document.getElementById("ua-table-body");
|
const tableBody = document.getElementById("ua-table-body");
|
||||||
const footerCount = document.getElementById("ua-footer-count");
|
const footerCount = document.getElementById("ua-footer-count");
|
||||||
const searchInput = document.getElementById("ua-search-input");
|
const searchInput = document.getElementById("ua-search-input");
|
||||||
|
const statusFiltros = document.getElementById("ua-status-filtros");
|
||||||
|
let statusFiltro = "ativos";
|
||||||
const newBtn = document.getElementById("ua-new-btn");
|
const newBtn = document.getElementById("ua-new-btn");
|
||||||
const backBtn = document.getElementById("ua-back-btn");
|
const backBtn = document.getElementById("ua-back-btn");
|
||||||
const cancelBtn = document.getElementById("ua-cancel-btn");
|
const cancelBtn = document.getElementById("ua-cancel-btn");
|
||||||
@ -69,6 +71,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
function renderList() {
|
function renderList() {
|
||||||
const term = searchInput.value.trim().toLowerCase();
|
const term = searchInput.value.trim().toLowerCase();
|
||||||
const rows = users
|
const rows = users
|
||||||
|
.filter((u) => statusFiltro === "todos" || (statusFiltro === "ativos") === u.is_active)
|
||||||
.filter((u) => !term || u.nome.toLowerCase().includes(term) || u.username.toLowerCase().includes(term))
|
.filter((u) => !term || u.nome.toLowerCase().includes(term) || u.username.toLowerCase().includes(term))
|
||||||
.slice()
|
.slice()
|
||||||
.sort((a, b) => a.nome.localeCompare(b.nome));
|
.sort((a, b) => a.nome.localeCompare(b.nome));
|
||||||
@ -281,6 +284,13 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
searchInput.addEventListener("input", renderList);
|
searchInput.addEventListener("input", renderList);
|
||||||
|
statusFiltros.addEventListener("click", (event) => {
|
||||||
|
const chip = event.target.closest("[data-ua-status]");
|
||||||
|
if (!chip) return;
|
||||||
|
statusFiltro = chip.dataset.uaStatus;
|
||||||
|
statusFiltros.querySelectorAll(".ua-status-chip").forEach((el) => el.classList.toggle("is-active", el === chip));
|
||||||
|
renderList();
|
||||||
|
});
|
||||||
newBtn.addEventListener("click", () => openEdit(null));
|
newBtn.addEventListener("click", () => openEdit(null));
|
||||||
backBtn.addEventListener("click", closeEdit);
|
backBtn.addEventListener("click", closeEdit);
|
||||||
cancelBtn.addEventListener("click", closeEdit);
|
cancelBtn.addEventListener("click", closeEdit);
|
||||||
|
|||||||
@ -257,6 +257,11 @@
|
|||||||
<section id="ua-list-view">
|
<section id="ua-list-view">
|
||||||
<div class="pa-header">
|
<div class="pa-header">
|
||||||
<h2>Usuários</h2>
|
<h2>Usuários</h2>
|
||||||
|
<div class="ua-status-filtros" id="ua-status-filtros">
|
||||||
|
<button type="button" class="ua-status-chip is-active" data-ua-status="ativos">Ativos</button>
|
||||||
|
<button type="button" class="ua-status-chip" data-ua-status="inativos">Inativos</button>
|
||||||
|
<button type="button" class="ua-status-chip" data-ua-status="todos">Todos</button>
|
||||||
|
</div>
|
||||||
<div class="pa-toolbar">
|
<div class="pa-toolbar">
|
||||||
<div class="pa-search">
|
<div class="pa-search">
|
||||||
<input type="text" id="ua-search-input" placeholder="Pesquisar usuário..." autocomplete="off" />
|
<input type="text" id="ua-search-input" placeholder="Pesquisar usuário..." autocomplete="off" />
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user