Skip to main content
Glama
miguelvzs
by miguelvzs
README.md
# Validador de Registros Tabulares

Automação que atua como **filtro de qualidade entre a captação de registros e o
sistema que vai consumi-los**: lê uma planilha, barra o que está inconsistente
explicando o motivo de cada rejeição, prioriza o que é válido por um critério de
urgência e ainda tenta **recuperar automaticamente**, com IA, os registros que
foram barrados.

O caso de origem são **pedidos de fábrica** (produção sob demanda), mas a lógica
vale para qualquer conjunto de registros tabulares que chega inconsistente e
precisa de conferência antes de seguir adiante — importações, cadastros,
integração entre sistemas. As regras de negócio vivem em `config.yaml`; trocar o
domínio é editar YAML, não código.

**Serviço no ar:** `https://validador-pedidos-gocase.onrender.com`

---

## O problema

Sempre que registros entram em um sistema vindos de várias origens, cada origem
valida na entrada de um jeito diferente — ou não valida. O resultado é um lote
onde convivem registros perfeitos e registros com campo obrigatório vazio,
e-mail quebrado, número zerado, valor que não fecha, data no passado ou
duplicidade.

Conferir isso à mão é lento, cansativo e deixa passar erro sutil — uma diferença
de centavos, uma duplicata separada por dezenas de linhas. Pior: um registro
válido pode ser rejeitado por **erro de preenchimento, não de conteúdo** — um
nome que faltou, um `@` que sumiu do e-mail. O dado certo existe; só não chegou
formatado.

No caso de origem, cada registro é um pedido que vira ordem de produção física.
Um pedido com dado quebrado não é só um registro errado — é material
personalizado gasto, hora-máquina perdida e cliente sem receber. É o mesmo
padrão de qualquer fluxo em que o registro ruim custa caro lá na frente.

---

## Como funciona

O núcleo é um pipeline de quatro etapas, exposto por três superfícies (terminal,
API HTTP, MCP) que chamam a **mesma** função:

```mermaid
flowchart LR
    A[Planilha .xlsx] --> B[Leitura + schema]
    B --> C[Validação<br/>9 regras]
    C -->|válidos| D[Priorização<br/>por prazo]
    C -->|rejeitados| E[Recuperação por IA]
    E -->|corrigido| C
    E -->|indeduzível| F[Revisão humana]
    D --> G[3 planilhas .xlsx]
    C --> G
```

1. **Leitura** (`src/leitor.py`) — lê o Excel, tipa colunas e confere o schema
   esperado. Coluna faltando vira erro legível, não falha genérica.
2. **Validação** (`src/validador.py`) — aplica as 9 regras a cada registro;
   separa válidos de rejeitados; acumula todos os motivos por registro.
3. **Priorização** (`src/organizador.py`) — calcula `dias_restantes` e ordena os
   válidos em fila de urgência.
4. **Relatório** (`src/relatorio.py`) — gera as 3 planilhas formatadas.
5. **Recuperação por IA** (`src/assistente_ia.py`, opcional) — tenta recuperar os
   rejeitados; o que a IA corrige volta pela validação, que não abre exceção.

### Como o operador usa

1. Abre o formulário no navegador.
2. Sobe a planilha `.xlsx`.
3. Recebe de volta um `.zip` com as três planilhas prontas.

Nada é instalado na máquina de ninguém: o processamento roda no servidor e o
resultado volta pelo navegador. O formulário é publicado pelo fluxo n8n que
acompanha o projeto em [`integracoes/`](integracoes/README.md), importado uma
única vez. Quem não usa n8n consome a API diretamente — o contrato está no mesmo
guia.

Para experimentar sem preparar dados, o repositório inclui
[`exemplo/pedidos_exemplo.xlsx`](exemplo/pedidos_exemplo.xlsx): 50 registros, dos
quais 10 contêm defeitos representativos.

> **Primeira execução do dia.** O serviço está hospedado em plano gratuito e
> hiberna após alguns minutos sem uso. A primeira chamada leva cerca de 50
> segundos para acordar o servidor; as seguintes respondem em menos de 1
> segundo. Se o fluxo acusar tempo esgotado na primeira tentativa, basta repetir.

---

