= REstaurant Manager - Developer Guide
:site-section: DeveloperGuide
:toc:
:toc-title:
:toc-placement: preamble
:sectnums:
:imagesDir: images
:stylesDir: stylesheets
:xrefstyle: full
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:warning-caption: :warning:
:experimental:
endif::[]
:repoURL: https://github.com/cs2103-ay1819S2-w11-2/main

By: `Team W11-2`      Since: `Jan 2019`      Licence: `MIT`

== Setting up

=== Prerequisites

. *JDK `9`* or later
+
[WARNING]
JDK `10` on Windows will fail to run tests in <<UsingGradle#Running-Tests, headless mode>> due to a https://github.com/javafxports/openjdk-jfx/issues/66[JavaFX bug].
Windows developers are highly recommended to use JDK `9`.

. *IntelliJ* IDE
+
[NOTE]
IntelliJ by default has Gradle and JavaFx plugins installed. +
Do not disable them. If you have disabled them, go to `File` > `Settings` > `Plugins` to re-enable them.


=== Setting up the project in your computer

. Fork this repo, and clone the fork to your computer
. Open IntelliJ (if you are not in the welcome screen, click `File` > `Close Project` to close the existing project dialog first)
. Set up the correct JDK version for Gradle
.. Click `Configure` > `Project Defaults` > `Project Structure`
.. Click `New...` and find the directory of the JDK
. Click `Import Project`
. Locate the `build.gradle` file and select it. Click `OK`
. Click `Open as Project`
. Click `OK` to accept the default settings
. Open a console and run the command `gradlew processResources` (Mac/Linux: `./gradlew processResources`). It should finish with the `BUILD SUCCESSFUL` message. +
This will generate all resources required by the application and tests.
. Open link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow.java`] and check for any code errors
.. Due to an ongoing https://youtrack.jetbrains.com/issue/IDEA-189060[issue] with some of the newer versions of IntelliJ, code errors may be detected even if the project can be built and run successfully
.. To resolve this, place your cursor over any of the code section highlighted in red. Press kbd:[ALT + ENTER], and select `Add '--add-modules=...' to module compiler options` for each error
. Repeat this for the test folder as well (e.g. check link:{repoURL}/src/test/java/seedu/address/ui/HelpWindowTest.java[`HelpWindowTest.java`] for code errors, and if so, resolve it the same way)

=== Verifying the setup

. Run the `seedu.address.MainApp` and try a few commands
. <<Testing,Run the tests>> to ensure they all pass.

=== Configurations to do before writing code

==== Configuring the coding style

This project follows https://github.com/oss-generic/process/blob/master/docs/CodingStandards.adoc[oss-generic coding standards]. IntelliJ's default style is mostly compliant with ours but it uses a different import order from ours. To rectify,

. Go to `File` > `Settings...` (Windows/Linux), or `IntelliJ IDEA` > `Preferences...` (macOS)
. Select `Editor` > `Code Style` > `Java`
. Click on the `Imports` tab to set the order

* For `Class count to use import with '\*'` and `Names count to use static import with '*'`: Set to `999` to prevent IntelliJ from contracting the import statements
* For `Import Layout`: The order is `import static all other imports`, `import java.\*`, `import javax.*`, `import org.\*`, `import com.*`, `import all other imports`. Add a `<blank line>` between each `import`

Optionally, you can follow the <<UsingCheckstyle#, UsingCheckstyle.adoc>> document to configure Intellij to check style-compliance as you write code.

==== Updating documentation to match your fork

After forking the repo, the documentation will still have the SE-EDU branding and refer to the `se-edu/addressbook-level4` repo.

If you plan to develop this fork as a separate product (i.e. instead of contributing to `se-edu/addressbook-level4`), you should do the following:

. Configure the <<Docs-SiteWideDocSettings, site-wide documentation settings>> in link:{repoURL}/build.gradle[`build.gradle`], such as the `site-name`, to suit your own project.

. Replace the URL in the attribute `repoURL` in link:{repoURL}/docs/DeveloperGuide.adoc[`DeveloperGuide.adoc`] and link:{repoURL}/docs/UserGuide.adoc[`UserGuide.adoc`] with the URL of your fork.

==== Setting up CI

Set up Travis to perform Continuous Integration (CI) for your fork. See <<UsingTravis#, UsingTravis.adoc>> to learn how to set it up.

After setting up Travis, you can optionally set up coverage reporting for your team fork (see <<UsingCoveralls#, UsingCoveralls.adoc>>).

[NOTE]
Coverage reporting could be useful for a team repository that hosts the final version but it is not that useful for your personal fork.

Optionally, you can set up AppVeyor as a second CI (see <<UsingAppVeyor#, UsingAppVeyor.adoc>>).

[NOTE]
Having both Travis and AppVeyor ensures your App works on both Unix-based platforms and Windows-based platforms (Travis is Unix-based and AppVeyor is Windows-based)

==== Getting started with coding

When you are ready to start coding,

1. Get some sense of the overall design by reading <<Design-Architecture>>.
2. Take a look at <<GetStartedProgramming>>.

== Design

[[Design-Architecture]]
=== Architecture

.Architecture Diagram
image::Architecture.png[width="600"]

The *_Architecture Diagram_* given above explains the high-level design of the App. Given below is a quick overview of each component.

[TIP]
The `.pptx` files used to create diagrams in this document can be found in the link:{repoURL}/docs/diagrams/[diagrams] folder. To update a diagram, modify the diagram in the pptx file, select the objects of the diagram, and choose `Save as picture`.

`Main` has only one class called link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp`]. It is responsible for,

* At app launch: Initializes the components in the correct sequence, and connects them up with each other.
* At shut down: Shuts down the components and invokes cleanup method where necessary.

<<Design-Commons,*`Commons`*>> represents a collection of classes used by multiple other components.
The following class plays an important role at the architecture level:

* `LogsCenter` : Used by many classes to write log messages to the App's log file.

The rest of the App consists of four components.

* <<Design-Ui,*`UI`*>>: The UI of the App.
* <<Design-Logic,*`Logic`*>>: The command executor.
* <<Design-Model,*`Model`*>>: Holds the data of the App in-memory.
* <<Design-Storage,*`Storage`*>>: Reads data from, and writes data to, the hard disk.

Each of the four components

* Defines its _API_ in an `interface` with the same name as the Component.
* Exposes its functionality using a `{Component Name}Manager` class.

For example, the `Logic` component (see the class diagram given below) defines it's API in the `Logic.java` interface and exposes its functionality using the `LogicManager.java` class.

.Class Diagram of the Logic Component
image::LogicClassDiagram.png[width="800"]

[discrete]
==== How the architecture components interact with each other

The _Sequence Diagram_ below shows how the components interact with each other for the scenario where the user issues the command `deleteMember 1`.

.Component interactions for `deleteMember 1` command
image::SDforDeletePerson.png[width="800"]

The sections below give more details of each component.

[[Design-Ui]]
=== UI component

.Structure of the UI Component
image::UiClassDiagram.png[width="800"]

*API* : link:{repoURL}/src/main/java/seedu/address/ui/Ui.java[`Ui.java`]

The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter`, `BrowserPanel` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class.

The `UI` component uses JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the link:{repoURL}/src/main/java/seedu/address/ui/MainWindow.java[`MainWindow`] is specified in link:{repoURL}/src/main/resources/view/MainWindow.fxml[`MainWindow.fxml`]

The `UI` component,

* Executes user commands using the `Logic` component.
* Listens for changes to `Model` data so that the UI can be updated with the modified data.

[[Design-Logic]]
=== Logic component

[[fig-LogicClassDiagram]]
.Structure of the Logic Component
image::LogicClassDiagram.png[width="800"]

*API* :
link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`]

