API Shop-Orders

API para listagem de produtos e cadastro de pedidos.

📜 Sumário

  1. Detalhes do projeto
  2. Tecnologias usadas
  3. Para rodar o projeto
  4. Documentação
  5. Autor

1. 🔍 Detalhes do projeto

A API Shop-Orders tem como objetivo persistir dados para gerenciamento de pedidos com base em um estoque de produtos. Foi realizado academicamente durante o Bootcamp Java Academy, iniciativa da Ada em parceria com a Avanade.

Cenário:

  • Sistema permite o cadastro de usuário, com validação de informações;
  • Sistema recupera e armazena, caso a tabela de produtos esteja vazia, os produtos da API externa: https://dummyjson.com/products/search?q=phone
  • Sistema permite apenas as requisições de listagem de produtos, detalhes de produto, cadastro de usuário e login sem autenticação por meio de JWT;
  • Com usuário logado, o sistema permite a criação de pedido, validando o estoque de produtos antes de armazenar o pedido;
  • Sistema atualiza o estoque automaticamente e encaminha e-mail de confirmação do pedido ao usuário;

2. 💻 Tecnologias usadas

Languages, Frameworks & Librarys:
Java SpringBoot Hibernate JSON JWT

Tests:
Insomnia JUnit

Database:
PostgreSQL

IDE:
Intellij

3. 🔌 Para rodar o projeto

  1. Instale as dependências necessárias com o Maven para rodar a API (relacionadas no pom.xml):

    mvn dependency:copy-dependencies
    
  2. A API utiliza o PostgreSQL como banco de dados, então se faz necessário que você tenha-o instalado em sua máquina.

  3. Com ele instalado, crie um database e preencha o arquivo "application.proporties" com a url (colocando o nome do database criado no local indicado), username e password.

    spring.datasource.url=jdbc:mysql://localhost/{nomedatabase}
    spring.datasource.username={username}
    spring.datasource.password={password}
    
  4. Rode a aplicação que o sistema já irá criar as tabelas e popular a tabela produtos automaticamente, deixando-as prontas para uso. Por padrão, a aplicação rodará na porta 8080.

  5. Você precisará de uma ferramenta de teste de requisições como o Insomnia ou utilizar o Swagger-Ui, devendo seguir as orientações da documentação abaixo para utilizar a API.

  6. Você pode rodar os testes automatizados criados com JUnit, caso queira (mais testes em desenvolvimento).

4. 🔌 Documentação

Endpoints

Auth
POST /auth/ - Autenticação de usuário (login)

User
GET /user/ - Listagem de usuários (Rota apenas para Admin)
GET /user/:id - Detalhamento de um usuário
POST /user/ - Criação de um novo usuário
PATCH /user/:id - Atualização de dados de um usuário
PATCH /user/admin/:id - Conceder credencial de Admin para usuário (Rota apenas para Admin)
DELETE /user/:id - Deleção de um usuário (Rota apenas para Admin)

Address
GET /address/:id - Detalhamento de um endereço
POST /address/ - Criação de um novo endereço
PUT /address/:id - Atualização de dados de um endereço
DELETE /address/:id - Deleção de um endereço

Product
GET /product/ - Listagem de produtos com parâmetros
GET /product/:id - Detalhamento um de produto
POST /product/ - Criação de um novo produto (Rota apenas para Admin)
PUT /product/:id - Atualização de dados de um produto (Rota apenas para Admin)
DELETE /product/:id - Deleção de um produto (Rota apenas para Admin)

Order
GET /order/ - Listagem de pedidos (Rota apenas para Admin)
GET /order/:id - Detalhamento de um pedido
POST /order/ - Criação de um novo pedido
DELETE /order/:id - Deleção de um pedido (Rota apenas para Admin)

POST auth

Request

Nome Obrigatório Tipo Descrição
username sim string Username do usuário
password sim string Senha do usuário

NOTA: Não é necessário enviar Token JWT via Authorization Header.


Response

Sucesso

{
  "type": "Bearer",
  "token": "abcdefghijklmnopqrstuvwxyz"
}

status: 200

Erro comum

{
    "message": "Authentication failed."
}

status: 401

GET user

Request

Listar todos os usuários

Nome Obrigatório Tipo Descrição
- - - Não é necessário enviar nenhum parâmetro

NOTA: É necessário enviar Token JWT via Authorization Header (rota exclusiva de administrador).


Response

Sucesso

[
   {
      "id": 1,
      "name": "Fulano",
      "username": "fulano",
      "cpf": "12345678910",
      "email": "fulano@email.com",
      "phone": "11999998888",
      "registerDate": "2023-08-25T21:00:00.000000",
      "addresses": null,
      "orders": null
   },
   {
      "id": 2,
      "name": "Beltrano",
      "username": "beltrano",
      "cpf": "98765432101",
      "email": "beltrano@email.com",
      "phone": "1133330000",
      "registerDate": "2023-08-25T21:30:00.000000",
      "addresses": null,
      "orders": null
   }
]

