Consiste em uma API HTTP (JSON) de e-commerce (venda online) e tem um endpoint de carrinho (checkout). Esse endpoint aceitará uma requisição com método POST, a estrutura do payload de requisição que segue o exemplo:
Em resumo a requisição deve conter uma lista de produtos e a quantidade de cada um a ser comprado.
{
"products": [
{
"id": 1,
"quantity": 1 // Quantidade a ser comprada do produto
}
]
}A API conta com as seguintes regras de negócio:
-
Para cada produto é calculada a porcentagem de desconto e isso é feito consumindo um serviço gRPC fornecido pela Hash, disponível em uma imagem Docker e o cliente foi gerado em Javascript a partir do arquivo proto
-
Caso o serviço de desconto esteja indisponível o endpoint de carrinho deverá continuar funcionando porém não vai realizar o cálculo com desconto.
-
É verificado se é black friday e caso seja, um produto brinde pode ser adicionado no carrinho. No arquivo products.json eles estão marcados com a flag
is_gift = truee não são aceitos em requisições para adicioná-los ao carrinho. A data da Black Friday pode ser configurada através de um arquivo .env, um arquivo exemplo foi anexado ao repositório para verificação de como setar as variáveis de ambiente. -
Há apenas uma entrada de produto brinde no carrinho.
Abaixo segue um exemplo de resposta com status HTTP 200 da API:
{
"total_amount": 20000, // Valor total da compra sem desconto
"total_amount_with_discount": 19500, // Valor total da compra com desconto
"total_discount": 500, // Valor total de descontos
"products": [
{
"id": 1,
"quantity": 2,
"unit_amount": 10000, // Preço do produto em centavos
"total_amount": 20000, // Valor total na compra desse produto em centavos
"discount": 500, // Valor total de desconto em centavos
"is_gift": false // É brinde?
},
{
"id": 3,
"quantity": 1,
"unit_amount": 0, // Preço do produto em centavos
"total_amount": 0, // Valor total na compra desse produto em centavos
"discount": 0, // Valor total de desconto em centavos
"is_gift": true // É brinde?
}
]
}- Node.js
- Scripts de teste na API foram escritos através do framework Jest
- Docker
- Docker-Compose
- NPM 8.5 ou superior
- Node 12.22 ou superior
- Docker 19.x ou superior
- Docker-Compose 1.26 ou superior
git clone https://github.com/felipedmsantos95/cart-gRPC-api
cd cart-gRPC-apiConsiderando que os requisitos para rodar a aplicação estejam satisfeitos, podemos executar os seguintes comandos:
Antes de execução dos comandos docker, precisamos configurar um .env na raiz do projeto, as variáveis devem ser configuradas seguindo o exemplo
touch .envModelo de conteúdo do arquivo:
# --------- #
## GENERAL ##
# --------- #
PROJECT_NAME=hash-cart-challenge
# You can change to run API in another HTTP port
API_PORT=3000
# --------- #
## gRPC ##
# --------- #
#If it is running in your local machine, please input IP address of your machine
GRPC_SERVER_ADDRESS=your_ip_server_address:50051
# -------------------#
## Bussiness Rules ##
# ------------------ #
# Date format ==> year/month/day
BLACK_FRIDAY_DAY=2022/02/16Para baixar as imagens docker necessárias e executar os containers com a API e o serviço de desconto da Hash:
docker-compose upEssa deve ser a sáida do terminal e a API estará pronta para receber requisições:
npm installExecutar serviço:
npm startExecutar serviço com reinício automático se for detectada alteração no código:
npm run devExecutar script de testes unitários e de integração da aplicação
npm test docker pull hashorg/hash-mock-discount-service
docker run -p 50051:50051 hashorg/hash-mock-discount-servicePOST /checkout: A rota deve receberproductsdentro do corpo da requisição, sendo sendo ele um array de objetos que por sua vez contém os campos numéricosidequantity, nesta rota também pode ser enviado nos headers a informaçãotoday_dateno formatoyyyy/mm/ddpara que o app possa comparar com o dia da Black Friday configurado no.env, se nenhum header for enviado, o app irá comparar a data da Black Friday configurada no .env automaticamente com a data de hoje.
GET /products: Exibe os produtos cadastrados no products.json.
Ao ter instaladas as dependências necessárias para rodar os testes, pode ser executado o comando npm test no teminal para que sejam vistas as seguintes validações que foram escritas no arquivo cart.spec.js
-
should be able to checkout cart with valid products: Permite que seja exibido o valor total do carrinho se a requisição for válida. -
shouldn't be able to checkout with params with invalid data type: Não permite que o seja feito checkout se um array de produtos no formato especificado não for enviado na requisição -
shouldn't be able to checkout with invalid products: Não permite que seja feito checkout se no carrinho houver um produto não cadastrado -
shouldn't be able to checkout with missing params: Não permite que seja feito checkout se no corpo da requisição houver parametros faltantes -
should be able to get all products info at database: Permite que sejam exibidos os produtos descritos em products.json -
should be able to add a gift product if it is Black Friday: Permite que seja feito checkout de um produto com a flagis_giftse for dia de Black Friday -
shouldn't be able to add more than one gift product input if it is Black Friday: Não permite que seja feito checkout de mais de um produto com a flagis_giftse for dia de Black Friday -
shouldn't be able to add more than one gift product in quantity if it is Black Friday: Não permite que seja feito produto com a flagis_giftcom o campoquantitymaior que 1 -
shouldn't be able to add gift product if it is NOT Black Friday: Não permite que seja feito checkout de um produto com a flagis_giftse não for dia de Black Friday
Para validar a regra 2 no desafio proposto, onde se pede que caso o serviço de desconto esteja indisponível o endpoint de carrinho deverá continuar funcionando porém não vai realizar o cálculo com desconto, foi feito o seguinte procedimento:
- API e Serviço de desconto em execução
- Parada do serviço de desconto
- Execução do checkout
- Status 200
{
"total_amount": 223715,
"total_amount_with_discount": 221583,
"total_discount": 2132,
"products_details": [
{
"id": 5,
"quantity": 1,
"unit_amount": 42647,
"total_amount": 42647,
"discount": 2132,
"is_gift": false
},
{
"id": 3,
"quantity": 3,
"unit_amount": 60356,
"total_amount": 181068,
"discount": 0,
"is_gift": false
}
]
}- Corpo da requisição inválido
{
"statusCode": 400,
"error": "Bad Request",
"message": "Validation failed",
"validation": {
"body": {
"source": "body",
"keys": [
"products.0.id"
],
"message": "\"id\" é um campo obrigatório"
}
}
}- Produto brinde em uma data não Black Friday
{
"validation": {
"message": [
"O produto de id 6 é um brinde de black friday e não pode ser adicionado ao carrinho por enquanto..."
]
}
}- Produto não cadastrado no banco de dados
{
"validation": {
"message": [
"O produto de id 50 não está cadastrado em nosso banco de dados",
"O produto de id 55 não está cadastrado em nosso banco de dados"
]
}
}- Mais de uma entrada de produtos brinde na black friday
{
"validation": {
"message": [
"Só pode haver a quantidade de 1 produto brinde na blackfriday."
]
}
}



