Skip to content

Latest commit

 

History

History
198 lines (153 loc) · 4.92 KB

File metadata and controls

198 lines (153 loc) · 4.92 KB

Client Workflow API

API para gerenciamento de clientes, simulação de integração com Pipefy via GraphQL e webhooks.

Tecnologias utilizadas

  • Python 3.12
  • FastAPI
  • SQLAlchemy 2.0
  • Pydantic v2
  • SQLite
  • uv
  • pytest
  • Ruff

Estrutura do projeto

app/
├── integrations/
│   └── pipefy_client.py     # Mutations GraphQL do Pipefy
├── models/
├── repositories/
├── routes/
├── schemas/
├── services/
├── config.py
├── database.py
├── exceptions.py
└── main.py
tests/
├── conftest.py
├── test_clients.py
└── test_webhooks.py

Execução local

Pré-requisitos

  • Python 3.12+
  • uv

Instalação

# Clonar o repositório
git clone https://github.com/lucasdavidoj/client-workflow-api.git
cd client-workflow-api

# Instalar dependências (cria o .venv automaticamente)
uv sync

Variáveis de ambiente

cp .env.example .env

O .env.example já contém os valores padrão para execução local com SQLite, não é preciso alterá-lo para rodar.

Rodando a API

uv run uvicorn app.main:app --reload

A API estará disponível em http://localhost:8000.

A documentação swagger estará em http://localhost:8000/docs.

Rodando os testes

uv run pytest -q

Os testes usam um banco SQLite em memória isolado por fixture.


Observação sobre a integração com Pipefy

As mutations foram estruturadas seguindo o formato esperado da API GraphQL do Pipefy, mas a aplicação não realiza chamadas reais ao Pipefy neste desafio.

Endpoints

POST /clientes — Criação de cliente

Cria um novo cliente com status inicial "Aguardando Análise" e retorna o payload GraphQL que seria enviado ao Pipefy para criar o card correspondente.

curl -s -X POST http://localhost:8000/clientes \
  -H "Content-Type: application/json" \
  -d '{
    "cliente_nome": "Lucas David",
    "cliente_email": "lucas.david@tests.com",
    "tipo_solicitacao": "Atualização cadastral",
    "valor_patrimonio": 250000
  }' | python3 -m json.tool

Resposta (201 Created):

{
  "client": {
    "id": 1,
    "name": "Lucas David",
    "email": "lucas.david@tests.com",
    "request_type": "Atualização cadastral",
    "asset_value": "250000.00",
    "status": "Aguardando Análise",
    "priority": null
  },
  "pipefy_payload": {
    "query": "mutation CreateCard($input: CreateCardInput!) { ... }",
    "variables": {
      "input": {
        "pipe_id": "pipe_id_placeholder",
        "title": "Lucas David",
        "fields_attributes": [...]
      }
    }
  }
}

POST /webhooks/pipefy/card-updated — Processamento de webhook

Simula o recebimento de um evento do Pipefy quando um card é atualizado. Aplica a regra de prioridade baseada no patrimônio do cliente e retorna o payload GraphQL que seria enviado ao Pipefy para atualizar os campos do card.

curl -s -X POST http://localhost:8000/webhooks/pipefy/card-updated \
  -H "Content-Type: application/json" \
  -d '{
    "event_id": "evt_123",
    "card_id": "card_456",
    "cliente_email": "lucas.david@tests.com",
    "timestamp": "2026-05-18T12:00:00Z"
  }' | python3 -m json.tool

Resposta (200 OK):

{
  "event_id": "evt_123",
  "client": {
    "id": 1,
    "name": "Lucas David",
    "email": "lucas.david@tests.com",
    "request_type": "Atualização cadastral",
    "asset_value": "250000.00",
    "status": "Processado",
    "priority": "prioridade_alta"
  },
  "pipefy_payload": {
    "query": "mutation UpdateCardFields(...) { ... }",
    "variables": {
      "statusInput": {
        "card_id": "card_456",
        "field_id": "status",
        "new_value": "Processado"
      },
      "priorityInput": {
        "card_id": "card_456",
        "field_id": "prioridade",
        "new_value": "prioridade_alta"
      }
    }
  }
}

Regras de prioridade:

valor_patrimonio Prioridade atribuída
>= R$ 200.000 prioridade_alta
< R$ 200.000 prioridade_normal

Idempotência: reenviar o mesmo event_id retorna 409 Conflict.


Visão de produção

Para escalar esse sistema em produção, eu trocaria o SQLite pelo PostgreSQL no AWS RDS em conjunto com AWS RDS Proxy para evitar excesso de conexões abertas no banco.

A API poderia ser exposta por API Gateway e processada por Lambdas separadas para criação de clientes e recebimento de webhooks. Para webhooks com maior volume, eu colocaria uma fila SQS entre o recebimento do evento e o processamento, dessa forma, a API responde rápido e o processamento pode ser refeito em caso de falha.

A idempotência por event_id poderia continuar no banco relacional ou ir para o DynamoDB, já que é uma consulta simples por chave única.

Para infraestrutura, usaria Terraform ou AWS SAM.