status: 200



Sucesso sem retorno de dados

[]

status: 200

GET user-id

Request

Detalhar um usuário

Nome Obrigatório Tipo Descrição
id sim number Enviar via parâmetro de rota

NOTA: É necessário enviar Token JWT via Authorization Header.


Response

Sucesso

{
   "id": 1,
   "name": "Fulano",
   "username": "fulano",
   "cpf": "12345678910",
   "email": "fulano@email.com",
   "phone": "11999998888",
   "registerDate": "2023-08-25T21:00:00.000000",
   "addresses": [
      {
         "id": 1,
         "street": "Rua 1",
         "number": "111, apto 01",
         "postalCode": "12345678",
         "city": "Cidade",
         "state": "Estado",
         "country": "País",
         "userId": 1
      }
   ],
   "orders": [
      {
         "id": 1,
         "userId": 1,
         "orderDate": "2023-08-25T22:45:06.786814",
         "totalPrice": 99100,
         "orderItems": [
            {
               "id": 1,
               "orderId": 1,
               "productId": 2,
               "qty": 1
            },
            {
               "id": 2,
               "orderId": 1,
               "productId": 3,
               "qty": 2
            }
         ]
      }
   ]
}

status: 200



Erro comum

{
   "message": "User not found."
}

status: 404


POST user

Criar um usuário

Request

Nome Obrigatório Tipo Descrição
name sim string Nome para perfil
username sim string Username do usuário
password sim string Senha do usuário
cpf sim string CPF do usuário
email sim string E-mail do usuário
phone sim string Telefone do usuário
address não object Endereço do usuário

Caso o endereço seja cadastrado junto com o registro do usuário, deve seguir os seguintes parâmetros:

Nome Obrigatório Tipo Descrição
street não string Rua/Avenida
number sim string Número com complemento
postalCode sim string CEP
city não string Cidade
state não string Estado
country não string País

Exemplo de requisição:

{
   "name": "Fulano",
   "username": "fulano",
   "password": "password",
   "cpf": "12345678910",
   "email": "fulano@email.com",
   "phone": "11999998888",
   "address": {
      "street": "Rua 1",
      "number": "111 apto 11",
      "postalCode": "12345678",
      "city": "Cidade 1",
      "state": "Estado 1",
      "country": "País 1"
   }
}

NOTA: Não é necessário enviar Token JWT via Authorization Header.


Response

Sucesso

{
   "id": 1,
   "name": "Fulano",
   "username": "fulano",
   "cpf": "12345678910",
   "email": "fulano@email.com",
   "phone": "11999998888",
   "registerDate": "2023-08-25T21:00:00.000000",
   "addresses": [
      {
         "id": 1,
         "street": "Rua 1",
         "number": "111, apto 01",
         "postalCode": "12345678",
         "city": "Cidade",
         "state": "Estado",
         "country": "País",
         "userId": 1
      }
   ],
   "orders": []
}

status: 201

Erros comuns

{
   "message": "User already exists."
}

status: 400

{
   "errors": [
      "invalid Brazilian individual taxpayer registry number (CPF)"
   ]
}

status: 400

{
   "field": "password",
   "message": "The password must have at least 8 characters"
}

status: 400

PATCH user

Request

Editar um usuário. Apenas nome, email e telefone poder ser editados.

Nome Obrigatório Tipo Descrição
id sim number ID do produto que será atualizado (recebido como parâmetro de rota)
name não string Nome do usuário
email não string Email do usuário
phone não string Telefone do usuário

NOTA: É necessário enviar Token JWT de Admin via Authorization Header.


Response

Sucesso

{
   "id": 1,
   "name": "Fulano Editado",
   "username": "fulano",
   "cpf": "12345678910",
   "email": "fulano.editado@email.com",
   "phone": "11999998888",
   "registerDate": "2023-08-25T21:00:00.000000",
   "addresses": [
      {
         "id": 1,
         "street": "Rua 1",
         "number": "111, apto 01",
         "postalCode": "12345678",
         "city": "Cidade",
         "state": "Estado",
         "country": "País",
         "userId": 1
      }
   ],
   "orders": [
      {
         "id": 1,
         "userId": 1,
         "orderDate": "2023-08-25T22:45:06.786814",
         "totalPrice": 99100,
         "orderItems": [
            {
            "id": 1,
            "orderId": 1,
            "productId": 2,
            "qty": 1
            },
            {
            "id": 2,
            "orderId": 1,
            "productId": 3,
            "qty": 2
            }
        ]
      }
   ]
}

status: 200

Erros comuns

{
   "message": "User not found."
}

status: 404

PATCH user-admin-id

Request

