It consists of an e-commerce (online selling) HTTP API (JSON) and has a cart (checkout) endpoint. This endpoint will accept a request with POST method, the request payload structure that follows the example:
In summary, the requisition must contain a list of products and the quantity of each to be purchased.
{
"products": [
{
"id": 1,
"quantity": 1
}
]
}
The API has the following business rules:
-
For each product, the discount percentage is calculated and this is done by consuming a gRPC service provided by Hash, available in a Docker image and the client was generated in Javascript from the proto file
-
If the discount service is unavailable, the cart endpoint should continue to work, but it will not perform the discount calculation.
-
It is verified if it is black friday and if it is, a gift product can be added to the cart. In file products.json they are
is_gift = true
flagged and are not accepted in requests to add them to the cart. The Black Friday date can be configured through an .env file, an example file was attached to this repository to check how to set the environment variables. -
There is only one gift product input in the cart.
Below is an example response with HTTP 200 status from the API:
{
"total_amount": 20000,
"total_amount_with_discount": 19500,
"total_discount": 500,
{
"id": 1,
"quantity": 2,
"unit_amount": 10000,
"total_amount": 20000,
"discount": 500,
"is_gift": false
},
{
"id": 3,
"quantity": 1,
"unit_amount": 0,
"total_amount": 0,
"discount": 0,
"is_gift": true
}
]
}
- Node.js
- API test scripts were written through Jest framework
- Docker
- Docker-Compose
- NPM 8.5 or later
- Node 12.22 or later
- Docker 19.x or later
- Docker-Compose 1.26 or later
git clone https://github.com/felipedmsantos95/cart-gRPC-api
cd cart-gRPC-api
Considering the application requirements are satisfied, we can run the following commands:
Before executing the docker commands, we need to configure an .env
in the project root, the variables must be configured following example
touch .env
File content model:
# --------- #
## 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/16
To download the necessary docker images and run the containers with the API and the Hash service discount:
docker-compose up
This should be the output of the terminal and the API will be ready to receive requests:
npm install
Run service:
npm start
Run service with automatic restart if code change is detected
npm run dev
Run application integration and unitary tests script
npm test
docker pull hashorg/hash-mock-discount-service
docker run -p 50051:50051 hashorg/hash-mock-discount-service
POST /checkout
: The route must receiveproducts
inside the body of the request, being it an array of objects that in turn contains the numeric fieldsid
andquantity
, in this route the informationtoday_date
can also be sent in the headers in theyyyy/mm/dd
format so that the app can compare with the Black Friday day configured in the.env
, if no header is sent, the app will automatically compare the Black Friday date configured in the .env with the date of today.
GET /products
: Displays the products registered in products.json.
Once you have installed the necessary dependencies to run the tests, you can run the npm test
command on the terminal to see the following validations that were written in the file cart.spec.js
-
should be able to checkout cart with valid products
: Allow the total value of the cart to be displayed as a valid request. -
shouldn't be able to checkout with params with invalid data type
: Does not allow checkout if an array of products in the specified format is not sent in the request -
shouldn't be able to checkout with invalid products
: Does not allow checkout if there is an unregistered product in the cart -
shouldn't be able to checkout with missing params
: Does not allow checkout if there are missing parameters in the request body -
should be able to get all products info at database
: Allows the products described in products.json to be displayed -
should be able to add a gift product if it is Black Friday
: Allows you to checkout a product with theis_gift
flag if it is a Black Friday day -
shouldn't be able to add more than one gift product input if it is Black Friday
: It does not allow the checkout of more than one product with theis_gift
flag if it is a Black Friday day -
shouldn't be able to add more than one gift product in quantity if it is Black Friday
: It does not allow making a product with theis_gift
flag with thequantity
field greater than 1 -
shouldn't be able to add gift product if it is NOT Black Friday
: Does not allow a product to be checked out with theis_gift
flag if it is not Black Fridayy
To validate the rule 2 in the proposed challenge, where it is asked that if the discount service is unavailable the cart endpoint should continue working but it will not perform the discount calculation, the following procedure was done:
- API and Discount Server in Execution
- Stopping discount service
- 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
}
]
}
- Invalid body
{
"statusCode": 400,
"error": "Bad Request",
"message": "Validation failed",
"validation": {
"body": {
"source": "body",
"keys": [
"products.0.id"
],
"message": "\"id\" é um campo obrigatório"
}
}
}
- is_gift product added in not Black Friday day
{
"validation": {
"message": [
"O produto de id 6 é um brinde de black friday e não pode ser adicionado ao carrinho por enquanto..."
]
}
}
- Product not found in database
{
"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"
]
}
}
- More than one is_gift product in Black Friday
{
"validation": {
"message": [
"Só pode haver a quantidade de 1 produto brinde na blackfriday."
]
}
}