👨💻 Descrição do projeto
O projeto é uma API RESTful com arquitetura MSC que consiste em um sistema de gerenciamento de vendas no formato dropshipping, onde é possível criar, visualizar, deletar e atualizar produtos e vendas em um banco de dados MySQL, também foram desenvolvidos testes unitários para todos os arquivos e funções de cada camada da aplicação.
📝 Detalhes do desenvolvimento
Nesse projeto foi utilizado Node.js com Express para o desenvolvimento da aplicação, foi utilizado express-rescue para capturar os erros não previstos nas rotas desenvolvidas e encaminhar para um middleware de error que exibi uma mensagem padrão para o usuário, para vailidação de dados foi utilizado o Joi, MySQL para o banco de dados e mocha, chai e sinon para os testes unitários.
Requisitos desenvolvidos:
- Criados os endpoints
/products
e/products/:id
para listar produtos; - Criado o endpoint
/products
para cadastrar produtos; - Criado validações para as informações recebidas no
body
da requisição para cadastrar um produto; - Criado o endpoint
/sales
para cadastrar vendas realizadas; - Criado validações para as informações recebidas no
body
da requisição para cadastrar uma venda; - Criados os endpoints
/sales
e/sales/:id
para listar vendas; - Criado o endpoint
/products/:id
para atualizar um produto; - Criado validações para as informações recebidas no
body
da requisição para atualizar um produto; - Criado o endpoint
/products/:id
para deletar um produto; - Criado o endpoint
/sales/:id
para deletar uma venda; - Criado o endpoint
/sales/:id
para atualizar uma venda; - Criado o endpoint
/products/search
para trazer produtos pelo nome enviado na url da requisição; - Criado testes para 100% de cobertura das camadas da aplicação.
🎲 Diagrama de entidades e relacionamentos
O banco terá três tabelas:
- A tabela
products
, com os atributosid
ename
; - A tabela
sales
, com os atributosid
edate
; - A tabela
sales_products
, com os atributossale_id
,product_id
equantity
;
A tabela products
tem o seguinte formato: (O id é gerado automaticamente)
A tabela sales
tem o seguinte formato: (O id e date são gerados automaticamente)
A tabela sales_products
, é a tabela que faz o relacionamento N:N
entre products
e sales
e tem o seguinte formato: (O produto e a venda são deletados automaticamente)
📖 Documentação
http://localhost:3000
▶️ Rotas para Produtos
Lista todos os produtos cadastrados no banco de dados
Os produtos possuem id
e nome
.
Os retornos seguem os formatos abaixo:
Ok
- Retorna todos os produtos cadastrados no banco de dados - Response status200
(application/json):
[
{
"id": 1,
"name": "Martelo de Thor",
},
{
"id": 2,
"name": "Traje de encolhimento",
}
/* ... */
]
Not found
- Quando não há produtos cadastrados no banco de dados - Response status404
(application/json):
{ "message": "Products not found" }
Lista apenas o produto com o id
presente na URL
O produto possui id
e nome
.
Os retornos seguem os formatos abaixo:
Ok
- Retorna o produto encontrado no banco de dados - Response status200
(application/json):
{
"id": 1,
"name": "Martelo de Thor",
}
Not found
- Quando o produto não está cadastrado no banco de dados - Response status404
(application/json):
{ "message": "Product not found" }
Lista os produtos conforme o parametro presente na URL
O produto possui id
e nome
.
O query params da requisição deverá seguir o seguinte formato:
http://localhost:PORT/products/search?q=nome_do_produto_para_pesquisa
Os retornos seguem os formatos abaixo:
Ok
- Retorna os produtos que possuem o termo enviado na URL - Response status200
(application/json):
// GET /products/search?q=Martelo
[
{
"id": 1,
"name": "Martelo de Thor",
}
]
Ok
- Retorna todos os produtos cadastrados quando o parametro é enviado vazio - Response status200
(application/json):
// GET /products/search?q=
[
{
"id": 1,
"name": "Martelo de Thor",
},
{
"id": 2,
"name": "Traje de encolhimento",
}
/* ... */
]
Cadastra um produto no banco de dados
O nome do produto deve ser enviado no body
no seguinte formato:
{
"name": "Produto_X",
}
Os retornos seguem os formatos abaixo:
Created
- Quando o produto é cadastrado com sucesso - Response status201
(application/json):
{
"id": 4, //id criado automaticamente no momento da inserção dos dados.
"name": "ProdutoX"
}
Bad request
- Quando o nome do produto não é enviado na requisição - Response status400
(application/json):
{ "message": "\"name\" is required" }
Unprocessable Entity
- Quando o nome do produto tem menos de 5 caracteres - Response status422
(application/json):
{ "message": "\"name\" length must be at least 5 characters long" }
Atualiza o produto com o id
presente na URL
O novo nome do produto deve ser enviado no body
no seguinte formato:
{
"name": "Produto_X_Atualizado",
}
Os retornos seguem os formatos abaixo:
Ok
- Quando o produto é atualizado com sucesso - Response status200
(application/json):
{
"id": 4,
"name": "Produto_X_Atualizado"
}
Not found
- Quando o produto não está cadastrado no banco de dados - Response status404
(application/json):
{ "message": "Product not found" }
Deleta o produto com o id
presente na URL
Os retornos seguem os formatos abaixo:
-
Deleted - No Content
- Quando o produto é deletado com sucesso - Response status204
. -
Not found
- Quando o produto não está cadastrado no banco de dados - Response status404
(application/json):
{ "message": "Product not found" }
▶️ Rotas para Vendas
Lista todas as vendas cadastradas no banco de dados
As vendas possuem saleId
, date
, productId
e quantity
.
Os retornos seguem os formatos abaixo:
Ok
- Retorna todas as vendas cadastradas no banco de dados - Response status200
(application/json):
[
{
"saleId": 1,
"date": "2021-09-09T04:54:29.000Z",
"productId": 1,
"quantity": 2
},
{
"saleId": 1,
"date": "2021-09-09T04:54:54.000Z",
"productId": 2,
"quantity": 2
}
/* ... */
]
Not found
- Quando não há vendas cadastradas no banco de dados - Response status404
(application/json):
{ "message": "Sales not found" }
Lista apenas a venda com o id
presente na URL
A venda possui id
, date
, productId
e quantity
.
Os retornos seguem os formatos abaixo:
Ok
- Retorna um array com os produtos e quantidades referente a venda - Response status200
(application/json):
[
{
"date": "2021-09-09T04:54:29.000Z",
"productId": 1,
"quantity": 2
},
{
"date": "2021-09-09T04:54:54.000Z",
"productId": 2,
"quantity": 2
}
/* ... */
]
Not found
- Quando a venda não está cadastrada no banco de dados - Response status404
(application/json):
{ "message": "Sale not found" }
Cadastra uma venda no banco de dados
A venda deve ser enviada no body
no seguinte formato:
[
{
"productId": 1,
"quantity":1
},
{
"productId": 2,
"quantity":5
}
]
Os retornos seguem os formatos abaixo:
Created
- Quando a venda é cadastrada com sucesso - Response status201
(application/json):
{
"id": 3,
"itemsSold": [
{
"productId": 1,
"quantity":1
},
{
"productId": 2,
"quantity":5
}
]
}
Bad request
- Quando oproductId
não é enviado na requisição - Response status400
(application/json):
{ "message": "\"productId\" is required" }
Bad request
- Quando aquantity
não é enviada na requisição - Response status400
(application/json):
{ "message": "\"quantity\" is required" }
Unprocessable Entity
- Quando o campoquantity
for menor ou igual a zero - Response status422
(application/json):
{ "message": "\"quantity\" must be greater than or equal to 1" }
Not found
- Quando oproductId
não está cadastrado no banco de dados - Response status422
(application/json):
{ "message": "Product not found" }
Atualiza a venda com o id
presente na URL
A venda atualizada deve ser enviada no body
no seguinte formato:
[
{
"productId": 1,
"quantity":10
},
{
"productId": 2,
"quantity":50
}
]
Os retornos seguem os formatos abaixo:
Ok
- Quando a venda é atualizada com sucesso - Response status200
(application/json):
{
"id": 3,
"itemsSold": [
{
"productId": 1,
"quantity":10
},
{
"productId": 2,
"quantity":50
}
]
}
Not found
- Quando a venda não está cadastrada no banco de dados - Response status404
(application/json):
{ "message": "Sale not found" }
Deleta a venda com o id
presente na URL
Os retornos seguem os formatos abaixo:
-
Deleted - No Content
- Quando a venda é deletada com sucesso - Response status204
. -
Not found
- Quando a venda não está cadastrada no banco de dados - Response status404
(application/json):
{ "message": "Sale not found" }
🐳 Rodando no docker
1.26.0
por 1.29.2
.
Clone o repositório:
git clone git@github.com:WBomfim/Store-Manager.git
Entre na pasta do repositório:
cd Store-Manager
Rode os serviços node
e db
:
docker-compose up -d
- Lembre-se de parar o
mysql
se estiver usando localmente na porta padrão (3306
), ou adapte, caso queria fazer uso da aplicação em containers; - Esses serviços irão inicializar um container chamado
store_manager
e outro chamadostore_manager_db
; - A partir daqui você pode rodar o container
store_manager
via CLI ou abri-lo no VS Code.
Acesse o terminal interativo do container criado pelo compose:
docker exec -it store_manager bash
Instale as dependências dentro do container:
npm install
package.json
(npm start, npm run test:mocha, ...) devem ser executados DENTRO do container, ou seja, no terminal que aparece após a execução do comando docker exec
citado acima.
Crie o banco de dados e gere as tabelas:
npm run migration
Limpe e popule o banco de dados:
npm run seed
Inicie o servidor Node:
npm start
💻️ Rodando localmente
Clone o repositório:
git clone git@github.com:WBomfim/Store-Manager.git
Entre na pasta do repositório:
cd Store-Manager
Instale as dependências:
npm install
.env.example
com as variáveis de ambiente.
Node.js
instalado em seu computador.
Node.js
e NPM
a ser utilizada é "node": ">=16.0.0"
e "npm": ">=7.0.0"
, como descrito a chave engines
no arquivo package.json
. Idealmente deve-se utilizar o Node.js na versão 16.14
, a versão na que esse projeto foi testado.
➡️ Variáveis de ambiente
Caso opte por rodar a aplicação localmente, na raiz do projeto renomeie o arquivo .env.example
para .env
e altere as variáveis de ambiente com seus dados locais. Por exemplo, caso o seu usuário SQL seja nome
e a senha 1234
seu arquivo ficará desta forma:
MYSQL_HOST=localhost
MYSQL_USER=nome
MYSQL_PASSWORD=1234
MYSQL_DATABASE=StoreManager
PORT=3000
⏩️ Scripts
Criar o banco de dados e gerar as tabelas:
npm run migration
Limpar e popular o banco de dados:
npm run seed
Iniciar o servidor Node:
npm start
Iniciar o servidor Node com nodemon:
npm run debug
Executar os testes de unidade:
npm run test:mocha
🕵🏿 Revisões futuras
- Revisar as funções para possíveis otimizações.
🚀 Próximas implementações
- Implementar testes de integração para garantir a interação de todas as funcionalidades da aplicação e tornar o ambiente mais robusto para as próximas alterações.