## Regras de validação

Cada registro é avaliado contra **todas** as regras. Um registro pode acumular
vários motivos, concatenados na coluna `motivo_rejeicao` — a lista completa de
problemas de uma vez, não um erro por reprocessamento.

| # | Campo | Regra |
|---|---|---|
| 1 | `id_pedido` | Não vazio e não duplicado. Na duplicata, a 2ª ocorrência é reprovada. |
| 2 | `cliente` | Não vazio. |
| 3 | `email` | Formato `texto@texto.dominio`. |
| 4 | `quantidade` | Inteiro positivo. |
| 5 | `valor_unitario` | Positivo. |
| 6 | `valor_total` | Bate com `quantidade × valor_unitario` (tolerância de R$ 0,02). |
| 7 | `prazo_entrega` | Não pode estar no passado. |
| 8 | `produto` | Não vazio. |
| 9 | `sku` | Não vazio. |

Os nomes de campo acima são os do domínio de origem (pedidos). O `mapa_colunas`
do `config.yaml` traduz os cabeçalhos de qualquer export para esses nomes, então
uma planilha de outro sistema não exige código novo.

### Prioridade

Os aprovados recebem `dias_restantes` e entram numa fila ordenada por urgência —
os mais apertados primeiro. As faixas (nomes, intervalos e cores) vivem no
`config.yaml`.

| Prioridade | Dias até o prazo | Cor na planilha |
|---|---|---|
| URGENTE | 0 a 2 | Vermelho claro |
| ALTA | 3 a 5 | Laranja claro |
| NORMAL | 6 a 10 | Verde claro |
| BAIXA | 11 ou mais | Sem cor |

---

## O que é entregue

| Planilha | Conteúdo |
|---|---|
| `pedidos_validados.xlsx` | Aprovados, na ordem de prioridade, coloridos por faixa. |
| `pedidos_rejeitados.xlsx` | Reprovados, com o motivo exato de cada um. |
| `resumo_execucao.xlsx` | Métricas do lote: totais, percentuais, prioridades, canais, valores. |

---

## Stack

| Camada | Tecnologia | Para quê |
|---|---|---|
| Planilhas | pandas, openpyxl | Ler o Excel, tipar colunas, gerar os relatórios formatados |
| API HTTP | FastAPI, uvicorn, python-multipart | Superfície de serviço; upload e download |
| Configuração | PyYAML | Regras de negócio fora do código (`config.yaml`) |
| IA | httpx + Anthropic Claude | Recuperação assistida dos rejeitados |
| Integração com IA | MCP | Interrogar a validação em linguagem natural |
| Orquestração | n8n | Formulário de upload low-code (padrão do caso de origem) |
| Hospedagem | Render | Serviço público |

Python 3.10+.

---

## Resultado medido

Lote de demonstração: 50 registros, com 10 problemas reais.

| Métrica | Valor |
|---|---|
| Registros processados | 50 |
| Reprovados na validação | 10 |
| **Recuperados pela IA** | **5** |
| Válidos ao final | 45 (90%) |
| Tempo de processamento | menos de 1 segundo |

Os números acima vêm da execução sobre `exemplo/pedidos_exemplo.xlsx` (dados
sintéticos), medidos localmente. Não são projeção de volume real de produção.

### O que a IA corrigiu na execução real

| Registro | Correção | De onde deduziu |
|---|---|---|
| PED-00003 | `cliente: '' → 'Camila Rodrigues'` | do e-mail `camila.rodrigues@...` |
| PED-00016 | `cliente: '' → 'Patricia Gomes'` | do e-mail `patricia.gomes@...` |
| PED-00034 | `cliente: '' → 'Daniel Oliveira'` | do e-mail `daniel.oliveira@...` |
| PED-00022 | `email: 'cliente@' → 'yasmin.monteiro@gmail.com'` | do nome do cliente |
| PED-00008 | `email: 'clientegocase.com' → 'cliente@gocase.com'` | faltava o `@` |

### O que ela corretamente não resolveu

Dos 10 reprovados, 5 permaneceram — e é assim que deve ser:

- **2 duplicatas** — exigem decisão humana sobre qual registro vale.
- **1 prazo vencido** — não é erro de dado, é problema operacional.
- **2 valores incoerentes** — a IA ajustou a quantidade, mas o `valor_total` não
  fechou, então o registro **continuou reprovado**. A validação não abre exceção
  para a IA.

---

## Camada de IA — recuperação de registros reprovados

Barrar um registro resolve metade do problema. A outra metade é **recuperá-lo**
quando o erro é de preenchimento, não de conteúdo. A divisão de trabalho é
explícita:

- **Erro mecânico** (valor que não fecha, espaço sobrando, e-mail a normalizar)
  → resolvido por regra, sem IA.
- **Erro semântico** (nome faltando, e-mail incompleto) → a IA infere cruzando
  os outros campos do próprio registro.
- **Dado impossível de deduzir** → sinalizado para revisão humana, nunca inventado.

### Trilha de auditoria

Correção automática só é confiável se for auditável. A IA **assina** o que fez,
dentro das planilhas entregues:

- Coluna `corrigido_por_ia` marca os registros recuperados.
- Coluna `correcao_ia` registra o antes → depois de cada campo alterado.
- O resumo traz a linha **"Registros recuperados pela IA"**.

Deduzir o nome a partir do e-mail é uma **inferência plausível, não um dado
confirmado**. Por isso a trilha existe: a IA acelera a recuperação e a decisão
final continua conferível por uma pessoa.

---

## Arquitetura

Responsabilidade única por módulo — cada arquivo faz uma coisa e é testável
isoladamente.

| Módulo | Responsabilidade |
|---|---|
| `src/leitor.py` | Lê o Excel, tipa colunas e confere o schema esperado. |
| `src/validador.py` | Aplica as 9 regras; separa aprovados de reprovados; acumula motivos. |
| `src/organizador.py` | Calcula `dias_restantes` e prioridade; ordena a fila. |
| `src/relatorio.py` | Gera as 3 planilhas formatadas. |
| `src/assistente_ia.py` | Prepara os reprovados para a IA, aplica as correções e marca a autoria. |
| `src/config.py` | Carrega `config.yaml` com fallback embutido. |
| `src/agente.py` | `executar_pipeline`: o fluxo completo, em uma função só. |
| `src/gerar_dados.py` | Gera a planilha de demonstração. Ferramenta de teste, não de produção. |
| `api.py` | Superfície HTTP: validação, download e correção por IA. |
| `mcp_server.py` | Superfície MCP: 5 ferramentas + 1 prompt para clientes de IA. |
| `main.py` | Execução por terminal, para desenvolvimento. |

**Fonte única de verdade.** O fluxo vive em `executar_pipeline`; as métricas são
montadas uma vez e reaproveitadas pelo relatório, pelo log e pela API. Nomes,
ordem e cores das faixas de prioridade existem apenas no `config.yaml`.

### Formas de consumo

Uma lógica de validação, três superfícies — sem regra duplicada.

| Superfície | Para quem | Como |
|---|---|---|
| **n8n** | Operação | Formulário de upload; devolve o `.zip` no navegador. Workflow pronto em `integracoes/`. |
| **API HTTP** | Qualquer sistema | HTTP + JSON padrão, sem SDK. Contrato em `integracoes/README.md`. |
| **MCP** | Ferramentas de IA | 5 ferramentas chamáveis por linguagem natural (ex.: Claude Desktop). |

O n8n executa a automação em lote; o MCP permite **interrogá-la** em linguagem
natural — *"quantos registros foram barrados e por quê?"*. Para habilitar num
cliente compatível (Claude Desktop, por exemplo), aponte-o para o servidor:

```json
{
  "mcpServers": {
    "validador-gocase": {
      "command": "python",
      "args": ["mcp_server.py"],
      "cwd": "caminho/para/validador-pedidos-gocase"
    }
  }
}
```

Ferramentas expostas: `validar_pedidos`, `consultar_resumo`,
`analisar_rejeitados`, `revalidar_com_correcoes` e `gerar_dados_exemplo`, mais
um prompt guia. As duas do meio formam o ciclo de correção assistida: o modelo
do próprio cliente propõe as correções e o servidor revalida.

A integração não amarra a ferramenta: por ser HTTP puro, Make, Power Automate ou
código próprio consomem a mesma API. O n8n é o caminho documentado e testado.