.  `Logic` uses the `RestaurantBookParser` class to parse the user command.
.  This results in a `Command` object which is executed by the `LogicManager`.
.  The command execution can affect the `Model` (e.g. adding a person).
.  The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
.  In addition, the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying help to the user.

Given below is the Sequence Diagram for interactions within the `Logic` component for the `execute("deleteMember 1")` API call.

.Interactions Inside the Logic Component for the `deleteMember 1` Command
image::DeletePersonSdForLogic.png[width="800"]

// tag::model[]
[[Design-Model]]
=== Model component

.Structure of the Model Component
image::ModelClassDiagram.png[width="800"]

.Structure of the Item Interface (split into a separate diagarm for clarity)
image::ModelItemDiagram.png[width="800"]

*API* : link:{repoURL}/src/main/java/seedu/address/model/Model.java[`Model.java`]

The `Model`,

* stores a `UserPref` object that represents the user's preferences.
* stores the Restaurant Book data.
* exposes an unmodifiable `ObservableList<Item>` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
* does not depend on any of the other three components.

// end::model[]

[[Design-Storage]]
=== Storage component

.Structure of the Storage Component
image::StorageClassDiagram.png[width="800"]

*API* : link:{repoURL}/src/main/java/seedu/address/storage/Storage.java[`Storage.java`]

The `Storage` component,

* can save `UserPref` objects in json format and read it back.
* can save the Restaurant Book data in json format and read it back.

[[Design-Commons]]
=== Common classes

Classes used by multiple components are in the `seedu.addressbook.commons` package.

== Implementation

This section describes some noteworthy details on how certain features are implemented.

// tag::addfeature[]

=== Add Feature

The add feature allows the user to add items to the `RestaurantBook`.
It also populates the item added to the `RestaurantBook` with parameters supplied by the user.

==== Current Implementation

The add feature is implemented as four separate commands, one for adding each type of item: `addMember`, `addBooking`, `addIngredient`, `addStaff`.
Each command is implemented as a `AddCommand` class. For example, the `addMember` command is implemented as the `AddMember` class.
All `AddCommand` class inherit from the `Command` class.
As the general flow of the various add commands are similar, the `addMember` command will be used as an example here.
The `AddMemberCommand` class adds the member to the `RestaurantBook` by utilising the `MemberModel#addMember` method exposed by the `MemberModel` interface, which facilitates the interaction with the `VersionedRestaurantBook` to add the member via the `VersionedRestaurantBook#addItem` method.
The state of the `RestaurantBook` is then saved via the `Model#commitRestaurantBook` method exposed by the `Model` interface, which saves the `RestaurantBook` using the `VersionedRestaurantBook#commit` method.

For the `AddBooking` command, the list of bookings is sorted after the new booking is added to ensure that bookings are ordered by time.

==== Design Considerations

**Aspect: Implementation of the four add commands**

* **Alternative 1 (current choice)**: four separate add commands, one for each type of item
** Pros:
*** Easier implementation
** Cons:
*** Causes code duplication, as all the add commands differ only by their parameters, and function similarly otherwise.
*** More types of commands for the user to remember

* **Alternative 2**: a single add command, with a type field to indicate the type of item to be added
** Pros
*** Reduces the number of distinct commands in the RestaurantBook, thus making the `RestaurantBook` a simpler application for users.
** Cons
*** Complicates the add command as the parameters for the add command depend on the command type parameter passed into the command
*** May have to display a long usage guide comprising examples of adding all four types of items

* Decision: Alternative 1 was selected for the following reasons:
** A greater variety of add commands is more intuitive than a single complex command.
** Separating the add commands allows for greater versatility in customising the various add commands.

// end::addfeature[]

// tag::ds[]

=== Data structure for holding records

Following the AB4 structure, the `RestaurantBook` (originally `AddressBook`) class serves as the main database, holding information of all records in the system. However, the database system required is more complicated than the one in AB4- there are four different kinds of records that need to be stored. The main operations are still largely CRUD (create, read, update, delete) in nature which are very similarly done. However, there are some differences between the types of records:

* Some commands such as `addBooking` needs to keep track of the `Capacity` of the restaurant- we must not allow the restaurant to be overbooked. There is no equivalent of this in the `addMember`, `addIngredient` or `addStaff` commands.
* The `editMember` command requires all `Booking` associated to the `Member` to have an updated copy of all the `Member` details. Again, there is no equivalent of this in the other edit-style commands.

==== Current implementation

We created the interface `Item` to represent a record. A `UniqueItemList` was used to handle the bulk of the CRUD logic, much like the way the `UniquePersonList` in the original AB4 was used to handle the CRUD logic. As the `Staff` and `Member` class store common attributes (`Name`, `Phone`, `Email`), an abstract class `Person` was used to capture this. However, in the `Model` interface, the methods are kept separate (using methods like `addMember`, `addBooking` instead of having a more generic `addItem` method).

==== Design Considerations

===== Aspect: Implementation of data structure
* **Alternative 1 (current choice):** Use the `Item` interface to capture the similarity between records.
** Pros: Reduces code duplication as we do not need separate classes `UniqueMemberList`, `UniqueBookingList`, `UniqueIngredientList`, `UniqueStaffList`.
** Cons: As the operations for different records are not exactly the same, RestaurantBook needs to be aware of the differences between the similar operations.

* **Alternative 2:** Create four separate classes which do not inherit from any parent class or interface.
** Pros: The precise CRUD operations can be heavily customised for each type of record.
** Cons: Lots of code duplication.

* Decision: Alternative 1 was adopted as the differences between the operations are relatively minor and can be done at the `RestaurantBook` level without creating too much confusion.

===== Aspect: Implementation of the model interface
* **Alternative 1 (current choice):** Maintain separate methods for the similar-looking CRUD-style methods
** Pros: Easier to implement.
** Cons: More code duplication, the `Model` API now contains many methods.

* **Alternative 2:** Generalize the methods so that there is only one of them for each type of command (e.g. `addItem` instead of `addBooking`, `addMember`) in the Model API.
** Pros: Reduces the overall amount of code needed with less duplication. The `Model` API looks simpler on the surface with less methods.
** Cons: Violates Separation of Concerns principle, due to the differences across the similar-looking methods. Since the implementation of various `add` commands are slightly different (`addBooking` needs to check the restaurant capacity first), many if-else statements will be required in the control flow of `RestaurantBook#addItem` method, potentially using `instanceof` checks. These `instanceof` checks can potentially violate type safety.

* Decision: Alternative 1 was adopted as we value simplicity over the potential problems that might arise with the generic methods.
// end::ds[]

// tag::editcmd[]

=== The `editMember` command

When a `Member` details (`Name`, `Phone`, or `Email`) is changed, the `Booking` object must reflect the change. This requires an internal modification to the `Booking` objects in some way.

==== Current implementation

When `RestaurantBook#setMember()` is called, the bookings are replaced with a new set of bookings. If an existing booking contains the modified member, the member will be replaced with a new `Booking` object that containing the updated member.

==== Proposed implementation

Each member is assigned an ID. Along with this, maintain a master list of ID to `Member` mappings. The `Booking` class only keep tracks of the `Member` s id, calling the `MasterMemberList` to obtain the `Member` object when necessary. The following (simplified) class diagram demonstrates the associations between `Booking`, `MasterMemberList` and `Member`:

.A class diagram showing the proposed implementation of managing the `Booking` and `Member` dependencies. This diagram is heavily simplified as unrelated methods and attributes are not shown.
image::editmemberclassdiagram.png[width="800"]

This proposed implementation simplifies the execution of the `editMember` command. The interactions between the various components of the proposed sequence diagram can be represented as follows:

.A sequence diagram showing the proposed implementation of the `editMember` command. For simplicity, we do not show the `Logic` component and we only focus on the `Model` component.
image::editmembersequencediagram.png[width="800"]

