Overview

This portfolio documents my contributions towards the project I have undertaken in the course CS2103T - Software Engineering. It aims to demonstrate the theoretical and practical knowledge I have gained in the field of Software Engineering over the semester.

PROJECT: MeNUS

MeNUS is an integrated restaurant management desktop application designed for restaurant owners. It comprises five sub-management systems - 1) Menu, 2) Inventory, 3) Sales, 4) Reservation and 5) Authentication, each of which plays an indispensable role in ensuring the success of a restaurant business. They were meticulously developed to streamline the process of tracking dishes, ingredients, bookings and sales records while upholding a substantial level of security.

MeNUS provides a Command Line Interface (CLI) for restaurant owners to interact with and is complemented with a Graphical User Interface (GUI) that is constructed with JavaFX. MeNUS is written in Java 9 with approximately 25 kLOC.

Summary of contributions

Given below are contributions I made for the project. They showcase my capability to
1) identify and specify functional and non-functional requirements for the product;
2) conduct product and implementation design to meet end-users' requirements;
3) write high quality code that is error-free, comprehensible, and reusable;
4) write effective and efficient test codes to ensure high quality assurance;
5) use various modelling and version control tools;
6) collaborate with other developers.

  • Code contributed: RepoSense

  • Major enhancement: Developed and integrated a Sales Management System (SMS) into MeNUS to help restaurant owners keep track of financial records, analyse their financial performance and devise marketing strategies.

    • What it does: SMS allows owners to add, modify and remove sales records. An Auto-ingredient update mechanism is incorporated to enable automatic consumption of ingredients whenever a record is added. Also provides owners with analytical features to generate sales report, plot sales chart and rank dates/items according to profitability.

    • Justification: These features provide efficiency and effectiveness in keeping track of huge amount of financial records every day which can be extremely tedious if done via the conventional means of pen and paper. The Auto-ingredient update mechanism also saves restaurant managers the trouble of frequent inventory tracking which often takes up a significant amount of time and effort. Analytical features assists restaurant owners in making strategic marketing decisions, projecting business’s revenue as well as monitoring its long-term growth. These ensure the financial success of the restaurant in the long run.

    • Highlights: This enhancement adds on to the limited number of key management aspects MeNUS can provide. It requires an in-depth analysis of design alternatives as well as a thorough understanding of the entire code architecture. The implementation was challenging as the Auto-ingredient update mechanism required the integration of the Menus, Ingredients and Sales management system. An extensive knowledge of how each management works was therefore essential. Analytical features also required substantial knowledge of front-end programming languages such as CSS and XML.

  • Other contributions:

    • Project Management:

      • Managed the integration and collaboration aspect of MeNUS. #147

      • Ensured loose coupling and flawless coordination between various management systems of MeNUS.

      • Maintained issue tracker and merging of pull requests (PRs).

      • Oversaw the Storage component of MeNUS and preserved its functionality throughout.

    • Enhancements to existing features:

      • Updated MeNUS’s Cascading Style Sheets (CSS) theme.

    • Quality Assurance:

      • Wrote unit and integration tests which helped improve the overall code coverage beyond 94%.

    • Documentation:

      • User Guide:

      • Developer Guide:

        • Wrote implementation details for display-sales and Auto-ingredient update features. #119, #192, #294

        • Drew Unified Modeling Language (UML) diagrams under various sections. #141, #202, #266

        • Specified requirements under user stories and use cases #36, #119,

    • Community:

Contributions to the User Guide

The following sections are my contributions to the User Guide. They reflect my ability to write clear and concise documentation targeting non-technical readers. Please refer to User Guide for more of my contributions. The full version of my contribution can be found under section 5.6 and 5.7.5 - 5.7.8 of the User Guide.

Sales Management

The following are sales-related commands to help you with financial tracking and analysis. The terms "sales record" and "record list" will be used frequently under this section so it is advisable to first understand their definition in the glossary.

Recording sales volume of an item: record-sales or rs

Records the sales volume of an item within a specific day into the record list.
Format: record-sales d/DATE n/ITEM_NAME q/QUANTITY_SOLD p/ITEM_PRICE or rs d/DATE n/ITEM_NAME q/QUANTITY_SOLD p/ITEM_PRICE

  • DATE must be written in the DD-MM-YYYY format.

  • DATE must exist in the calendar.

  • Both DATE and ITEM_NAME cannot be same as another record in the record list.

  • ITEM_NAME is case insensitive. "Cheesy Pasta" and "cheesy pasta" are regarded as the same item.

Examples:

  • record-sales d/25-09-2018 n/Fried Rice q/35 p/5.50

  • rs d/25-09-2018 n/Fried Rice q/35 p/5.50

Auto-ingredient update mechanism

record-sales also determines all the ingredients you used and automatically deducts them from the ingredient list, subjected to the following conditions:
1) The item exists in the menu.
See Section 5.4.1, “Adding an item to the menu" for more information.
2) The required ingredients to make one unit of ITEM_NAME is specified.
See Section 5.4.14, “Add required ingredients" for more information.
3) All required ingredients exist in the ingredient list.
See Section 5.3.1, “Adding an ingredient" for more information.
4) There are sufficient ingredients to make QUANTITY_SOLD units of ITEM_NAME.
See Section 5.3.6, “Stocking up an ingredient" for more information.

