Online Food Ordering App (5)
Tags: express, node, react, reactnative
Published: 2021-01-26 12:39:07

*<span>Photo by <a href="https://unsplash.com/@abillion?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">abillion</a> on <a href="https://unsplash.com/s/photos/food-mobile-app?utm_source=unsplash&amp;utm_medium=referral&amp;utm_content=creditCopyText">Unsplash</a></span>*

<br/>
Hi, Welcome back to part 5 of this series.<br/>
In today's post we are going to implement the functionality that allows a customer to view an order they have placed and for the admin to view a list of orders placed by customers as well as a specific order's details.<br/><br/>

### Project steps
1. [Backend - Project Setup](https://dev.to/the22mastermind/online-food-ordering-app-1-594j)
2. Backend - Authentication
  1. [Backend - Authentication - Signup](https://dev.to/the22mastermind/online-food-ordering-app-2-28po)
  2. [Backend - Authentication - Login and Logout](https://dev.to/the22mastermind/online-food-ordering-app-3-1g8h)
3. [Backend - Place order](https://dev.to/the22mastermind/online-food-ordering-app-4-5dc5)
4. [Backend - View orders list and view a specific order]() :pushpin:
5. [Backend - Update order]()
6. [Frontend - Authentication]()
7. [Frontend - Place order, view orders list, and view order details]()

<br/>
Let us begin by implementing the functionality to fetch an order by it's id from the perspective of a customer. We are going to add checks to verify if the id submitted is valid, if the order it refers to exists, and finally, if the user who is making this request is the one who placed that order.<br/>
Later on, we could build on top of this functionality to add features such as `Quick re-order` and `Order live-tracking`.<br/>

- Update `src/utils/messages.js` and add the following new messages:

![carbon (1)](https://dev-to-uploads.s3.amazonaws.com/i/5uzuvu672x4lup8n1emu.png)

- Update `tests/orders.test.js` and add the `customer get order` test suite:

![carbon](https://dev-to-uploads.s3.amazonaws.com/i/8qtfu2tyjkel2awonunw.png)

In the last two test cases we placed a new order, then we try to fetch it by it's id. We are also checking to see if the data object in the returned response has all the information related to that order, like its contents, and the details of the user who placed the order.

- Update `src/validations/orders.js` and add the `getOrder` function which will help us to validate the order id:

![carbon (2)](https://dev-to-uploads.s3.amazonaws.com/i/mdly1kl6wqso66qt5zq2.png)

- Update `src/services/services.js` and add the `findOrderByConditionAll` function that will help us to find an order given certain conditions. In this case, we want to find an order given it's id and the id of the user who placed it.<br/>
Sequelize allows us to use logical operators to filter queries as you would with normal SQL queries. Learn more [here](https://sequelize.org/master/manual/model-querying-basics.html#applying-where-clauses).<br/>
We can even go as far as fetching associated models provided that we have made these associations before. In our case, we want to fetch the order's contents and the details of the user who placed it.

![carbon (3)](https://dev-to-uploads.s3.amazonaws.com/i/pbn8aslw1kp9trkc51cx.png)

Note how we included the entire model of Contents and how we selected only the relevant fields that we want on the User model.<br/>

- Update `src/middlewares/orders.js` and add the `validateGetOrder` and `findUserOrderById` function.

![carbon (4)](https://dev-to-uploads.s3.amazonaws.com/i/u01ffbnwogu9pt1n6ihb.png)

`validateGetOrder` will help us to use our `getOrder` validation function.<br/>
Note how instead of passing `req.body` to getOrder as a parameter, we pass `req.params`. This is because the id we want to validate will not be generated by the user, instead it will be mapped to our route. This means that, given a route `/orders/:id`, the id property is available as `req.params.id`.<br/>

In `findUserOrderById` we destructure that id from params then create a userId variable from req.userData (this is the id of the user who's making this request). Then we use id from params and userId to put together our condition object which we use in the `findOrderByConditionAll` service.<br/>

- Update `src/controllers/orders.js` and add `getSpecificOrder` method:

![carbon (5)](https://dev-to-uploads.s3.amazonaws.com/i/ao7xe3a3hta8rq7hwmh1.png)

- Update `src/routes/ordersRoutes.js` to look like the following:

![carbon (6)](https://dev-to-uploads.s3.amazonaws.com/i/v3354drsmc7k20hp0q1t.png)
 
<br/>Now run the tests and they should all pass.<br/>

So far a customer can place an order and she can view that order's details.<br/>

Let's now see how fetching orders looks like from the perspective of the admin.<br/>

For the admin, we will create a new route path where all the admin related sub routes will go. This means that in our route index file we will have 3 parent routes: `/api/auth`, `/api/orders`, and `/api/admin`.<br/>

But before we create the routes, let us write our tests.<br/>

- Update `tests/orders.js` and add the following:

![carbon (7)](https://dev-to-uploads.s3.amazonaws.com/i/yu3kfr9w06e412wroeg5.png) 

Note how we added our new tests suite before and after `CUSTOMER PLACE ORDER` and `CUSTOMER GET ORDER` suites. This allows us to test the Not Found or Empty scenario and the Success scenario respectively.<br/>

In short, we are testing the absence of something, then create something, and finally test the presence of that thing. Does it make sense?<br/>
This is one way to do it though.<br/>

Let us now create a service that will allow the admin to fetch all the orders placed by customers, starting with the most recently placed:

![carbon (8)](https://dev-to-uploads.s3.amazonaws.com/i/98zb9iwdrfwceonre4tu.png)

- Update `src/middlewares/orders.js` and add the `findOrderById` and `findOrdersList` functions:

![carbon (10)](https://dev-to-uploads.s3.amazonaws.com/i/dlm0qanzegwwynie4k0i.png)

To make sure the middlewares we just created are only accessible to the admin, we need to create  another middleware that checks the role of the user who is making  the request and then grants access or not.

- Update `src/middlewares/authentication.js` and add the `checkAdminRole` function:

![carbon (11)](https://dev-to-uploads.s3.amazonaws.com/i/nblrvwvie9gtjhwwo8iw.png)
 
- Update `src/controllers/orders.js` and add the `getOrdersList` method:

![carbon (12)](https://dev-to-uploads.s3.amazonaws.com/i/rlnoz3txata3ggt1jglr.png)

Now let us create the admin sub routes and include them in the main routes.

- Create a new `src/routes/adminRoutes.js` file and paste the following inside:

![carbon (13)](https://dev-to-uploads.s3.amazonaws.com/i/3xqwdr8q2sujafei8jsa.png)
  
- Finally, update `src/routes/index.js` and include the admin routes:

![carbon (14)](https://dev-to-uploads.s3.amazonaws.com/i/72wpyunatmbiim4vv0xb.png)

<br/>
Now run the tests and they should all pass.<br/>
Now we can commit our changes to GitHub, open a PR, wait for Travis to successfully build then merge the PR to trigger a new production build.
<br/>
Thank you for following this series.<br/>
In the next post, we are going to wrap up our API with the functionality that allows the admin to update the status of an order.
<br/>
The code in this post can be found [here](https://github.com/the22mastermind/gourmet-api)
<br/>
See you in the next one!
<br/>