Skip to content

didifive/quickcup-api

Repository files navigation

Repository language count Repository code size GitHub last commit

Made by Didi

Repository license

IntelliJ IDEA

technology Java technology Spring

QuickCup API ☕

API Back-end com Java e Spring Boot e Front-end Administrativo com Thymeleaf para delivery de uma cafeteria.

🎯 Objetivo

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

🔧 Principais Tecnologias

  • 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

🔣 Diagramas

Os diagramas foram criados na sintaxe Mermaid.

Diagrama de Classes

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
    
Loading

Diagrama de Sequencia

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
    
Loading

Diagrama de Entidade e Relacionamento

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"

Loading

📷 Prints do Projeto

🎥 Demonstração de Telas e Funcionamento

Demonstração de Telas e Funcionamento

Spring banner personalizado

Spring banner personalizado

Tela Inicial do QuickCup Admin

Tela Inicial do QuickCup Admin

Tela Atendimento Pedidos

Tela Atendimento Pedidos

Menu e Instruções conforme nível de acesso

Menu sem logar

Menu sem Logar

Tela de Login

Tela de Login

Perfil Admin

Perfil Admin - Menu Perfil Admin - Instruções

Perfil Atendente

Perfil Atendente - Menu Perfil Atendente - Instruções

Perfil Dev

Perfil Dev - Menu Perfil Dev - Instruções

Swagger QuickCup API

Swagger QuickCup API
Swagger QuickCup API Authorization With ApiKey

JaCoCo Coverage

JaCoCo Coverage

Variáveis de Ambiente configuradas no Railway:

Railway Environments Variables


✔️ Testes

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

⚙ Executando o projeto localmente

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).

🌍 Variáveis de Ambiente

Antes de executar é preciso ter atenção e configurar as variáveis de ambiente:

  • SPRING_PROFILES_ACTIVE: Ambiente de desenvolvimento ou produção
  • PGHOST: Host Postgres
  • PGPORT: Porta Postgres
  • PGDATABASE: Nome do database Postgres
  • POSTGRES_USER: Usuário Postgres
  • POSTGRES_PASSWORD: Senha Postgres
  • QUICKCUP_API_KEY: Chave de acesso da API
  • QUICKCUP_USERS_DEFAULT_PASSWORD: Senha padrão para os usuários do painel administrativo
  • CROSS_ORIGIN_URLS: URLs para configurar o CORS para acesso de aplicativos externos aos endpoints REST API
  • LINK_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.

🌍 Variáveis de Ambiente no Railway

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.

🐘 Postgres Docker Compose

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.

⚡ Executando

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

📚 OpenApi / Swagger

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

👪 Populate

Para popular dados básicos no banco de dados ao iniciar o projeto, foi criada a migration do FlyWay V999__Initial_Inserts.sql.

☁️ Deploy na Nuvem

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