Conceder credencial de Admin para um usuário

Nome Obrigatório Tipo Descrição
id sim number Enviar via parâmetro de rota

NOTA: É necessário enviar Token JWT via Authorization Header.


Response

Sucesso no body returned for response
status: 200



Erro comum

{
   "message": "User not found."
}

status: 404


DELETE user

Deletar um usuário

Request

Nome Obrigatório Tipo Descrição
id sim number ID do produto que será deletado (recebido como parâmetro de rota)

NOTA: É necessário enviar Token JWT de Admin via Authorization Header (rota exclusiva de administrador).


Response

Sucesso
no body returned for response
status: 204

Erro comum

{
   "message": "User not found."
}

status: 404

GET address

Request

Detalhar endereço

Nome Obrigatório Tipo Descrição
id sim number Enviar via parâmetro de rota

NOTA: É necessário enviar Token JWT via Authorization Header.


Response

Sucesso

{
   "id": 1,
   "street": "Rua 1",
   "number": "111, apto 01",
   "postalCode": "12345678",
   "city": "Cidade",
   "state": "Estado",
   "country": "País",
   "userId": 1
}

status: 200



Erro comum

{
   "message": "Address not found."
}

status: 404

POST address

Cadastrar um endereço

Request

Nome Obrigatório Tipo Descrição
userId sim number Id do usuário que o endereço pertence
street não string Rua/Avenida
number sim string Número com complemento
postalCode sim string CEP
city não string Cidade
state não string Estado
country não string País

NOTA: É necessário enviar Token JWT de Admin via Authorization Header.


Response

Sucesso

{
   "id": 2,
   "street": "Rua 2",
   "number": "222, apto 02",
   "postalCode": "87654321",
   "city": "Cidade",
   "state": "Estado",
   "country": "País",
   "userId": 1
}

status: 201

Erros comuns

{
   "message": "User not found."
}

status: 404

[
   {
      "field": "number",
      "message": "must not be blank"
   }
]

status: 400

PUT address

Editar um endereço

Request

Nome Obrigatório Tipo Descrição
userId sim number Id do usuário (recebido por parâmetro)
street não string Rua/Avenida
number sim string Número com complemento
postalCode sim string CEP
city não string Cidade
state não string Estado
country não string País

NOTA: É necessário enviar Token JWT de Admin via Authorization Header.


Response

Sucesso

{
   "id": 2,
   "street": "Rua 22",
   "number": "444, apto 04",
   "postalCode": "87654321",
   "city": "Cidade",
   "state": "Estado",
   "country": "País",
   "userId": 1
}

status: 200

Erros comuns

{
   "message": "Address not found."
}

status: 404

{
   "message": "User not found."
}

status: 404

DELETE address

Request

Nome Obrigatório Tipo Descrição
id sim number ID do produto que será deletado (recebido por parâmetro)

NOTA: É necessário enviar Token JWT de Admin via Authorization Header.


Response

Sucesso
no body returned for response
status: 204

Erro comum

{
   "message": "Address not found."
}

status: 404

GET products

Listar produtos (pode receber filtros)

Request

Nome Obrigatório Tipo Descrição
title não string Nome do produto a ser pesquisado
brand não string Marca do produto a ser pesquisado
category não string Categoria do produto a ser pesquisado

Response

Sucesso

[
   {
      "id": 1,
      "title": "Produto 1",
      "description": "Qualquer coisa",
      "price": 2000,
      "stock": 50,
      "brand": "Marca 1",
      "category": "Eletronico"
   },
   {
      "id": 2,
      "title": "Produto 2",
      "description": "Qualquer coisa 2",
      "price": 4000,
      "stock": 70,
      "brand": "Marca 2",
      "category": "Vestuario"
   }
]

status: 200



Sucesso sem retorno de dados

[]

status: 200

GET products-id

Detalhar um produto

Request

Nome Obrigatório Tipo Descrição
id sim number Enviar via parâmetro de rota

NOTA: É necessário enviar Token JWT via Authorization Header.


Response

Sucesso

{
   "id": 3,
   "title": "Produto 3",
   "description": "Qualquer coisa 3",
   "price": 1000,
   "stock": 10,
   "brand": "Marca 3",
   "category": "Eletronico"
}

status: 200



Erro comum

{
   "message": "Product not found."
}

status: 404


POST products

Cadastrar um produto

Request

Nome Obrigatório Tipo Descrição
title sim string Nome do produto
description sim string Descrição do produto
price sim number Preço do produto
stock sim number Estoque do produto
brand sim string Marca do produto
category sim string Categoria do produto

NOTA: É necessário enviar Token JWT de Admin via Authorization Header (rota exclusiva de administrador).


Response

Sucesso

{
   "id": 4,
   "title": "Produto 4",
   "description": "Qualquer coisa",
   "price": 52000,
   "stock": 5,
   "brand": "Marca 4",
   "category": "Mobiliario"
}