---

## Configuração sem código

Regras de negócio ficam fora do código, em `config.yaml`: tolerância de valor,
padrão de e-mail, colunas obrigatórias e as faixas de prioridade (nomes,
intervalos e cores). Um gestor ajusta limites sem abrir Python.

O `mapa_colunas` traduz os cabeçalhos de um export real para os nomes esperados —
é o ponto de troca de domínio: outra planilha, mesma lógica.

Configuração ausente ou inválida não derruba nada: o sistema avisa e usa os
padrões embutidos.

---

## Testes

`testar.py` executa **13 verificações** de ponta a ponta, sem framework externo —
é um script que roda o fluxo real e confere invariantes:

- geração da planilha de exemplo e execução do pipeline;
- existência e conteúdo das 3 planilhas e do log;
- consistência (`aprovados + reprovados = total`);
- presença de motivo em **todos** os reprovados;
- a API (validação, download do pacote, recusa de planilha fora do formato com
  erro legível);
- o MCP Server, exercitado pelo protocolo real: handshake, catálogo de
  ferramentas e uma ferramenta executada de ponta a ponta.

Outras salvaguardas embutidas: relatório aberto no Excel é tratado com novas
tentativas e mensagem clara; correção malformada vinda da IA é descartada sem
derrubar o lote; arquivos temporários do servidor expiram sozinhos em 1 hora.

```bash
python testar.py
```

---

## Como rodar

**Pré-requisitos:** Python 3.10+.

```bash
# 1. Dependências
pip install -r requirements.txt

# 2a. Modo terminal — gera dados de exemplo se não houver planilha real
python main.py

# 2b. Modo API HTTP
uvicorn api:app --host 0.0.0.0 --port 8000
# Docs interativas em http://localhost:8000/docs
```

Para colocar a planilha real, salve-a em `data/pedidos_entrada.xlsx` antes de
rodar `main.py`.

### Variáveis de ambiente (opcionais)

Todas têm padrão; nenhuma é obrigatória para validar. A correção por IA só liga
com a chave presente.

| Variável | Papel |
|---|---|
| `ANTHROPIC_API_KEY` | Liga a correção por IA no servidor. Ausente → `/corrigir-automatico` responde 503 e o resto segue normal. |
| `MODELO_IA` | Modelo Claude usado na correção. |
| `MAX_REJEITADOS_IA` | Teto de rejeitados por chamada à IA (controle de custo). |
| `JOBS_TTL_SEGUNDOS` | Tempo de vida dos arquivos temporários de cada job. |

A chave nunca fica no repositório — só no ambiente do servidor.

---

## Limitações e próximos passos

**Escopo desta entrega.** A API está publicada **sem autenticação**, por decisão
de escopo. A URL deve ser usada apenas com a planilha de demonstração (dados
sintéticos); registros reais contêm dados pessoais e exigem autenticação por
chave antes de trafegar por uma URL aberta. É um passo consciente do roadmap,
não um esquecimento.

**O que quebraria em escala maior.** O processamento é síncrono e carrega a
planilha inteira em memória (pandas) — adequado a lotes de milhares de linhas,
não a milhões. A detecção de duplicata olha apenas dentro do lote atual, não
entre execuções.

**Evolução natural.** Ler os registros direto da fonte (ERP, banco) em vez de
planilha; escrever o status de volta no sistema de origem; notificação ativa
quando o índice de reprovação subir; histórico entre lotes para detectar
duplicidade que atravessa execuções.

---

## Origem do projeto

Este projeto nasceu como **business case para o processo seletivo de Estágio em
RPA na GoCase (GoGroup)**, área de Operações de Fábrica. O domínio original é a
validação de pedidos de produção sob demanda, onde cada registro quebrado vira
material personalizado gasto e hora-máquina perdida.

A documentação foi generalizada porque a solução — conferência automática de
registros tabulares que chegam inconsistentes, com recuperação do que é erro de
preenchimento e não de conteúdo — se aplica a qualquer fluxo do mesmo tipo. O
vocabulário de pedidos permanece nas regras e nos exemplos por ser o caso real
medido, não por ser o único cabível.