API Back-end com Java e Spring Boot e Front-end Administrativo com Thymeleaf para delivery de uma cafeteria.
Este aplicativo foi criado através da oportunidade do desafio do trabalho semestral da faculdade UNIFRAN / Cruzeiro do Sul, Projeto Integrador Transdisciplinar, do segundo semestre de 2024. Todo o conteúdo é fictício.
O defasio consistia em desenvolver um sistema para gerenciamento de delivery para uma cafeteria.
Para a solução, foi criado o sistema QuickCup com dois módulos:
- QuickCup API e ADMIN: O QuickCup API e Admin é essa aplicação e interface desenvolvida para o acesso da loja poder cadastrar os produtos e visualizar os pedidos realizados pelo consumidor. Nessa aplicação foram criados endpoints API REST para que o QuickCup App possa interagir com o QuickCup API. O QuickCup Admin foi produzido para ser responsivo, mas para uma melhor experiência é ideal acessar com notebook ou computador. (Esse repositório contém o QuickCup API e Admin)
- QuickCup APP: O QuickCup App foi desenvolvido com React e Bootstrap CSS para trazer experiência de responsividade para acesso por via de diversos dispositivos mobiles ou notebooks e computadores. Link para o repositório do APP: didifive/quickcup-app
- Java 17
- Maven
- Spring Boot 3.3.5
- Spring Web
- Spring Data JPA
- PostgreSQL
- Flyway
- Thymeleaf
- Docker e Docker Compose 3 para desenvolvimento local com postgres
- IntelliJ IDEA
Os diagramas foram criados na sintaxe Mermaid.
classDiagram
class BasicEntity {
<<Abstract>>
- Long id
+ getId()
+ setId()
}
class Empresa {
- Short id
- String nome
- String email
- String telefone
- BigDecimal valorEntrega
- Time tempoEntrega
- String cep
- String logradouro
- Integer numero
- String complemento
- String bairro
- String cidade
- String estado
- BigDecimal longitude
- BigDecimal latitude
+ Getters() and Setters()
}
class Cliente {
- String nome
- String telefone
- List~Endereco~ enderecos
+ Getters() and Setters()
}
class Endereco {
- Long clienteId
- String nome
- String cep
- String logradouro
- Integer numero
- String complemento
- String bairro
- String cidade
- String estado
- BigDecimal longitude
- BigDecimal latitude
+ Getters() and Setters()
}
class Grupo {
- String nome
- String descricao
- List~Produto~ produtos
+ Getters() and Setters()
}
class Produto {
- String codigo
- String nome
- String descricao
- String imagem
- BigDecimal valorOriginal
- BigDecimal valorDesconto
- boolean enabled
- Grupo grupo
+ Getters() and Setters()
}
class PedidoStatus {
<<Enumeration>>
NOVO
CONFIRMADO
CANCELADO
EM_PREPARO
EM_ENTREGA
FINALIZADO
}
class FormaPagamento {
<<Enumeration>>
DINHEIRO
CARTAO_CREDITO
CARTAO_DEBITO
PIX
}
class Pedido {
- Cliente cliente
- PedidoStatus status
- BigDecimal valorEntrega
- boolean retira
- String endereco
- FormaPagamento formaPagamento
- String observacoes
- Instant dataHoraPedido
- List~ItemPedido~ itens
+ Getters() and Setters()
}
class ItemPedidoId {
<<Embeddable>>
- Pedido pedido
- Produto produto
+ ItemPedidoId()
+ ItemPedidoId(Pedido, Produto)
+ Getters() and Setters()
+ hashCode()
+ equals()
}
class ItemPedido {
- ItemPedidoId id
- Integer quantidade
- BigDecimal valorUnitarioOriginal
- BigDecimal valorUnitarioDesconto
+ Getters() and Setters()
}
class DiaSemana {
<<Enumeration>>
DOMINGO
SEGUNDA
TERCA
QUARTA
QUINTA
SEXTA
SABADO
+ from(DayOfWeek)
}
class Funcionamento {
- DiaSemana diaSemana
- Time horaInicio
- Time horaFim
+ Getters() and Setters()
}
class FuncionamentoEspecialTipo {
<<Enumeration>>
ABERTO
FECHADO
}
class FuncionamentoEspecial {
- String nome
- Instant dataInicio
- Instant dataFim
- FuncionamentoEspecialTipo tipo
+ Getters() and Setters()
}
Cliente -- BasicEntity : herda
Endereco -- BasicEntity : herda
Grupo -- BasicEntity : herda
Produto -- BasicEntity : herda
Pedido -- BasicEntity : herda
FuncionamentoEspecial -- BasicEntity : herda
Pedido -- PedidoStatus : contém
Pedido -- FormaPagamento : contém
Cliente "1" -- "0..*" Endereco : possui
Grupo "1" -- "0..*" Produto : contém
Pedido "1" -- "0..*" Cliente : pertence
ItemPedidoId "1" -- "1" ItemPedido : inclui
ItemPedido "1" -- "0..*" Pedido : inclui
Funcionamento -- DiaSemana : possui
FuncionamentoEspecial -- FuncionamentoEspecialTipo : possui
sequenceDiagram
actor Cliente
participant Aplicativo
participant API
actor Atendente
Cliente->>+Aplicativo: Cliente acessa aplicativo
Aplicativo->>+Cliente: Loja em funcionamento disponibiliza menu
Cliente->>+Aplicativo: Escolhe item do menu
Cliente->>+Aplicativo: Adiciona produto com quantidade ao carrinho
Aplicativo->>+Cliente: Retorna tela do carrinho
Cliente->>+Aplicativo: Informa nome e telefone
Cliente->>+Aplicativo: Informa opção de entrega e endereço
Cliente->>+Aplicativo: Informa modo de pagamento
Cliente->>+Aplicativo: Faz o pedido
Aplicativo->>+API: Encaminha o pedido
API->>+Aplicativo: Retorna pedido efetuado
API->>+Atendente: Informa pedido novo
Atendente->>+API: Atualiza status pedido
Cliente->>+Aplicativo: Consulta pedido
Aplicativo->>+API: Consulta Status Pedido
API->>+Aplicativo: Retorna Status Pedido
Aplicativo->>+Cliente: Informa status pedido
erDiagram
EMPRESA {
SMALLINT id PK
VARCHAR nome
VARCHAR email
VARCHAR telefone
DECIMAL valor_entrega
TIME tempo_entrega
VARCHAR cep
VARCHAR logradouro
INTEGER numero
VARCHAR complemento
VARCHAR bairro
VARCHAR cidade
VARCHAR estado
DECIMAL longitude
DECIMAL latitude
}
CLIENTE {
BIGINT id PK
VARCHAR nome
VARCHAR telefone
}
ENDERECO {
BIGINT id PK
BIGINT cliente_id FK
VARCHAR nome
VARCHAR cep
VARCHAR logradouro
INTEGER numero
VARCHAR complemento
VARCHAR bairro
VARCHAR cidade
VARCHAR estado
DECIMAL longitude
DECIMAL latitude
}
GRUPO {
BIGINT id PK
VARCHAR nome
VARCHAR descricao
}
PRODUTO {
BIGINT id PK
VARCHAR codigo
VARCHAR nome
VARCHAR descricao
VARCHAR imagem
DECIMAL valor_original
DECIMAL valor_desconto
BOOLEAN enabled
BIGINT grupo_id FK
}
PEDIDO {
BIGINT id PK
BIGINT cliente_id FK
VARCHAR status
DECIMAL valor_entrega
BOOLEAN retira
VARCHAR endereco
VARCHAR forma_pagamento
VARCHAR observacoes
TIMESTAMP data_hora_pedido
}
ITEM_PEDIDO {
BIGINT pedido_id PK
BIGINT produto_id PK
INTEGER quantidade
DECIMAL valor_unitario_original
DECIMAL valor_unitario_desconto
}
FUNCIONAMENTO {
VARCHAR dia_semana PK
TIME hora_inicio
TIME hora_fim
}
FUNCIONAMENTO_ESPECIAL {
BIGINT id PK
VARCHAR nome
TIMESTAMP data_inicio
TIMESTAMP data_fim
VARCHAR tipo
}
CLIENTE ||--|{ ENDERECO : possui
GRUPO ||--o{ PRODUTO : "contém"
PEDIDO ||--o| CLIENTE : pertence
ITEM_PEDIDO ||--o| PEDIDO : inclui
ITEM_PEDIDO ||--|{ PRODUTO : "contém"
%% Triggers
ITEM_PEDIDO ||--|{ prevent_delete_or_update_item_pedido_trigger : "prevenção de delete/update"
PEDIDO ||--|{ prevent_delete_pedido_trigger : "prevenção de delete"
PEDIDO ||--|{ allow_update_status_only_trigger : "permitir update apenas no status"
Os testes foram feitos utilizando JUnit 5, Mockito e MockMVC com Hamcrest.
Para executar os testes pode executar sua IDE ou
Utilizando o terminal (PowerShell, Bash ou similiar), basta executar na pasta do projeto o comando abaixo:
./mvnw clean verify -Dspring.profiles.active=test
Antes de mais nada, é preciso possuir no mínimo JDK 21 LTS instalado na máquina em que irá executar. A execução do projeto pode ser feita utilizando recurso de sua IDE ou com comando (demonstrado no próximo item).
Antes de executar é preciso ter atenção e configurar as variáveis de ambiente:
SPRING_PROFILES_ACTIVE
: Ambiente de desenvolvimento ou produçãoPGHOST
: Host PostgresPGPORT
: Porta PostgresPGDATABASE
: Nome do database PostgresPOSTGRES_USER
: Usuário PostgresPOSTGRES_PASSWORD
: Senha PostgresQUICKCUP_API_KEY
: Chave de acesso da APIQUICKCUP_USERS_DEFAULT_PASSWORD
: Senha padrão para os usuários do painel administrativoCROSS_ORIGIN_URLS
: URLs para configurar o CORS para acesso de aplicativos externos aos endpoints REST APILINK_FORMULARIO_TESTES
: URL para acessar o formulário de testes (para carregar no index do painel administrativo, não afeta o funcionamento da aplicação)LINK_APLICACAO_CLIENTE
: URL para acessar a aplicação do cliente (para carregar no index do painel administrativo, não afeta o funcionamento da aplicação)
Para facilitar eu deixei o arquivo .env.sample
com as variáveis de ambiente. Basta renomear para .env
para que a aplicação
carregue as informações das variáveis de ambiente.
Para a aplicação hospedada no Railway, além de definir as variáveis de ambiente mínimas para a aplicação é necessário definir a variável de ambiente abaixo:
NIXPACKS_JDK_VERSION
: Variável de ambiente para definir a versão do JDK, no caso desse projeto é21
.
Essa aplicação depende do Postgres para funcionar, acima existem variáveis de ambiente para configurar o acesso ao banco de dados.
Caso já possua um banco de dados Postgres, basta ajustar as variáveis de ambiente para acessá-lo.
Nesse projeto utilizamos o Postgres Docker Compose para facilitar a execução do projeto localmente sem necessitar de ter o Postgres instalado
ou configurado. Para executar o Postgres Docker Compose, basta executar na pasta do projeto o comando abaixo:
docker compose up
O docker compose também está preparado para ler as informações do arquivo .env
mencionado no item anterior, isso facilita a integração da
aplicação com o banco de dados já que ambas utilizando variáveis de ambiente em comum.
No docker compose docker-compose.yml
também foi configurado para subir uma instancia do pgadmin para que se possa
ter acesso visual ao banco Postgres.
Depois de configurar as variáveis de ambiente e executar o Postgres Docker Compose (ou ter considerado as configurações de seu Postgres), digite no terminal:
- PowerShell:
./mvnw spring-boot:run
- Bash:
./mvnw spring-boot:run
- CMD:
mvnw spring-boot:run
Quando a aplicação estiver no ar, é possível acessar a documentação da API com endpoints REST utilizando o Swagger OpenAPI v3.1 através do link: http://localhost:8080/swagger-ui/index.html
Para popular dados básicos no banco de dados ao iniciar o projeto, foi criada a migration do FlyWay V999__Initial_Inserts.sql.
Esse projeto foi implantado no Railway que faz integração com o repositório do GitHub. URL da aplicação: https://quickcup-api.zancanela.dev.br
Feito com ❤️ e dedicação por Luis Zancanela