Skip to content

vitoriadeveloper/vifood

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

257 Commits
Β 
Β 
Β 
Β 

Repository files navigation

🍽️ vifood β€” Food Delivery API

Project developed during the AlgaWorks Spring Boot specialization course. REST API inspired by the food delivery domain, built with Spring Boot 3.5.7, Java 21, and Hexagonal Architecture (Ports & Adapters).


πŸ“‘ Table of Contents

  1. Overview
  2. Tech Stack
  3. Architecture
  4. Project Structure
  5. Domain Models
  6. API Endpoints
  7. Exception Handling
  8. Validation
  9. Database Migrations (Flyway)
  10. How to Run
  11. Tests
  12. Implemented Features

🌐 Overview

vifood is a food delivery REST API for managing restaurants, menus, orders, payment methods, users, and permissions. The project applies modern best practices such as Hexagonal Architecture, Bean Validation, global exception handling, pagination, dynamic filters via JPA Specifications, and versioned database migrations with Flyway.


πŸ›  Tech Stack

Technology Version Purpose
Java 21 Main language
Spring Boot 3.5.7 Base framework
Spring Web β€” REST API
Spring Data JPA β€” Persistence
Spring Validation β€” Bean Validation (Jakarta)
Hibernate β€” ORM
PostgreSQL 42.7.7 Database
Flyway 10.15.0 Schema versioning
Lombok β€” Boilerplate reduction
Thymeleaf β€” Template engine
Flying Saucer 9.1.22 PDF generation (HTML β†’ PDF)
iText 2.1.7 PDF library
H2 Database β€” In-memory DB (testing)
Maven β€” Build tool
Docker Compose β€” Local orchestration

Application port: 8081


πŸ› Architecture

The project follows Hexagonal Architecture (Ports & Adapters) with three well-defined layers:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚             INFRA (Adapters)                   β”‚
β”‚  REST Controllers | JPA Adapters | DTOs        β”‚
β”‚  Mappers | Configurations | Exception Handler  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚ implements
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           APPLICATION (Use Cases)              β”‚
β”‚  Services that implement the inbound ports     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                   β”‚ depends on
                   β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚              DOMAIN (Core)                     β”‚
β”‚  Entities | Ports (in/out) | Exceptions        β”‚
β”‚  Filters | No Spring dependencies              β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Layers

  • Domain β€” Business core. Entities, business rules, ports (interfaces), and business exceptions. No Spring dependencies.
  • Application β€” Use case implementations (Services). Orchestrates domain logic and uses outbound ports.
  • Infra β€” Adapters: REST Controllers, JPA repositories, DTOs, mappers, configurations, exception handlers.

πŸ“ Project Structure

src/main/java/com/vitoriadeveloper/vifood/
β”‚
β”œβ”€β”€ domain/
β”‚   β”œβ”€β”€ model/              # JPA entities (Restaurant, Kitchen, Order…)
β”‚   β”œβ”€β”€ ports/
β”‚   β”‚   β”œβ”€β”€ in/             # Inbound ports (use cases)
β”‚   β”‚   └── out/            # Outbound ports (repositories)
β”‚   β”œβ”€β”€ exceptions/         # Business exceptions
β”‚   └── filters/            # Filters (RestaurantFilter, OrderFilter)
β”‚
β”œβ”€β”€ application/
β”‚   β”œβ”€β”€ services/           # Use case implementations
β”‚   └── config/             # ValidationConfig
β”‚
└── infra/
    β”œβ”€β”€ adapters/
    β”‚   β”œβ”€β”€ http/           # REST Controllers
    β”‚   β”œβ”€β”€ repositories/   # JPA Adapters
    β”‚   └── model/
    β”‚       β”œβ”€β”€ dto/
    β”‚       β”‚   β”œβ”€β”€ request/    # Input DTOs
    β”‚       β”‚   └── response/   # Output DTOs
    β”‚       └── mapper/         # Manual mappers
    β”œβ”€β”€ repositories/       # Spring Data JPA Repositories
    β”‚   └── spec/           # Specifications (dynamic filters)
    β”œβ”€β”€ validation/         # Validation groups
    β”œβ”€β”€ config/             # JpaConfig
    β”œβ”€β”€ exceptions/         # ApiExceptionHandler
    └── utils/              # ErrorResponse

πŸ“¦ Domain Models

Restaurant (tb_restaurantes)

The core entity. Has name, delivery fee, status (active/inactive, open/closed), creation/update timestamps, embedded address, kitchen, payment methods, products, and owners.

Field Type Description
id UUID Identifier
nome String Restaurant name
taxaFrete BigDecimal Delivery fee
ativo Boolean Active flag
aberto Boolean Open flag
dataCadastro OffsetDateTime Creation timestamp
dataAtualizacao OffsetDateTime Last update timestamp
cozinha Kitchen (ManyToOne) Kitchen type
endereco Address (Embedded) Address
formasPagamento List Accepted payments
produtos List Menu
responsaveis List Owners/managers

Methods: open(), close(), inactive(), active(), associateRestaurantOwner(), disassociateRestaurantOwner().