==== Design Considerations

* **Alternative 1 (current choice):** Manually perform a corresponding change to the `Booking` list whenever the personal details of a member changes.
** Pros: Easier to implement as it does not require much change to the already-existing AB4 codebase.
** Cons: Poor efficiency. This involves scanning through the entire list of bookings just to change the personal details of a single `Member`. Also, if some other command changes a `Member` details without going through the `RestaurantBook#setMember()` method, the update will not be reflected.

* **Alternative 2:** Make the `Member` class mutable. Whenever the `Member` details changes, the `Booking` will automatically extract the correct details of the `Member` and nothing needs to be done.
** Pros: This eases the load on the `RestaurantBook` class and does not require special treatment. It is also more efficient as no additional work is done.
** Cons: The current `undo` and `redo` commands rely on the immutabilty of the `Member` class to work correctly. Doing so may require a huge change in implementation of `undo` and `redo` commands. Also, allowing mutable variables can potentially be a source of other bugs.

* **Alternative 3 (proposed) :** Assign each `Member` an ID and store the mapping from ID to `Member`. Instead of storing the full details of the `Member`, the `Booking` object simply stores the `ID` of the member that made the booking. When an update occurs, we simply need to update the ID to `Member` map.
** Pros: The `RestaurantBook#setMember()` method does not depend on the `Booking` class, reducing coupling and dependency. The execution of the `editMember` command only changes `Member` objects without changing `Booking` objects.
** Cons: Uses additional data structure to store the mappings and requires significantly more code changes.

* Decision: Alternative 1 was adopted as we felt that it was the simplest way to implement the feature, requiring minimal code changes to the existing codebase. However, we feel that alternative 3 is a better implementation but did not adopt it due to time constraints.
// end::editcmd[]

// tag::suggestbooking[]

=== Suggesting alternative booking timeslots

REM does not allow additional bookings to be added into the system if this causes the capacity to be exceeded. We want to suggest an alternative timing to the user instead of simply displaying a message saying that the restaurant is full. In order to achieve this, REM calculates the earliest timeslot after the input date and time that can be accepted.

==== Current implementation
All calculations involving the restaurant capacity is done in the `Capacity` class. In particular, the following related methods are implemented:

* `Capacity#canAccomodate(List<Booking> bookings)` -- Checks if the capacity is sufficient to hold the bookings.
* `Capacity#canAddBooking(Booking toAdd, List<Booking> existingBookings)` -- Checks if the booking list stays within capacity after adding the booking. Guarantees immutability of `existingBookings`.
* `Capacity#suggestNextAvailableTime(Booking toAdd, List<Booking> existingBookings)` -- The next available time that the restaurant can accommodate the booking, subjected to the constraint that the returned time must occur after `toAdd`. In other words, suggestion always shifts the booking later and never earlier.


In this document, we will focus on the implementation of `suggestNextAvailableTime`:

.  The program first checks that the input satisfies the preconditions of the method which are required for the method to return a meaningful answer. These are pre-conditions:
.. The number of persons of the booking cannot exceed the capacity value (if my restaurant can only seat 20 people, I will never be able to make space for a booking of 30).
.. `existingBookings` must fit within the capacity (if this condition is violated, it is impossible to add a new booking in a way that fits within capacity).
.  The program then checks if the current booking can be accepted. If yes, the start time of the booking is returned and no further computations needs to be done.
.  As the final answer must correspond to a customer leaving (the best time for a customer to arrive is when another customer leaves), the set of all end times among the existing bookings are generated and sorted in chronological order. This is the list of all the potential answers.
.  For each possible answer, these two conditions are checked:
.. The returned time must be later than the start time of the incoming booking.
.. The incoming booking `toAdd` must fit within the capacity (as determined by `canAddBooking` method) after the time is modified accordingly.
. If both conditions pass, the end time of the booking is successfully returned. The pre-conditions in Step 1 ensures that at least one of the end times is valid. Since the list is sorted, only the earliest one will be returned (i.e. it is impossible to run through the loop without returning an answer).

The current implementation can be described by the following activity diagram:

.An activity diagram that shows the implementation of the `suggestNextAvailableTime` method.
image::suggesttimeslot.png[width='800']

// end::suggestbooking[]
// tag::delete[]
=== Delete Feature

The delete feature is used to delete a specific record in the restaurant book, i.e. deleting a member, staff, booking, ingredient or recipe.
In comparison to the original AB4 codebase, REstaurant Manager has more than 1 type of record in the restaurant book, and has a high level of dependency/ coupling between certain components:

* Between Member and Booking: a booking contains a specific member -  Booking is highly coupled to Member
* Between Ingredient and Recipe: a recipe contains ingredients – Recipe is highly coupled to Ingredient

Therefore, there are some design considerations that we have to make when it comes to deleting a record.

==== Current implementation
* There are separate delete commands for each of the 4 components, namely `deleteMember`, `deleteBooking`, `deleteStaff`, `deleteIngredient` and `deleteRecipe`, and the command explicitly specifies the object being deleted.
 Each specific delete command has a `DeleteCommand` class that extends abstract class `Command` and is supported by a `CommandParser` class (e.g. `deleteIngredient` command has `deleteIngredientCommand` class and `deleteIngredientCommandParser` class).
The sequence diagram for `deleteIngredient` command is as follows: +

.Sequence Diagram for DeleteIngredient
image::DeleteIngredientSequenceDiagram.png[width="630"]

* The delete commands are called by typing the component-specific command, followed by an index, which refers to the index number shown in the most recent listing (e.g. `deleteIngredient 3`).

* When a member is deleted, all booking objects containing the deleted member must be similarly deleted.  Also, when an ingredient is deleted, all recipe objects containing the deleted ingredient must also be deleted.
In other words, when RestaurantBook#deleteMember() or RestaurantBook#deleteIngredient() is called, this triggers all related bookings or recipes to be deleted as well.

==== Design Considerations

===== Aspect: Separate delete commands/ Generic delete command
* ** Alternative 1 (current choice):** separate commands for each component, i.e. `deleteMember`, `deleteBooking`, `deleteStaff`, `deleteIngredient`, `deleteRecipe` to delete from respective lists.
*** Pros: Easier implementation
*** Cons:
** Leads to code duplication, as each delete command requires an additional `Command` and `CommandParser` class.
** Inconvenient for user to type out a longer command (e.g. `deleteIngredient` vs `delete`).

* ** Alternative 2:** one generic delete command, requiring the model to determine the active list (currently displayed list on the panel), and to delete from that particular list
*** Pros: Shorter commands required from user, (e.g. `delete` vs `deleteIngredient`).
*** Cons: Requires user to type in additional command prior to the `delete` command (e.g. list or filter command), to change the state of the intended list to active.

* Decision: Alternative 1 was selected since aliases are implemented as a shortcut to the long commands (e.g. `db` for `deleteBooking`, `dm` for `deleteMember`) and no longer inconvenient for users.
Since 4 panels are implemented in U/I, this provides easy cross-reference across linked records. It is hard for the user to detect an active list at first glance, since all lists are already displayed. With chosen implementation, specific delete command can be called without a prior command to mark the list as active (e.g.  `deleteIngredient` can be called directly to make changes to Ingredient list), providing convenience to user.


===== Aspect: Deletion by index/ Deletion by field
* ** Alternative 1 (current choice):** delete records by index in the most recent listing.
*** Pros:
** Easier implementation as it does not require much change to the already-existing AB4 codebase.
** Standardized command format for all delete commands (e.g. `deleteIngredient INDEX` and `deleteBooking INDEX`).
** Index for a record is easily identified from its corresponding list.

