Developer Guide
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
-
Appendix: Requirements
- Product scope
- User stories
-
Use cases
- Use case: UC C1 - List Customers
- Use case: UC C2 - View Customer
- Use case: UC C3 - Delete Customer
- Use case: UC C4 - Edit Customer
- Use case: UC C5 - Bookmark/Unbookmark Customer
- Use case: UC C6 - Set/Append Customer Note
- Use case: UC C7 - Set/Add Customer Points
- Use case: UC O1 - List Orders
- Use case: UC O2 - Create Order
- Use case: UC O3 - View Order
- Use case: UC O4 - Delete Order
- Use case: UC O5 - Edit Order
- Use case: UC O6 - Advance/Revert/Cancel Order Status
- Use case: UC O7 - Set/Append Order Note
- Non-Functional Requirements
- Glossary
-
Appendix: Instructions for manual testing
- Launch and shutdown
- Adding a customer
- Listing customers
- Finding customers
- Viewing a customer
- Editing a customer
- Deleting a customer
- Marking/Unmarking a customer
- Setting/Appending a customer’s note
- Setting/Adding a customer’s points
- Adding an order
- Listing orders
- Finding orders
- Viewing an order
- Editing an order
- Deleting an order
- Setting/Appending an order’s note
- Advancing an order’s status
- Reverting an order’s status
- Cancelling an order
- Appendix: Planned Enhancements
Acknowledgements
- This project is based on the AddressBook-Level3 project created by the SE-EDU initiative.
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
![:bulb: :bulb:](https://github.githubassets.com/images/icons/emoji/unicode/1f4a1.png)
.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 deletec 1
.
Each of the four main components (also shown in the diagram above),
- defines its API in an
interface
with the same name as the Component. - implements its functionality using a concrete
{Component Name}Manager
class (which follows the corresponding APIinterface
mentioned 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
, CustomerListPanel
, 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
Logic
component. - listens for changes to
Model
data so that the UI can be updated with the modified data. - keeps a reference to the
Logic
component, because theUI
relies on theLogic
to execute commands. - depends on some classes in the
Model
component, as it displaysCustomer
andOrder
objects residing in theModel
.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic
component:
How the Logic
component works:
- When
Logic
is called upon to execute a command, it uses theAddressBookParser
class to parse the user command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,AddCustomerCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to add a customer). - The result of the command execution is encapsulated as a
CommandResult
object which is returned back fromLogic
.
The Sequence Diagram below illustrates the interactions within the Logic
component for the execute("deletec 1")
API call.
![:information_source: :information_source:](https://github.githubassets.com/images/icons/emoji/unicode/2139.png)
DeleteCustomerCommandParser
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
AddressBookParser
class creates anXYZCommandParser
(XYZ
is a placeholder for the specific command name e.g.,AddCustomerCommandParser
) which uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,AddCustomerCommand
) which theAddressBookParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,AddCustomerCommandParser
,DeleteCustomerCommandParser
, …) inherit from theParser
interface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java
The Model
component stores:
-
the unique list of all
Customer
andOrder
objects in aUniqueCustomerList
andUniqueOrderList
. -
the current filtered list of
Customer
andOrder
objects as separateFilteredList<Customer>
andFilteredList<Order>
objects, which uses the unique lists as their source. -
the current sorted list of
Customer
andOrder
objects as separateSortedList<Customer>
andSortedList<Order>
objects, which uses the filtered lists as their source.These are exposed to the outside as unmodifiable
ObservableList<Customer>
andObservableList<Order>
objects 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.
-
the current ‘displayed’
Customer
orOrder
object. -
the list of
Order
objects associated with the current ‘displayed’Customer
as a separateFilteredList<Order>
This is exposed to the outside as an
ObservableList<Order>
object. -
a
UserPref
object that represents the user’s preferences.This is exposed to the outside as a
ReadOnlyUserPref
object.
![:information_source: :information_source:](https://github.githubassets.com/images/icons/emoji/unicode/2139.png)
Model
does not depend on any of the other three components (as the Model
represents data entities of the domain, they should make sense on their own without depending on other components)
Storage component
API : Storage.java
The Storage
component,
- can save both address book data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
AddressBookStorage
andUserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Model
component (because theStorage
component’s job is to save/retrieve objects that belong to theModel
)
Common classes
Classes used by multiple components are in the seedu.loyaltylift.commons
package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Bookmark Customer
The commands markc
and unmarkc
are responsible for bookmarking or un-bookmarking a customer respectively.
Parsing of the user input is done by the LogicManager
and AddressBookParser
(as explained in the section of Logic component).
Using the markc
command as an example, the parsing process will create a MarkCustomerCommand
object.
The MarkCustomerCommand
is then executed, and its process is described in the following sequence diagram.
- The list of filtered customers is retrieved from the
Model
, and the index is used to find the customer that needs to be bookmarked. - A new
Customer
object is created with it’sMarked
attribute to reflect that it is bookmarked. -
Model
is called again to replace the original customer to the newly created customer.
The sequence for the unmarkc
command is similar as the above.
Future Enhancements
Instead of using commands to manipulate the bookmark-ed status of a customer, LoyaltyLift can allow users to use the mouse to select the bookmark icon to swap between bookmarked and not bookmarked.
As we wanted to ensure that LoyaltyLift is optimised as a CLI application, we prioritised the implementation of markc
and unmarkc
over the ability to select on the graphical user interface.
However, certain users may find it more convenient to select the icon or prefer the flexibility of doing both depending on the situation.
Add/Deduct reward points feature
A new feature of adding and deducting points for a customer was required. A cumulative points system also had to be introduced. Adding points should increase the cumulative points, while deducting points should not affect the cumulative points of the customer.
As a result, a new attribute cumulative
was introduced to Points
.
For the parsing of the addpoints
command, we considered multiple design choices.
The one we ultimately settled on was simply utilising the Integer.valueOf()
method to parse the points inputted by the user.
Also, in the execution of AddPointsCommand
class, the points to add would exist as an Integer
object instead of a Points
object. The addition or subtraction of points from the Points
class would then be as simple as adding the
points to current points and cumulative points when it is positive, and subtracting from current points when it is negative.
This straightforward design would be sufficient to achieve the intended feature.
Lastly, to store the cumulative points of Customer
, a new attribute cumulativePoints
was introduced to JsonAdaptedCustomer
.
Alternative approaches
There were other designs we were considering, listed below.
-
A design choice we had to make was for the implementation of the
addpoints
command.Originally, we intended for the command to include a modifier syntax for the user to specify if he or she wishes to add or subtract points from the customer. For instance, the command could be
addpoints 1 mod/- pt/100
to indicate that the user wants to subtract 100 points from the customer in the first index. This implementation would be more consistent with the other commands that follow the syntax of[PREFIX]/
for the user to specify their command.However, we subsequently decided that this may be inconvenient for the user, and since it is more intuitive for the user to input 100 or -100 points, we decided to implement the command such that the modifier comes after the prefix
pt/
-
We also considered creating a static inner class
AddPoints
inPoints
.This inner class will encapsulate the addition or subtraction of points. Consequently, the
AddPointsCommand
would take in an instance ofPoints.AddPoints
as an attribute. This would allow an enummodifier
to exist within theAddPoints
inner class, allowing future extension of editing reward points by simply including a new enumeration of modifier.This would also allow a validity check of the points to be added or deducted. However, we later decided that this may not be necessary as checking the validity of the resultant
Points
after adding or subtracting is sufficient. Moreover, utilising theInteger.valueOf
method inAddPointsCommandParser
would make parsing much simpler as compared to evaluating the enum modifier that would come before points.This simpler design would also be sufficient as we had no plans to incorporate features other than the addition or subtraction of points.
Customer and Order Notes
Implementation
A note is any string that is associated with a Customer
or an Order
.
To implement this, a new note
field of type Note
has been added to Customer
and Order
.
-
Note
is a class with aString
field that can take any value exceptnull
. - If a
Customer
orOrder
has a note, a Note section will be shown in their view panel - An empty note is indicated by a blank string, in which case the Note section will not be shown.
There are four commands to manipulate a given customer/order’s note
-
setnotec
to set or overwrite aCustomer
’s note -
appendnotec
to add some string to the end of aCustomer
’s existing note -
setnoteo
to set or overwrite anOrder
’s note -
appendnoteo
to add some string to the end of anOrder
’s existing note
We settled on just a set and append command as deleting a note can be done by simply setting the note to an empty string. On the other hand, there is no clear way to edit text in a CLI application.
Potential Enhancements
-
Multiple Notes
Currently, a customer/order can have a single note. It may be useful if they can have multiple notes instead. This would involve an alternative set of commands to add and remove notes for a given customer/order.
-
Note Tags
Different notes between different customers and orders may have related themes. Thus, the ability to add tags to these related notes can help the user group their notes.
This could be done inline using a special character (e.g.
#
) within the note itself, where the system would automatically detect the tags.We can then provide an additional command to view all the notes with a specific tag, along with their associated customer/order.
Sorting feature
Customers and Orders can be sorted by certain attributes. We decided to implement the sorting as a parameter for the list commands.
The sorting is done by adding a JavaFX SortedList
to the Model
, with the original FilteredList
as its source. This SortedList
is then used to display the customer and order list in place of the FilteredList
.
The SortedList
can be sorted by a Comparator
.
- The
Comparator
s for each sorting option is provided as static constants by theCustomer
andOrder
class. - To facilitate the comparators, the relevant attribute classes (e.g.
Name
andPoints
) will also implement theComparable
interface.
Order Status
An order’s status
attribute represents the stage of an order, which can be one of these:
- Pending
- Paid
- Shipped
- Completed
- Cancelled
Note: Other than the Cancelled
stage, an order is expected to start from Pending
and proceed along the order as mentioned above.
For the implementation, we introduce a few classes.
- Firstly,
StatusValue
is an enumeration whose values are the stages mentioned above. - Next, the
StatusUpdate
class encapsulates aStatusValue
and a date. - Finally, a
Status
class serves as the attribute of an order that has multipleStatusUpdate
.
A StatusUpdate
encapsulates the date an Order
transitions into a StatusValue
.
Thus, an order’s Status
is associated with many StatusUpdate
to represent the history of how an order progresses from one stage to another.
Alternative Approaches
We also considered implementing the status attribute as an array of dates with a size of 5. Each entry of this array would correspond to each possible stage of the order.
However, this design would not be extensible for including other information such as a note or comment for each stage.
Furthermore, this design assumes that the order’s status can only move forward in progress and cannot revert without losing information.
E.g. An order may return from Shipped
to Paid
again if the shipping fails to succeed for the business owner.
With the current implemented approach, StatusUpdate
can encapsulate other information such as a note or comment.
Furthermore, the Status
class has many StatusUpdate
without assuming its size or any other information.
Hence, this potentially allows subsequent StatusUpdate
to have a stage that is before the previous entry of StatusUpdate
.
More details are explained in Potential Enhancements.
Potential Enhancements
-
Improvement in Reverting Order Progress
Currently, the implementation reverts an order’s status by deleting the latest
StatusUpdate
. Hence, information is lost that an order was once in that state before returning back. Furthermore,Status
sortsStatusUpdate
by itsStatusValue
so that the assumption that the latest entry is the latest is always true.In the future, it may be useful that this information be preserved and not deleted from the system. A potential implementation is by appending new
StatusUpdate
intoStatus
instead of deleting the latest entry. However, do note that the sorting logic must be updated. -
More Status Information
In the future, the user may find it useful to provide additional information when updating an order’s status. E.g. Add notes about the shipping details when the order updates from
Paid
toShipped
.
[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.
-
The user launches the application for the first time. The
VersionedAddressBook
will be initialized with the initial address book state, and thecurrentStatePointer
pointing to that single address book state. -
The user executes
deletec 5
command to delete the 5th customer in the address book. Thedeletec
command callsModel#commitAddressBook()
, causing the modified state of the address book after thedeletec 5
command executes to be saved in theaddressBookStateList
, and thecurrentStatePointer
is shifted to the newly inserted address book state. -
The user executes
addc n/David …
to add a new customer. Theaddc
command also callsModel#commitAddressBook()
, causing another modified address book state to be saved into theaddressBookStateList
.Note: If a command fails its execution, it will not call
Model#commitAddressBook()
, so the address book state will not be saved into theaddressBookStateList
. -
The user now decides that adding the customer was a mistake, and decides to undo that action by executing the
undo
command. Theundo
command will callModel#undoAddressBook()
, which will shift thecurrentStatePointer
once to the left, pointing it to the previous address book state, and restores the address book to that state.Note: If the
currentStatePointer
is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. Theundo
command usesModel#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:
Note: The lifeline for
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 callsModel#redoAddressBook()
, which shifts thecurrentStatePointer
once to the right, pointing to the previously undone state, and restores the address book to that state.Note: If the
currentStatePointer
is at indexaddressBookStateList.size() - 1
, pointing to the latest address book state, then there are no undone AddressBook states to restore. Theredo
command usesModel#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. -
The user then decides to execute the command
list
. Commands that do not modify the address book, such aslist
, will usually not callModel#commitAddressBook()
,Model#undoAddressBook()
orModel#redoAddressBook()
. Thus, theaddressBookStateList
remains unchanged. -
The user executes
clear
, which callsModel#commitAddressBook()
. Since thecurrentStatePointer
is not pointing at the end of theaddressBookStateList
, all address book states after thecurrentStatePointer
will be purged. Reason: It no longer makes sense to redo theaddc 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
deletec
, just save the customer being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
{more aspects and alternatives to be added}
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
Small business owners who:
- has a need to manage a sizeable number of customers and orders
- wants to improve customer relations and increase customer loyalty
- prefers desktop apps over using note-taking applications or spreadsheets
- are proficient in typing
- prefers typing to mouse interactions
- is reasonably comfortable using CLI applications
Value propositions:
- Manage a list of customers and their respective profiles
- Create orders with statuses for their respective customers
- Foster lasting relationships with customers by offering rewards for their continued business
User stories
Priorities: * * *
- High (must have) , * *
- Medium (nice to have), *
- Low (unlikely to have)
Priority | As a … | I can … | So that I can… |
---|---|---|---|
* * * |
small business owner | create, view, update and delete basic profile information of my customers | track and view who are my current customers |
* * * |
small business owner | create, view, update and delete basic information of my customers’ orders | track and view what are my customers’ orders |
* * * |
small business owner | assign an order to a specific customer | track all the orders under a specific customer |
* * * |
small business owner | advance & revert status of an order (eg. Pending, Paid, Shipped, Completed, Cancelled) | track the progress of my customer’s order |
* * * |
forgetful small business owner | bookmark customers | remind myself to communicate with some customers |
* * * |
customer-focused small business owner | track current and cumulated reward points associated to my customers | determine who I should reward as part of the reward system |
* * * |
customer-focused small business owner | add or deduct reward points from a customer | claim rewards for my customers |
* * * |
small business owner | view or search my customers’ previous orders | easily navigate to their previous orders to view relevant information |
* * * |
small business owner | save the customers and orders list after every action | avoid remembering information of my customers and orders |
* * * |
small business owner | assign a customer as an enterprise or an individual | include companies in my list of customers |
* * * |
attentive business owner | set or append note for a customer | take note of details such as preferences of my customers |
* * * |
attentive business owner | set or append note for an order | take note of details such as special requests of my orders |
* * |
customer-focused small business owner | sort customers by their reward points | determine who are my loyal customers |
* * |
customer-focused small business owner | sort the order list by status | be on track with customers’ orders |
* * |
small business owner | filter between individual and enterprise customers | view customers of a specific type when necessary |
* * |
small business owner | filter order based on status | view orders that require specific attention |
* * |
small business owner | filter customers that are bookmarked | identify customers that requires attention |
* * |
small business owner | view an order progress or history for each order | refer to it for future reference |
* * |
small business owner | search for customers using a keyword | easily find specific customers |
* * |
small business owner | search for orders using a keyword | easily find specific orders |
* * |
small business owner | clear my saved data | reset the application’s state |
* * |
analytical small business owner | view basic statistics of my customer base | understand the demographics of my customers better |
* * |
analytical small business owner | view an overall history tab to have a high level view of the orders I have completed on any particular date | see what orders are popular or unpopular to decide on goods to sell |
* * |
customer-focused small business owner | see how long an order has been unprocessed | prevent customers from waiting for too long |
* |
attentive business owner | create, view and delete multiple notes for a customer | customise notes for each customer |
* |
attentive business owner | create, view and delete multiple notes for an order | customise notes for each order |
* |
small business owner | include tags in my customer notes | view notes from multiple customers with a similar theme |
* |
attentive small business owner | view what were my customers’ previous preferences for my product | can easily communicate with the customer about their previous preferences to provide a good service |
* |
small business owner who wants to reduce costs | group orders with delivery addresses close to each other | allocate resources efficiently for order deliveries |
* |
small business owner | assign individuals to an enterprise | group individuals working in the enterprise |
* |
customer-focused business owner | set the reward points threshold for each tier | customise tiers to decide who are my loyal customers |
* |
customer-focused small business owner | create, view, update and delete reward prizes with its availability and points | know what rewards I have prepared to give away to loyal customers |
Use cases
For all use cases below, the System is LoyaltyLift (LL)
and the Actor is the user
, unless specified otherwise.
Use case: UC C1 - List Customers
MSS
- User requests list of customers.
-
LL displays list of customers.
Use case ends.
Extensions
-
2a. Customer list is empty.
Use case ends.
Use case: UC C2 - View Customer
MSS
- User gets list of customers (UC C1).
- User requests to view a customer.
-
LL displays the customer information.
Use case ends.
Extensions
-
2a. Requested customer does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC C3 - Delete Customer
MSS
- User gets list of customers (UC C1).
- User requests to delete a customer.
-
LL deletes the customer.
Use case ends.
Extensions
-
2a. Requested customer does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC C4 - Edit Customer
MSS
- User gets list of customers (UC C1).
- User enters new data for a customer.
-
LL updates the customer and displays the customer information.
Use case ends.
Extensions
-
2a. Requested customer does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
-
2b. LL detects invalid input data.
-
2b1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC C5 - Bookmark/Unbookmark Customer
MSS
- User gets list of customers (UC C1).
- User requests to bookmark/unbookmark a customer.
-
LL bookmarks/unbookmarks the customer.
Use case ends.
Extensions
-
2a. Requested customer does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC C6 - Set/Append Customer Note
MSS
- User gets list of customers (UC C1).
- User enters note for a customer.
-
LL sets/appends note to the customer and displays the customer information.
Use case ends.
Extensions
-
2a. Requested customer does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC C7 - Set/Add Customer Points
MSS
- User gets list of customers (UC C1).
- User enters customer points.
-
LL updates the customer’s points and displays the customer.
Use case ends.
Extensions
-
2a. Requested customer does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
-
2b. LL detects invalid input data.
-
2b1. LL shows an error message.
Use case resumes from step 1.
-
-
3a. Update results in invalid value.
-
3a1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC O1 - List Orders
MSS
- User requests list of orders.
-
LL displays list of orders.
Use case ends.
Extensions
-
2a. Order list is empty.
Use case ends.
Use case: UC O2 - Create Order
MSS
- User gets list of customers (UC O1).
- User enters customer id and new order data.
- LL creates the order and assigns the order to the customer.
-
LL displays the order information.
Use case ends.
Extensions
-
2a. Requested customer does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
-
2b. LL detects invalid input data.
-
2b1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC O3 - View Order
MSS
- User gets list of orders (UC O1).
- User requests to view an order.
-
LL displays the order information.
Use case ends.
Extensions
-
2a. Requested order does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC O4 - Delete Order
MSS
- User gets list of orders (UC O1).
- User requests to delete an order.
-
LL deletes the order.
Use case ends.
Extensions
-
2a. Requested order does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC O5 - Edit Order
MSS
- User gets list of orders (UC O1).
- User enters new data for an order.
-
LL updates the order and displays the order information.
Use case ends.
Extensions
-
2a. Requested order does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
-
2b. LL detects invalid input data.
-
2b1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC O6 - Advance/Revert/Cancel Order Status
MSS
- User gets list of orders (UC O1).
- User requests to advance/revert/cancel an order’s status.
-
LL updates the order’s status and displays the order information.
Use case ends.
Extensions
-
2a. Requested order does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
-
2b. Order status cannot be advanced/reverted/cancelled.
-
2b1. LL shows an error message.
Use case resumes from step 1.
-
Use case: UC O7 - Set/Append Order Note
MSS
- User gets list of orders (UC O1).
- User enters note for an order.
-
LL sets/appends note to the order and displays the order information.
Use case ends.
Extensions
-
2a. Requested order does not exist.
-
2a1. LL shows an error message.
Use case resumes from step 1.
-
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11
or above installed. - Should be able to hold up to 1000 customers and orders 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.
- Should be able to handle incorrect user input without crashing, and instruct the user on correct input format.
- Should work in both offline and online environments.
- Should have a response time of 5 seconds or less.
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- CLI: Command Line Interface, a text-based interface for user interaction
- GUI: Graphical User Interface, a visual interface for user interaction
- API: Application Programming Interface, a set of protocols, tools, and routines for building software applications
- Small business: Product-selling business that has much fewer employees and lower revenue than a regular-sized business
- Enterprise customers: Companies that order a large amount of products, much more than individual customers
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
![:information_source: :information_source:](https://github.githubassets.com/images/icons/emoji/unicode/2139.png)
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.
-
Adding a customer
-
Adding an individual customer
-
Prerequisites: No customer with the name
Amy Bee
exists in the list. -
Test case:
addc ct/ind n/Amy Bee p/12345678 e/amy@example.com a/312, Amy Street 1
, Expected: Customer ‘Amy Bee’ is added to the list. The added customer is displayed in the information panel. Details of the added customer shown in the status message.
-
-
Adding an enterprise customer
-
Prerequisites: No customer with the name
The Enterprise
exists in the list. -
Test case:
addc ct/ent n/The Enterprise p/12345678 e/the@enterprise.com a/Enterprise Street 1
, Expected: Customer ‘The Enterprise’ is added to the list. The added customer is displayed in the information panel. Details of the added customer shown in the status message.
-
-
Adding a customer with invalid parameters
-
Prerequisites: No customer with the name
Amy Bee
exists in the list. -
Test case:
addc ct/invalid n/Amy Bee p/12345678 e/amy@example.com a/312, Amy Street 1
, Expected: No customer is added. Information panel remains the same. Error details shown in the status message. -
Test case:
addc ct/ind n/Amy Bee* p/12345678 e/amy@example.com a/312, Amy Street 1
, Expected: Similar to previous. -
Test case:
addc ct/ind n/Amy Bee p/invalid e/amy@example.com a/312, Amy Street 1
, Expected: Similar to previous. -
Test case:
addc ct/ind n/Amy Bee p/12345678 e/invalid a/312, Amy Street 1
, Expected: Similar to previous. -
Test case:
addc ct/ind n/Amy Bee p/12345678 e/amy@example.com a/
, Expected: Similar to previous.
-
Listing customers
-
Listing all customers
-
Prerequisites: Multiple customers in the list.
-
Test case:
listc
Expected: All customers are shown in the list. Success message shown in the status message.
-
-
Listing customers with valid sorting and filter options
-
Prerequisites: Multiple customers in the list.
-
Test case:
listc s/points
Expected: All customers are shown in the list sorted by points. Success message shown in the status message. -
Test case:
listc f/ind
Expected: Only individual customers are shown in the list. Success message shown in the status message. -
Test case:
listc s/points f/ind
Expected: Only individual customers are shown in the list sorted by points. Success message shown in the status message. -
Other valid test cases to try:
listc s/x
,listc f/y
,listc s/x f/y
,...
(where x is a valid sorting option and y is a valid filter option)
Expected: List is sorted or filtered according to x and y.
-
-
Listing customers with invalid sorting or filter options
-
Prerequisites: Multiple customers in the list.
-
Test case:
listc s/invalid f/marked
Expected: List remains the same. Error details shown in the status message. -
Test case:
listc s/points f/invalid
Expected: List remains the same. Error details shown in the status message. -
Other incorrect test cases to try:
listc s/x
,listc f/y
,listc s/x f/y
,...
(where x is an invalid sorting option and y is an invalid filter option)
Expected: Similar to previous.
-
Finding customers
-
Finding existing customers
-
Prerequisite: Only the customers ‘Amy Bee’ and ‘Bob Choo’ exists in the list.
-
Test case:
findc Amy
Expected: Only the customer ‘Amy Bee’ is shown. Success message with number of listed customers (1) shown in the status message. -
Test case:
findc Bee Amy
Expected: Only the customer ‘Amy Bee’ is shown. Success message with number of listed customers (1) shown in the status message. -
Test case:
findc Amy Bob
Expected: Both customers ‘Amy Bee’ and ‘Bob Choo’ are shown. Success message with number of listed customers (2) shown in the status message.
-
-
Finding non-existent customers
-
Prerequisite: Only the customers ‘Amy Bee’ and ‘Bob Choo’ exists in the list.
-
Test case:
findc A
Expected: No customers are shown. Success message with number of listed customers (0) shown in the status message.
-
-
Finding customers with zero keywords
-
Prerequisite: Multiple customers in the list
-
Test case:
findc
Expected: List remains the same. Error details shown in the status message.
-
Viewing a customer
-
Viewing a customer with a valid index
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
viewc 1
Expected: First customer is displayed in the information panel. Details of the viewed customer shown in the status message.
-
-
Viewing a customer with an invalid index
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
viewc 0
Expected: Information panel remains the same. Error details shown in the status message. -
Other incorrect view commands to try:
viewc
,viewc x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Editing a customer
-
Editing a customer with valid parameters
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. No customer with the nameAmy Bee
exists in the list. -
Test case:
editc 1 p/12345678
Expected: First customer’s phone number updated to ‘12345678’. The updated customer is displayed in the information panel. Details of the updated customer shown in the status message. -
Test case:
editc 1 ct/ent n/Amy Bee
Expected: First customer’s customer type updated to enterprise and name updated to ‘Amy Bee’. The updated customer is displayed in the information panel. Details of the updated customer shown in the status message.
-
-
Editing a customer with invalid parameters
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
editc ct/invalid
Expected: No customer is edited. Error details shown in the status message. -
Test case:
editc n/Amy Bee*
Expected: Similar to previous. -
Test case:
editc p/invalid
Expected: Similar to previous. -
Test case:
editc e/invalid
Expected: Similar to previous. -
Test case:
editc a/
Expected: Similar to previous.
-
-
Editing a customer with an invalid index
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
editc 0
Expected: Information panel remains the same. Error details shown in the status message. -
Other incorrect edit commands to try:
editc
,editc x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Deleting a customer
-
Deleting a customer with a valid index while all customers are being shown
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
deletec 1
Expected: First customer and any orders belonging to the customer is deleted from the list. Details of the deleted customer shown in the status message.
-
-
Deleting a customer with a valid index while the customer is being displayed
-
Prerequisites: List and view the first customer using
listc
followed byviewc 1
. Multiple customers in the list. -
Test case:
deletec 1
Expected: First customer and any orders belonging to the customer is deleted from the list. Information panel is cleared. Details of the deleted customer shown in the status message.
-
-
Deleting a customer with a valid index while the customer’s order is being displayed
-
Prerequisites: At least one order is in the list. List and view the first order using
listo
followed byviewo 1
. Find the order’s customer usingfindc FULL CUSTOMER NAME
. -
Test case:
deletec 1
Expected: First customer and any orders belonging to the customer is deleted from the list. Information panel is cleared. Details of the deleted customer shown in the status message.
-
-
Deleting a customer with an invalid index
-
Prerequisites: List customers using the
listc
command. Multiple customers in the list. -
Test case:
deletec 0
Expected: No customer or order is deleted. Information panel remains the same. Error details shown in the status message. -
Other incorrect delete commands to try:
deletec
,deletec x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Marking/Unmarking a customer
-
Marking/Unmarking a customer with a valid index
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
markc 1
Expected: First customer is marked. The marked customer is displayed in the information panel. Details of the marked customer shown in the status message. -
Test case:
unmarkc 1
Expected: First customer is unmarked. The marked customer is displayed in the information panel. Details of the unmarked customer shown in the status message.
-
-
Marking/Unmarking a customer with an invalid index
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
markc 0
Expected: No customer is marked/unmarked. Information panel remains the same. Error details shown in the status message. -
Test case:
unmarkc 0
Expected: Similar to previous. -
Other incorrect mark/unmark commands to try:
markc
,markc x
,unmarkc
,unmarkc x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Setting/Appending a customer’s note
-
Setting/Appending the note of a customer with valid parameters
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. First customer in the list has a non-empty note. -
Test case:
setnotec 1 nt/
Expected: The first customer’s note is cleared. The customer is displayed in the information panel. Details of the customer shown in the status message. -
Test case:
setnotec 1 nt/Example Note
Expected: The first customer’s note is set to ‘Example Note’. The customer is displayed in the information panel. Details of the customer shown in the status message. -
Test case:
appendnotec 1 nt/Extra Note
Expected: ‘Extra Note’ is appended to the first customer’s existing note. The customer is displayed in the information panel. Details of the customer shown in the status message.
-
-
Setting/Appending the note of a customer with invalid parameters
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
setnotec 0 nt/
Expected: No customer’s note is affected. Information panel remains the same. Error details shown in the status message. -
Test case:
appendnotec 0 nt/
Expected: Similar to previous. -
Other incorrect note commands to try:
setnotec 1
,appendnotec 1
,setnotec x nt/
,appendnotec x nt/
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Setting/Adding a customer’s points
-
Setting/Adding the points of a customer with valid parameters
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
setpoints 1 pt/0
Expected: The first customer’s points and cumulative points is set to zero. The customer is displayed in the information panel. Details of the customer shown in the status message. -
Test case:
setpoints 1 pt/100
Expected: The first customer’s points and cumulative points is set to 100. The customer is displayed in the information panel. Details of the customer shown in the status message. -
Test case:
addpoints 1 pt/0
Expected: The first customer’s points and cumulative points remains the same. The customer is displayed in the information panel. Details of the customer shown in the status message. -
Test case:
addpoints 1 pt/100
Expected: 100 is added to the first customer’s points and cumulative points. The customer is displayed in the information panel. Details of the customer shown in the status message. -
Test case:
addpoints 1 pt/-100
Expected: 100 is subtracted from the first customer’s points, while cumulative points remains the same. The customer is displayed in the information panel. Details of the customer shown in the status message.
-
-
Adding the points of a customer resulting in points being out of range
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test Case:
setpoints 1 pt/999999
, followed byaddpoints 1 pt/1
Expected: Points will end up out of range. No customer’s points is affected. Information panel remains the same. Error details shown in the status message. -
Test Case:
setpoints 1 pt/0
, followed byaddpoints 1 pt/-1
Expected: Points will end up out of range. Similar to previous. -
Test Case:
setpoints 1 pt/999999
, followed byaddpoints 1 pt/-999999
, followed byaddpoints 1 pt/1
Expected: Cumulative points will end up out of range. Similar to previous.
-
-
Setting/Adding the points of a customer with invalid parameters
-
Prerequisites: List all customers using the
listc
command. Multiple customers in the list. -
Test case:
setpoints 1 pt/1000000
Expected: No customer’s points is affected. Information panel remains the same. Error details shown in the status message. -
Test case:
setpoints 1 pt/-1
Expected: Similar to previous. -
Test case:
addpoints 1 pt/1000000
Expected: Similar to previous. -
Test case:
setpoints 0 pt/100
Expected: Similar to previous. -
Test case:
addpoints 0 pt/100
Expected: Similar to previous. -
Other incorrect points commands to try:
setpoints x pt/100
,addpoints x pt/100
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Adding an order
-
Adding an order
-
Prerequisites: A customer with the name
Amy Bee
exists as the first customer in the customer list, but has no orders -
Test case:
addo 1 n/Banana Cake
Expected: OrderBanana Cake
is added to the order list. The order should have a quantity of 1 and address that is the same toAmy Bee
. The added order is displayed in the information panel. Details of the added order shown in the status message. -
Test case:
addo 1 n/Chocolate Roll q/5 a/Gardens By The Bay
Expected: OrderChocolate Roll
is added to the order list. The order should have a quantity of 5 and address ofGardens By The Bay
. The added order is displayed in the information panel. Details of the added order shown in the status message.
-
-
Adding an order with invalid parameters
-
Prerequisites: Only 1 customer exist in the customer list.
-
Test case:
addo 0 n/Banana Roll
Expected: No order is added. Information panel remains the same. Error details shown in the status message. -
Test case:
addo 2 n/Banana Roll
Expected: Similar to previous.
-
Listing orders
-
Listing all orders
-
Prerequisites: Multiple orders in the orders list.
-
Test case:
listo
Expected: All orders are shown in the list. Success message shown in the status message.
-
-
Listing orders with valid sorting and filter option
-
Prerequisites: Multiple orders in the orders list.
-
Test case:
listo s/status
Expected: All orders are shown in the list sorted by status. Success message shown in the status message. -
Test case:
listo f/pending
Expected: Only orders whose status are ‘pending’ are shown in the list. Success message shown in the status message. -
Test case:
listo s/name f/paid
Expected: Only orders whose status are ‘paid’ are shown in the list sorted by name. Success message shown in the status message. -
Other valid test cases to try:
listo s/x
,listo f/y
,listo s/x f/y
,...
(where x is a valid sorting option and y is a valid filter option)
Expected: List is sorted or filtered according to x and y.
-
-
Listing orders with invalid sorting or filter options
-
Prerequisites: Multiple orders in the list.
-
Test case:
listo s/invalid f/pending
Expected: List remains the same. Error details shown in the status message. -
Test case:
listo s/status f/invalid
Expected: List remains the same. Error details shown in the status message. -
Other incorrect test cases to try:
listo s/x
,listo f/y
,listo s/x f/y
,...
(where x is an invalid sorting option and y is an invalid filter option)
Expected: Similar to previous.
-
Finding orders
-
Finding existing orders
-
Prerequisite: Only the orders ‘Banana Cake’ and ‘Chocolate Roll’ exists in the order list.
-
Test case:
findo Banana
Expected: Only the order ‘Banana Cake’ is shown. Success message with number of listed orders (1) shown in the status message. -
Test case:
findo Cake Banana
Expected: Only the order ‘Banana Cake’ is shown. Success message with number of listed orders (1) shown in the status message. -
Test case:
findo Banana Chocolate
Expected: Both orders ‘Banana Cake’ and ‘Chocolate Roll’ are shown. Success message with number of listed orders (2) shown in the status message.
-
-
Finding non-existent orders
-
Prerequisite: Only the orders ‘Banana Cake’ and ‘Chocolate Roll’ exists in the order list.
-
Test case:
findo A
Expected: No orders are shown. Success message with number of listed orders (0) shown in the status message.
-
-
Finding orders with zero keywords
-
Prerequisite: Multiple orders in the list
-
Test case:
findo
Expected: List remains the same. Error details shown in the status message.
-
Viewing an order
-
Viewing an order with a valid index
-
Prerequisites: List all orders using the
listo
command. Multiple orders in the list. -
Test case:
viewo 1
Expected: First order is displayed in the information panel. Details of the viewed order shown in the status message.
-
-
Viewing an order with an invalid index
-
Prerequisites: List all orders using the
listo
command. Multiple customers in the list. -
Test case:
viewo 0
Expected: Information panel remains the same. Error details shown in the status message. -
Other incorrect view commands to try:
viewo
,viewo x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Editing an order
-
Editing an order with valid parameters
-
Prerequisites: List all orders using the
listo
command. Multiple orders in the list. No order with the name of ‘Banana Cake’, with quantity of 50 exists. -
Test case:
edito 1 a/5th Smith Street
Expected: First order’s address updated to ‘5th Smith Street’. The updated order is displayed in the information panel. Details of the updated order shown in the status message. -
Test case:
edito 1 q/50 n/Banana Cake
Expected: First order’s quantity updated to 50 and name updated to ‘Banana Cake’. The updated order is displayed in the information panel. Details of the updated order shown in the status message.
-
-
Editing an order with invalid parameters
-
Prerequisites: List all orders using the
listo
command. Multiple orders in the list. -
Test case:
edito q/invalid
Expected: No order is edited. Error details shown in the status message. -
Test case:
edito a/
Expected: Similar to previous.
-
Deleting an order
-
Deleting an order with a valid index while all orders are being shown
-
Prerequisites: List all orders using the
listo
command. Multiple orders in the list. -
Test case:
deleteo 1
Expected: First order is deleted from the list. Details of the deleted order shown in the status message.
-
-
Deleting an order with a valid index while the order is being displayed
-
Prerequisites: List and view the first order using
listo
followed byviewo 1
. Multiple orders in the list. -
Test case:
deleteo 1
Expected: First order is deleted from the list. Information panel is cleared. Details of the deleted order shown in the status message.
-
-
Deleting an order with an invalid index
-
Prerequisites: List orders using the
listo
command. Multiple orders in the list. -
Test case:
deleteo 0
Expected: No order is deleted. Information panel remains the same. Error details shown in the status message. -
Other incorrect delete commands to try:
deleteo
,deleteo x
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Setting/Appending an order’s note
-
Setting/Appending the note of an order with valid parameters
-
Prerequisites: List all orders using the
listo
command. Multiple orders in the list. First order in the list has a non-empty note. -
Test case:
setnoteo 1 nt/
Expected: The first order’s note is cleared. The order is displayed in the information panel. Details of the order shown in the status message. -
Test case:
setnoteo 1 nt/Example Note
Expected: The first order’s note is set to ‘Example Note’. The order is displayed in the information panel. Details of the order shown in the status message. -
Test case:
appendnoteo 1 nt/Extra Note
Expected: ‘Extra Note’ is appended to the first order’s existing note. The order is displayed in the information panel. Details of the order shown in the status message.
-
-
Setting/Appending the note of an order with invalid parameters
-
Prerequisites: List all order using the
listo
command. Multiple orders in the list. -
Test case:
setnoteo 0 nt/
Expected: No order’s note is affected. Information panel remains the same. Error details shown in the status message. -
Test case:
appendnoteo 0 nt/
Expected: Similar to previous. -
Other incorrect note commands to try:
setnoteo 1
,appendnoteo 1
,setnoteo x nt/
,appendnoteo x nt/
,...
(where x is larger than the list size)
Expected: Similar to previous.
-
Advancing an order’s status
-
Advancing an order
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Pending’ status. -
Test case:
advo 1
Expected: The first order’s note status is now ‘Paid’. The order is displayed in the information panel. Details of the order shown in the status message.
-
-
Advancing an order that is completed
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Completed’ status. -
Test case:
advo 1
Expected: No order’s status is affected. Information panel remains the same. Error details shown in the status message.
-
-
Advancing an order that is cancelled
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Cancelled’ status. -
Test case:
advo 1
Expected: No order’s status is affected. Information panel remains the same. Error details shown in the status message.
-
Reverting an order’s status
-
Reverting an order
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Paid’ status. -
Test case:
revo 1
Expected: The first order’s note status is now ‘Pending’. The order is displayed in the information panel. Details of the order shown in the status message.
-
-
Advancing an order that is pending
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Pending’ status. -
Test case:
revo 1
Expected: No order’s status is affected. Information panel remains the same. Error details shown in the status message.
-
Cancelling an order
-
Cancelling an order
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Pending’ status. -
Test case:
cancelo 1
Expected: The first order’s note status is now ‘Cancelled’. The order is displayed in the information panel. Details of the order shown in the status message.
-
-
Cancelling an order that is completed
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Completed’ status. -
Test case:
cancelo 1
Expected: No order’s status is affected. Information panel remains the same. Error details shown in the status message.
-
-
Cancelling an order that is cancelled
-
Prerequisites: list all orders using the
listo
command. At least one order in the list. The first order is in ‘Cancelled’ status. -
Test case:
cancelo 1
Expected: No order’s status is affected. Information panel remains the same. Error details shown in the status message.
-
Appendix: Planned Enhancements
Enabling Customers with Duplicate Names to be Created
Current Situation / Problem
It is a common occurrence for 2 customers to have the same full name. However, an attempt to create a 2nd customer with the same name will fail as the user will face an error.
The error occurs because LoyaltyLift does not allow 2 customers with the same name to exist.
In Customer.java
, Customer::isSameCustomer
is responsible for determining if 2 customers have the same identity, and it returns true if they have the same name.
Possible Enhancements
Ideally, a customer can be uniquely identified by a government-issued identification number (e.g. NRIC for Singaporeans). However, this information is most likely unavailable to the small business owner; hence is not a feasible solution.
Therefore, we propose 3 possible tweaks or solutions.
-
Use phone number to uniquely identify a customer
Instead of using the customer’s name, their phone number is a better unique identifier. With this solution,
Customer::isSameCustomer
will return true if 2 customers’ phone numbers are equal.Pros: There is a much lower probability of conflicts in the customer’s phone number. One of the few possible occurrences is when a customer changes phone number, and another customer obtains that customer’s previous phone number.
Cons: However, a customer may not want to be contacted through phone but through email instead. Hence, the business owner will not be able to create a customer in this situation.
-
Combining multiple attributes to uniquely identify a customer
Building upon the idea of using phone number as a unique identifier, we can instead use a combination of attributes as a unique identifier. Combining the customer’s name, phone number and home address is possible. With this combination,
Customer::isSameCustomer
will return true if 2 customers’ names, phone numbers and home addresses are all equal.Pros: More robustly uniquely identify a customer in the absence of government-issued identification number.
Cons: It is more error-prone as a customer’s information, such as his phone number and address can change over time. More attributes must be updated compared to just using a single attribute as a unique identifier.
-
Use a hidden identification number
Instead of using the customer’s name, a customer can be uniquely identified with a hidden, randomly generated unique identifier. On creating every customer object, LoyaltyLift will allocate a new unique identifier number to the customer.
Customer::isSameCustomer
will return true if 2 customers’ hidden unique identifier are the same.Pros: This tweak removes the dependency on the customer’s personal information. Randomly generated unique identifier are quick to generate and have a very low chance of generating the same unique identifier.
Cons: Duplicated customers may be created in the application. Without any dependency, this increases the possibility for a single real customer to exist as 2 customers in LoyaltyLift. If the business owner is not careful or is unaware that the customer already exists in LoyaltyLift, he may accidentally create the same customer again. With a unique identifier such as the phone number or customer’s name, the user will face an error when adding a 2nd customer with the same personal information. This indicates that the business owner may be making a mistake because the customer already exists in LoyaltyLift.
Extra Remarks
While the above solutions are mostly feasible, we can also explore the idea of giving the flexibility to the business owner to decide the unique identifier. Using a phone number as the default unique identifier, most business owners may be satisfied and only face a few issues. This is because business owners can request that all customers share their phone numbers.
However, future implementations can allow the business owner to configure LoyaltyLift to use an email address or a combination of phone number and email address as the unique identifier instead. More experience users may wish for the freedom to configure this option or some users may require this feature to comply with regulations around sensitive customer data.
Allow Customers to have similar Orders
Currently, a customer cannot have two orders with the same product name, quantity, and address on the same day.
This is because the orders will be considered as duplicates, as defined by Order::isSameOrder
.
To improve this, we plan to assign a unique ID for each order such that two orders are considered duplicates if they have the same ID.
This ID can initially be randomly generated, but we then allow the user to define their own format as required by their business (e.g. some users may want to incorporate the order’s created date into the identifier).
Setting Tiers
Currently, the number of tiers in LoyaltyLift are hardcoded at three tiers. The names and points required for each tier are also cannot be customized. However, this can be inconvenient as users may have different point schemes.
To support this, we plan to add a settier
command that allows the user to set each tier’s name and required points by index.
For example, the customer may set the third tier to Platinum
at 10,000 points by entering settier 3 Platinum 10000
.
While each tier will have some default color, we can also consider including an option for the user to provide a hex code for their desired color, e.g. settier 3 Platinum 10000 1affff
.
To complement this new command, we also plan to include a viewtiers
command to display the existing tiers and a deletetier
command to remove an existing tier.
Access Orders made by a specific Customer
This enhancement consists of two parts:
- Accessing orders from a customer’s order history
- Filtering the order list by customer name or index
Accessing orders from a customer’s order history
Currently, the user can see a customer’s list of orders by viewing the customer using the viewc
command. However, there is no way to view each order in detail afterwards.
There are two approaches to make this possible:
-
Use the same list for the main order list and the customer view order list
As described in the Model component section, the order list of the displayed customer is a separate
FilteredList<Order>
. By using the same list as the main order list, we can use theviewo
command to directly access the orders in the customer view. -
Provide a separate command for viewing the orders displayed in the customer view
This command may tentatively be called
viewco
, where it will specifically be used to access orders in the separateFilteredList<Order>
.
Filtering the order list by customer name
Currently, the order list cannot be filtered to show only orders created by a specific customer. Moreover, the order list does not show the customer it’s associated with. This can be inconvenient as multiple customers may make similar orders.
Thus, we plan to:
-
Update the UI of the order list to display each order’s associated customer.
-
Enhance the
listo
command to support filtering by customer name.This can be implemented as a separate parameter
by/CUSTOMER_NAME
(e.g.listo by/Alice
) where the keyword search logic would work in a similar manner asfindc
(case-insensitive, order-insensitive, full-word,OR
search).