Kitchen (tb_cozinhas)

Kitchen type/category (Italian, Japanese, etc.). OneToMany relationship with Restaurant.

Product (tb_produtos)

Menu item belonging to a restaurant. Has name, description, price, active flag. Can have an image (OneToOne with ProductImage).

Order (tb_pedidos)

Order placed by a client at a restaurant. Has items, status (state machine), total value, and delivery address.

Order status (state machine):

CRIADO β†’ CONFIRMADO β†’ PREPARANDO β†’ PRONTO β†’ SAIU_PARA_ENTREGA β†’ ENTREGUE
   (created) (confirmed)  (preparing)  (ready)  (out for delivery)  (delivered)
              ↓
           CANCELADO  (from CRIADO, CONFIRMADO, or PREPARANDO)
            (cancelled)

Methods: addItem(), removeItem(), confirmOrder(), cancelOrder(), changeStatus(), calculateTotalValue().

OrderItem (tb_itens_pedido)

Line item in an order. Quantity, unit price, total price, and notes. Computes total via calculateTotal().

User (tb_usuarios)

System user. Has name, unique email, password. Belongs to multiple GroupPermission entries (ManyToMany).

GroupPermission (tb_grupos)

Permission group. Holds multiple UserPermission entries.

UserPermission (tb_permissao)

Atomic system permission (name + description).

State (tb_estados)

Federative unit: name + 2-letter code.

City (tb_cidades)

City linked to a State.

Address (Embeddable)

ZIP code, street, number, complement, neighborhood, city. Used in Restaurant and Order.

PaymentMethod (tb_formas_pagamento)

Accepted payment method (description).


πŸ”Œ API Endpoints

πŸ› States β€” /estados

Method Path Description
GET /estados List all states
GET /estados/{id} Get state by ID
DELETE /estados/{id} Delete state

πŸ™ Cities β€” /cidades

Method Path Description
POST /cidades Create city
GET /cidades List cities
GET /cidades/{id} Get by ID
PUT /cidades/{id} Update
DELETE /cidades/{id} Delete

🍳 Kitchens β€” /cozinhas

Method Path Description
POST /cozinhas Create kitchen
GET /cozinhas?page=0&size=10 List (paginated)
GET /cozinhas/{id} Get by ID
PUT /cozinhas/{id} Update
DELETE /cozinhas/{id} Delete

🍴 Restaurants β€” /restaurantes

Method Path Description
POST /restaurantes Create restaurant
GET /restaurantes List (filters: nome, taxaFreteMin, taxaFreteMax)
GET /restaurantes/{id} Get by ID
PUT /restaurantes/{id} Update
PATCH /restaurantes/{id} Partial update
DELETE /restaurantes/{id} Delete
PUT /restaurantes/{id}/ativar Activate
PUT /restaurantes/{id}/inativar Deactivate
POST /restaurantes/batch/ativar Batch activate
POST /restaurantes/batch/inativar Batch deactivate
POST /restaurantes/{idRestaurante}/formas-pagamento Associate payment method
DELETE /restaurantes/{idRestaurante}/formas-pagamento/{idFormaPagamento} Disassociate payment method
GET /restaurantes/{idRestaurante}/responsaveis List owners
POST /restaurantes/{idRestaurante}/responsaveis/{idResponsavel} Add owner
DELETE /restaurantes/{idRestaurante}/responsaveis/{idResponsavel} Remove owner
GET /restaurantes/{idRestaurante}/produtos List products
POST /restaurantes/{idRestaurante}/produtos Add product
PUT /restaurantes/{idRestaurante}/produtos/{idProduto} Update product
DELETE /restaurantes/{idRestaurante}/produtos/{idProduto} Delete product

πŸ’³ Payment Methods β€” /formas-pagamento

Method Path Description
GET /formas-pagamento List
POST /formas-pagamento Create
GET /formas-pagamento/{id} Get
DELETE /formas-pagamento/{id} Delete

πŸ‘€ Users β€” /usuarios

Method Path Description
GET /usuarios List users
POST /usuarios Create user
GET /usuarios/{id} Get by ID
DELETE /usuarios/{id} Delete
PUT /usuarios/{usuarioId}/{grupoId} Associate user with group
DELETE /usuarios/{usuarioId}/{grupoId} Disassociate user from group

πŸ” Permissions β€” /permissoes

Method Path Description
GET /permissoes List
POST /permissoes Create
GET /permissoes/{id} Get
PUT /permissoes/{id} Update
DELETE /permissoes/{id} Delete

πŸ‘₯ Groups β€” /grupos

Method Path Description
GET /grupos List
POST /grupos Create
GET /grupos/{id} Get
PUT /grupos/{id} Update
DELETE /grupos/{id} Delete
POST /grupos/{grupoId}/permissoes/{permissaoId} Add permission
DELETE /grupos/{grupoId}/permissoes/{permissaoId} Remove permission

πŸ›’ Orders β€” /pedidos

