Penny API é uma aplicação full-stack para gerenciamento de finanças pessoais, permitindo aos usuários controlar receitas, despesas e categorias de forma segura e intuitiva.
- 🔐 Autenticação e autorização com JWT
- 👤 Cadastro e gerenciamento de usuários
- 📁 CRUD completo de categorias personalizadas
- Ícones e cores customizáveis
- Isolamento por usuário
- 💰 Gerenciamento de transações financeiras
- Tipos: Receitas e Despesas
- Paginação e filtragem
- Associação com categorias
- 📊 Dashboard financeiro
- Total de receitas
- Total de despesas
- Saldo atual
- 🛡️ Tratamento global de exceções
- 📚 Documentação interativa com Swagger
- ✅ Testes automatizados (unitários e integração)
- Java 21 - Linguagem de programação
- Spring Boot 4.0.0 - Framework principal
- Spring Web MVC - API REST
- Spring Data JPA - Persistência de dados
- Spring Security - Autenticação e autorização
- PostgreSQL 15+ - Banco de dados relacional
- Auth0 java-jwt 4.4.0 - Tokens JWT
- Gradle 9.2.1 - Build tool
- React 19.2.3 - Biblioteca UI
- React Router 7.10.1 - Roteamento
- TypeScript 5.9.2 - Type safety
- TailwindCSS 4.1.13 - Framework CSS
- Vite 7.1.7 - Build tool
- JUnit 5 - Framework de testes
- TestContainers 1.20.4 - Testes de integração
- JaCoCo
- SpringDoc OpenAPI 3.0.0 - Documentação API
- Swagger UI - Interface interativa
graph TB
subgraph "Frontend - React 19.2.3"
WEB[Web Application<br/>React Router 7<br/>TailwindCSS]
end
subgraph "Backend - Spring Boot 4.0.0"
API[REST API<br/>Port 8080]
AUTH[JWT Authentication<br/>Spring Security]
SERVICE[Business Logic Layer<br/>Services]
REPO[Data Access Layer<br/>JPA Repositories]
end
subgraph "Database"
DB[(PostgreSQL 15+<br/>Port 5432)]
end
subgraph "Documentation"
SWAGGER[Swagger UI<br/>/swagger-ui.html]
end
WEB -->|HTTP/JSON| API
API --> AUTH
AUTH --> SERVICE
SERVICE --> REPO
REPO --> DB
API --> SWAGGER
style WEB fill:#61dafb,stroke:#333,stroke-width:2px,color:#000
style API fill:#6db33f,stroke:#333,stroke-width:2px,color:#fff
style AUTH fill:#6db33f,stroke:#333,stroke-width:2px,color:#fff
style SERVICE fill:#6db33f,stroke:#333,stroke-width:2px,color:#fff
style REPO fill:#6db33f,stroke:#333,stroke-width:2px,color:#fff
style DB fill:#336791,stroke:#333,stroke-width:2px,color:#fff
style SWAGGER fill:#85ea2d,stroke:#333,stroke-width:2px,color:#000
erDiagram
USER ||--o{ CATEGORY : "owns"
USER ||--o{ TRANSACTION : "creates"
CATEGORY ||--o{ TRANSACTION : "categorizes"
USER {
UUID id PK
String name
String email UK
String password
LocalDateTime createdAt
}
CATEGORY {
UUID id PK
String name
String icon
String color
UUID userId FK
LocalDateTime createdAt
}
TRANSACTION {
UUID id PK
String description
BigDecimal amount
TransactionType type
LocalDate date
UUID categoryId FK
UUID userId FK
LocalDateTime createdAt
}
Antes de começar, certifique-se de ter instalado:
- Java 21 - Download OpenJDK 21
- PostgreSQL 15+ - Download PostgreSQL
- Node.js 18+ e npm - Download Node.js
- Git - Download Git
java -version # Deve mostrar Java 21
psql --version # Deve mostrar PostgreSQL 15+
node -version # Deve mostrar Node.js 18+
npm -version # Verifica instalação do npmgit clone https://github.com/vittordeaguiar/penny-api.git
cd penny-api# Acesse o PostgreSQL
psql -U postgres
# Crie o banco de dados
CREATE DATABASE penny_db;
# Crie um usuário (opcional)
CREATE USER penny_user WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE penny_db TO penny_user;
# Saia do PostgreSQL
\q# Navegue até o diretório da API
cd api
# Configure as variáveis de ambiente (opcional)
export JWT_SECRET="your-secret-key-here"
export JWT_EXPIRATION=3600000
# Se criou um usuário específico, atualize application.properties:
# src/main/resources/application.properties
# spring.datasource.username=penny_user
# spring.datasource.password=your_password
# Execute os testes para verificar
./gradlew test
# Compile o projeto
./gradlew build# Navegue até o diretório web
cd ../web
# Instale as dependências
npm install# A partir do diretório raiz do projeto
cd api
./gradlew bootRunA API estará disponível em: http://localhost:8080
Em um novo terminal:
# A partir do diretório raiz do projeto
cd web
npm run devA aplicação web estará disponível em: http://localhost:5173
- Aplicação Web: http://localhost:5173
- API REST: http://localhost:8080
- Documentação Swagger: http://localhost:8080/swagger-ui.html
- API Docs (JSON): http://localhost:8080/v3/api-docs
- Acesse http://localhost:5173
- Crie uma nova conta através do registro
- Faça login com suas credenciais
- Comece a gerenciar suas finanças!
O projeto possui uma suíte completa de testes com 80% de cobertura mínima.
# A partir do diretório api
cd api
# Executar todos os testes
./gradlew test
# Executar apenas testes unitários
./gradlew test --tests "com.vittor.pennyapi.service.*"
# Executar apenas testes de integração
./gradlew test --tests "com.vittor.pennyapi.integration.*"# Gerar relatório JaCoCo
./gradlew jacocoTestReport
# O relatório HTML será gerado em:
# build/jacocoHtml/index.html# Verificar se a cobertura atende aos requisitos (80%)
./gradlew jacocoTestCoverageVerificationapi/src/test/java/com/vittor/pennyapi/
├── integration/ # 6 testes de integração (TestContainers)
│ ├── AuthenticationIntegrationTest.java
│ ├── CategoryIntegrationTest.java
│ ├── TransactionValidationIntegrationTest.java
│ ├── UserJourneyIntegrationTest.java
│ └── ...
├── service/ # 3 testes unitários (service layer)
│ ├── CategoryServiceTest.java
│ ├── TransactionServiceTest.java
│ └── UserServiceTest.java
└── security/ # Testes de segurança
└── TokenServiceTest.java
| Variável | Descrição | Valor Padrão | Obrigatória |
|---|---|---|---|
JWT_SECRET |
Chave secreta para tokens JWT | 22c22bc4d641b1b5 |
Não* |
JWT_EXPIRATION |
Tempo de expiração do token (ms) | 3600000 (1 hora) |
Não |
SPRING_DATASOURCE_URL |
URL de conexão PostgreSQL | jdbc:postgresql://localhost:5432/penny_db |
Não |
SPRING_DATASOURCE_USERNAME |
Usuário do banco | vittordeaguiar |
Não |
SPRING_DATASOURCE_PASSWORD |
Senha do banco | (vazio) | Não |
* Importante: Em produção, sempre configure um JWT_SECRET customizado e seguro!
Linux/macOS:
export JWT_SECRET="your-very-secure-secret-key-here"
export JWT_EXPIRATION=7200000Windows (PowerShell):
$env:JWT_SECRET="your-very-secure-secret-key-here"
$env:JWT_EXPIRATION=7200000penny-api/
├── api/ # Backend Spring Boot
│ ├── src/
│ │ ├── main/
│ │ │ ├── java/com/vittor/pennyapi/
│ │ │ │ ├── config/ # Configurações (Security, Swagger)
│ │ │ │ ├── controller/ # REST Controllers
│ │ │ │ │ ├── AuthController.java
│ │ │ │ │ ├── CategoryController.java
│ │ │ │ │ └── TransactionController.java
│ │ │ │ ├── dto/ # Data Transfer Objects
│ │ │ │ ├── entity/ # Entidades JPA
│ │ │ │ │ ├── User.java
│ │ │ │ │ ├── Category.java
│ │ │ │ │ └── Transaction.java
│ │ │ │ ├── enums/ # Enumerações (TransactionType)
│ │ │ │ ├── exception/ # Exception handlers
│ │ │ │ ├── repository/ # JPA Repositories
│ │ │ │ ├── security/ # JWT & Security filters
│ │ │ │ └── service/ # Lógica de negócio
│ │ │ └── resources/
│ │ │ └── application.properties
│ │ └── test/ # Testes (9 classes)
│ ├── build.gradle
│ └── gradlew
│
├── web/ # Frontend React
│ ├── app/ # Código da aplicação
│ ├── public/ # Assets estáticos
│ ├── package.json
│ └── vite.config.ts
│
├── ROADMAP.md # Planejamento do projeto
└── README.md # Este arquivo
A documentação completa da API está disponível via Swagger UI.
Com a aplicação rodando, acesse:
- Interface Interativa: http://localhost:8080/swagger-ui.html
- Documentação JSON: http://localhost:8080/v3/api-docs
POST /api/auth/register- Registrar novo usuárioPOST /api/auth/login- Login e obtenção de token JWT
GET /api/categories- Listar categorias do usuárioPOST /api/categories- Criar nova categoriaGET /api/categories/{id}- Obter categoria específicaPUT /api/categories/{id}- Atualizar categoriaDELETE /api/categories/{id}- Deletar categoria
GET /api/transactions- Listar transações (paginado)POST /api/transactions- Criar nova transaçãoGET /api/transactions/{id}- Obter transação específicaPUT /api/transactions/{id}- Atualizar transaçãoDELETE /api/transactions/{id}- Deletar transaçãoGET /api/transactions/summary- Resumo financeiro (dashboard)
Todos os endpoints (exceto registro e login) requerem autenticação JWT.
Header necessário:
Authorization: Bearer {seu-token-jwt}
Exemplo com curl:
# 1. Registrar usuário
curl -X POST http://localhost:8080/api/auth/register \
-H "Content-Type: application/json" \
-d '{"name":"João Silva","email":"joao@example.com","password":"senha123"}'
# 2. Login
curl -X POST http://localhost:8080/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"joao@example.com","password":"senha123"}'
# 3. Usar o token para acessar endpoints protegidos
curl -X GET http://localhost:8080/api/categories \
-H "Authorization: Bearer {token-retornado}"Contribuições são bem-vindas! Para contribuir:
- Fork o projeto
- Crie uma branch para sua feature (
git checkout -b feature/MinhaFeature) - Commit suas mudanças (
git commit -m 'Adiciona MinhaFeature') - Push para a branch (
git push origin feature/MinhaFeature) - Abra um Pull Request
- Siga as convenções do Java (Google Java Style Guide)
- Mantenha a cobertura de testes acima de 80%
- Documente novos endpoints no Swagger
- Escreva mensagens de commit descritivas
Vittor de Aguiar
- GitHub: @vittordeaguiar
- LinkedIn: @vittordeaguiar