Skip to content

lucasdavidoj/client-workflow-api

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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.

About

FastAPI backend for client workflow management with Pipefy GraphQL integration, webhook idempotency, SQLAlchemy and pytest.

Topics

Resources

Stars

Watchers

Forks

Contributors

Languages