*** Cons:
** Index may be incorrectly typed, especially if the list is too long or there are similar records in the list.
** Unfiltered list may be too long for user to scroll through to find the index. Methods are required to filter the list or find a specific record before `delete INDEX` command is called.

* ** Alternative 2:** delete records by field.
*** Pros: Greater certainty that the right record is deleted.
*** Cons:
** Variations in command format for each delete command. They may have different prefixes and fields that the user has to type in.
** Some records are identified by more than 1 field, and all necessary fields must be provided for successful deletion of a record, making the command longer and harder to type (e.g. `deleteBooking` command requires `bookingWindow` and `customerName` fields to be present to delete a record).

* Decision: Alternative 1 was adopted for greater standardisation across the 5 components (Member, Bookings, Ingredient, Recipe, and Staff).


===== Aspect: Highly coupled records
* ** Alternative 1 (current choice):** Deleting a member will result in the deletion of all bookings done by this member. Similarly, deleting an ingredient will result in the deletion of all recipes using this ingredient.
*** Pros: Automates the deletion process of bookings or recipes, when member or ingredients are deleted.

*** Cons: There is a possibility that the user accidentally deletes a record (e.g. member), and all other records (e.g. bookings made by this member) referencing this record is also accidentally deleted.

* ** Alternative 2:** Only records that are not referenced can be deleted. (e.g. During an attempt to delete a member that has made a booking, an error message is displayed to prompt the user that this member is referenced in the booking list. The user is required to manually delete all bookings done by this member before he is allowed to delete the member).
*** Pros: Reduces the possibility that the user accidentally deletes a record (e.g. member), and all other records (e.g. bookings made by this member) referencing this record is also accidentally deleted.
*** Cons: Inconvenient for the user to manually remove all referencing records before he can delete the referenced record.

* Decision: Alternative 1 was adopted as it is an easier implementation and it makes it more convenient for the user to delete a record. It is intuitive that if a deleteMember or deleteIngredient command is called and these objects cease to exist in the restaurant book, the corresponding Booking or Recipe containing these objects should also cease to exist.
 To deal with the possibility that the member or ingredient is accidentally deleted, and all referenced bookings and recipes is unintentionally deleted, the number of bookings deleted, and all recipe names of recipes deleted will be shown. If the user had accidentally deleted the member or ingredient, he can execute the `undo` command.

The current implementation of `deleteIngredient` can be represented by the activity diagram below: +

.Activity diagram for `deleteIngredient`
image::activity_diagram_deleteingredient.png[width="400"]
The indication of the deletion of associated recipes when a particular ingredient is deleted is shown below:

.Printed message for deleted recipes after an ingredient is deleted
image::deleteingredientss.png[width="300"]

// end::delete[]

// tag::shifts[]

=== Shifts feature

The shifts feature allows users to maintain shift rosters for staff members.

==== Current Implementation

The shifts feature comprises of two main commands: the `addshift` command and the `deleteshift` command.
The `addshift` command allows shifts to be added to the shift roster of a staff member, and the `deleteshift` command allows shifts to be deleted from the shift roster of a staff member.
The shifts feature is supported by two models, the `Shift` model and the `ShiftRoster` model. The `Shift` model represents a single shift that takes place during a single interval of time, while the `ShiftRoster` model stores an immutable, sorted list of shifts for a single staff member. The following (simplified) class diagram shows the relationship between the `Staff`, `ShiftRoster` and `Shift` classes.

image::ShiftClassDiagram.png[width="1000"]

The following seqeuence diagram shows how the `addshift` command works, with some details in the model component omitted.

image::AddShiftSequenceDiagram.png[width="1000"]

==== Design Considerations

===== Aspect: Implementation of the shift roster

* **Alternative 1 (current choice):** Store a weekly shift roster for each staff member, which stores a list of sorted shifts.
** Pros:
*** Enables the possibility of storing shifts for staff members who work multiple shifts.
** Cons:
*** Must ensure that there are no clashes between any two shifts in a single shift roster.

* **Alternative 2:** Each staff member can only have one shift over a single interval of time.
** Pros:
*** Easy to implement.
** Cons:
*** Impossible to represent all the shifts for staff members that work for more than one shift.

** Decision: Alternative 1 was adopted as it provides greater versatility, and it is likely for a single staff member to work different shifts on multiple days in a week.

===== Aspect: Implementation of the time range of shifts

* **Alternative 1 (current choice):** Represent weekly shifts by storing the start day and time as well as the end day and time in a date range, where the start day and end day are different.
** Pros:
*** Enables to possibility of storing shifts across multiple days, thereby providing restaurant owners with the flexibility to define shifts in terms of day ranges instead of time ranges.
*** Greater certainty as to exactly when a shift starts and ends.
*** Allows validation checks by ensuring that shifts are of positive duration.
** Cons:
*** Tedious to check if two shifts clash in the shift roster.

* **Alternative 2:** Represent weekly shifts by storing only the start day, start time and end time. If the end time is before the start time, then it is assumed that the shift ends on the next day.
** Pros:
*** Easy to implement.
*** Easy to check if two shifts clash in the shift roster.
** Cons:
*** Impossible to provide validation checks as there are no invalid shifts.
*** Implicit assumption that the shift ends on the following day if the end time is earlier than the start time may be confusing for users.

** Decision: Alternative 1 was adopted as it allows shifts to be more flexible, and provides greater certainty for the time intervals of the shifts.

===== Aspect: Implementation of the `deleteShift` command

* **Alternative 1 (current choice):** Requiring the user to specify the exact start day and time as well as the end day and time of the shift to be deleted.
** Pros:
*** Provides greater certainty for the shift that is to be deleted as shifts are not indexed.
*** Requiring the user to key in the exact shift to be deleted acts as a form of confirmation for the deletion.
** Cons:
*** Causes the command to be long winded and hard to type.

* ** Alternative 2:** Requiring the user to specify the index of the shift to be deleted.
** Pros:
*** Reduces the number of parameters in the `deleteShift` command, thus making the command easier to type.
** Cons:
*** As the shifts are not indexed, the user may delete the incorrect shift by mistake.

* Decision: Alternative 1 was adopted as it is more reliable and provides certainty for which shift is to be deleted.

// end::shifts[]

// tag::stats[]
=== The `statstime` command

When the `statstime` command is entered, the current statistics of the amount of bookings is to be displayed to the user in the form of a bar chart, where each bar corresponds to the number of customers in a particular time of the day.

==== Current implementation

When the user enters the `statstime` command, the command will be parsed, and the `Statistics` class would be called. The Statistics class fetches the relevant data for user display (ie what are the axes, values, and legends of the bar chart). It would then call the `StatsWindow` class which handles the UI. The bar chart will appear in a new window and does not affect the current window.

.StatsTime Sequence Diagram
image::StatsTimeSequenceDiagram.png[width="1000"]

The _Sequence Diagram_ given above shows how the components interact with each other for the scenario where the user issues the command `statstime 100`.

==== Design Considerations

===== Aspect: Implementation of data structure

* **Alternative 1 (current choice):** Doing the calculation only when the user wants to view the statistics.
** Pros: Calculating only when needed is more efficient.
** Cons: The command would take some time to calculate before being able to display the statistics.

* **Alternative 2:** Every change to the database updates the statistics on the fly.
** Pros: Displaying the statistics on the UI would be faster.
** Cons: Need to change the implementation of every command that causes a change to the database. Calculations have to be done every operation, potentially affecting the efficiency of the `add` or `delete` commands.

* Decision: Alternative 1 was adopted as the other commands do not need to be changed and it is easier to implement. As the number of times the `stats` command is called is likely to be low as compared to an `add` or `delete` operation, doing the calculation after every operation would be a waste of computation power.

===== Aspect: Design of UI display

