Restaurant Management System in C++

Do not miss this exclusive book on Binary Tree Problems. Get it now for free.

In this article, we are going to discuss about a restaurant management system which can handle table allocation and other services required by the customers.

Table of Contents
Click here to view the code we are talking here.

  • Features & Requirements
  • Implementation Details
  • Working
  • Output
  • Conclusion

Features & Requirements

The features of this restaurant management system are:

  • Allocate tables: First we access the number of people in the group and then allocate the table in an optimized manner. That is if there are 3 people then they will be allocated 4 seater only, what ever happens they will get a 4 seater. If there are no 4 seater available then they are put in a queue. There are 2, 4, 6 seater and each of them has their own queue.
  • Taking the order: Once the customers gets a table allocated they will have an option to oder the food, when they do so, a menu appears and they can select the needed items by entering the numbers. To place the order they can type any character which is not in the menu range and then the order will be placed. The customer can add orders at any time they want.
  • Billing: Once the customer is ready to view the bill, they can request for a bill by entering the table id. Once the pill is paid in one click the customer in queue (if present) will be allocated that table.
  • Overview: A managerial overview option is available to get an overview of the whole restaurant. With this we can see which all tables are free, allocated and their orders and complete information about the waiting queues present.

We will be pulling off this project using various data structures, classes and objects.

Implementation Details

  • Classes: Class is a user-defined data type that can contain both data members and member functions. It is used to define objects, which are instances of the class. The data members of a class are the variables that hold data for each object created from the class, while the member functions are the operations or methods that can be performed on those data members.
  • system("pause"): It is a C++ statement that is sometimes used to pause the execution of a program and wait for the user to press a key before continuing. Normally in the console window closes after executing the program and this can be used to prevent the console window from closing immediately. When this statement is executed, the console window will display a message like "Press any key to continue...", and the program will wait for the user to press a key before continuing. This gives the user a chance to see the output of the program before the console window closes.
  • cin.clear(): It is a member function of cin and it is used to clear the error flags of the input stream. If an error occurs during an input such as when a user enters a wrong data type then the error flag of the cin object is set and this will cause the subsequent input operations to fail even if the users enter correct inputs. This function only clears the error flags from the input streams it wont remove it.
  • cin.ignore(numeric_limits<streamsize>::max(), '\n'): It is a C++ statement used to discard the characters from the input stream up to and including the next newline character (\n). Here in our program we will be using this after the cin.clear() to remove the character which caused error flags.

Working

So as a first step we need to create the necessary classes which are Table, Order, Bill and Overview classes.

Table Class
Here we will be dealing with allocation of tables to the customers. So for this first we have a map variable tableCount (it is a private variable which can be accessed by the functions of that class only) which has the number of available tables for the respective seater available. Then we have another map which is a public variable and this helps us to keep track of the existing table id's, whether they are allocated or not and if its allocated how many customers are there in that table. We also have the three queues for each seater type which keeps track of the people in queue.
Now we have the allocate function. In this function we will first accept the number of people in the group and then calculate the table required using if statements, tableCount map and then we will calculate the id of the table using the formula tableId = it.first * 10 + it.second; which takes into account the table seater and the remaining number of them. If none of them are remaining then the customer is put in a queue where they should enter a customer id. Once the seats are available then they will be informed. Here we also have a function called isValid() which would check if the table id entered by the customer is existing and allotted. We would be using this function in the future.

class Table
{

private:
    map<int, int> tableCount = {
        {2, 4},
        {4, 6},
        {6, 2}};

public:
    unordered_map<int, pair<bool, int>> tableStatus = {
        {21, {true, 0}},
        {22, {true, 0}},
        {23, {true, 0}},
        {24, {true, 0}},
        {41, {true, 0}},
        {42, {true, 0}},
        {43, {true, 0}},
        {44, {true, 0}},
        {45, {true, 0}},
        {46, {true, 0}},
        {61, {true, 0}},
        {62, {true, 0}},
    };
    queue<int> waiting2;
    queue<int> waiting4;
    queue<int> waiting6;

