Developer Guide
Table of Contents
- Table of Contents
- Acknowledgements
- Setting up, getting started
- Design
-
Implementation
- Book Management
- Toggling between vendor and guest list
- Checking in a Guest
- Checking in a returning Guest
- Editing a Guest
- Editing a Vendor
- Charging a guest
- Checking out a Guest
- Filter feature
- Deleting a Guest
- Deleting a Vendor
- Clear all Guest
- Clear all Vendors
- Invoice Generation
- [Proposed] Undo/redo feature
- Documentation, logging, testing, configuration, dev-ops
- Appendix A: Requirements
-
Appendix B: Instructions for manual testing
- Launch and shutdown
- Check in a guest
- Editing a guest
- Charging a guest for services
- Checking out a guest
- Viewing invoice generated
- Return check in
- Filter guest
- Show all guests
- Delete guest
- Clear guest
- Adding a vendor
- Editing a vendor
- Filter vendor
- Show all vendors
- Deleting a vendor
- Clear vendor
- Saving data
- Appendix C: Effort
Acknowledgements
This project is a brown-field team project based on the AddressBook-Level 3 (AB3) project.
Credits:
- iText7 Event Handlers
- Java DateTime Format
- Rounding to 2 decimal places by Bharat Sinha
- Create borderless cells in iText7 by Samuel HuylebroeckAdd
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.puml files used to create diagrams in this document can be found in
the diagrams folder. Refer to the PlantUML
Tutorial at se-edu/guides to learn how to create and edit
diagrams.
Architecture

The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main has two classes
called Main
and 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 methods where necessary.
Commons represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
-
UI: The UI of the App. -
Logic: The command executor. -
Model: Holds the data of the App in memory. -
Storage: Reads data from, and writes data to, the hard disk.
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 deletevendor vid/123.

