About the project
RestOrRant is a command line application that my team and I had to work on for a Software Engineering project. Given a basic code for an address book, we had the choice of enhancing or morphing it into a desktop application that caters to specific users' needs.
We decided to morph it into RestOrRant (ROR), a restaurant management application for restaurant managers, waiters and cashiers. It is designed for them to perform front-end operations more efficiently like managing tables, handling orders, tracking the availability of menu items and calculating statistical data using the Command Line Interface (CLI).
RestOrRant is split into 4 main features: Tables, Orders, Menu and Statistics. To cater to needs of the user, modes are created to make the application user-friendly. Restaurant Mode, Table Mode, Menu Mode and Statistics Mode are modes meant to handle these 4 features respectively. Each of my teammates are in charge of one feature and mine was Statistics. In the following sections, I will elaborate on my contributions and extract relevant parts from the User Guide and Developer Guide that I wrote for the Statistics feature.+
You may find it useful to refer to the table below for the different symbols and formatting used in this portfolio.
|
Command that can be typed into the command box |
|
Expected result after executing the command |
|
Additional information that is good to know |
|
Important pointers to take note |
Summary of contributions
Overall, my role in this project encompasses managing the documentation of the project, keeping track the deadlines and deliverable, enhancing and cleaning up the UI components and Statistics feature. You may refer below for a detailed summary of the coding, documentation and other helpful contributions I have contributed to the team project.
-
Major enhancements: I add Statistics feature and its relevant commands.
-
Calling for bill:
bill
command-
What it does: It allows users to calculate and record the total bill accumulated from the table’s order.
-
Justification: This feature is necessary to update the restaurant’s revenue, status of the specified table and the quantity of the menu items that were ordered.
-
Highlights: This command is only usable in Table Mode.
-
-
Changing the Statistics Mode display:
yearly
,monthly
,daily
commands-
What it does: Changes the display to show yearly, monthly and daily trends of the restaurant’s earnings as well as the popularity of the menu items.
-
Justification: This feature allows the restaurant manager to study the restaurant performance.
These makes it easier for the manager to make essential back-end and front-end management arrangements to cater to the days and months that receives more customers.
The popularity of the menu items also helps the manager decide what kind of prior preparations are needed to cater to the popular dishes. -
Highlights: At most 30 year, months or days along with its revenue are displayed to prevent overflow of data.
-
-
Calling for revenue:
revenue
,revenue y/YEAR
,revenue y/YEAR m/MONTH
,revenue y/YEAR m/MONTH d/DAY
-
What it does: It allows users to retrieve the required yearly, monthly, daily revenue the user specifies.
-
Justification: This feature allows the restaurant manager to conveniently calculate and obtain the revenue he/she wants. It also eliminates the possibility of human errors when calculating the revenue.
-
Highlights: This command is only usable for day, month, year that are valid and dates that exists in the calendar. In the case where no day, month and year are specified, the current day’s revenue will be returned.
-
-
-
Minor enhancement: Create a Bill Mode that displays a receipt for the user.
-
Code contributed: Please refer to these links to view my code
[Project Code Dashboard] -
Other contributions:
-
Project management:
-
Ensures that the User Guide and Developer Guide are completed according to what was required.
-
Documents essential discussion pointers during meetings and share them with the team.
-
Use buffers to set deadlines and ensure everyone are informed and on task.
-
-
Enhancements to existing features:
-
Updated the GUI color scheme
-
Wrote tests for bill and statistics features
-
-
Documentation:
-
Reorganise the User Guide according to modes: [PR: #123]
-
-
Community:
-
Contributions to the User Guide
This section shows the contributions that I have made to the User Guide. I have included information about how the bill and Statistics features work.
Even though |
Calling the bill of an order : bill
Now that all the orders have been served and the customer is ready to pay for the meal, you can call the bill to obtain the customer’s receipt.
This command is irreversible. Once the command is executed, the order will be cleared and the table’s occupancy will be reset to allow new customers to use the table. The money earned from the bill will automatically be added to RestOrRant’s revenue statistics. |
The bill can only be called when all order items have been served.
|
|
You will see a success message in the Results Display and the user interface will change its colour scheme and
display. |
As seen from the image below, Table 5 has 4 items in the Order Panel. Note that all items have been
served. When When you switch to Restaurant Mode using the |
You may refer to contributions to Developer Guide to have a better understanding of bill
command.
Statistics Mode
In Statistics Mode, you can obtain statistics related to your restaurant, such as the popularity of dishes and the revenue of a specified year, month or day.
The user interface for Statistics Mode is shown in the image below.
The function of the side and main panels are as follows:
-
Item Panel: This panel shows you the list of menu items sorted by its popularity. This is meant to help you decide what ingredients to order to cater to the demands of the popular dishes.
-
Revenue Panel: This panel displays the revenue from the recent years, months or days, depending on the view that you have selected. This allows you to study trends in your restaurant’s revenue.
By default the Statistics Mode displays revenue up to 30 days in the Revenue Panel unless you execute
yearly , monthly or daily commands to change its display.
Here are the commands that you can use in this mode to study the statistical data of your restaurant.
|
Changing the Revenue Panel to daily view : daily
This command helps you to change the Revenue Panel back to its default display of the statistical daily revenue
for you to study its trends.
|
You will see a success message in the Results Display and the Revenue Panel changes to display the daily revenue for up to the past 30 days, starting from the most recent record. |
Notice that the first revenue is the most recent day recorded. This saves you the trouble of scrolling through the rest of the record. |
monthly
and yearly
commands also work similarly.
Getting the total revenue : revenue
If you want to obtain the revenue earned in a particular year, month or day, you can obtain it with this command.
Order of the parameters does not matter. For example, r y/2019 d/6 m/4 will still return the revenue earned on
6th April 2019.If no arguments are included, the revenue earned from the current day will be returned by default. |
If there are no records of the stated period, it will be returned as $0.00. Refer to commands to take note of the parameter restrictions of YEAR , MONTH and DAY .
|
|
You will see a success message and the revenue of the specified year, month or day in the Results Display. |
|
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide.
_ Since |
Classes for Statistics feature in Model
The Statistics feature was implemented with the introduction of a new set of classes to Model. A new Statistics class encapsulates all the methods and classes related to this feature. It also contains a listener that is used to update the storage when any modification is made to the statistics. The Statistics object is stored in RestOrRant and it exposes a read-only interface ReadOnlyStatistics to allow the other components to retrieve statistics-related information while maintaining data integrity.
Statistics contains a RevenueList, which contains a list of all the revenue recorded in the restaurant, represented by Revenue objects. Each Revenue object consists of 3 objects:
-
Year indicates the year which the revenue was earned
-
Month indicates the month which the revenue was earned
-
Day indicates the day which the revenue was earned
YearlyRevenue, MonthlyRevenue and DailyRevenue are classes that extends Revenue to inherit its properties. Hence, they are all uniquely identified by Year, Month and Day. Similarly, Date and Bill also consists and are identified by the above 3 objects.
The Statistics Class Diagram below shows the relationship between the classes.
Before elaborating on the bill feature, we have to understand the design considerations for statistics storage. |
Design Considerations for Statistics Storage
The data stored in Storage (/data/statistics.json) only encompasses Day, Month, Year and Revenue earned on
that specific date. These data are stored when the bill
command is called.
Aspect | Alternative 1 | Alternative 2 |
---|---|---|
Storage of statistical data |
Stores daily revenue which comprises of day, month, year and revenue. In a restaurant, it is unlikely that a customer will request for a refund after consuming and paying for the meal. Even if there are complaints about the meal, they will demand for a newly cooked dish before calling for the bill. Hence, we did not see the need to store receipts in the storage and chose this design. |
Stores bill which comprises of the day, month, year, bill, table number and receipt. |
Billing an order
Each Bill is unique to a Table. Hence, the bill
mechanism can only be executed under Table Mode.
The Table and its TableNumber was specified when switching over to Table Mode.
The way TableNumber is specified is explained in Orders feature.
Once the bill
command is called, it will internally switch to Bill Mode where the receipt of
the specified table is displayed. Concurrently, the bill mechanism accesses functions from Tables, Orders, Menu and
Statistics to execute the following:
-
Table: Updates specified table’s occupancy to accommodate new customers.
-
Order: Clears the order list that belongs to the specified table.
-
Menu: Saves the quantity of menu items ordered in the Menu storage (/data/menu.json).
-
Statistics: Saves the revenue in the Statistics Storage (/data/statistics.json).
Current Implementation
The main crux of Bill mechanism is implemented in BillCommand. Just like any other commands, BillCommand#execute() overrides Command#execute() which is called in LogicManager. It takes in the current mode, model and command history which will provide the necessary functions it will need to execute the command properly with the following operations:
-
BillCommand#calculateBill() — Creates a bill with a receipt of all menu items ordered and updates the quantity of menu items ordered in Menu#menuItems.
-
BillCommand#createOrUpdateRevenue() — Either saves the bill as a new DailyRevenue or updates an existing Revenue in the Statistics#revenueList.
-
BillCommand#updateStatusOfTable() — Updates the occupancy of the specified table to indicate that it has zero customers and resets the selected table to null.
-
Model#clearOrderItemsFrom() — Clears the order list to prepare for the next customer.
This sequence diagram provides an overview of how the operations above work together to execute bill
command.
bill
commandTo give you a better understanding of the sequence diagram, the following is a usage scenario and how the bill mechanism behaves at each step.
Step 1.
Let’s assume that the user is in Table Mode 1. This means Table 1 is the selected table. Before the
bill
command can be executed successfully, BillCommand#execute() conducts 2 checks.
-
Checks that current table obtained from Model#getSelectedTable() exists.
-
Checks that all order items in Model#getFilteredOrderItemList() have been served. The status of the order item is determined via Model#getOrderItemStatus().
Step 2. Given that the command passes all checks, the user can successfully run BillCommand#calculateBill() to assign a new calculated bill to the tableToBill attribute. Let’s refer to the function’s sequence diagram below.
BillCommand#calculateBill() calls both Model#getFilteredOrderItemList() and ReadOnlyRestOrRant#getMenu() to obtain the table’s list of orders and the restaurant’s menu. After which, it iterates through the list of orders to obtain individual OrderItem and executes the following in each iteration:
-
Gets MenuItem by passing the code of the OrderItem into Menu#getItemFromCode().
-
Retrieves the quantity of OrderItem ordered using OrderItem#getQuantityOrdered().
-
Updates the quantity of menu item ordered using ReadOnlyMenu#updateMenuItemQuantity().
-
Creates a receipt that appends the MenuItem#getCode(), MenuItem#getName(), MenuItem#getPrice() and the quantity retrieved previously.
-
Adds the price of each MenuItem multiplied by the quantity ordered to the total bill.
After iterating through the list of orders, receipt appends the final calculation of the total bill and the function returns a new Bill that contains the updated tableNumber, totalBill and receipt. This new Bill will be assigned to the bill attribute and passed into Model#setRecentBill() to update the Model’s recent bill (This step is needed when changing the user interface to Bill Mode).
Now that bill is updated, it is passed into BillCommand#createOrUpdateRevenue() to store the calculated bill in Statistics#revenueList. Refer to the function’s sequence diagram below.
As shown above, BillCommand#createOrUpdateRevenue() creates a DailyRevenue with the bill’s year, month and day. It checks if the newly created DailyRevenue exists in the revenueList via Model#hasRevenue(). If it is true that DailyRevenue exists, the function iterates through the Model#getFilteredRevenueList() and searches for a an existing Revenue that has the same year, month and day as the DailyRevenue. Once the Revenue is found, Revenue#addToRevenue() is used to add the total bill of the DailyRevenue into Revenue. Otherwise, the DailyRevenue is added into the revenueList via Model#addRevenue().
Now, that the necessary data are updated in the internal list of Menu and Statistics, BillCommand#execute() calls BillCommand#updateStatusOfTable() and Model#clearOrderItemsFrom() to make the table available for new customers.
BillCommand#updateStatusOfTable() updates the table status by creating a new Table with an updated TableStatus and replace the existing Table with the new one. After the table is updated, the program sets the selected table to null to indicate that the table is no longer in use.
Once these essential functions are executed, BillCommand#execute() moves on to indicate that the Tables, Orders, Menu and Statistics data have been modified via Model#updateTables(), Model#updateOrders(), Model#updateMenu(), Model#updateStatistics(). After which it returns the CommandResult to LogicManager#excute() where the it will check if the Tables, Orders, Menu and Statistics data have been modified and updates the storage accordingly. The same CommandResult is returned to MainWindow#executeCommand() where the user interface switches to Bill Mode to display the receipt of the recent Bill.
Internally the program switches to Bill Mode. However, this mode is shown to the user as Table Mode to avoid confusion. |
Design Considerations
Aspect | Alternative 1 | Alternative 2 |
---|---|---|
Design calculateBill() |
Iterates through the FilteredOrderItemList once to append the receipt, update quantity ordered of
the items in Menu and calculate the bill. We chose this design to prioritize efficiency in this use case. Since |
Create different functions that specifically calculates the bill, creates a bill receipt and update the quantity of
menu items ordered. |
I have decided to include a brief description of the following commands' implementation as they make up the main crux of the Statistics Mode. |
Changing Statistics Mode display
The following implementation applies for yearly
, monthly
and daily
commands.
These commands make adjustments to the user interface to display statistical data trends.
Current Implementation
The execution of these commands is similar to changing the mode. The only difference is that isYearly, isMonthly and isDaily boolean variables are used in MainWindow#executeCommand(). These boolean variables are passed into MainWindow#handleChangeMode() where it will determine which display to switch to. You may refer to the activity diagram to understand the cause of actions in the Statistics Mode user interface.
Since these commands changes the user interface, a huge portion of their mechanism is dependent on StatisticsFlowPanel. It determines the layout and arrangement of the revenue cards displayed.
Once the revenue observable list and boolean variables are passed into StatisticsFlowPanel, the function
checks which boolean variable is true. Lets assume that isDaily is true for daily
command. The function
enters a while loop that iterates through the revenue list until at most 30 DailyRevenue objects are created
and added to a list of DailyRevenue.
The list of DailyRevenue generated is sorted in a reverse chronological order of the date. Hence, even if there are no revenue recorded on a specific date, a DailyRevenue object is still created and added to the list. |
After which, the list of DailyRevenue is iterated to generate DailyStatisticsCard for each DailyRevenue. These DailyStatisticsCard are added to the StatisticsFlowPanel#statisticsFlowPane to update the user interface.
Design Considerations
Aspect | Alternative 1 | Alternative 2 |
---|---|---|
Arrangement of [XXX]StatisticsCard |
[XXX]StatisticsCard are arranged in descending order. |
[XXX]StatisticsCard are arranged in ascending order. |
Limit the number of [XXX]StatisticsCard |
Maximum [XXX]StatisticsCard shown is 30. |
Display all [XXX]StatisticsCard created from stored revenue data. |
Create additional [XXX]StatisticsCard with $0 revenue |
Display all [XXX]StatisticsCard in chronological order. |
Only display all [XXX]StatisticsCard created from stored revenue data. |
The current implementation uses the designs in Alternative 1. However, in version 2.0, the application will take the pros of Alternative 2 designs and incorporate them to the current implementation. To help users better study the revenue trends, v2.0 will allow users to call the commands with an argument that indicates the month or year that they want. The display will arrange the DailyStatisticsCard in a calender view with 7 columns for each day. A limit of 31 DailyStatisticsCard will be used to replicate a calendar and prevent overflowing.