    void allocation()
    {
        int people, tableId = 0;
        cout << "Enter number of people: ";
        cin >> people;
        if (people > 6)
        {
            cout << "Sorry we don't have that capacity" << endl;
            system("pause");
            return;
        }
        for (auto it : tableCount)
        {
            if (it.first >= people && it.second > 0)
            {
                tableId = it.first * 10 + it.second;
                tableCount[it.first]--;
                tableStatus[tableId].first = false;
                tableStatus[tableId].second = people;
                break;
            }

            else if (it.first >= people)
            {
                break;
            }
        }
        if (tableId != 0)
        {
            cout << "You have been allocated table id: " << tableId << endl;
        }
        else
        {
            int custId;
            cout << "Tables are full, you are in queue!" << endl;
            cout << "Enter your ID: ";
            cin >> custId;
            if (people <= 2)
                waiting2.push(custId);
            else if (people <= 4)
                waiting4.push(custId);
            else if (people <= 6)
                waiting6.push(custId);
            cout << "Thankyou,  just wait for a while!" << endl;
        }
        system("pause");
        return;
    }
    bool isValid(int tno)
    {
        if (tableStatus.find(tno) == tableStatus.end())
            return false;
        else if (tableStatus[tno].first == true)
            return false;
        return true;
    }
};

Order Class
The order class is a child class of the Table class, it inherits all the public data members and the public member functions of its parent class. Here the order class only has public variables and functions. The menu map shows the id, dish name and its price, this is used to display the menu in the coming part. In the orderFood() function we first asks the customer to enter the table id, then we will use the isValid() function (inherited) to verify if the table exists and had been allotted. if Its a no then we will print "INVALID", if its not we will show them the menu and asks them to enter their required dish id. As they are entering the order id, we will be saving them into the viewBill map of map, which keeps track of the orders at every single table.
If they enter an character or number which is not in the menu range then the order is placed. Then we use cin.clear() and cin.ignore(numeric_limits<streamsize>::max(), '\n'); to clear out the last input which we don't need.

class Order : public Table
{
public:
    unordered_map<int, unordered_map<int, int>> viewBill;

    map<int, pair<string, int>> menu{
        {1, {"Vada", 10}},
        {2, {"Dosa", 70}},
        {3, {"Idly", 50}},
        {4, {"Pizza", 175}},
        {5, {"Burger", 160}},
        {6, {"Upma", 60}},
        {7, {"Meals", 80}},
        {8, {"Naan", 18}},
        {9, {"Curry", 210}},
        {10, {"Ice", 250}},
        {11, {"Chai", 15}},
        {12, {"Coffee", 250}}};

    void orderFood()
    {
        int tableId;
        cout << "Enter table id: ";
        cin >> tableId;
        if (!isValid(tableId))
        {
            cout << "INVALID" << endl;
            system("pause");
            return;
        }
        cout << "-----------MENU-----------" << endl;
        cout << "S.No\tItem\tPrice" << endl;
        for (auto it : menu)
        {
            cout << it.first << ".\t" << it.second.first << "\t" << it.second.second << endl;
        }
        int orderNo;
        cout << "Enter the numbers you want to order one by one." << endl
             << "When you finish, enter any character: ";
        while (1)
        {
            cin >> orderNo;
            if (cin.fail() || orderNo > 12 || orderNo < 1)
                break;
            viewBill[tableId][orderNo]++;
        }
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
        cout << "Order has been placed successfully...!" << endl;
        system("pause");
        return;
    }
};

Bill Class
The Bill class is a child class of the Order class so it have access to the public variables and functions of both Table and Order class. Here we have a function called printBill() which takes in the table id and then it prints it. We will be using this in other functions. The next function is the billing function. In this function we will take the table id as the input then we will verify if that table exists and has been allocated then we will pass the id value to the printBill() which will print the bill. After payment the user will continue and then the allocateQueue() will be called. It is a private function of the Bill class and it will check if any queue has waiting members, if yes then we will check which seater just got emptied and then we will allocate that group to the table and will update the tableStatus map accordingly.