Each of the four main components (also shown in the diagram above),
- defines its API in an
interfacewith the same name as the Component. - implements its functionality using a concrete
{Component Name}Managerclass (which follows the corresponding APIinterfacementioned in the previous point.
For example, the Logic component defines its API in the Logic.java interface and implements its functionality using
the LogicManager.java class which follows the Logic interface. Other components interact with a given component
through its interface rather than the concrete class (reason: to prevent outside component’s being coupled to the
implementation of a component), as illustrated in the (partial) class diagram below.

The sections below give more details of each component.
UI component
The API of this component is specified
in Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, GuestListPanel
, VendorListPanel
, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class which captures
the commonalities between classes that represent parts of the visible GUI.
The UI component uses the 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 MainWindow
is specified
in MainWindow.fxml
The UI component,
- executes user commands using the
Logiccomponent. - listens for changes to
Modeldata so that the UI can be updated with the modified data. - keeps a reference to the
Logiccomponent, because theUIrelies on theLogicto execute commands. - depends on some classes in the
Modelcomponent, as it displaysGuestandVendorobject residing in theModel.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic component:

How the Logic component works:
- When
Logicis called upon to execute a command, it uses thePocketHotelParserclass to parse the user command. - This results in a
Commandobject (more precisely, an object of one of its subclasses e.g.,CheckInNewGuestCommand) which is executed by theLogicManager. - The command can communicate with the
Modelwhen it is executed (e.g. to check in a guest). - The result of the command execution is encapsulated as a
CommandResultobject which is returned back fromLogic.
The Sequence Diagram below illustrates the interactions within the Logic component for
the execute("deletevendor vid/123") API call.

DeleteVendorCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:

How the parsing works:
- When called upon to parse a user command, the
PocketHotelParserclass creates anXYZCommandParser(XYZis a placeholder for the specific command name e.g.,CheckInNewGuestCommandParser) which uses the other classes shown above to parse the user command and create aXYZCommandobject (e.g.,CheckInNewGuestCommand) which thePocketHotelParserreturns back as aCommandobject. - All
XYZCommandParserclasses (e.g.,CheckInNewGuestCommandParser,DeleteVendorCommandParser, …) inherit from theParserinterface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java

The Model component,
- stores the vendorbook and guestbook data i.e., all
VendorandGuestobjects. - stores the currently ‘selected’
GuestorVendorobjects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Guest>orObservableList<Vendor>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. - stores a
UserPrefobject that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPrefobjects. - does not depend on any of the other three components (as the
Modelrepresents data entities of the domain, they should make sense on their own without depending on other components)
Tag list in the GuestBook, which Guest references. This allows GuestBook to only require one Tag object per unique tag, instead of each Guest needing their own Tag objects.
Storage component
API : Storage.java

The Storage component,
- can save both vendor book data, guest book data, archive data, and user preference data in json format, and read them back into corresponding objects.
- inherits from
GuestBookStorage,VendorBookStorage,ArchiveStorageandUserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Modelcomponent (because theStoragecomponent’s job is to save/retrieve objects that belong to theModel)
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.
Book Management
PH allows the user to manage vendors and guests.
As mentioned in the Model section earlier, there are three different types of lists:
- GuestBook (Management of guests)
- VendorBook (Management of vendors)
- Archive (Management of archived guests; currently not exposed to the user)
All the lists are managed by the ModelManager which supports some common operations across them, with certain
variations depending on which list we are currently executing the operation on.
Some common operations include:
-
addvendorfor vendors andcheckinfor guests - creates the entity and adds to the respective books. -
editvendorfor vendors andeditguestfor guests - edits the entity and updates the book accordingly. -
deletevendorfor vendors anddeleteguestfor guests - removes the existing entity from the respective book. -
listvendorfor vendors andlistguestfor guest - renders all the entities of the respective book. -
clearvendorfor vendors andclearguestfor guest - removes all the entities from the respective book.
By segregating the model into its respective books/lists, we felt that this embraced OOP concepts, as it reduces coupling and increases cohesion.
The following class diagram shows the general structure of a GuestBook. The same concepts were applied when building
the VendorBook and Archive.

The GuestBook implements the ReadOnlyGuestBook interface. The getGuestList() method returns an ObservableList of
guests. ObservableList makes use of the Observer pattern, as it notifies the ModelManager of any changes that occur
in the guest list, and reflect those changes onto the GUI.
Toggling between vendor and guest list
Other than toggling between the two lists via the GUI. The user can make use of the commands listguest
and listvendor to toggle between the two. After certain commands like filterguest and filtervendor, the list also
gets toggled automatically for the user. The toggling is executed depending on the state of the CommandResult, after
executing the user command.
MainWindow has a function toggleTab() that reads in the state of the CommandResult and renders the correct list
accordingly.
The following activity diagram illustrates what happens to the MainWindow of the UI component when a user inputs a
command.

Checking in a Guest
Implementation
The implementation of the checkin command was mostly based off the original AB3 implementation, with changes made to
support the Archive and with curated fields tied to a guest. The checkin command makes use of the filtered guest
list to search for the guest to be checked in to see whether they are a duplicate guess and Archive class to determine
if the user is trying to check in a guest that has been archived, which are both not allowed. This is done through the
implementation of Model called ModelManager. The operation
ModelManager#getFilteredGuestList() gets the last shown list of guests in the UI, after which a search is done to see
if the list contains the guest to check in. If the guest is not found, the details of the guest will be added. If the
guest is found, which means that there is a duplicate guest, the operation will not be allowed. In the event that the
guest cannot be found in the last shown list, the operation
ModelManager#getArchivedGuest(PassportNumber passportNumber) checks if the user is trying to check in a guest that has
been archived, which is not allowed.
The checkin command is facilitated by the CheckInNewGuestCommandParser and CheckInNewGuestCommand of PH. The
following sequence diagram shows how the checkin operation works:

The following activity diagram shows what happens when a user executes a checkin command.

Checking in a returning Guest
Implementation
The implementation of the returncheckin command was mostly based off the original AB3 implementation, with changes
made to support the Archive and with curated fields tied to a guest. The returncheckin command makes use of the
filtered guest list to search for the guest to be checked in to see whether they are a duplicate guess, which is not
allowed, and Archive class to determine if the user is trying to check in a guest that has been archived. This is done
through the implementation of Model called ModelManager. The operation
ModelManager#getFilteredGuestList() gets the last shown list of guests in the UI, after which a search is done to see
if the list contains the guest to edit. If the guest is not found, the details of the guest will be added. If the guest
is found, which means that there is a duplicate guest, the operation will not be allowed. In the event that the guest
canno bet found in the last shown list, the operation
ModelManager#getArchivedGuest(PassportNumber passportNumber) checks if the user is trying to check in a guest that has
been archived, which is the purpose of this command.
The returncheckin command is facilitated by the CheckInReturningGuestCommandParser and
CheckInReturningGuestCommand of PH. The following sequence diagram shows how the checkin operation works:

The following activity diagram shows what happens when a user executes a checkin command.

Editing a Guest
Implementation
The implementation of the editguest command was largely based off the original AB3 implementation, with changes made
to support the Archive and edit by the guest details instead of index in list. The editguest command makes use of
the filtered guest list to search for the guest to be edited and Archive class to determine if the user is trying to
edit a guest that has been archived, which is not allowed.
This is done through the implementation of Model called ModelManager. The operation
ModelManager#getFilteredGuestList() gets the last shown list of guests in the UI, after which a search is done to see
if the list contains the guest to edit. If the guest is found, the details of the guest will be edited.
In the event that the guest cannot found in the last shown list, the operation
ModelManager#getArchivedGuest(PassportNumber passportNumber) checks if the user is trying to edit a guest that has
been archived, which is not allowed.
It is worth noting that the passport number of a guest cannot be edited.

Editing a Vendor
Implementation
The implementation of the editvendor command was largely based off the original AB3 implementation, with changes made
to edit a different model, Vendor and edit by the vendor details instead of index in list.
The difference between the Guest and Vendor model is that Vendors cannot be archived. Therefore, the implementation of
the editvendor command is the same as the editguest command, but only the VendorBook
(the GuestBook equivalent for vendors) has to be searched.

Charging a guest
Implementation
The implementation of the chargeguest is a new command implemented for the invoice to work nicely together.
The chargeguest would identity the guest by their passport number and vendor by their vendor id.
The service provided by the vendor would be charged to the assigned guest with the important information such as
ServiceName, Quantity, Cost, CompanyName.
The chargeguest command would increment the quantity for duplicate items.
The chargeguest command is facilitated by the ChargeGuestCommandParser and ChargeGuestCommand of PH. The
following sequence diagram shows how the chargeguest operation works:


Checking out a Guest
Implementation
The implementation of the checkout command builds upon the original AB3 implementation of ‘delete’, with changes made
to delete the guest from the model by the guest details instead of index in list. The ‘checkout’ command first generate
an invoice for the guest if vendor services were engaged during his/her stay. After which, the guest is deleted from the
model, and then archived.
The checkout command makes use of the filtered guest list to search for the guest to be checked out and Archive
class to archive the guest.
This is done through the implementation of Model called ModelManager. The operation
ModelManager#getFilteredGuestList() gets the last shown list of guests in the UI, after which a search is done to see
if the list contains the guest to check out.
If the guest is found, a check is done to see if the guest engaged any vendor services (by seeing if he/she has any chargeables). As mentioned earlier, the invoice is generated only if the guest has chargeables.
Once the invoice (if any) is generated, the chargeables (if any) of the guest will be cleared using the operation
Guest#clearChargeables().
The guest is then deleted from the model using ModelManager#deleteGuest(Guest guest) and added to the archive using
ModelManager#addArchivedGuest(Guest guest).

Filter feature
Implementation
The filter feature makes use of the Model#updateFilteredGuestList and Model#updateFilteredVendorList operations,
where each function takes in a Predicate<Guest> and Predicate<Vendor> respectively. To avoid repetition, we will
cover how the
filterguest command is implemented. The filtervendor command follows the exact same logic with its own unique
fields.
The filterguest command is facilitated by the FilterGuestCommandParser and FilterGuestCommand of PH. The
following sequence diagram shows how the filterguest operation works:

FilterGuestCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Given above is an example of a user filtering guests by a tag, deluxe. The end result is a filtered list of guests with
the tag, deluxe. The execution of the above example follows the same flow as all the other commands. One important to
take note is that, the FilterGuestCommandParser
returns a GuestPredicate. This GuestPredicate implements Predicate<Guest>, and the instance instantiated by the
parser is what gets passed into Model#updateFilteredGuestList to achieve the end result. filtervendor makes use of a
class VendorPredicate that follows the same idea.
The following activity diagram shows what happens when a user executes a filterguest command, filtervendor follows
the same flow.

Deleting a Guest
Implementation
The implementation of the deleteguest command was largely based off the original AB3 implementation, with changes made
to support the Archive and delete by the guest details instead of index in list. The deleteguest command makes use
of the GuestBook and Archive class to search for the guest to be deleted.
This is done through the implementation of Model called ModelManager. The operations
ModelManager#getGuest(PassportNumber passportNumber) andModelManager#getArchivedGuest(PassportNumber passportNumber)
are used to check if the guests details can be found in Pocket Hotel (Either in the archive or currently checked in). If
the guest details is found in either locations, it would be deleted.

Deleting a Vendor
Implementation
The implementation of the deletevendor command was largely based off the original AB3 implementation, with changes
made to delete a different model, Vendor and delete by the vendor details instead of index in list.
The difference between the Guest and Vendor model is that Vendors cannot be archived. Therefore, the implementation of
the deletevendor command is the same as the deleteguest command, but only the VendorBook
(the GuestBook equivalent for vendors) has to be searched.

Clear all Guest
Implementation
The implementation of the clearguest command was largely based off the original AB3 implementation.
The clearguest command makes use
of the GuestBook and removes all guest on the list.

Clear all Vendors
Implementation
The implementation of the clearvendor command was largely based off the original AB3 implementation.
The clearvendor command makes use
of the VendorBook and removes all Vendors on the list.

Invoice Generation
Implementation
Invoices in Pocket Hotel was created using the iText7 Core library, which provides an API to create PDF documents in Java.
The implementation of invoice generation can be found in the Invoice class which contains almost all the code for
generating invoices. The Invoice class is meant to be used as a static method and should not be instantiated. It has
only one method that has the public access modifier is the static method Invoice#generatePdfInvoice
The other static methods are private helper functions to perform the generation of the PDF.

An invoice has 5 components:
- Invoice header
- Billing details: Includes the guest name and their allocated room number
- The invoice table: Contain services the guest used during their stay as well as the total cost. Each row contains, the item number (row number), the name of the vendor, their vendor ID, service type, quantity and cost per unit, as well as line cost (quantity multiplied by cost per unit) are included
- A short note of thanks
- Page number
Given below is the sequence diagram of how the invoice is created by Invoice#generatePdfInvoice.

Referring back to the components that we have to include in the invoice. The InvoiceNewPageHandler would add
the invoice header and the page number. The addGuestBillingDetailsToPdf adds the billing details, addInvoiceTableToPdf
adds the invoice table and addThankYouParagraphToPdf adds a short note of thanks.
[Proposed] Undo/redo feature
Proposed Implementation
The proposed undo/redo mechanism is facilitated by VersionedAddressBook. It extends AddressBook with an undo/redo
history, stored internally as an addressBookStateList and currentStatePointer. Additionally, it implements the
following operations:
-
VersionedAddressBook#commit()— Saves the current address book state in its history. -
VersionedAddressBook#undo()— Restores the previous address book state from its history. -
VersionedAddressBook#redo()— Restores a previously undone address book state from its history.
These operations are exposed in the Model interface as Model#commitAddressBook(), Model#undoAddressBook()
and Model#redoAddressBook() respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The VersionedAddressBook will be initialized with the
initial address book state, and the currentStatePointer pointing to that single address book state.

Step 2. The user executes delete 5 command to delete the 5th person in the address book. The delete command
calls Model#commitAddressBook(), causing the modified state of the address book after the delete 5 command executes
to be saved in the addressBookStateList, and the currentStatePointer is shifted to the newly inserted address book
state.

Step 3. The user executes add n/David … to add a new person. The add command also calls Model#commitAddressBook()
, causing another modified address book state to be saved into the addressBookStateList.

Model#commitAddressBook(), so the address book state will not be saved into the addressBookStateList.
Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing
the undo command. The undo command will call Model#undoAddressBook(), which will shift the currentStatePointer
once to the left, pointing it to the previous address book state, and restores the address book to that state.

currentStatePointer is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The undo command uses Model#canUndoAddressBook() to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following sequence diagram shows how the undo operation works:

UndoCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The redo command does the opposite — it calls Model#redoAddressBook(), which shifts the currentStatePointer once
to the right, pointing to the previously undone state, and restores the address book to that state.
currentStatePointer is at index addressBookStateList.size() - 1, pointing to the latest address book state, then there are no undone AddressBook states to restore. The redo command uses Model#canRedoAddressBook() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
Step 5. The user then decides to execute the command list. Commands that do not modify the address book, such
as list, will usually not call Model#commitAddressBook(), Model#undoAddressBook() or Model#redoAddressBook().
Thus, the addressBookStateList remains unchanged.

Step 6. The user executes clear, which calls Model#commitAddressBook(). Since the currentStatePointer is not
pointing at the end of the addressBookStateList, all address book states after the currentStatePointer will be
purged. Reason: It no longer makes sense to redo the add n/David … command. This is the behavior that most modern
desktop applications follow.

The following activity diagram summarizes what happens when a user executes a new command:

Design considerations:
Aspect: How undo & redo executes:
-
Alternative 1 (current choice): Saves the entire address book.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2: Individual command knows how to undo/redo by itself.
- Pros: Will use less memory (e.g. for
delete, just save the person being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
Documentation, logging, testing, configuration, dev-ops
Appendix A: Requirements
Product scope
Target user profile: Front-desk receptionists at small-scale hotels
- has a need to manage a significant number of contacts (both vendors and guests)
- prefers to have everything centralized in one application
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
- tired of using pen and paper to keep track of contacts
Value proposition: Automate front-desk operations, elevating guest experience and lightens the front desk’s workload.
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * |
user | add details of vendors | look up vendors that suit the guest’s needs and phone them. |
* * * |
user | edit contact details of vendors and guests | have the most updated information. |
* * * |
user | delete guests/vendors | keep track of only guests checked into the hotel and vendors working with hotel. |
* * * |
user | see help instructions | get help on how to use the app |
* * * |
user | save the details I enter | |
* * * |
user | check in new guests | manage all guests currently checked into the hotel. |
* * * |
user | have a faster check in for returning guests | reduce the average check-in time at the front desk |
* * * |
user | check out my guests | archive them and generate an invoice form for them. |
* * |
new user | generate an invoice form | charge the guest for their stay. |
* * |
user | charge my guests for vendors hired | generate an invoice form for them when they check out. |
* * |
new user | clear all current data | get rid of sample data |
* * |
potential user | see app populated with sample data | easily learn and get a feel for the app |
* * |
user | filter guests and vendors | look at them in more manageable lists. |
* * |
user | add tags to vendors/guests | easily categorize and filter them |
* |
expert user | personalize my GUI to my liking | optimise the layout to cater to my needs |
* |
CLI user | add aliases to my commands | execute commands quickly with shorter syntax |
* |
new user | learn how to use the app (Tutorial) | get more familiar with the features they offer and how I can use it better |
Use cases
(For all use cases below, the System is the PH and the Actor is the user, unless specified otherwise)
Navigation
UC01 - Viewing the Vendor List
MSS:
1. User requests to go the vendor list.
2. Pocket Hotel switches to the vendor list, where user can see all the vendors working with the hotel.
Use case ends.
UC02 - Viewing the Guest List
MSS:
1. User requests to go the guest list.
2. Pocket Hotel switches to the guest list, where user can see all guests currently checked into the hotel.
Use case ends.
Utility
UC03 - Viewing the help tab
MSS:
1. User requests to go to the help tab.
2. Pocket Hotel opens the help window directing the user to a guide on how to use the application.
Use case ends.
UC04 - Exiting Pocket Hotel
MSS:
1. User requests to exit the app.
2. Pocket Hotel closes the application window.
Use case ends.
UC05 - Saving your data
MSS:
1. User executes a valid action.
2. Pocket Hotel's data gets modified accordingly, and replaces the existing local save-file.
3. Pocket Hotel shows a success message to user indicating action has been executed successfully.
Use case ends.
Extensions:
1a. Action carried out by user is invalid.
1a1. Pocket Hotel shows an error message.
Use case ends.
2a. Unable to overwrite save file.
2a1. Pocket Hotel shows an error message.
Use case ends.
Managing Guests
UC06 - Checking in new guests
Preconditions: Guest must not already be currently checked into the hotel.
Guarantees: Guest list gets updated with the new guest checked in.
MSS:
1. User requests to check in a new guest.
2. Pocket Hotel adds the requested guest.
3. Pocket Hotel shows a success message to user indicating guest has been successfully checked in.
Use case ends.
Extensions:
1a. Guest is already checked in.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Guest is a returning guest.
1b1. Pocket Hotel shows an error message.
Use case ends.
1c. Given fields such as passport number, name, etc. is invalid.
1c1. Pocket Hotel shows an error message.
Use case ends.
UC07 - Checking in returning guests
Preconditions: Guest must not already be currently checked into the hotel and must be a returning guest.
Guarantees: Guest list gets updated with the returning guest checked in.
MSS:
1. User requests to check in the returning guest.
2. Pocket Hotel adds the requested guest.
3. Pocket Hotel shows a success message to user indicating guest has been successfully checked in.
Use case ends.
Extensions:
1a. Guest is already checked in.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Guest is not a returning guest.
1b1. Pocket Hotel shows an error message.
Use case ends.
1c. Given fields such as passport number or room number is invalid.
1c1. Pocket Hotel shows an error message.
Use case ends.
UC08 - Editing guests
Preconditions: Guest must exist and be currently checked into the hotel.
Guarantees: Guest list gets updated with the guest edited.
MSS:
1. User requests to edit a guest.
2. Pocket Hotel updates the guest with its new details.
3. Pocket Hotel shows a success message to user indicating guest has been successfully edited.
Use case ends.
Extensions:
1a. Guest with given passport number is not checked in.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Given fields such as room number, name, etc. is invalid.
1b1. Pocket Hotel shows an error message.
Use case ends.
1c. No field is given to edit.
1c1. Pocket Hotel shows an error message.
Use case ends.
UC09 - Deleting guests
Preconditions: Guest must exist and be currently checked into the hotel.
Guarantees: Guest list gets updated with the guest removed.
MSS:
1. User requests to delete a guest.
2. Pocket Hotel deletes the guest.
3. Pocket Hotel shows a success message to user indicating guest has been successfully deleted.
Use case ends.
Extensions:
1a. Guest is not checked in.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Given identifier, passport number is invalid.
1b1. Pocket Hotel shows an error message.
Use case ends.
UC10 - Checking out guests
Preconditions: Guest must exist and be currently checked into the hotel.
Guarantees: Guest list gets updated with the guest archived and invoice form generated.
MSS:
1. User requests to check out a guest.
2. Pocket Hotel archives the guest and generates the invoice form.
3. Pocket Hotel shows a success message to user indicating guest has been successfully checked out.
Use case ends.
Extensions:
1a. Guest is not checked in.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Given identifier, passport number is invalid.
1b1. Pocket Hotel shows an error message.
Use case ends.
UC11 - Clearing guests
Preconditions: None.
Guarantees: Guest list gets cleared.
MSS:
1. User requests to clear all guest data.
2. Pocket Hotel clears all guest data.
3. Pocket Hotel shows a success message to user indicating all guest data has been successfully cleared.
Use case ends.
UC12 - Filtering guests
Preconditions: Only guest fields are given for the filter.
Guarantees: Guest list gets filtered to user's specifications.
MSS:
1. User requests to filter guests.
2. Pocket Hotel filters the guests, and only shows those that fit the user's specifications.
3. Pocket Hotel shows a success message to user with the number of guests that have been filtered.
Use case ends.
Extensions:
1a. No fields are given to filter.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Fields given do not follow correct syntax.
1b1. Pocket Hotel shows an error message.
Use case ends.
UC13 - Charging guests
Preconditions: Guest must exist and be currently checked into the hotel.
Guarantees: Pocket Hotel keeps track of the vendors hired by the guest.
MSS:
1. User requests to charge a guest.
2. Pocket Hotel keeps track of the vendor hired by the guest.
3. Pocket Hotel shows a success message to user indicating the guest has been successfully charged.
Use case ends.
Extensions:
1a. Guest is not checked in.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Vendor hired does not exist.
1b1. Pocket Hotel shows an error message.
Use case ends.
Managing Vendors
UC14 - Adding vendors
Preconditions: Vendors must not already exist in the app.
Guarantees: Vendor list gets updated with the new vendor added.
MSS:
1. User requests to add a new vendor.
2. Pocket Hotel adds the requested vendor.
3. Pocket Hotel shows a success message to user indicating the vendor has been successfully added.
Use case ends.
Extensions:
1a. Vendor already exists.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Given operating hour start time is after the end time.
1b1. Pocket Hotel shows an error message.
Use case ends.
1c. Given fields such as vendor id, name, etc. is invalid.
1c1. Pocket Hotel shows an error message.
Use case ends.
UC15 - Editing vendors
Preconditions: Vendor must exist in the app.
Guarantees: Vendor list gets updated with the vendor edited.
MSS:
1. User requests to edit a vendor.
2. Pocket Hotel updates the vendor with its new details.
3. Pocket Hotel shows a success message to user indicating vendor has been successfully edited.
Use case ends.
Extensions:
1a. Vendor with given vendor id does not exist.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Given fields such as email, name, etc. is invalid.
1b1. Pocket Hotel shows an error message.
Use case ends.
1c. No field is given to edit.
1c1. Pocket Hotel shows an error message.
Use case ends.
UC16 - Deleting vendors
Preconditions: Vendor must exist in the app.
Guarantees: Vendor list gets updated with the vendor removed.
MSS:
1. User requests to delete a vendor.
2. Pocket Hotel deletes the vendor.
3. Pocket Hotel shows a success message to user indicating vendor has been successfully deleted.
Use case ends.
Extensions:
1a. Vendor with given vendor id does not exist.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Given identifier, vendor id is invalid.
1b1. Pocket Hotel shows an error message.
Use case ends.
UC17 - Clearing vendors
Preconditions: None.
Guarantees: Vendor list gets cleared.
MSS:
1. User requests to clear all vendor data.
2. Pocket Hotel clears all vendor data.
3. Pocket Hotel shows a success message to user indicating all vendor data has been successfully cleared.
Use case ends.
UC18 - Filtering vendors
Preconditions: Only vendor fields are given for the filter.
Guarantees: Vendor list gets filtered to user's specifications.
MSS:
1. User requests to filter vendors.
2. Pocket Hotel filters the vendors, and only shows those that fit the user's specifications.
3. Pocket Hotel shows a success message to user with the number of vendors that have been filtered.
Use case ends.
Extensions:
1a. No fields are given to filter.
1a1. Pocket Hotel shows an error message.
Use case ends.
1b. Fields given do not follow correct syntax.
1b1. Pocket Hotel shows an error message.
Use case ends.
Non-Functional Requirements
- Should work on any Mainstream OS as long as it has Java
11or above installed. - Should be able to hold up to 1000 contacts without a noticeable sluggishness in performance for typical usage.
- 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.
- PH should retain all functionalities even without a connection to the internet.
- PH is meant to be used by single user at any given time.
- PH should be user-friendly for any receptionist who can use a computer, and does not require any technical knowledge or previous experience of CLI apps.
- PH should not crash on any incorrect user input, this should be handled safely with exceptions. Ideally, rendering a useful error message to the user. {More to be added}
Glossary
- PH: Acronym for Pocket Hotel
- Mainstream OS: Windows, Linux, Unix, OS-X
- Private contact detail: A contact detail that is not meant to be shared with others
- Guest: A person staying in Pocket Hotel
- Staff: An employee of Pocket Hotel
- OOP: Object-oriented programming. A programming paradigm that relies on the idea of designing data around objects and classes.
- GUI: Graphical user interface
- AB3: Address Book 3
Appendix B: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
-
Initial launch
-
Download the jar file and copy into an empty folder
Perform one of the steps (Option 2 recommended for mac) -
Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
Run
java -jar PH.jarin the directory that you placed your jar
-
-
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.
-
Check in a guest
-
Check in a new guest to PH
-
Test case:
checkin n/Bobby pn/S1234 e/bobby@email.com r/23 t/VIP t/Deluxe Room
Expected: A guest card will be created with the passport number S1234 with name “Bobby”, email “bobby@gmail.com”, room number “23”, and tags “VIP” and “Deluxe Room” -
Test case:
checkin n/bobby
Expected: Invalid command format error
-
Editing a guest
-
Editing a guest while all guests are being shown
-
Prerequisites: List all guests using the ‘listguest’ command. Alternatively, click on the “Guests” tab to view the list of guests.
-
Test case:
editguest pn/S1234 n/Alexander Poon
Expected: The guest card of the guest identified by passport number S1234 should be updated to reflect the new name, “Alexander Poon”. The result display shows the details of the guest that has just been edited. -
Test case:
editguest pn/
Expected: No guest is edited. Error details shown in the result display. -
Other incorrect editguest commands to try:
editguest pn/S1234,editguest n/Bernice Yu.
Expected: Similar to previous.
-
Charging a guest for services
-
Charges a guest a service
-
Test case:
chargeguest pn/S123 vid/001
Expected: Service from vendor with vid001has been billed to guest with passport numberS123. -
Test case:
chargeguest
Expected: No transaction occurs and invalid command format will be shown in the result display. -
Test case:
chargeguest pn/S123
Expected: No transaction occurs and invalid command format will be shown in the result display. -
Test case:
chargeguest vid/001
Expected: No transaction occurs and invalid command format will be shown in the result display. -
Test case:
chargeguest pn/A999 vid/001which passport number does not exist
Expected: No transaction occurs andGuest with this passport number does not existwill be shown in the result display. -
Test case:
chargeguest pn/S123 vid/99999which vendor id does not exist
Expected: No transaction occurs andVendor with this vendorId does not existwill be shown in the result display.
-
Checking out a guest
-
Checking out a guest while all guests are being shown
-
Prerequisites: List all guests using the ‘listguest’ command. Alternatively, click on the “Guests” tab to view the list of guests.
-
Test case:
checkout pn/S1234
Expected: The guest card of the guest identified by passport number S1234 should no longer be visible in the guests list. The result display shows the details of the guest that has just been checked out. An invoice is generated for the guest as well. -
Test case:
checkout pn/
Expected: No guest is checked out. Error details shown in the result display. -
Other incorrect editguest commands to try:
checkout pn/A123,editguest pn/@@@@@. Expected: Similar to previous.
-
Viewing invoice generated
-
Upon performing the
checkoutcommand in the previous section, a PDF invoice of all the guests expenses will be generated.- Test case: From previous step
Expected: Check directory which contains jar file for PDF namedS1234 <CURRENT_TIME>, PDF should contain base price of hotel stay and the 2 charges by vendor 001
- Test case: From previous step
Return check in
-
Return check in for guests whose details have been previously entered into the hotel
- Test case:
returncheckin pn/S1234 r/411
Expected: Checked in guest.
- Test case:
Filter guest
-
Filter guests with fields
- Test case:
filter guest n/Ale, filters all guest that name starts with “Ale” Expected: Message sayingX guest listed
- Test case:
Show all guests
-
Removes filters and switches to the guest list
-
Test case:
-
Perform filter guest example above
-
Click on vendor list
-
listguest
Expected: List will switch to guest and remove filters
-
-
Delete guest
-
Deletes guest based on its passport number.
-
Test case:
deleteguest pn/S1234
Expected: Message notifying that guest is deleted -
Test case (Deleting an archived guest):
-
checkin n/Bobby pn/S1234 e/bobby@email.com r/23 t/VIP t/Deluxe Room -
checkout pn/1234 -
deleteguest pn/1234
Expected: Message notifying that guest is deleted
-
-
Clear guest
-
Deletes all guests from PH, even archived ones
-
Test case:
-
checkin n/Bobby pn/S1234 e/bobby@email.com r/23 t/VIP t/Deluxe Room -
checkout pn/1234 -
clearguest -
returncheckin pn/S1234 r/111
Expected: All guests from guest list will be cleared,returncheckincommand will throw an error as guest cannot be found in archive
-
-
Adding a vendor
-
Add vendor to list of vendors
-
Test case:
-
addvendor vid/123 n/Wang's Satay e/satayMan@email.com p/84711231 a/Geylang Street 31 sn/Satay c/5 oh/15 0800-2000
Expected: Adds vendor with vendor ID 123, called Wang’s Satay with email address satayMan@email.com, phone number 84711231, address Geylang Street 31 , service name “Satay”, and operating hours Monday and Friday 0800-2000.
-
-
Editing a vendor
-
Editing a vendor while all vendors are being shown
-
Prerequisites: List all vendors using the ‘listvendor’ command. Alternatively, click on the “Vendors” tab to view the list of vendors.
-
Test case:
editvendor vid/001 n/Jeremy Western Delivery
Expected: The vendor card of the vendor identified by vendor id 001 should be updated to reflect the new name, “ Jeremy Western Delivery”. The result display shows the details of the vendor that has just been edited. -
Test case:
editvendor vid/
Expected: No vendor is edited. Error details shown in the result display. -
Other incorrect editvendor commands to try:
editvendor vid/001,editvendor n/Bing Massage Parlour.
Expected: Similar to previous.
-
Filter vendor
-
Filters vendors according to filter
-
Test case:
filtervendor oh/5 0800
Expected: Filters vendors that are open at 0800 and displays to the GUI -
Test case:
filtervendor oh/5 0800-1300
Expected: Filters all vendors that operate anywhere between 0800 and 1300 on a Friday and displays them to the GUI -
Test case:
filtervendor sn/Food
Expected: Filters all vendors that have a service name field of food.
-
Show all vendors
-
Removes filters and switches to the vendor list
-
Test case:
-
Perform filter vendor example above
-
Click on guest list
-
listvendor
Expected: List will switch to vendor and removes filters
-
-
Deleting a vendor
-
Deletes a vendor based on its vendor ID
- Test case:
deletevendor vid/123
Expected: Deletes vendor with vid 123 from PH
- Test case:
Clear vendor
-
Deletes all vendors from PH.
- Test case:
clearvendor
Expected: Deletes all vendors from PH, vendor list will be empty.
- Test case:
Saving data
-
Dealing with missing/corrupted data files
i. Test case: go to
data\addressbook.jsonand corrupt the file. On bootup of the program, there should be a notification in the command box saying “File corrupted! Restored a new file.” and the program will delete and load a fresh new file.ii. Rename
data\addressbook.jsonto something else likedata\addressbook.jsonwould cause the addressbook to be not found and load the sample contacts into the addressbook.
Appendix C: Effort
Challenges faced
Prior to the 1.3b iteration, PH was aimed at managing Guests and Staff. However, upon meeting with our CS2101 lecturer, we realised that our use cases were ill-defined and we had failed to adequately address the needs of our target audience. Coming up with meaningful use cases for that iteration was difficult and our team gathered to brainstorm ideas on what core features we should include and who our target audience should really be. We eventually came to a consensus that our application would be front desk oriented and ended up redesigning the entire workflow of the application. Instead of managing Guests and Staff, our app would now manage guests and external vendors, with a focus on streamlining all guest-related processes such as check in, checkout, charging guests etc. That was one of the longest meetings spanning over 5 hours as we cleared out most of the edge case scenarios and came up with features that would be useful to the application.
With 5 days left to the submission deadline, we set out to achieve what most groups would take 4 weeks to do. We had to
make significant changes to refactor the original codebase. Our original commands such as edit, add (which was
converted to checkin and returncheckin) and delete had to be duplicated for both guests and vendors, which greatly
increased the workload for implementation and testing. Additionally, we made changes to the original Model by
introducing an Archive, which would be used to store checked out guests and implemented several new features that were
dissimilar to any of those in AB3, such as invoice generation for guests who engaged vendor services during their
stay. We also have more json files to manage such as guests.json, vendors.json and archive.json, which increased
the amount of testing and implementation required.
In particular, with the additional feature of generating invoices, we have a new workflow to allow this functionality with the added logic for charging guests and checking out a guest for a smoother process. The parsing of the information and generation of the layout was also tricky.
Two major entities are involved: Guest and Vendor:
The two classes have some fields in common but are different from one another. For example, Vendors have operating hours
while Guests have a list of things that they are charged for.
The difference in workflow also greatly increases the workload of implementation and testing for both the Guest and Vendors due to the separate command logic and storage required to handle them.
Achievements
We managed to revamp our existing v1.3 iteration to a whole new PH in v1.3b iteration within a week with all the new features added such as filter, archive, invoice, chargeable, and returning guest check in.
Our team managed to deliver a convincing pitch and demo of our product and both our CS2101 lecturer and CS2103T tutor were impressed with our work.