status: 201

Erros comuns

[
   {
      "field": "price",
      "message": "must be greater than or equal to 1"
   }
]

status: 400

{
    "message": "Product already exist"
}

status: 400

PUT products

Editar um produto

Request

Nome Obrigatório Tipo Descrição
title não string Nome do produto
description não string Descrição do produto
price não number Preço do produto
stock não number Estoque do produto
brand não string Marca do produto
category não string Categoria do produto

NOTA: É necessário enviar Token JWT de Admin via Authorization Header (rota exclusiva de administrador).


Response

Sucesso

{
   "id": 2,
   "title": "Produto 2",
   "description": "Qualquer coisa",
   "price": 2000,
   "stock": 50,
   "brand": "Marca 2",
   "category": "Eletronico"
}

status: 200

Erros comuns

{
   "message": "Product not found."
}

status: 404

[
   {
      "field": "price",
      "message": "must be greater than or equal to 1"
   }
]

DELETE products

Deletar um produto

Request

Nome Obrigatório Tipo Descrição
id sim number ID do produto que será deletado (recebido por parâmetro)

NOTA: É necessário enviar Token JWT de Admin via Authorization Header (rota exclusiva de administrador).


Response

Sucesso
no body returned for response
status: 204

Erro comum

{
   "message": "Product not found."
}

status: 404

GET order

Listar pedidos

Request

Nome Obrigatório Tipo Descrição
- - - Não é necessário enviar nenhum parâmetro

NOTA: É necessário enviar Token JWT de Admin via Authorization Header (rota exclusiva de administrador).


Response

Sucesso

[
   {
      "id": 1,
      "userId": 1,
      "orderDate": "2023-08-26T14:45:06.786814",
      "totalPrice": 50000,
      "orderItems": [
         {
            "id": 1,
            "orderId": 1,
            "productId": 2,
            "qty": 5
         },
         {
            "id": 2,
            "orderId": 1,
            "productId": 3,
            "qty": 1
         }
      ]
   },
   {
      "id": 2,
      "userId": 1,
      "orderDate": "2023-08-26T18:41:12.651864",
      "totalPrice": 100000,
      "orderItems": [
         {
            "id": 3,
            "orderId": 2,
            "productId": 5,
            "qty": 20
         },
         {
            "id": 4,
            "orderId": 2,
            "productId": 1,
            "qty": 8
         }
      ]
   }
]

status: 200


Sucesso sem retorno de dados
[]

status: 200

GET order-id

Detalhar um produto

Request

Nome Obrigatório Tipo Descrição
id sim number Enviar via parâmetro de rota

NOTA: É necessário enviar Token JWT via Authorization Header.


Response

Sucesso

{
   "id": 1,
   "userId": 1,
   "orderDate": "2023-08-26T23:59:38.468445729",
   "totalPrice": 94500,
   "orderItems": [
      {
         "id": 1,
         "orderId": 1,
         "productId": 2,
         "qty": 1
      },
      {
         "id": 2,
         "orderId": 1,
         "productId": 3,
         "qty": 1
      }
   ]
}

status: 200



Erro comum

{
   "message": "Order not found."
}

status: 404


POST order

Criar um pedido

Request

Nome Obrigatório Tipo Descrição
userId sim number Id do usuário
orderItems sim object Lista de produtos e quantidades
productId sim number Id do produto
qty sim number Quantidade do produto

Exemplo de requisição:

{
   "userId": 1,
   "orderItems": [
      {
         "productId": 2,
         "qty": 1
      },
      {
         "productId": 3,
         "qty": 1
      }
   ]
}

NOTA: É necessário enviar Token JWT de Admin via Authorization Header.


Response

Sucesso

{
   "id": 1,
   "userId": 1,
   "orderDate": "2023-08-26T23:59:38.468445729",
   "totalPrice": 94500,
   "orderItems": [
      {
         "id": 1,
         "orderId": 1,
         "productId": 2,
         "qty": 1
      },
      {
         "id": 2,
         "orderId": 1,
         "productId": 3,
         "qty": 1
      }
   ]
}

status: 201

Erros comuns

{
   "field": null,
   "message": "No stock available"
}

status: 400

{
   "message": "Product not found."
}

status: 404

{
   "message": "USer not found."
}

status: 404

DELETE products

Request

Nome Obrigatório Tipo Descrição
id sim number ID do pedido que será deletado (recebido por parâmetro)

NOTA: É necessário enviar Token JWT de Admin via Authorization Header (rota exclusiva de administrador).


Response

Sucesso
no body returned for response
status: 204

Erro comum

{
   "message": "Order not found."
}

status: 404

5. 👨‍💻 Autor

Criado por Daniel Justo

linkedin github

Obrigado pela visita!