Sales volume will still be recorded even if some of the above conditions are not met. However, ingredient list will not be updated

Ingredient used: MeNUS will remember the name and quantity of ingredients you used as long as the item and its required ingredients have been specified in the menu component

If you recorded a sales volume by mistake, you can use the Undo command to recover the deducted ingredients, provided that the ingredients have been deducted automatically

Display sales report: display-sales or dis

Generate and display the sales report for a specific day.
Format: display-sales DATE or dis DATE

  • DATE must be written in the DD-MM-YYYY format.

  • DATE must exist in the calendar.

  • There must be at least one sales record associated with the specified DATE.

Examples:

  • display-sales 30-09-2018

  • dis 30-09-2018
    Displays the sales report dated 30-09-2018.

The following (Figure 5.6.2.1) is an example of what you will see if the sales report is generated and displayed correctly:

display sales pic

Figure 5.6.2.1: Sales Report

Deleting a sales record: delete-sales or des

Deletes the sales record identified by the index.
Format: delete-sales INDEX or des INDEX

  • Deletes the record at the specified INDEX.

  • INDEX refers to the index number shown in the record list.

  • INDEX must be a positive integer 1, 2, 3, …​

Deleting a sales record will not undo the effect of "Auto-ingredient update" which may or may not have happened during recording

Examples:

  • delete-sales 2

  • des 2
    Deletes the 2nd record from the record list.

Editing a sales record: edit-sales or es

Edits the sales record identified by the index.
Format: edit-sales INDEX [d/DATE] [n/ITEM_NAME] [q/QUANTITY_SOLD] [p/ITEM_PRICE] or es INDEX [d/DATE] [n/ITEM_NAME] [q/QUANTITY_SOLD] [p/ITEM_PRICE]

  • Edits the record at the specified INDEX.

  • INDEX refers to the index number shown in the record list.

  • INDEX must be a positive integer 1, 2, 3, …​

  • At least one of the optional fields must be provided.

  • Existing values will be updated to the input values.

Editing a sales record will permanently delete its "Ingredient used" data

Editing a sales record will not update the ingredient list. See Auto-ingredient update for more information

Examples:

  • edit-sales 3 n/Fried Omelet

  • es 3 n/Fried Omelet
    Edits the item name of the 3rd record to be "Fried Omelet".

  • edit-sales 7 q/37 p/6.50

  • es 7 q/37 p/6.50
    Edits the quantity sold and price of the 7th record to be 37 and 6.50 respectively.

Ranking dates according to total revenue: rank-date or rad

Ranks and displays all existing dates in the record list based on the total revenue.
Format: rank-date or rad

  • Record list must not be empty.

You can generate the sales report of a specific date to get a more detailed analysis. See Section 5.6.2, “Display sales report" for more information

The following (Figure 5.6.6.1) is an example of what you will see if the ranking is generated and displayed correctly:

rank date pic

Figure 5.6.6.1: Ranking of dates by revenue

Contributions to the Developer Guide

The following sections are my contributions to the Developer Guide. They reflect my ability to convey technical information in a comprehensible manner. It also showcases the technical depth of my contributions. Please refer to Developer Guide for more of my contributions. The full version of my contribution can be found under section 4.4, 4.5, and UC5XX of appendix A.

Auto-ingredient update feature

The auto-ingredient update mechanism is facilitated by RecordSalesCommand and triggers whenever the "record-sales" command is invoked. A SalesRecord will be instantiated based on the information given and attempts to compute the ingredients used before deducting them from the ingredient list automatically.

Current Implementation

A SalesRecord is associated with 6 attributes - Date, ItemName, QuantitySold, Price, Revenue and IngredientUsed.
The success of the auto-ingredient update mechanism is subjected to the following conditions:

1) ItemName exists in the Menu.
2) The required ingredients to make one unit of ItemName is specified in the Menu.
3) The required ingredients exist in the Ingredient list.
4) There are sufficient ingredients to make QuantitySold units of ItemName in the Ingredient list.

If any of the above conditions are not satisfied, sales volume will be recorded without updating the ingredient list
If conditions 1 and 2 are satisfied, RecordSalesCommand will compute all the ingredients used and store the data in IngredientUsed attribute of SalesRecord

This mechanism is aided by methods from the Menu and Ingredient components, all of which are exposed in the Model interface. Given below is an example scenario and how the auto-ingredient update mechanism behaves at each step.

Step 1. The user executes record-sales d/11-01-2018 n/Fried Rice q/35 p/5.50 command to record the sales volume of Fried Rice on 11-01-2018. A SalesRecord would be instantiated based on the command arguments given.

Step 2. RecordSalesCommand will request for the item Fried Rice from Menu. This is done through the Item findItem (Name) method given in Menu component. This also checks if condition 1 is satisfied.