* **Alternative 1 (current choice):** Displaying the statistics in a new window.
** Pros: The statistics would be displayed independently from the database and would not interfere with each other.
** Cons: The user can open multiple windows which contains different data and not know which is the correct window.

* **Alternative 2:** Hide the displayed database to show the statistics. A separate command would be used to toggle the view.
** Pros: There would be only 1 window to manage at any point in time.
** Cons: Cannot view the statistics and the database concurrently.

* Decision: Alternative 1 was adopted as it is an easier implementation. Implementing the `stats` window as a static window that will not change would not affect the other parts of the app, and there is no need to hide and show the current screen. Moreover, the user might want to view the statistics together with the database, which is only possible with multiple windows.

=== The `statsdays` command

When the `statsdays` command is entered, the current statistics of the amount of bookings is to be displayed to the user in the form of a bar chart, where each bar corresponds to the number of customers between certain dates.

As the implementation of this command is very similar to <<The `statstime` command>>, it will not be covered.

// end::stats[]

// tag::panelui[]
=== The panel UI for `Member`, `Staff`, `Booking`, and `Ingredient`

The restaurant book displays the entire database in the form of "cards", which is the same as AB4. Each item has its own panel.

==== Current implementation

The panel is formatted in the `ItemListPanel.fxml` file, and each item has its own controller (`MemberListPanel`, `StaffListPanel`, `BookingListPanel`, and `IngredientListPanel`) that extends from `ItemListPanel`. The panel displays the database via cards. Each item has its own card (`MemberCard`, `StaffCard`, `BookingCard`, and `IngredientCard`).

image::itemListPanelClassDiagram.png[width="1000"]

==== Design Considerations

===== Aspect: Design of card display

* **Alternative 1 (current choice):** Making a separate fxml file for each type of item card.
** Pros: Able to customise the card to suit the item.
** Cons: Need to duplicate common elements that all the cards share, such as the numbering on the list.

* **Alternative 2:** Using the same fxml file for each item card.
** Pros: Less duplication.
** Cons: Hard to customise the contents of each card.

* Decision: Alternative 1 was adopted as each card do not share much in common other than the numbering on the list. Each card needs to display different information. For example, the `Member` item would need to display the email, while the `Ingredient` item would need to display other fields such as the quantity. Hence, not much code is duplicated, and creating 4 files would be the easiest implementation.

===== Aspect: Design of panel display

* **Alternative 1 (current choice):** Using the same fxml file for each item panel.
** Pros: Less duplication.
** Cons: Hard to customise the contents of each panel.

* **Alternative 2:** Making a separate fxml file for each item panel
** Pros: Able to customise the panel to suit the item.
** Cons: Need to duplicate common elements that all the item panels share.

* Decision: Alternative 1 was adopted. Currently, the only difference between the panels is the header (implemented via a `label`) which contains the name of the item type. This only affects a single label, which is easy to edit via code. Hence, sharing the fxml file reduces the code duplication. If the display of the panels were to be modified in the future, say to add more padding or to change the size, only one fxml file needs to be modified.
// end::panelui[]

=== Logging

We are using `java.util.logging` package for logging. The `LogsCenter` class is used to manage the logging levels and logging destinations.

* The logging level can be controlled using the `logLevel` setting in the configuration file (See <<Implementation-Configuration>>)
* The `Logger` for a class can be obtained using `LogsCenter.getLogger(Class)` which will log messages according to the specified logging level
* Currently log messages are output through: `Console` and to a `.log` file.

*Logging Levels*

* `SEVERE` : Critical problem detected which may possibly cause the termination of the application
* `WARNING` : Can continue, but with caution
* `INFO` : Information showing the noteworthy actions by the App
* `FINE` : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size

[[Implementation-Configuration]]
=== Configuration

Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: `config.json`).

== Documentation

We use asciidoc for writing documentation.

[NOTE]
We chose asciidoc over Markdown because asciidoc, although a bit more complex than Markdown, provides more flexibility in formatting.

=== Editing Documentation

See <<UsingGradle#rendering-asciidoc-files, UsingGradle.adoc>> to learn how to render `.adoc` files locally to preview the end result of your edits.
Alternatively, you can download the AsciiDoc plugin for IntelliJ, which allows you to preview the changes you have made to your `.adoc` files in real-time.

=== Publishing Documentation

See <<UsingTravis#deploying-github-pages, UsingTravis.adoc>> to learn how to deploy GitHub Pages using Travis.

=== Converting Documentation to PDF format

We use https://www.google.com/chrome/browser/desktop/[Google Chrome] for converting documentation to PDF format, as Chrome's PDF engine preserves hyperlinks used in webpages.

Here are the steps to convert the project documentation files to PDF format.

.  Follow the instructions in <<UsingGradle#rendering-asciidoc-files, UsingGradle.adoc>> to convert the AsciiDoc files in the `docs/` directory to HTML format.
.  Go to your generated HTML files in the `build/docs` folder, right click on them and select `Open with` -> `Google Chrome`.
.  Within Chrome, click on the `Print` option in Chrome's menu.
.  Set the destination to `Save as PDF`, then click `Save` to save a copy of the file in PDF format. For best results, use the settings indicated in the screenshot below.

.Saving documentation as PDF files in Chrome
image::chrome_save_as_pdf.png[width="300"]

[[Docs-SiteWideDocSettings]]
=== Site-wide Documentation Settings

The link:{repoURL}/build.gradle[`build.gradle`] file specifies some project-specific https://asciidoctor.org/docs/user-manual/#attributes[asciidoc attributes] which affects how all documentation files within this project are rendered.

[TIP]
Attributes left unset in the `build.gradle` file will use their *default value*, if any.

[cols="1,2a,1", options="header"]
.List of site-wide attributes
|===
|Attribute name |Description |Default value

|`site-name`
|The name of the website.
If set, the name will be displayed near the top of the page.
|_not set_

|`site-githuburl`
|URL to the site's repository on https://github.com[GitHub].
Setting this will add a "View on GitHub" link in the navigation bar.
|_not set_

|`site-seedu`
|Define this attribute if the project is an official SE-EDU project.
This will render the SE-EDU navigation bar at the top of the page, and add some SE-EDU-specific navigation items.
|_not set_

|===

[[Docs-PerFileDocSettings]]
=== Per-file Documentation Settings

Each `.adoc` file may also specify some file-specific https://asciidoctor.org/docs/user-manual/#attributes[asciidoc attributes] which affects how the file is rendered.

Asciidoctor's https://asciidoctor.org/docs/user-manual/#builtin-attributes[built-in attributes] may be specified and used as well.

[TIP]
Attributes left unset in `.adoc` files will use their *default value*, if any.

[cols="1,2a,1", options="header"]
.List of per-file attributes, excluding Asciidoctor's built-in attributes
|===
|Attribute name |Description |Default value

|`site-section`
|Site section that the document belongs to.
This will cause the associated item in the navigation bar to be highlighted.
One of: `UserGuide`, `DeveloperGuide`, ``LearningOutcomes``{asterisk}, `AboutUs`, `ContactUs`

_{asterisk} Official SE-EDU projects only_
|_not set_

|`no-site-header`
|Set this attribute to remove the site navigation bar.
|_not set_

|===

=== Site Template

The files in link:{repoURL}/docs/stylesheets[`docs/stylesheets`] are the https://developer.mozilla.org/en-US/docs/Web/CSS[CSS stylesheets] of the site.
You can modify them to change some properties of the site's design.

The files in link:{repoURL}/docs/templates[`docs/templates`] controls the rendering of `.adoc` files into HTML5.
These template files are written in a mixture of https://www.ruby-lang.org[Ruby] and http://slim-lang.com[Slim].

