Developer Guide
Welcome to the PocketEstate Developer Guide! This guide will take you through the underlying components that make up PocketEstate, and provide the essential information required for you to get started with becoming a PocketEstate developer.
Table of Contents
- 1. Setting up, getting started
- 2. Design
- 3. Implementation
- 4. Documentation, logging, testing, configuration, dev-ops
- Appendix A: Product scope
- Appendix B: User Stories
- Appendix C: Use Cases
- Appendix D: Non-Functional Requirements
- Appendix E: Glossary
- Appendix F: Instructions for manual testing
- Appendix G: Effort
1. Setting up, getting started
Please refer to the guide Setting up and getting started to learn how to set up this project in your computer.
2. Design
2.1 Architecture

The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
.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.
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.
Each of the four components,
- defines its API in an
interfacewith the same name as the Component. - exposes its functionality using a concrete
{Component Name}Managerclass (which implements the corresponding APIinterfacementioned in the previous point.
For example, the Logic component (see the class diagram given below) defines its API in the Logic.java interface and exposes its functionality using the LogicManager.java class which implements the Logic interface.

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 delete property 1.

The sections below give more details of each component.
2.2 UI component

API :
Ui.java
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PropertyListPanel, AppointmentListPanel 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 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.
2.3 Logic component

API :
Logic.java
-
Logicuses thePocketEstateParserclass to parse the user’s input command. - Depending on the command string passed in by the user,
- a specific command parser (e.g.
AddPropertyCommandParser) may be created to parse the input arguments to produce the correspondingCommandobject, or - the
Commandobject can be directly created for some commands (e.g.HelpCommand).
- a specific command parser (e.g.
- The
Commandobject is then executed by theLogicManager. - The command execution can affect the
Model(e.g. adding a property, deleting a property). - The result of the command execution is encapsulated as a
CommandResultobject, which is passed back to theUi. The feedback to the user is then displayed to the user. - In addition, the
CommandResultobject can also instruct theUito 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("add property n/Bishan t/Hdb a/Blk 150 Bishan Street 11 #02-101 p/570150 d/30-06-2021") API call.

AddPropertyCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
2.4 Model component

API : Model.java
The Model,
- stores a
UserPrefsobject that represents the user’s preferences, such as- the preferred GUI settings (e.g. window size of the app)
- the preferred storage filepath for the property book
- the preferred storage filepath for the appointment book
- stores the property book and appointment book data
- exposes an unmodifiable
ObservableList<Property>and an unmodifiableObservableList<Appointment>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
2.5 Storage component

API : Storage.java
The Storage component,
- can save
UserPrefsobjects in json format and read it back. - can save the appointment book data in json format and read it back.
- can save the property book data in json format and read it back.
2.6 Common classes
Classes used by multiple components are in the seedu.address.commons package.
Some examples of common classes:
-
Messages.java: Container for user visible messages -
FileUtil.java: Writes and reads files -
JsonUtil.java: Converts a Java object instance to JSON and vice versa
3. Implementation
This section describes some noteworthy details on how certain features are implemented.
3.1 Property component

3.1.1 Current Implementation
A Property is stored in a UniquePropertyList, which ensures that there are no duplicate properties in the PropertyBook. Each Property is uniquely identified by its pair of Address and PostalCode.
A `Property consists of the following mandatory attributes,
- a
Name: the name of the property - a
Type: the housing type of the property (HDB
, Condo
, Landed
, etc.) - an
Address: the address of the property - a
PostalCode: the postal code of the property - a
Deadline: the property’s deadline for selling
and the following optional attributes,
- a
Remark: a note about the property - a
Status: represents the current stage of the selling (Option, Sales Agreement, Completion) - a
Client: represents the seller of the property - a
Tagset: a set of zero or moreTagobjects describing the property
A Client consists of at least one of the following attributes,
- a
Name: the name of the client - a
Contact: the contact number of the client - an
Email: the email of the client - an
AskingPrice: the asking price of the client
3.1.2 Design Consideration
Aspect: How each attribute of Property is stored
-
Current implementation: Each attribute of
Propertyis immutable. When a property is to be edited, a newPropertycontaining the updated fields will be created to replace the originalPropertyobject.- Pros: Prevent accidental modification of a
Propertyobject (less prone to bugs) - Cons: More code to be written as a separate
Propertyobject has to be created for each edit operation
- Pros: Prevent accidental modification of a
-
Alternative: Allow mutable
Propertyobjects (provide setter methods to update the attributes of aProperty)- Pros: Easy to implement
- Cons: More prone to bugs
Aspect: How each tag is stored
- An alternative (arguably, a more OOP) model is given below. It has a
Taglist in thePropertyBook, whichPropertyreferences. This allowsPropertyBookto only require oneTagobject per uniqueTag, instead of eachPropertyneeding their ownTagobject.- Pros: Prevents creating the same tag multiple times when each
Propertyneeds to refer to the tag - Cons: Harder to implement
- Pros: Prevents creating the same tag multiple times when each

3.2 Appointment component

3.2.1 Current Implementation
An Appointment is stored in a UniqueAppointmentList, which ensures that there are no duplicate appointments in the AppointmentBook. Each Appointment is uniquely identified by its pair of Date and Time.
An Appointment consists of the following mandatory attributes,
- a
Name: the name of the appointment - a
Remark: a note about the appointment - a
Date: the date of the appointment - a
Time: the time of the appointment
3.2.2 Design Consideration
Aspect: How each attribute of Appointment is stored
Similar design considerations as how each attribute of Property is stored
3.3 Undo feature
3.3.1 Current Implementation
The undo mechanism is facilitated by PocketEstate. It implements the undo feature with an undo history, stored internally as previousAppointmentLists and previousPropertyLists respectively.
-
AppointmentBook#undo()— Restores the previous appointment book state from its history. -
PropertyBook#undo()— Restores the previous property book state from its history.
These operations are exposed in the Model interface as Model#undoAppointmentBook() and Model#undoPropertyBook() respectively.
Given below is an example usage scenario and how the undo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The PocketEstate will be initialized with the initial appointment book state and property book state, and the currentAppointmentBookStatePointer currentPropertyBookStatePointer pointing to the two initial book states respectively.

Step 2. The user executes delete appointment 1 command to delete the 1st appointment in the appointment book. The delete appointment executes previousAppointmentLists.push(new ArrayList<>(appointments.asUnmodifiableObservableList())), causing the previous state of the appointment book before the delete appointment 1 command executes to be saved in the previousAppointmentLists, and the currentAppointmentBookStatePointer still points to the current appointment book state.

Step 3. The user executes add appointment … to add a new appointment. The add appointment command also executes previousAppointmentLists.push(new ArrayList<>(appointments.asUnmodifiableObservableList())), causing a copy of the current appointment book state to be saved into the previousAppointmentLists.

previousAppointmentLists.push(new ArrayList<>(appointments.asUnmodifiableObservableList())), so the appointment book state will not be saved into the previousAppointmentLists.
Step 4. The user now decides that adding the appointment was a mistake, and decides to undo that action by executing the undo command. The undo command will call Model#undoAppointmentBook(), which will shift the currentAppointmentBookStatePointer to the most recently saved state, pointing it to the previous appointment book state, and restores the appointment book to that state.

previousAppointmentLists is empty, then there are no previous AppointmentBook states to restore. The undo command uses commandHistory.empty() 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.
Step 5. The user then decides to execute the command list. Commands that do not modify the appointment book, such as list, will usually not executes previousAppointmentLists.push(new ArrayList<>(appointments.asUnmodifiableObservableList())). Thus, the previousAppointmentLists remains unchanged.

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

3.3.2 Design consideration:
Aspect: How undo executes
-
Alternative 1 (current choice): Saves the entire appointment/property book.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2: Saves only changes made by previous commands (Similar to commit and restore in version control).
- Pros: Will use less memory (e.g. for
delete, may only save the appointment/property being deleted, and the deleted appointment/property is added back if the command is undone). - Cons: Difficult to implement, different implementations are required to restore different changes.
- Pros: Will use less memory (e.g. for
3.4 Update feature
3.4.1 Current Implementation
The update mechanism is facilitated by PocketEstate. It implements the update feature with 3 parts, the Status field in Property, a UpdateCommandParser and UpdateCommand.
The Status field consists of a Status interface with a next() method that returns a Status representing the next stage of the property selling process. There are 3 classes that implement Status, Option, SalesAgreement and Completion. Each class takes in an Offer which represents the price that was offered for the property.
-
Option— Represents the stage where the buyer exercises the Option to Purchase. -
SalesAgreement— Represents the stage where the buyer is considering the Sales and Purchase Agreement. -
Completion— Represents the stage where the property has been sold.

The UpdateCommand is assisted by 3 subcommands that extend the abstract class UpdateCommand which itself extends Command. The subcommands are, UpdateNewCommand, UpdateProceedCommand and UpdateCancelCommand. The subcommands help execute on the model when the user calls u/new, u/proceed or u/cancel respectively.
-
UpdateNewCommand— Takes in anIndexand an Amount to create a newStatuswith the given Amount for the property at the givenIndex. -
UpdateProceedCommand— Takes in anIndexand moves theStatusof the property at the givenIndexto the nextStatusif applicable. -
UpdateNewCommand— Takes in anIndexand removes theStatusof the property at the givenIndexif applicable.

Given below is an example usage scenario and how the update mechanism behaves at each step.
Step 1. The user launches the application for the first time. The PocketEstate will be initialized with the initial appointment book state and property book state.

Step 2. The user executes update 1 u/new 600,000 command to add a new status with value 600,000 to the first property.

Step 3. The user executes update 1 u/proceed to move the Status of the first property to SalesAgreement.

Step 4. The user executes update 1 u/proceed to move the Status of the first property to Completion.

Step 5. The user then decides that having the Completion status on the first property was a mistake and executes the command update 1 u/cancel.

3.4.2 Design consideration:
Aspect: How Update executes
The following activity diagram summarizes what happens when a user executes an UpdateCommand:

The following sequence diagram shows how the update operation works:

UpdateCommandParser and UpdateNewCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
3.5 Find feature
3.5.1 Current Implementation
The find mechanism is facilitated by PocketEstate. It implements the search feature that allows the user to specify the fields to search for and use multiple parameters.
This feature is implemented separately for both property and appointment, as well as an additional find client feature that searches both properties and appointments.
find appointment and find property uses AppointmentPredicateList and PropertyPredicateList to keep track of all
predicates that FindAppointmentCommandParser and FindPropertyCommandParser generated respectively. A unique predicate
class exist for every attribute that Appointment and Property classes have. find client command is implemented by
combining an AppointmentNamePredicate and a PropertyClientNamePredicate, and using the same keywords for both.
Since they are implemented similarly, given below is an example usage scenario and how the find mechanism behaves at each step for find appointment.
Step 1. The user executes find appointment n/alex d/25-12-2021 n/john command to find an appointment in the appointment book
that contains alex in its name and has date set to 25-12-2021.
Step 2. PocketEstateParser parses user input and calls FindAppointmentParser.
Step 3. For each unique option type in the input, in this case n/ for name, and d/ for date, FindAppointmentCommandParser
creates a AppointmentPredicateList, then creates predicates for each keyword, storing them in the AppointmentPredicateList
for their corresponding option type. i.e. the AppointmentPredicateList for d/ will contain 1 AppointmentDatePredicate
that checks for 25-12-2021, while that for n/ will contain 2 AppointmentNamePredicates, 1 checking for alex, and the other
checking for john.
Step 4. FindAppointmentCommandParser creates a new AppointmentPredicateList containing a list of all
previously created AppointmentPredicateList.
Step 5: FindAppointmentCommandParser creates a FindAppointmentCommand with the AppointmentPredicateList as argument.
Step 6: FindAppointmentCommand creates a single Predicate by calling AppointmentPredicateList#combine.
* This function combines all predicates by:
1. Calling AppointmentPredicateList#combineDisjunction, which combines predicates with logical OR, on every AppointmentPredicateList
stored within itself
1. Combining all created predicates into a single Predicate with logical AND
Step 7: FindAppointmentCommand calls Model#updateFilteredAppointmentList with the new Predicate to update the filtered
list that is viewed by the user.
3.5.2 Design consideration:
Aspect: How Find executes
The following activity diagram summarizes what happens when a user executes a FindAppointmentCommand:

Aspect: How predicates of the same type interact with each other
-
Initial implementation: Conjunction of all predicates where all predicates are combined with logical
AND.- Pros: Easy to implement.
- Cons: Very restrictive for users, testers also complained that this felt unintuitive.
-
Current implementation: All predicates of the same type are first combined with logical
OR, then combined with other predicates with logicalAND.- Pros: Allows for more flexible searches.
- Cons: More difficult to implement and test.
4. Documentation, logging, testing, configuration, dev-ops
Appendix A: Product scope
Target user profile:
- property agent who has a need to manage a significant number of properties and appointments
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value proposition: PocketEstate enables easy organization of mass clientele property information through sorting of information by price, location and housing type, that may otherwise be difficult to manage.
Appendix B: User Stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * |
new user | see usage instructions | refer to instructions when I forget how to use the App |
* * * |
user | add a property | keep track of my clients’ properties |
* * * |
user | add an appointment | keep track of my upcoming schedule |
* * * |
user | list all properties on sale | know the number of properties that I have to sell |
* * * |
user | list all appointments I have | know all the meetings I have |
* * * |
user | view all properties and appointments side by side | simultaneously view related property and appointment data |
* * * |
user | view the notes/special remarks of a seller | so that I keep in mind special considerations when negotiating with a potential buyer. |
* * * |
user | identify properties with expired deadlines | focus on current properties that I have to sell |
* * * |
user | view the client asking price of a property | keep the price in mind when negotiating with the buyer |
* * |
user | edit the address of the property listing | change the address of the property when I have made a mistake |
* * |
user | search for properties based on some criteria | easily filter out the properties I want to see |
* * |
user | search for appointments based on some criteria | easily filter out the appointments I want to see |
* * |
user | search for all appointments and properties related to a client | easily find out any appointments with a client and what properties they are interested in |
* * |
potential user exploring the app | see the app populated with sample data | easily see how the app looks like when it is in use |
* * |
user | be able to create tags to classify properties | easily organize my properties |
* * |
user | be able to use icons to classify property types | easily differentiate the different property types in a list |
* * |
user | update the status of property listings(completed, Option, Sale Agreement) | follow up with clients on time |
* * |
user | edit the deadline of the property listing | extend the time period for selling the property |
* * |
user | edit the name of the property listing | change the name of the property when I have made a mistake |
* * |
user | edit the address of the property listing | change the address of the property when I have made a mistake |
Appendix C: Use Cases
(For all use cases below, the System is the PocketEsate app, and the Actor is the user, unless specified otherwise)
Use case: UC01 - Add a property
MSS
- User request to add a property
-
PocketEstate shows an updated list of properties
Use case ends.
Extensions
-
1a. The property to be added has missing required fields.
-
1a1. PocketEstate shows an error message.
Use case ends.
-
-
1b. The property to be added has a deadline that is already over.
-
1b1. PocketEstate shows an error message.
Use case ends.
-
Use case: UC02 - Add an appointment
MSS
- User request to add an appointment
-
PocketEstate shows an updated list of appointments
Use case ends.
Extensions
-
1a. The appointment to be added has missing required fields.
-
1a1. PocketEstate shows an error message.
Use case ends.
-
-
1b. The appointment to be added has a date and time that is already over.
-
1b1. PocketEstate shows an error message.
Use case ends.
-
Use case: UC03 - Listing all properties and appointments
MSS
- User requests to list all properties and appointments.
-
PocketEstate shows the entire list of properties and appointments.
Use case ends.
Extensions
-
1a. List command used has unrecognized fields.
-
1a1. PocketEstate shows an error message.
Use case ends.
-
Use case: UC04 - Edit a property
MSS
- User request to edit a property
-
PocketEstate shows an updated list of properties
Use case ends.
Extensions
-
1a. The property to be edited has unrecognized fields.
-
1a1. PocketEstate shows an error message with the unrecognized fields.
Use case ends.
-
-
1b. The property to be edited has a deadline that is already over.
-
1b1. PocketEstate shows an error message.
Use case ends.
-
Use case: UC05 - Edit an appointment
MSS
- User request to edit an appointment
-
PocketEstate shows an updated list of appointments
Use case ends.
Extensions
-
1a. The appointment to be edited has unrecognized fields.
-
1a1. PocketEstate shows an error message with the unrecognized fields.
Use case ends.
-
-
1b. The appointment to be edited has a date and time that is already over.
-
1b1. PocketEstate shows an error message.
Use case ends.
-
Use case: UC06 - Update status of a property
MSS
- User request to update status of a property
-
PocketEstate shows an updated list of properties
Use case ends.
Extensions
-
1a. The property to be updated has incorrect fields.
-
1a1. PocketEstate shows an error message.
Use case ends.
-
Use case: UC07 - Searching for property
MSS
- User requests to search for properties of a certain type.
-
PocketEstate shows a list of properties that are of that type.
Use case ends.
Use case: UC08 - Searching for appointment
MSS
- User requests to search for appointments with a certain person.
-
PocketEstate shows a list of all appointments with that person.
Use case ends.
Appendix D: Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11or above installed. - 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 by using commands over the mouse.
- Should be able to hold up to 500 properties and 500 appointments concurrently without a noticeable sluggishness in performance for typical usage.
- The app should respond within two seconds after each user command.
- The GUI of the app should clearly differentiate the different property types (HDB
, Condo
, Landed
, etc.) of each property in the list. - The app should be able to run without internet connection.
- The app should be resizable and can be enlarged to the maximum window width.
- There should be sample data in the app when the user opens the app for the first time.
Appendix E: Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Property: A property listing with mandatory attributes: Name, Property type, Address, Postal code, Deadline, and with optional attributes: Remarks, Status, Client name, Client contact, Client email, Client asking price, a set of Tags (containing 0 or more tags)
- Appointment: An appointment listing with mandatory attributes: Name, Remarks, Date, Time
Appendix F: 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
-
Double-click the jar file Expected: Shows the GUI with a set of sample properties and appointments. 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.
-
-
Exiting
-
Prerequisites: The application is running.
-
Test case:
exit
Expected: App shuts down.
-
Adding a property
-
Adding a new unique property.
-
Prerequisites: None of the current properties in the app has an (address, postal code) pair of (
Blk 150 Bishan Street 11 #02-101,570150) -
Test case:
add property n/Bishan t/Hdb a/Blk 150 Bishan Street 11 #02-101 p/570150 d/30-06-2021
Expected: A new property is added to the property list. The result display panel shows the details of the newly added property. -
Test case:
add property
Expected: No property is added. An error messageInvalid command format!is shown in the result display. -
Other incorrect add property commands to try:
add property n/Bishan,add property t/Condo
Expected: No property is added. An error messageInvalid command format!is shown in the result display.
-
-
Adding a duplicate property.
-
Prerequisites: A property with an (address, postal code) pair of (
Blk 150 Bishan Street 11 #02-101,570150) already exist in the app. -
Test case:
add property n/Bishan t/Hdb a/Blk 150 Bishan Street 11 #02-101 p/570150 d/30-06-2021
Expected: No property is added. An error messageThis property already exists in the appis shown in the result display.
-
Adding an appointment
-
Adding a new unique appointment.
-
Prerequisites: None of the current appointments in the app has a (date, time) pair of (
19-05-2021,1930) -
Test case:
add appointment n/Meet Jacob r/For collection of commission d/19-05-2021 t/1930
Expected: A new appointment is added to the appointment list. The result display panel shows the details of the newly added appointment. -
Test case:
add appointment
Expected: No appointment is added. An error messageInvalid command format!is shown in the result display. -
Other incorrect add appointment commands to try:
add appointment n/Meet Jacob,add appointment d/19-05-2021 t/1930
Expected: No appointment is added. An error messageInvalid command format!is shown in the result display.
-
-
Adding a duplicate appointment.
-
Prerequisites: An appointment with a (date, time) pair of (
19-05-2021,1930) already exist in the app. -
Test case:
add appointment n/Meet Jacob r/For collection of commission d/19-05-2021 t/1930
Expected: No appointment is added. An error messageThis appointment already exists in the appis shown in the result display.
-
Deleting a property
-
Deleting a property while all properties are being shown
-
Prerequisites: List all properties using the
list propertycommand. Multiple properties in the list. -
Test case:
delete property 1
Expected: First property is deleted from the list. Details of the deleted property shown in the status message. -
Test case:
delete property 0
Expected: No property is deleted. Error details shown in the status message. -
Other incorrect delete commands to try:
delete,delete property x(where x is larger than the list size)
Expected: Similar to previous.
-
Find commands
-
Find
- Test case:
find
Expected: Both lists are not updated, error message showing the two types offindcommands is shown.
- Test case:
-
Finding properties
-
Prerequisites: Using default example data (or make sure when
list propertyis entered, you can see the propertyWoodlands Crescentthat has typehdband price at$800,000). -
Test case:
find property n/woodlands
Expected:Woodlands Crescentproperty is shown in the list, properties that do not contain the wordwoodlandsin the name are not shown. -
Test case:
find property pm/$700000 t/hdb
Expected:Woodlands Crescentproperty is shown in the list, properties with price less than $700,000 or are not HDB are not shown. -
Test case:
find property n/
Expected: Property list is not updated. Error details shown in the status message. -
Test case:
find property pm/abc
Expected: Property list is not updated. Error details shown in the status message. -
Other incorrect find property commands to try:
find property x/, where x is any of the permissible options. Expected: Similar to previous.
-
-
Finding appointments
-
Prerequisites: Using default example data (or make sure when
list appointmentis entered, you can see the appointmentMeet Emilythat has remarksAt Mayfair Gardens, date atJun 15 2021, and time at11:00AM). -
Test case:
find appointment n/emily
Expected:Meet Emilyappointment is shown in the list, appointments that do not contain the wordemilyin the name are not shown. -
Test case:
find appointment d/15-06-2021 t/1100
Expected:Meet Emilyappointment is shown in the list, appointments whose date is notJun 15, 2021and time is not11:00AMare not shown. -
Test case:
find appointment n/
Expected: Appointment list is not updated. Error details shown in the status message. -
Test case:
find appointment d/abc
Expected: Appointment list is not updated. Error details shown in the status message. -
Other incorrect find property commands to try:
find appointment x/, where x is any of the permissible options. Expected: Similar to previous.
-
-
Finding clients
-
Prerequisite: Using default example data (or make sure when
list allis entered, you can see the appointmentMeet Aliceand the property withAliceas client name). -
Test case:
find client aliceExpected:Meet Aliceappointment is shown in appointment list, and properties withAliceinClient Namefield are shown in property list. -
Test case:
find clientExpected: Both lists are not updated. Error details shown in the status message.
-
Listing all properties and appointments
-
List all properties and appointments in the property list and appointment list after a
find client [KEYWORD]command.-
Prerequisites: There exists at least one property and one appointment in the property list and appointment list respectively.
-
Perform a
find client [KEYWORD]command that returns filtered property and appointment lists with client name as per input keyword. -
Test case:
list allExpected: Filter from
findcommand will be cleared, and all properties and appointments in the property list and appointment list are displayed, with a result message showingListed all properties and appointments.
-
-
List all properties and appointments in the property and appointment lists after a
clearcommand.-
Prerequisites: There exists at least one property and one appointment in the property list and appointment list respectively.
-
Perform a
clear allcommand such that all properties and appointments are cleared from the lists. -
Test case:
list allExpected: No properties and appointments are displayed, with a result message showing:
No existing properties and appointments available
-
Editing a property
-
Editing a property.
-
Prerequisites: Property list has at least 1 property
-
Test case:
edit property 1 n/Bishan Village
Expected: The first property in the property list is edited to have the nameBishan Village. The result display panel shows the full details of the edited property. -
Test case:
edit property
Expected: No property is edited. An error messageInvalid command format!is shown in the result display. -
Other incorrect edit property commands to try:
edit property n/Bishan Village,edit property +1
Expected: No property is added. An error messageInvalid command format!is shown in the result display.
-
-
Editing to a duplicate property.
-
Prerequisites: A property with an (address, postal code) pair of (
Blk 150 Bishan Street 11 #02-101,570150) already exist in the app that is not the first property in the property list. -
Test case:
edit property 1 a/Blk 150 Bishan Street 11 #02-101 p/570150
Expected: No property is edited. An error messageAnother property with the same address and postal code already exists in the appis shown in the result display.
-
Editing an appointment
-
Editing an appointment.
-
Prerequisites: The appointment list is not empty
-
Test case:
edit appointment 1 n/Meet Nathaniel
Expected: The first appointment in the appointment list has the name changed toMeet Nathaniel. The result display panel shows the full details of the edited appointment. -
Test case:
edit appointment
Expected: No appointment is edited. An error messageInvalid command format!is shown in the result display. -
Other incorrect edit appointment commands to try:
edit appointment n/Meet Nathaniel,edit appointment +1 n/Meet Nathaniel
Expected: No appointment is edited. An error messageInvalid command format!is shown in the result display.
-
-
Editing to a duplicate appointment.
-
Prerequisites: An appointment with a (date, time) pair of (
19-05-2021,1930) already exist in the app that is not the first appointment in the appointment list. -
Test case:
edit appointment 1 d/19-05-2021 t/1930
Expected: No appointment is edited. An error messageAnother appointment with the same date and time already exists in the appis shown in the result display.
-
Appendix G: Effort
Introduction
AB3 only dealt with one entity type, but PocketEstate took twice the effort since it involved 2 entity types - Properties & Appointments. The number of commands and attributes implemented were doubled in PocketEstate, signifying greater parsing, storage and tests effort due to the numerous different commands and data types involved.
To support all of that, we greatly expanded the application, increasing the lines of code from 6k to 19k.
New Features
1. Update Command
- Implementation of
updatecommand required effort due to addition of 3 sub commands, namelynew,proceed,cancelcommands.
newcommand introduces a new status attribute to each property for display in Ui.
proceedcommand moves status of the property to the next stage.
cancelcommand removes the status bar associated with that property.
2. Find Command
- AB3’s
findcommand only searched for existence of keywords in the Names of Properties and Appointments.
To make theFindcommand more useful and flexible, we expanded theFindcommand to apply keyword search in all attributes for Properties and Appointments.
3. Sort Command
- Significant effort was required to implement individual comparators for each sorting key.
For example, supportingsortby name requires a comparator for thenameattribute that provides alphabetical ordering while being case insensitive.
4. Undo Command
- Great effort was necessary to retrieve and store data in the AddressBook log, as well as to save the state of property and appointment books after each command.
Challenges 1: User Interface
The user interface for original AddressBook was only optimised to display only one list. During the conceptualisation of PocketEstate, we struggled to find a way to display both property and appointments list in an organised but minimalist manner due to the numerous attributes associated with properties and appointments.
We found our original implementation of displaying one list at a time to be less user friendly as the user had to use list property or list appointment command before using other commands.
We overcame this by displaying both properties and appointments side by side for easy referral, without having to call list property or list appointment prior to a sort or filter. This design was also optimal in allowing find features that are simultaneously done on both lists. Eg. find client [KEYWORD] where keyword is searched from both property and appointment lists.
The new UI structure of a side by side property and appointment list required a redesign of the user interface that was more complex, where we faced some sizing issues such as text wrapping, window issues due to the large amount of data displayed. In doing so, we also changed the colour scheme of the UI to be a light themed one in order to allow greater emphasis on some data (bolding of words) and less focus on other data Eg. Greying out of properties and appointments with expired deadlines. The original UI that was dark themed would not allow colour play with the different shades of black.
Challenges 2: Parsing
Several attributes such as date, time and price are new attributes relative to AB3, so we have to implement parsing support for these attributes from scratch. The challenge was to provide maximum convenience to the user by allowing flexible inputs (such as having optional commas in prices), but at the same time ensuring correct input validation. To achieve this, a strict validation regex is implemented for all of the input attributes, and all input arguments for each attribute is validated upon the execution of a user command.
There was also a challenge in determining what was considered a valid or invalid input. Eg. How do we validate postal code / email. Such problems were further reviewed during the mock practical exam, where questions to what were considered valid inputs were further raised. By considering the suggestions of our peers, we improved our input validation by implementing stricter regex.
Achievements:
- User story - We originally planned to fulfill 15 User stories, but exceeded expectation by adding new User stories upon addition of new features, eventually fulfilling a total of 20 user stories.
-
Design - Kept the simplicity and cohesiveness of the features from the original AB3 project.
- Testing - Provided extensive unit and manual testing on the product, making it reliable and efficient for production usage.