DEV Community

Cover image for Online Food Ordering App (5)
Bertrand Masabo
Bertrand Masabo

Posted on

Online Food Ordering App (5)

Photo by abillion on Unsplash



Hi, Welcome back to part 5 of this series.

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.

Project steps

  1. Backend - Project Setup
  2. Backend - Authentication
    1. Backend - Authentication - Signup
    2. Backend - Authentication - Login and Logout
  3. Backend - Place order
  4. Backend - View orders list and view a specific order 📌
  5. Backend - Update order
  6. Frontend - Authentication
  7. Frontend - Place order, view orders list, and view order details



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.

Later on, we could build on top of this functionality to add features such as Quick re-order and Order live-tracking.

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

carbon (1)

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

carbon

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)

  • 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. Sequelize allows us to use logical operators to filter queries as you would with normal SQL queries. Learn more here. 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)

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

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

carbon (4)

validateGetOrder will help us to use our getOrder validation function.

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.

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.

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

carbon (5)

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

carbon (6)


Now run the tests and they should all pass.

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

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

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.

But before we create the routes, let us write our tests.

  • Update tests/orders.js and add the following:

carbon (7)

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.

In short, we are testing the absence of something, then create something, and finally test the presence of that thing. Does it make sense?

This is one way to do it though.

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)

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

carbon (10)

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)

  • Update src/controllers/orders.js and add the getOrdersList method:

carbon (12)

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)

  • Finally, update src/routes/index.js and include the admin routes:

carbon (14)



Now run the tests and they should all pass.

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.


Thank you for following this series.

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.


The code in this post can be found here


See you in the next one!

Top comments (2)

Collapse
 
labibllaca profile image
labibllaca

It looks really interesting as a project. Definitely gonna walk your steps here and try this for myself. Thanks for sharing.

Collapse
 
the22mastermind profile image
Bertrand Masabo

Thank you @labibllaca , Im glad you find it interesting. Please reach out to me if you get any issues. See you in the next posts.