[WARNING]
====
Modifying the template files in link:{repoURL}/docs/templates[`docs/templates`] requires some knowledge and experience with Ruby and Asciidoctor's API.
You should only modify them if you need greater control over the site's layout than what stylesheets can provide.
The SE-EDU team does not provide support for modified template files.
====

[[Testing]]
== Testing

=== Running Tests

There are three ways to run tests.

[TIP]
The most reliable way to run tests is the 3rd one. The first two methods might fail some GUI tests due to platform/resolution-specific idiosyncrasies.

*Method 1: Using IntelliJ JUnit test runner*

* To run all tests, right-click on the `src/test/java` folder and choose `Run 'All Tests'`
* To run a subset of tests, you can right-click on a test package, test class, or a test and choose `Run 'ABC'`

*Method 2: Using Gradle*

* Open a console and run the command `gradlew clean allTests` (Mac/Linux: `./gradlew clean allTests`)

[NOTE]
See <<UsingGradle#, UsingGradle.adoc>> for more info on how to run tests using Gradle.

*Method 3: Using Gradle (headless)*

Thanks to the https://github.com/TestFX/TestFX[TestFX] library we use, our GUI tests can be run in the _headless_ mode. In the headless mode, GUI tests do not show up on the screen. That means the developer can do other things on the Computer while the tests are running.

To run tests in headless mode, open a console and run the command `gradlew clean headless allTests` (Mac/Linux: `./gradlew clean headless allTests`)

=== Types of tests

We have two types of tests:

.  *GUI Tests* - These are tests involving the GUI. They include,
.. _System Tests_ that test the entire App by simulating user actions on the GUI. These are in the `systemtests` package.
.. _Unit tests_ that test the individual components. These are in `seedu.address.ui` package.
.  *Non-GUI Tests* - These are tests not involving the GUI. They include,
..  _Unit tests_ targeting the lowest level methods/classes. +
e.g. `seedu.address.commons.StringUtilTest`
..  _Integration tests_ that are checking the integration of multiple code units (those code units are assumed to be working). +
e.g. `seedu.address.storage.StorageManagerTest`
..  Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together. +
e.g. `seedu.address.logic.LogicManagerTest`


=== Troubleshooting Testing
**Problem: `HelpWindowTest` fails with a `NullPointerException`.**

* Reason: One of its dependencies, `HelpWindow.html` in `src/main/resources/docs` is missing.
* Solution: Execute Gradle task `processResources`.

== Dev Ops

=== Build Automation

See <<UsingGradle#, UsingGradle.adoc>> to learn how to use Gradle for build automation.

=== Continuous Integration

We use https://travis-ci.org/[Travis CI] and https://www.appveyor.com/[AppVeyor] to perform _Continuous Integration_ on our projects. See <<UsingTravis#, UsingTravis.adoc>> and <<UsingAppVeyor#, UsingAppVeyor.adoc>> for more details.

=== Coverage Reporting

We use https://coveralls.io/[Coveralls] to track the code coverage of our projects. See <<UsingCoveralls#, UsingCoveralls.adoc>> for more details.

=== Documentation Previews
When a pull request has changes to asciidoc files, you can use https://www.netlify.com/[Netlify] to see a preview of how the HTML version of those asciidoc files will look like when the pull request is merged. See <<UsingNetlify#, UsingNetlify.adoc>> for more details.

=== Making a Release

Here are the steps to create a new release.

.  Update the version number in link:{repoURL}/src/main/java/seedu/address/MainApp.java[`MainApp.java`].
.  Generate a JAR file <<UsingGradle#creating-the-jar-file, using Gradle>>.
.  Tag the repo with the version number. e.g. `v0.1`
.  https://help.github.com/articles/creating-releases/[Create a new release using GitHub] and upload the JAR file you created.

=== Managing Dependencies

A project often depends on third-party libraries. For example, Address Book depends on the https://github.com/FasterXML/jackson[Jackson library] for JSON parsing. Managing these _dependencies_ can be automated using Gradle. For example, Gradle can download the dependencies automatically, which is better than these alternatives:

[loweralpha]
. Include those libraries in the repo (this bloats the repo size)
. Require developers to download those libraries manually (this creates extra work for developers)

// tag::appendixAB[]
[appendix]
== Product Scope

*Target user profile*: a restaurant owner who:

* has a need to manage a significant number of <<restaurant-records, restaurant records>>
* prefer desktop apps over other types
* can type fast
* prefers typing over mouse input
* is reasonably comfortable using <<cli, CLI>> apps

*Value proposition*: manage records faster than a typical mouse/GUI driven app

[appendix]
== User Stories

Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (unlikely to have) - `*`

[width="59%",cols="22%,<23%,<25%,<30%",options="header",]
|=======================================================================
|Priority |As a ... |I want to ... |So that I can...
|`* * *` |restaurant owner |*Member Management:* keep track of the members of the restaurant |reward members with special benefits

|`* * *` |restaurant owner |*Booking Management:* manage the bookings made by customers |ensure customers who have made bookings have a table

|`* * *` |restaurant owner |*Booking Management:* view which bookings clash and which are available |ensure restaurant will not be overbooked

|`* * *` |restaurant owner |*Inventory Management:* keep track of food inventory |do necessary restocking

|`* * *` |restaurant owner |*Inventory Management:* keep track of my recipes and necessary ingredients |know what customers can order

|`* * *` |restaurant owner |*Staff Management:* keep track of the staff working for my restaurant |hire staff accordingly

|`* * *` |restaurant owner |*Staff Management:* keep track of what shift each staff is working |assign shifts and pay them accordingly

|`* *` |restaurant owner |*Booking Management:* view the statistics of customers |plan for resources and for future business expansion

|`* *` |restaurant owner |*Booking Management:* view the frequency statistics based on booking time |hire more staff at peak periods appropriately

|`* *` |restaurant owner |*Inventory Management:* predict how many dishes can be prepared with current food inventory |plan for business operations

|`*` |restaurant owner |keep track of my profits |

|`*` |restaurant owner |view my total expenditure |

|`*` |restaurant owner |keep track of customer feedback |improve on my restaurant
|=======================================================================

// end::appendixAB[]


[appendix]

// tag::usecases[]
== Use Cases

(For all use cases below, the *System* is the `RestaurantBook` and the *Actor* is the `user`, unless specified otherwise)

[discrete]
=== Use case: Add member

*MSS*

1.  User requests to add member
2.  RestaurantBook adds the member
3.  RestaurantBook shows a list of members
+
Use case ends.

*Extensions*

[none]
* 1a. The member already exists.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

* 3a. The member data is given in the wrong format.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

[discrete]
=== Use case: Delete member

*MSS*

1.  User requests to list members
2.  RestaurantBook shows a list of members
3.  User requests to delete a specific member in the list
4.  RestaurantBook deletes the member
+
Use case ends.

*Extensions*

[none]
* 2a. The list is empty.
+
Use case ends.

* 3a. The given index is invalid.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 2.

[discrete]
=== Use case: List members

*MSS*

1.  User requests to list members and gives a list of words
2.  RestaurantBook shows a list of members whose name contains any of the words given
+
Use case ends.

*Extensions*

[none]
* 1a. The list of words given is empty
+
[none]
** 3a1. RestaurantBook lists all members instead.
+
Use case resumes at step 1.

[discrete]
=== Use case: Add booking

*MSS*

1.  User requests to add booking
2.  RestaurantBook adds the booking
3.  RestaurantBook shows a list of bookings
+
Use case ends.

*Extensions*

[none]
* 1a. The booking already exists.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

* 3a. The booking data is given in the wrong format.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

[discrete]
=== Use case: Delete booking

*MSS*

1.  User requests to list bookings
2.  RestaurantBook shows a list of bookings
3.  User requests to delete a specific booking in the list
4.  RestaurantBook deletes the booking
+
Use case ends.

*Extensions*

