👨💻 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
/productse/products/:idpara listar produtos; - Criado o endpoint
/productspara cadastrar produtos; - Criado validações para as informações recebidas no
bodyda requisição para cadastrar um produto; - Criado o endpoint
/salespara cadastrar vendas realizadas; - Criado validações para as informações recebidas no
bodyda requisição para cadastrar uma venda; - Criados os endpoints
/salese/sales/:idpara listar vendas; - Criado o endpoint
/products/:idpara atualizar um produto; - Criado validações para as informações recebidas no
bodyda requisição para atualizar um produto; - Criado o endpoint
/products/:idpara deletar um produto; - Criado o endpoint
/sales/:idpara deletar uma venda; - Criado o endpoint
/sales/:idpara atualizar uma venda; - Criado o endpoint
/products/searchpara 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 atributosidename; - A tabela
sales, com os atributosidedate; - A tabela
sales_products, com os atributossale_id,product_idequantity;
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_pesquisaOs 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 oproductIdnão é enviado na requisição - Response status400(application/json):
{ "message": "\"productId\" is required" }Bad request- Quando aquantitynão é enviada na requisição - Response status400(application/json):
{ "message": "\"quantity\" is required" }Unprocessable Entity- Quando o campoquantityfor menor ou igual a zero - Response status422(application/json):
{ "message": "\"quantity\" must be greater than or equal to 1" }Not found- Quando oproductIdnã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.gitEntre na pasta do repositório:
cd Store-ManagerRode os serviços node e db:
docker-compose up -d- Lembre-se de parar o
mysqlse 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_managere outro chamadostore_manager_db; - A partir daqui você pode rodar o container
store_managervia CLI ou abri-lo no VS Code.
Acesse o terminal interativo do container criado pelo compose:
docker exec -it store_manager bashInstale as dependências dentro do container:
npm installpackage.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 migrationLimpe e popule o banco de dados:
npm run seedInicie o servidor Node:
npm start💻️ Rodando localmente
Clone o repositório:
git clone git@github.com:WBomfim/Store-Manager.gitEntre na pasta do repositório:
cd Store-ManagerInstale 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 migrationLimpar e popular o banco de dados:
npm run seedIniciar o servidor Node:
npm startIniciar o servidor Node com nodemon:
npm run debugExecutar 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.