Method Path Description
POST /pedidos Create order
GET /pedidos/{pedidoId} Get by ID
GET /pedidos/cliente/{clienteId} Orders by client
GET /pedidos/restaurante/{restauranteId} Orders by restaurant
GET /pedidos/filtros Filter (clienteId, restauranteId, status) with pagination
PATCH /pedidos/{pedidoId} Partial update
DELETE /pedidos/{pedidoId} Delete
PUT /pedidos/{pedidoId}/confirmar Confirm (CRIADO β†’ CONFIRMADO)
PUT /pedidos/{pedidoId}/cancelar Cancel order
PATCH /pedidos/{pedidoId}/status?status={status} Change status

πŸ“Š Statistics β€” /estatisticas

Method Path Description
POST /estatisticas Generate statistics
GET /estatisticas Query statistics

🚨 Exception Handling

Custom Exceptions (domain/exceptions/)

  • BusinessException β€” Base for business rule violations
  • KitchenNotFoundException, RestaurantNotFoundException
  • CityNotFoundException, StateNotFoundException
  • UserNotFoundException, OrderNotFoundException
  • ProductNotFoundException, PaymentMethodNotFoundException
  • GroupPermissionNotFoundException, PermissionNotFoundException
  • InvalidStateReferenceException

Global Handler β€” ApiExceptionHandler

Annotated with @RestControllerAdvice, extends ResponseEntityExceptionHandler, and converts exceptions into standardized HTTP responses:

Exception Status
*NotFoundException 404 Not Found
DataIntegrityViolationException 409 Conflict
MethodArgumentNotValidException 400 Bad Request (with field details)
HttpMessageNotReadableException 400 Bad Request
InvalidFormatException 400 Bad Request
PropertyBindingException 400 Bad Request
MethodArgumentTypeMismatchException 400 Bad Request

Error response shape (ErrorResponse)

{
  "timestamp": "2026-05-01T10:00:00-03:00",
  "status": 400,
  "title": "Invalid data",
  "message": "One or more fields are invalid",
  "fields": { "nome": "must not be blank" }
}

βœ… Validation

  • Bean Validation (Jakarta): @NotBlank, @NotNull, @Valid, @PositiveOrZero
  • Validation Groups (infra/validation/Groups.java): Groups.CozinhaId for conditional validation with @ConvertGroup
  • Cascading validation with @Valid on nested fields
  • Strict Jackson: FAIL_ON_UNKNOWN_PROPERTIES=true rejects unknown JSON fields

πŸ—„ Database Migrations (Flyway)

Version Description
V001 Initial schema: kitchens, states, cities, restaurants, products, payment methods, users, groups, permissions, and join tables
V002 Restaurant flags and timestamps (active, open, dataCadastro, dataAtualizacao), embedded address, product description
V003 tb_pedidos and tb_itens_pedido tables
V004 Product FK on order items + delivery address on orders
V005 Restaurant FK on orders
V006 Restaurant timestamps converted to TIMESTAMP WITH TIME ZONE
V007 tb_restaurante_responsaveis table (restaurant owners)
V008 Product images table (tb_produto_imagens)

▢️ How to Run

Prerequisites

  • Java 21
  • Maven 3.9+
  • Docker (for PostgreSQL)

1. Start the database

docker-compose up -d

2. Run the application

./mvnw spring-boot:run

Or on Windows:

mvnw.cmd spring-boot:run

3. Access

The API will be available at http://localhost:8081.

Configuration

  • Database: PostgreSQL on localhost:5432, database vifood
  • HikariCP pool: max 5, min idle 3
  • DDL: validate (Hibernate only validates; Flyway handles schema)

πŸ§ͺ Tests

Class Type What it tests
VifoodApplicationTests Smoke Spring context loading
RestaurantControllerTests Integration CRUD, filters, activation/deactivation
KitchenControllerTests Integration CRUD, pagination
KitchenServiceIT Integration Service logic, transactions

The maven-failsafe plugin (v3.2.5) runs integration tests (suffix IT).

Run tests:

./mvnw test
./mvnw verify    # includes integration tests

✨ Implemented Features

βœ… Full Restaurant CRUD with dynamic filters (name, delivery fee range) βœ… Open/close and activate/deactivate operations (single and batch) βœ… Menu (Products) management per restaurant (with image upload) βœ… Complete Order system with a 7-state state machine βœ… Payment Methods management and association with restaurants βœ… Hierarchical Location management (States β†’ Cities) βœ… Restaurant categorization via Kitchens βœ… Users, Groups, and Permissions system βœ… Restaurant owners (managers) βœ… Pagination for kitchens and orders listings βœ… Dynamic filters via JPA Specifications βœ… Validation with Bean Validation + groups βœ… Global exception handling with localized messages βœ… Versioned migrations via Flyway (8 migrations) βœ… PDF generation (Flying Saucer + Thymeleaf) βœ… Statistics and reporting


πŸ‘©β€πŸ’» Author

VitΓ³ria Carolina Dantas Project developed as part of the AlgaWorks Spring Boot specialization course.

πŸ“… Last updated: May/2026

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors