Project Info View here
On the POST request to http://localhost:5000/api/calculate-price
, calculatePrice
controller code is called for calculating the total cost of food delivery.
- First and foremost, we will be validating the passed parameters in request body (req.body).
validateReqBody
utility function is used for this validation purpose.- The first step is to create an array of missing fields (missingFields). We are checking if the zone, organization_id, total_distance and item_type are there in the request body or not.
- If any of these above 4 parameters are not passed, we will be pushing the name of those parameters to the missingFields array.
- If the missingFields has any data, then we will return the function with
success: false
anderror
with missing field(s). Now as we have these 4 parameters in request body, we will now use 4 different hooks namelyvalidateZone
,validateOrganizationId
,validateTotalDistance
andvalidateItemType
to validate them.validateZone
utility function:- It takes zone as parameter and checks if its value is string or not. If zone is not string, then we will return
error
. - Then we check that the zone is in allowedZones array or not. If it is not in the array, then return
error
. - Now if the zone is in the allowed zones, then we will replace hyphen (-) with underscore (_). Its because we can't add hyphen symbol as data in our PostgreSQL table.
- Then after passing all checks, we will return formatted zone as
data
from this utility function.
- It takes zone as parameter and checks if its value is string or not. If zone is not string, then we will return
validateOrganizationId
utility function:- It takes organization_id as parameter and checks if its value is string or not. If organization_id is not string, then we will return
error
. - Then we will check if the organization_id is empty or not. If it is empty, then we will return
error
. - Now, we will be adding leading zeros to organization_id to make it at least 3 characters long.
- Then we will return formatted organization ID as
data
from this utility function.
- It takes organization_id as parameter and checks if its value is string or not. If organization_id is not string, then we will return
validateTotalDistance
utility function:- It takes total_distance as parameter and checks if its value is number or not. If total_distance is not number, then we will return
error
. - Now we check if this total_distance is negative. If it is negative, the we return
error
. - After passing these above checks, we will return total_distance as
data
from this utility function.
- It takes total_distance as parameter and checks if its value is number or not. If total_distance is not number, then we will return
validateItemType
utility function:- It takes item_type as parameter and checks if its value is string or not. If item_type is not string, then we will return
error
. - Then we check that the item_type is in allowedTypes array or not. If it is not in the array, then return
error
. - Now if the item_type is in the allowed types, then we will replace hyphen (-) with underscore (_).
- Then we will return formatted item type as
data
from this utility function.
- It takes item_type as parameter and checks if its value is string or not. If item_type is not string, then we will return
- Using these above 4 validation hooks, we will store their returned value to
validationResults
array. Then we will check if in this array, there is any error which might be returned from any of these hooks and store it in inhasErrors
constant. - If there is any error (
hasErrors
is true), then we will filter thevalidationResults
which has truthyresult.error
and store it inerrorMessages
. Then we will returnsuccess: false
and error messages inerror
from thisvalidateReqBody
function. - If there wasn't any error (
hasErrors
is false), then returnsuccess: true
and validatedZone, validatedOrganizationId, validatedTotalDistance and validatedItemType indata
from thisvalidateReqBody
function.
- Now in
calculatePrice
controller, we will be usingvalidateReqBody
utility function to getsuccess
(true or false),error
(if there was any error returned - whensuccess: false
) ordata
(valiadted parametrs passed in request body - whensuccess: true
) and store it invalidationResult
. - Then if
validationResult
object hassuccess: false
, then we return response from this POST request witherror
. Here's the response object:
{
success: false,
error: appropiate error message in the form of string
}
- If the
validationResult
object hassuccess: true
, then we destructure thevalidationResult.data
to get validatedZone, validatedOrganizationId, validatedTotalDistance and validatedItemType. - Now we query the Pricing table and find if there exists any row for
{ organizationId: validatedOrganizationId },
{ item: { type: validatedItemType } },
{ zone: validatedZone }
and if there is no such data with matching parameters, then return
{
success: false,
error: "No Item found"
}
- If we do get any row with the matching data, then we calculate the
totalCost
with the logic- If validated total distance is greater than 5 km, then
totalCost = fixPrice + ((validatedTotalDistance - baseDistanceInKm) * kmPrice);
- Else when validated total distance is less than or equal to 5 km, then
totalCost = fixPrice
- If validated total distance is greater than 5 km, then
The data available:
fixPrice = 1000 cents
validatedTotalDistance = validated total_distance
baseDistanceInKm = 5 km
kmPrice = decided based upon if type is "perishable" (150 cents) or "non_perishable" (100 cents)
- Our cost in the Pricing table is in cents. So we divide the
totalCost
with 100 to get the cost in the Euro (€) and return the response
{
success: true,
total_price: (totalCost / 100)
}