[none]
* 2a. The list is empty.
+
Use case ends.

* 3a. The given index is invalid.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 2.

[discrete]
=== Use case: Add ingredient

*MSS*

1.  User requests to add ingredient
2.  RestaurantBook adds the ingredient
3.  RestaurantBook shows a list of ingredients
+
Use case ends.

*Extensions*

[none]
* 1a. The ingredient already exists.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

* 3a. The ingredient data is given in the wrong format.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

[discrete]
=== Use case: Delete ingredient

*MSS*

1.  User requests to list ingredients
2.  RestaurantBook shows a list of ingredients
3.  User requests to delete a specific ingredient in the list
4.  RestaurantBook deletes the ingredient
+
Use case ends.

*Extensions*

[none]
* 2a. The list is empty.
+
Use case ends.

* 3a. The given index is invalid.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 2.

=== Use case: Add staff

*MSS*

1.  User requests to add staff
2.  RestaurantBook adds the staff
3.  RestaurantBook shows a list of staff
+
Use case ends.

*Extensions*

[none]
* 1a. The staff to be added already exists.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

* 3a. The staff data is given in the wrong format.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 1.

[discrete]
=== Use case: Delete staff

*MSS*

1.  User requests to list staff
2.  RestaurantBook shows a list of staff
3.  User requests to delete a specific staff in the list
4.  RestaurantBook deletes the staff
+
Use case ends.

*Extensions*

[none]
* 2a. The list is empty.
+
Use case ends.

* 3a. The given index is invalid.
+
[none]
** 3a1. RestaurantBook shows an error message.
+
Use case resumes at step 2.
// end::usecases[]

[appendix]
== Non Functional Requirements

.  Should work on any <<mainstream-os,mainstream OS>> as long as it has Java `9` or higher installed.
.  Should be able to hold up to 200 <<restaurant-records, restaurant records>> without a noticeable sluggishness in performance for typical usage.
.  Should be able to respond to every command in less than 3 seconds on any mainstream OS.
.  System should be able to start up in less than 10 seconds on any mainstream OS.
.  A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
.  Should be able to retain and recover restaurant records in the event of a program crash or forced shut-down.
.  Should still work even without internet access.

[appendix]
== Glossary

[[cli]] Command-Line-Interface::
Text-based interface where the user is required to issue commands to the program in the form of successive lines of text.

[[mainstream-os]] Mainstream OS::
Windows, Linux, Unix, OS-X

[[restaurant-records]] Restaurant Records::
Information pertaining to ingredient and recipe inventory, staff, members and bookings of a restaurant

[appendix]
== Instructions for Manual Testing

Given below are instructions to test the app manually.

[NOTE]
These instructions only provide a starting point for testers to work on; testers are expected to do more _exploratory_ testing.

=== Launch and Shutdown

. Initial launch

.. Download the jar file and copy into an empty folder
.. Double-click the jar file +
   Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.

. Saving window preferences

.. Resize the window to an optimum size. Move the window to a different location. Close the window.
.. Re-launch the app by double-clicking the jar file. +
   Expected: The most recent window size and location is retained.

=== Add and delete members
. Add and delete members
.. Prerequisites: List all members using the `listMembers` command. List of all members should be empty. The whole restaurant book can be cleared using the `clear` command
.. Test case: `addmember n/John Doe p/98765432 e/johnd@example.com l/12` +
   Expected: A new member is added. The name, phone number, email, as well as loyalty points is shown in the Member column.
.. Test case: `addmember n/Alice Smith p/91234567 e/alice.s@example.com` +
   Expected: A new member with 0 loyalty points is added. The name, phone number, email, as well as loyalty points is shown in the Member column.
.. Test case: `deletemember 1` +
   Expected: The member corresponding to the first index is deleted.

=== List members
. List members by name and/or loyalty points
.. Prerequisites: List all members using the `listMembers` command. List of all members should be empty. The whole restaurant book can be cleared using the `clear` command
.. Test case: `addmember n/John Doe p/98765432 e/johnd@example.com l/12` +
   Expected: A new member is added.
.. Test case: `addmember n/Jane Doe p/98765433 e/janed@example.com l/23` +
   Expected: A new member is added.
.. Test case: `addmember n/Alice Smith p/98765434 e/alices@example.com l/100` +
   Expected: A new member is added.
.. Test case: `listmembers n/doe` +
   Expected: `John Doe` and `Jane Doe` are listed.
.. Test case: `listmembers n/doe l/20` +
   Expected: `Jane Doe` is listed.
.. Test case: `listmembers l/20` +
   Expected: `Jane Doe` and `Alice Smith` are listed.
.. Test case: `listmembers` +
   Expected: All members are listed.

=== Add and delete bookings
. Add and delete bookings
.. Prerequisites: List all members using the `listMembers` command. List of members is non-empty.
.. Test case: `addbooking c/1 n/7 ts/2019-04-07T12:00`
   Expected: A new booking is added. The name, phone number, booking time as well as number of persons is shown in the Booking column.
.. Test case: `deletebooking 1`
   Expected: The booking corresponding to the first index is deleted.

=== Capacity tests for booking feature
. Test that the capacity constraint is enforced
.. Prerequisites: At least 2 members listed using the `listMembers` command. Booking column should be empty (if not, delete the bookings as per previous section). The commands below are to be executed in sequence with no other commands in between.
.. Test case: `updateCapacity 10` +
   Expected: The capacity is successfully updated to 10 with a suitable message shown. The booking panel should show an updated capacity value. If this value is not shown, increase the height of the app.

.If the booking panel looks like the left, the height of the app is too small. Increase the height to make it look like the one on the right.
image::capacitypanel.png[width="400"]

[start=3]
.. Test case: `addbooking c/1 n/7 ts/2019-04-07T12:00` +
   Expected: The booking is successfully added into the system.
.. Test case: `addbooking c/2 n/7 ts/2019-04-07T11:30` +
   Expected: The system rejects the booking and instead suggests an alternative timeslot of 2019-04-07T13:00. (Explanation: if this booking is accepted, there will be 7+7=14 customers in the restaurant at 2019-04-07T12:00. This exceeds the capacity of 10 and thus REM rejects the booking. For more details, refer to `addbooking` command in the User Guide.)
.. Test case: `addbooking c/2 n/7 ts/2019-04-07T10:30` +
   Expected: The booking is successfully added into the system. (Explanation: REM assumes that bookings last for 1 hour. Since this member is expected to leave by 2019-04-07T11:30, the restaurant will be empty at 2019-04-07T12:00. This set of bookings does not cause the capacity of 10 to be exceeded. For more details, refer to `addbooking` command in the User Guide.)


=== List ingredients test for ingredient feature
. Test that the `listIngredients` command lists ingredients with key word and/or ingredient quantity falling below ingredient warning amount.
.. Prerequisites: Ingredient panel should be empty, if not, execute `deleteIngredient` command (Refer to User Guide). The commands below are to be executed in sequence.
.. Test case: +
`addIngredient in/tomato q/20 w/10 u/whole`  +
`addIngredient in/tomato ketchup q/20 w/10 u/bottles` +
`addIngredient in/tomato soup q/10 w/20 u/cans` +
`addIngredient in/potato q/10 w/20 u/sacks` +
Expected: 4 ingredients, tomato, tomato ketchup, tomato soup and potato are added into ingredient panel. Upon success, ingredient panel should look like this:
+
.Successfully adding 4 ingredients into restaurant book
image::addIngredients.png[width=1000]

.. Test case: `listIngredients in/tomato`  +
Expected: 3 ingredients, tomato, tomato ketchup and tomato soup containing the word "tomato" are listed on the ingredient panel. Upon success, ingredient panel should look like this:
+
.Successfully listing 3 ingredients in ingredient panel
image::listIngredients_tomato.png[width=1000]