class Bill : public Order
{
public:
    void printBill(int tno)
    {
        int i = 1, total = 0;
        cout << "\nS.No\tItem\t\t\tCount\tPrice\n";
        for (auto it : viewBill[tno])
        {
            cout << i << ".\t" << menu[it.first].first << "\t\t\t" << it.second << "\t" << menu[it.first].second * it.second << endl;
            total += menu[it.first].second * it.second;
            i++;
        }
        cout << endl
             << "\t\tTotal:\t" << total << endl;
    }
    void billing()
    {
        int tno, total = 0;
        cout << "Enter table number: ";
        cin >> tno;
        if (!isValid(tno))
        {
            cout << "INVALID" << endl;
            system("pause");
            return;
        }
        cout << "--------------------BILL--------------------" << endl;

        printBill(tno);

        cout << "Continue after payment." << endl;
        system("pause");
        cout << endl;
        cout << "    Thankyou! Visit again...!" << endl;
        system("pause");
        viewBill[tno].clear();
        allocateQueue(tno);
        return;
    }

private:
    void allocateQueue(int tno)
    {
        if (waiting2.size() > 0 || waiting4.size() > 0 || waiting6.size() > 0)
        {
            int custId;
            if (tno / 10 <= 2)
            {
                custId = waiting2.front();
                waiting2.pop();
            }
            else if (tno / 10 <= 4)
            {
                custId = waiting4.front();
                waiting4.pop();
            }
            else if (tno / 10 <= 6)
            {
                custId = waiting6.front();
                waiting6.pop();
            }
            cout << "Seats are available" << endl
                 << "Table no " << tno << " is allotted for " << custId << endl;
            int peopleCount;
            cout << "Enter number of people: ";
            cin >> peopleCount;
            tableStatus[tno].second = peopleCount;
            system("pause");
        }
        else
        {
            tableStatus[tno].first = true;
            tableStatus[tno].second = 0;
        }
    }
};

Overview Class
The Overview class is the child class of Bill class so this class will have access to the public functions and variables of all the above mentioned classes. Here this class has only one member function detailedOverview() it first provides the number of people in each queue. Then it shows the available tables and then it shows the allotted tables along with their order details and the number of people occupying each of these tables. These are all the information it provides. We would be using this class as it has the access to all the classes.

class Overview : public Bill
{
public:
    void detailedOverview()
    {
        cout << "Number of groups in queue (2-seater): " << waiting2.size() << endl
             << "Number of groups in queue (4-seater): " << waiting4.size() << endl
             << "Number of groups in queue (6-seater): " << waiting6.size() << endl;
        system("pause");
        cout << "\t---------Table Status---------" << endl;
        cout << "Available tables are: ";
        for (auto it : tableStatus)
        {
            if (it.second.first == true)
            {
                cout << it.first << " ";
            }
        }
        cout << endl;
        system("pause");
        for (auto it : tableStatus)
        {
            if (it.second.first == false)
            {
                cout << "Table " << it.first << " is allotted, " << it.second.second << " people occupied the table, order details: " << endl;
                printBill(it.first);
            }
        }
        system("pause");
    }
};

int main()
Inside the main() we first create the object for the overview class ov and then we will call the necessary functions inside the switch statement. The user will enter the number from the menu and that action would call the necessary function.

int main()
{
    Overview ov;
    while (1)
    {
        int option;
        cout << "     Welcome to restaurant management system" << endl;
        cout << "*************************************************" << endl;
        cout << "1. Table allocation" << endl
             << "2. Order food" << endl
             << "3. View Bill" << endl
             << "4. Manager overview" << endl
             << "5. Exit" << endl
             << "Enter your choice: ";
        cin >> option;
        switch (option)
        {
        case 1:
            ov.allocation();
            break;
        case 2:
            ov.orderFood();
            break;
        case 3:
            ov.billing();
            break;
        case 4:
            ov.detailedOverview();
            break;
        case 5:
            exit(0);
            break;
        default:
            cout << "Invalid" << endl;
        }
    }
    return 0;
}

Output

Table allocation

Waiting in queue

Ordering

Overview

Billing & queue allocation

Conclusion

With this article at OpenGenus, you must have the complete idea of designing Restaurant Management System in C++. This system has many limitations and could be improved by a large extend. Some points for improvements are:

  • Making this a GUI application
  • Enabling password protection for the overview option
  • Payment integration
  • Different menu for customers and manager

Sign up for FREE 3 months of Amazon Music. YOU MUST NOT MISS.