Step 3. RecordSalesCommand then proceeds to request for the required ingredients to make a unit of Fried Rice from Menu. This is done through the Map<IngredientName, Integer> getRequiredIngredients(Item) method given in Menu. This also checks if condition 2 is satisfied.

Step 4. With the required ingredients per unit data now at hand, RecordSalesCommand will compute the total ingredients used in making 35 units of Fried Rice. The IngredientUsed attribute in SalesRecord will then be updated.

Step 5. RecordSalesCommand will then pass the computed IngredientUsed to Ingredient component to request for an update of ingredients. This is done through the void consumeIngredients(Map<IngredientName, Integer>) method given in Ingredient component. This checks for condition 3 & 4.

Step 6. The SalesRecord is then finally added into UniqueRecordList via the void addRecord(SalesRecord) method given in Sales component of Model.

An exception will be thrown in step 2, 3 or 5 should the conditions be violated. In such scenario, RecordSalesCommand will jump to step 6 instantly and omit the remaining steps

The following activity diagram (Figure 4.4.1.1) summarizes what happens when a user executes record-sales command:

RecordSalesActivityDiagram

Figure 4.4.1.1: Activity Diagram for record-sales command

Display sales report feature

Current Implementation

The display sales report mechanism is facilitated by the Model, UI and Event components of the App. A SalesReport class encapsulates the attributes of a sales report to be displayed. The sales report is internally generated by generateSalesReport(Date) in UniqueRecordList. It then propagates up the Model call hierarchy to getSalesReport(Date) in ModelManager, which is exposed in the Model interface.

The following sequence diagram (Figure 4.5.1.1) illustrates how the display sales report operation works when the user enters display-sales 25-12-2017:

DisplaySalesSequenceDiagram

Figure 4.5.1.1: Sequence Diagram for display-sales command

The sequence diagram for the "Parse Command" reference frame above is shown below in Figure 4.5.1.2:

DisplaySalesSequenceDiagramRef

Figure 4.5.1.2: Sequence Diagram for "Parse Command" reference frame

Given below is an example usage scenario and how the display sales report operation behaves at each step.

Step 1. The user executes display-sales 25-12-2017 command to request for the sales report dated 25-12-2017. The display-sales command calls Model#getSalesReport(Date), passing in the date "25-12-2017", and gets the generated SalesReport in return.

display-sales command will not call Model#getSalesReport(Date) if the specified date is invalid
If no sales record associated with the given Date is found, an empty SalesReport will be returned. In such cases, the command will terminate with a message notifying the user about the absence of such record

Step 2. The display-sales command then raises the DisplaySalesReportEvent event, which also encapsulates the generated SalesReport in step 1.

Step 3. The EventsCenter reacts to the above event, which results in handleDisplaySalesReportEvent(Event) in UI’s MainWindow being called. This method instantiates a SalesReportWindow object by passing in the SalesReport to its constructor. This SalesReportWindow acts as the controller for the sales report window.

Step 4. The SalesReportWindow is then initialized and displayed on user’s screen.

Design Considerations

Aspect: How SalesReport is generated internally
  • Alternative 1 (current choice): generateSalesReport(Date) in UniqueRecordList filters the entire record list. Records that match the given Date are added into a List<SalesRecord>. The SalesReport is generated based on this list.

    • Pros: Easy to implement.

    • Cons: Execution is of linear time complexity and would be considerably slow should the list size be very large.

  • Alternative 2: Maintain another list that sorts itself by date every time it is modified. Conduct a binary search to fill in the List<SalesRecord> every time a sales report is requested.

    • Pros: SalesReport can be generated with a O(logN) time complexity.

    • Cons: Sorting after every input would require O(NlogN) time which is slow. Additionally, the sorted list also takes up an O(N) memory space.

Use case: UC501 - Record sales volume of an item

Guarantees:

  • A new sales record of an item will be appended to the record list.

MSS

  1. User requests to record sales volume of an item for a specified day.

  2. App computes the ingredients used and updates the ingredient list automatically.

  3. App appends the record at the end of record list.

  4. App returns a success message confirming that the recording is successful.

    Use case ends.

Extensions

  • 1a. Invalid command format entered by the user.

    • 1a1. App returns a message telling user that the command format is invalid.

    • 1a2. User requests to record sales volume again.

      Steps 1a1-1a2 are repeated until a valid command format is entered.

      Use case resumes at step 2.

  • 1b. The given date or name or quantity sold or price is invalid.

    • 1b1. App returns a message telling user that the date or name or quantity sold or price is invalid.

    • 1b2. User requests to record sales volume again.

      Steps 1b1-1b2 are repeated until all fields entered by the user are valid.

      Use case resumes at step 2.

  • 1c. Sales record of the same date and item name already exists in the record list.

    • 1c1. App returns a message telling user that the item’s record already exists.

    • 1c2. User requests to record sales volume again.

      Steps 1c1-1c2 are repeated until a record with unique date and item name is entered.

      Use case resumes at step 2.

  • 2a. One or more of the criteria to update ingredient list were not satisfied.

    • 2a1. App takes note of which criteria were not satisfied, and appends a notification message after the success message.

      Use case resumes at step 3.