.. Test case: `listIngredients in/tomato w/`  +
Expected: 1 ingredient, tomato soup, containing the word "tomato", and ingredient quantity falling below ingredient warning amount is listed on the ingredient panel. Upon success, ingredient panel should look like this:
+
.Successfully listing 1 ingredient in ingredient panel
image::listingredients_tomato_warningamt.png[width=1000]

.. Test case: +
`listIngredients` +
`consumeIngredient i/1 q/15`  +
Expected: 15 units of tomatoes are consumed, ingredient quantity of tomato in ingredient panel changes to 5 whole tomatoes. Upon success, ingredient panel should look like this:
+
.Successfully consuming 1 ingredient in ingredient panel
image::consumeIngredient.png[width=1000]

.. Test case: `listIngredients in/tomato w/`  +
Expected: 2 ingredients, tomato soup and tomato, containing the word "tomato", and ingredient quantity falling below ingredient warning amount is listed on the ingredient panel. Upon success, ingredient panel should look like this:
+
.Successfully listing 2 ingredients in ingredient panel
image::listIngredient_tomato_warningamt2.png[width=1000]

=== Number of servings test for recipe feature
. Test that the number of servings in recipe is correctly calculated based on ingredient quantity in inventory (ingredient panel) and ingredient quantity per serving (recipe panel).
.. Prerequisites: Recipe and ingredient panels should be empty, if not, execute `deleteIngredient` and `deleteRecipe` commands (Refer to User Guide). The commands below are to be executed in sequence.
.. Test case: +
`addIngredient in/cheese u/slices q/20` +
`addIngredient in/fries u/packets q/10` +
   Expected: 2 ingredients, cheese and fries are added into ingredient panel. Upon success, ingredient panel should look like this:
+
.Successfully adding 2 ingredients into restaurant book
image::addRecipe-addIngredientCommand.png[width=1000]

.. Test case: `addRecipe r/cheese fries iq/1&1 iq/2&1` +
   Expected: 1 recipe, cheese fries is added into recipe panel. Each serving of cheese fries requires 1 slice of cheese and 1 packet of fries with 10 number of servings possible.
   Upon success, recipe panel should look like this:
+
.Successfully adding 1 recipe, displaying the number of servings possible.
image::addRecipe-successful.png[width=1000]

.. Test case: `restockIngredient i/2 q/10` +
   Expected: 1 ingredient, fries is restocked by 10 packets, ingredient quantity of fries in ingredient panel changes to 20 packets.
   Number of servings possible for cheese fries changes to 20. (For more details, refer to `addRecipe` command in the User Guide.)
+
.Successfully restocking 1 ingredient, displays the new number of servings possible.
image::addRecipe-restockIngredient.png[width=1000]

=== Add, edit and delete staff
. Add, edit and delete staff
.. Test case: `addstaff n/Jane Smith p/91234567 e/jsmith@example.com a/Server`
   Expected: A new staff is added. The name, phone number, email and appointment is shown in the Staff column.
.. Test case `editstaff 1 p/97654321 a/Head Chef`
   Expected: The phone number and appointment of the staff corresponding to the first index is updated.
.. Test case: `deletestaff 1`
   Expected: The staff corresponding to the first index is deleted.

=== List staff
. List staff
.. Prerequisites: Staff panel should be empty. Then, the commands below must be executed in sequence.
... `addstaff n/Jane Smith p/91234567 e/jsmith@example.com a/Server`
... `addstaff n/Jack Smith p/92345678 e/jasmith@example.com a/Server`
... `addstaff n/Jack Tan p/91234567 e/jtan@example.com a/Cook`
... `addstaff n/Simon Loh p/91234567 e/sloh@example.com a/Cook`
.. After executing the four commands above, the staff panel should look like that in figure 25 below.
+
.The staff panel after the four commands above have been executed
image::liststaff_prereq.png[width=1000]
+
.. Test case: `liststaff`
   Expected: All four staff added by the command above are listed.
.. Test case: `liststaff n/smith`
   Expected: The two staff members whose names contain the word 'smith' are listed, as shown in figure 26 below.
+
.The staff panel after the `liststaff n/smith` command has been executed
image::liststaff_smith.png[width=1000]
+
.. Test case: `liststaff a/cook`
   Expected: The two staff members whose appointments contain the word 'cook' are listed, as shown in figure 27 below.
+
.The staff panel after the `liststaff a/cook` command has been executed
image::liststaff_cook.png[width=1000]
+
.. Test case: `liststaff n/jack a/server`
   Expected: The staff member whose name contains the word 'jack' and whose appointment contains the word `server` are listed, as shown in figure 28 below.
+
.The staff panel after the `liststaff n/jack a/server` command has been executed
image::liststaff_jack_server.png[width=1000]
+
.. Test case: `liststaff n/simon a/server`
   Expected: No staff members should be listed, as shown in figure 29 below.
+
.The staff panel after the `liststaff n/simon a/server` command has been executed
image::liststaff_simon_server.png[width=1000]


=== Add and delete shifts
. Add shifts
.. Prerequisites: List all staff using the `listStaff` command. List of staff has size of at least 2. The staff corresponding to the first and second index have no shifts.
.. Test case: `addshift 1 sd/MONDAY ts/12:00 ed/MONDAY te/14:00`
   Expected: The shift is successfully added to the staff corresponding to the first index.
. Test that the constraints for shifts is enforced
.. Test case: `addshift 1 sd/MONDAY ts/13:00 ed/MONDAY te/15:00`
   Expected: The system rejects the shift. (Explanation: It clashes with the shift on MONDAY, 12:00 to MONDAY, 14:00.)
.. Test case: `addshift 1 sd/MONDAY ts/16:00 ed/MONDAY te/10:00`
   Expected: The system rejects the shift. (Explanation: Shifts must not end on the same start day of week but at an earlier time.)
.. Test case: `addshift 2 sd/SUNDAY ts/00:00 ed/SATURDAY te/23:59`
   Expected: The shift is successfully added to the staff corresponding to the second index.
.. Test case: `addshift 2 sd/SATURDAY ts/23:59 ed/SUNDAY te/00:00`
   Expected: The system rejects the shift. (Explanation: The total durations of all shifts for a single staff must not last longer than one week.)
. Delete shifts
.. Test case: `deleteshift 1 sd/MONDAY ts/12:00 ed/MONDAY te/14:00 `
   Expected: The shift on MONDAY, 12:00 to MONDAY, 14:00 corresponding to the first staff is deleted.
.. Test case: `deleteshift 1 sd/MONDAY ts/16:00 ed/MONDAY te/18:00 `
   Expected: The system rejects the attempt to delete the shift. (Explanation: The first staff does not have a shift from MONDAY, 16:00 to MONDAY, 18:00.)

=== Statistics
. Test that the statistics feature displays the bar graph correctly.
.. Prerequisites: There are exactly 3 bookings with date being: today's date, yesterday's date, and the day before's date
.. Test case: `statsdays 3` +
   Expected: A new window appears displaying a bar graph with 3 bars. The height of the bar is the number of customers in each booking.
.. Test case: `statsdays 10` +
   Expected: A new window appears displaying a bar graph spanning 10 days, but only 3 of them have a bar. The height of the bar is the number of customers in each booking. +

.Bar graph displayed by `statsdays 10` command
image::statsdays_example.png[width="700"]

The image above shows the new window, and the current bookings. The screenshot is taken on 15 April 2019.

[start=4]
.. Test case: `statstime 3` +
   Expected: A new window appears displaying a bar graph. The height of the bar is the number of customers in that specific time slot.

.Bar graph displayed by `statstime 3` command
image::statstime_example.png[width="700"]

The image above shows the new window, and the current bookings. The screenshot is taken on 15 April 2019.
