Developer Guide
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- 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
- Launch and shutdown
- Starting up with missing/corrupted data files
- Adding an inventory item
- Listing all inventory items
- Finding an inventory item
- Deleting an inventory item
- Editing an inventory item
- Adding an order
- Listing all orders
- Finding order(s)
- Sorting orders by time created
- Deleting an order
- Editing an order
- Marking an order
- Getting help
- Clearing data in TrackO
- Exiting TrackO
- Editing the data file
Acknowledgements
- This application is built on code from the AddressBook-Level3 project created by SE-EDU initiative at https://se-education.org/
- Libraries used in our application: JavaFX, Jackson, JUnit5
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.puml
files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides to learn how to create and edit diagrams.
Architecture
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main
has two classes called Main
and MainApp
. It is responsible for,
- At app launch: Initializes the components in the correct sequence, and connects them up with each other.
- At shut down: Shuts down the components and invokes cleanup methods where necessary.
Commons
represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
-
UI
: The UI of the App. -
Logic
: The command executor. -
Model
: Holds the data of the App in memory. -
Storage
: Reads data from, and writes data to, the hard disk.
How the architecture components interact with each other
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command deletei 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
, ItemListPanel
, OrderListPanel
, 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 displaysOrder
andInventoryItem
object 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 theTrackOParser
class to parse the user command. - This results in a
Command
object (more precisely, an object of one of its subclasses e.g.,AddOrderCommand
) which is executed by theLogicManager
. - The command can communicate with the
Model
when it is executed (e.g. to add a person). - 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("deletei 1")
API call.
DeleteItemCommandParser
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
TrackOParser
class creates anXYZCommandParser
(XYZ
is a placeholder for the specific command name e.g.,AddOrderCommandParser
) which uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,AddOrderCommand
) which theTrackOParser
returns back as aCommand
object. - All
XYZCommandParser
classes (e.g.,AddOrderCommandParser
,DeleteOrderCommandParser
, …) 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 TrackO data i.e., all
InventoryItem
andOrder
objects (which are contained in anInventoryList
andOrderList
object respectively). - stores the currently ‘selected’
InventoryItem
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<InventoryItem>
that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores the currently selected
Order
objects (e.g., results of a search query) as a separate filtered list, which is wrapped within a sorted list (Order
objects can be sorted by time of creation), which is exposed to outsiders as an unmodifiableObservableList<Order>
that can be ‘observed’ e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. - stores a
UserPref
object that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPref
objects. - 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)
Tag
list in the TrackO
, which InventoryItem
references. This allows TrackO
to only require one Tag
object per unique tag, instead of each InventoryItem
needing their own Tag
objects.Storage component
API : Storage.java
The Storage
component,
- can save both TrackO data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
TrackOStorage
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 tracko.commons
package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Inventory Management
Inventory management is one of two core features of TrackO alongside order management. These two features work together to form the backbone of the application, allowing for efficient and reliable tracking of order and inventory data.
Overview
As per the Model diagram given above, the application keeps track of one InventoryList
at any point in time. This InventoryList
instance represents the container that keeps track of all inventory item
data in the system.
Currently, the application features 5 main operations that interact directly with the InventoryList
. They are
represented by the following commands:
-
AddItemCommand
- creates a new item to be added to theInventoryList
-
FindItemCommand
- filters and display matching items from theInventoryList
based on provided keywords -
ListItemCommand
- display all inventory data from theInventoryList
-
EditItemCommand
- edit the data of an item from theInventoryList
-
DeleteItemCommand
- deletes an existing item from theInventoryList
The inventory management feature is supported by the InventoryItem
class, represented by the class diagram below.
The InventoryItem
class encapsulates item-related data packaged in the following classes/attributes:
-
ItemName
,Description
,SellPrice
,CostPrice
- inventory data related to theInventoryItem
-
Quantity
- quantity of an item currently in the inventory -
Tag
- 30-character long tag to help classify items in the inventory
Add Item Feature
The add item feature allows users to add an InventoryItem
to be tracked by the system.
Implementation
The add item command will be executed by AddItemCommand
. Items added will be stored in InventoryList
.
Given below is an example usage scenario and how the add item mechanism behaves at each step.
Step 1. The user launches the application for the first time. The TrackO
will be initialized with the initial TrackO state, and the InventoryList
will contain sample data.
The initial state of TrackO Model before running add item command will be as such.
Step 2. The user executes addi i/Key q/200 d/Cabinet keys sp/9.90 cp/4.90 t/new
command to add 200 keys to the inventory list in TrackO.
The addi
command creates an AddItemCommandParser
which checks that the following input arguments are present
before parsing the arguments into an AddItemCommand
object:
- item name (prefixed by
i/
) - quantity (prefixed by
q/
) - description (prefixed by
d/
) - sell price (prefixed by
sp/
) - cost price (prefied by
cp
)
Tags (which are prefixed by t/
) are optional inputs and will be parsed into the AddItemCommand
as well if they are present.
The AddItemCommand
calls Model#addItem()
to add the item and its corresponding quantity into the inventory list.
Model#addItem()
, so the incomplete item will not be saved to InventoryList
.
The following sequence diagram shows how the add item operation works:
AddItemCommand
should
end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The following activity diagram summarizes what happens when a user executes a new command:
Design considerations
Aspect: How add item executes:
-
Alternative 1 (current choice): User inputs all required fields in a single input
- Pros: easier to implement
- Cons: user input is very long and may be more prone to typos
Delete Item Feature
The delete item feature allows the user to delete an InventoryItem
currently being tracked by the system.
Implementation
The delete item command deletei
is supported by the DeleteItemCommand
. It extends Command
.
Given below is an example usage scenario and how the edit item mechanism behaves at each step.
Step 1. The user inputs the command deletei 1
. This calls:
LogicManager#execute()
-
TrackOParser#parseCommand()
. This parses the command as anDeleteItemCommand
and returns aDeleteItemCommandParser
object. -
DeleteItemCommandParser#parse()
parses the arguments and returns anDeleteItemCommand
with the targetIndex
.
Step 2. DeleteItemCommand#execute()
is called and the DeleteItemCommand
calls Model#deleteItem()
which deletes
the InventoryItem
at the target Index
from the Model
.
The sequence diagram below illustrates this process.
DeleteItemCommandParser
and DeleteItemCommand
should end at
the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the
end of diagram.
Design Considerations
Aspect: How deletei is implemented
-
Alternative 1 (current choice): The command deletes the target
InventoryItem
based on the targetIndex
.- Pros: Easier to implement,
- Cons: The user must check for the
InventoryItem
for itsIndex
.
-
Alternative 2: The command can delete
InventoryItem
objects based on theirItemName
.- Pros: User do not need to check for the
InventoryItem
object’sIndex
. - Cons: Harder to implement.
- Pros: User do not need to check for the
List Items Feature
The list items feature allows the user to list all the existing InventoryItem
s in the inventory.
Implementation
The list item feature is supported by the ListItemsCommand
. It extends Command
.
Given below is an example usage scenario and how the ListItemsCommand
mechanism behaves at each step.
Step 1. The user inputs listi
. This calls LogicManager#execute()
, which then calls TrackOParser#parseCommand()
.
This method will return a new instance of ListItemsCommand
.
Step 2. ListItemsCommand#execute()
is called, which then calls the method
Model#updateFilteredOrderList(PREDICATE_SHOW_ALL_ITEMS)
. This will show all the InventoryItem
s in the existing
inventory list.
The sequence diagram below illustrates this process.
ListItemsCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline
reaches the end of diagram.
Design Considerations
Aspect: How the listi
command executes
-
Alternative 1 (current choice): The command lists all the items in the inventory list.
- Pros: Easier to implement.
- Cons: Unable to filter specific items.
Find Item Feature
The find item feature allows the user to find InventoryItem
(s) by keyword(s) given by the user.
Implementation
The find item command is supported by FindItemCommand
. It extends Command
.
Given below is an example usage scenario and how the find item mechanism behaves at each step.
Step 1. The user executes findi chair mattress
command to find the items with the keywords
chair or mattress. The findi
command calls FindItemCommandParser
which checks for the correct command
syntax and separates the keywords, utilising each space as a delimiter.
Step 2. The keywords are then passed into a constructor for ItemContainsKeywordsPredicate
,
which extends Predicate<InventoryItem>
, to construct a predicate that will filter the items according to the keywords.
The predicate is passed into a new instance of FindItemCommand
. FindItemCommand
then calls
Model#updateFilteredItemList()
to filter Model#filteredOrders
according to the previously constructed
ItemContainsKeywordsPredicate
.
The sequence diagram below illustrates this process.
FindItemCommandParser
and FindItemCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline
reaches the end of diagram.
Design Considerations
Aspect: How findi
is implemented
-
Alternative 1 (current choice): The command finds items based on their
ItemName
.- Pros: Easier to implement, and users do not have to use prefixes to find items.
- Cons: Cannot search based on other item fields, e.g. searching based on the price range of the items.
-
Alternative 2: The command can find items based on all of their fields.
- Pros: Can search based on more fields, useful if the user has large number of items to navigate through.
- Cons: Harder to implement.
Edit Item Feature
The edit item feature allows the user to edit an InventoryItem
currently being tracked by the system.
Implementation
The edit item command editi
is supported by the EditItemCommand
. It extends Command
.
Given below is an example usage scenario and how the edit item mechanism behaves at each step.
Step 1. The user inputs the command editi 1 i/Chair q/20
. This calls:
LogicManager#execute()
-
TrackOParser#parseCommand()
. This parses the command as anEditItemCommand
and returns anEditItemCommandParser
object. -
EditItemCommandParser#parse()
parses the arguments and returns anEditItemCommand
with the targetIndex
and the appropriateEditItemDescriptor
as input.
The EditItemDescriptor
contains information which the newly edited InventoryItem
should have and is used in the creation of the new InventoryItem
object. In this case, the EditItemDescriptor
contains a new
ItemName
and Quantity
taken from the user input, while all other fields are copied from the existing InventoryItem
at the
target Index
1.
Step 2. EditItemCommand#execute()
is called and the EditItemCommand
creates a new InventoryItem
using createEditedItem()
and the EditItemDescriptor
.
It then checks if this InventoryItem
already exists in the inventory list by using Model#hasItem()
. If it already exists, a
CommandException
is thrown with MESSAGE_DUPLICATE_ITEM
.
An item already exists if there is another item in the
inventory list with same ItemName
. InventoryItem#isSameItem()
returns true when both InventoryItem
have the same ItemName
. This is
because having 2 InventoryItem
with the same ItemName
can be confusing to the user and this safeguards the user from such a
situation.
Step 3. The InventoryItem
at the target index is then replaced by the newly created InventoryItem
using Model#setItem()
,
successfully executing the edit item command in the Model
.
The sequence diagram below illustrates this process.
EditItemCommandParser
should end at
the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the
end of diagram.
Design Considerations
Aspect: Whether to implement the edit item feature
-
Alternative 1 (current choice): The command is implemented and edits the item based on the prefixes
inputted by the user.
- Pros: The user can edit only the fields that they want to edit.
- Cons: The user may have to input long commands.
-
Alternative 2: No edit command, users have to delete and re-add items should there be any change.
- Pros: Less bug-prone, more convenient for the developers to implement.
- Cons: Not user-friendly and makes things more difficult for the user.
Order Management
Order management is one of two core features of TrackO alongside inventory management. These two features work together to form the backbone of the application, allowing for efficient and reliable tracking of order and inventory data.
Overview
As per the Model diagram given above, the application keeps track of one OrderList
at any point in time. This OrderList
instance represents the container that keeps track of all order data in the system.
Currently, the application features 5 main operations that interact directly with the OrderList
. They are represented by
the following commands:
-
AddOrderCommand
- creates a new order to be added to theOrderList
-
FindOrderCommand
- filters and display matching orders from theOrderList
based on provided keywords -
ListOrderCommand
- display all order data from theOrderList
-
EditOrderCommand
- edit the data of an order from theOrderList
-
DeleteOrderCommand
- deletes an existing order from theOrderList
-
MarkOrderCommand
- marks an existing order from theOrderList
as paid or delivered
The order management feature is supported by the Order
class, represented by the class diagram below.
The Order
class encapsulates order-related data packaged in the following classes/attributes:
-
Name
,Phone
,Email
,Address
- customer data related to theOrder
-
ItemQuantityPair
- represents an orderedInventoryItem
in theOrder
, with an accompanyingQuantity
that represents the amount of units of saidInventoryItem
ordered by the customer -
LocalDateTime
- the time at which the order entry was created in the system -
isPaid
/isDelivered
- represents the completion status of the order (anOrder
is considered complete if both fields are true)
Add Order Feature
The add order feature allows the user to add an Order
to be tracked by the system.
Implementation
The add order feature is supported by the AddOrderCommand
, which extends from the MultiLevelCommand
class.
The user will enter multiple rounds of input before an Order
is successfully added to the system.
Before giving an example usage scenario, lets assume that the user has already added some inventory items to be tracked by the system, but has not added any orders yet. Hence, our initial state before the add order command is initiated is illustrated as such.
Given below is an example usage scenario that works with the given model state as depicted above, and how the add order mechanism behaves at each step.
Step 1. The user enters the following input into the UI’s command box:
addo n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25
. This instantiates an AddOrderCommand
, that references
a new Order
which encapsulates the input customer data. This then sets the LogicManager
to reference said instantiated AddOrderCommand
in its inProgressCommand
field. The UI then prompts the user for further input.
Step 2a. The user then enters i/Eraser q/3
, representing that the order requires 3 quantities (or units) of Erasers
to fulfill.
The system updates the instantiated command, by first having the AddOrderCommand
stage the input item name and quantity for validation,
using the AddOrderCommand#stageForValidation()
method.
Step 2b. On the AddOrderCommand#execute()
method call, the system searches the model’s inventory for an item that has a matching name to the user’s input item name.
In this scenario, we assume that the user has already added an InventoryItem
with its ItemName
value to be Eraser
, to the model’s list of tracked InventoryItem
s.
Hence, upon execution, a valid item will be found based on the user’s input item name, and the Order#addToItemList()
method is called on the toAdd
object, with the found
InventoryItem
in the model and Quantity
object that was previously staged for validation as method parameters.
This adds a new ItemQuantityPair
object that references the found InventoryItem
and given Quantity
to the list of ordered items in the toAdd
object.
Step 3. The user repeats Step 2 multiple times to fill up the instantiated Order
’s list of ordered items.
Step 4. The user then enters done
after inputting all the required order item details. On the following AddOrderCommand#execute()
method call,
the AddOrderCommand
will no longer await input, and the LogicManager
also removes its reference to the AddOrderCommand
.
The built up Order
object is finally added to the model’s OrderList
.
The following sequence diagrams show how the add order feature works for a user entering an order with only one ordered item. Take note that the sequences occurring in the following diagrams are meant to occur in one full sequence (under one diagram) but for readability, have been separated into 3 smaller diagrams.
-
Initiating the add order command (Step 1)
-
Adding item details (Step 2a, 2b, 3)
-
Adding item details (Step 4)
The following activity diagram below illustrates the general flow of the user’s experience in adding an order.
Design considerations
Aspect: How the add order command receives input and executes
-
Alternative 1: Single level command, user inputs all required information in one long command.
- Pros: Easier to implement as the implementation will follow the already in-place command execution structure.
- Cons: Users have to type out a very long command, and multiple times if they were to mistype certain details and have to re-enter data (e.g, enter multiple instances of
i/ITEM_NAME q/QUANTITY
on the same line of input).
-
Alternative 2 (current choice): Multi-level command. User enters inputs in levels (customer data -> multiple iterations of item/quantity information -> “done”/”cancel” ).
- Pros: Better user experience. Users can be sure that any previously entered input is already validated by the application, making it less overwhelming to input large amounts of information.
- Cons: Harder to implement as it deviates from the original command execution structure (where one instance of user input relates to one full command execution).
Find Order Feature
The find order feature allows the user to find an Order
to be tracked by the system.
Implementation
The find order command is supported by FindOrderCommand
. It extends Command
.
Given below is an example usage scenario and how the find order mechanism behaves at each step.
Step 1. The user launches the application for the first time. TrackO
will be initialised with the initial TrackO
state, and the OrderList
will contain sample data.
Step 2. The user executes findo -D -p n/Alex a/Serangoon
command to find the orders which are paid but not
delivered made by customer with the Name
Alex
and Address
containing the word Serangoon
. The findo
command calls FindOrderCommandParser
which checks for the correct command syntax and separates the keywords,
utilising each space as a delimiter. The keywords are then passed as a List
into a constructor for
OrderMatchesFlagsAndPrefixPredicate
, which extends Predicate<Order>
, to construct a predicate
that will filter the items according to the keywords. The predicate is passed into a new instance of
FindOrderCommand
. FindOrderCommand
then calls Model#updateFilteredOrderList()
to filter
Model#filteredOrders
according to the predicate.
FindOrderCommandParser
will throw a ParseException
.
The following sequence diagram shows how the find order command works:
FindItemCommandParser
and FindItemCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline
reaches the end of diagram.
The following activity diagram summarizes what happens when a user executes a valid find order command:
Design considerations
Aspect: What fields the find order command should search by:
-
Alternative 1: The command finds orders based on the
ItemName
of ordered items of each other.- Pros: Easier to implement, and users do not have to use prefixes to find items.
- Cons: Cannot search based on other fields, such as the customer’s details (eg. name, address) and order’s delivery or payment status.
-
Alternative 2 (current choice): The command finds orders based on
ItemName
,Name
,Address
, delivery status and payment status.- Pros: More robust searching functionality, allowing users to search by more fields at once. This benefits users with a large customer base. The ability to search by delivery and payment status also allows users to keep track of the orders which have yet to be paid/delivered.
- Cons: Harder to implement.
Edit Order Feature
The edit order feature allows the user to edit an Order
currently tracked by the system.
Implementation
The edit order feature is supported by EditOrderCommand
. It extends Command
.
Given below is an example usage scenario and how the EditOrderCommand
mechanism behaves at each step.
Step 1. The user inputs edito 3 n/John Doe i/Banana q/5
. The following methods are called, in the given order:
-
LogicManager#execute
, which then calls -
TrackOParser#parseCommand
. It will parse the input as anEditOrderCommand
and call the constructor ofEditOrderCommandParser
. -
EditOrderCommandParser#parse
will parse the user command based on the prefixes given by the user, and returns anEditOrderCommand
with the target index andEditOrderDescriptor
as input.
The EditOrderDescriptor
contains information that a newly edited order should have; in this case,
it contains a Name
, InventoryItem
, and Quantity
. The rest of the fields that are not provided are copied from the existing
order at target index 3
(This index is one-based).
Step 2. EditOrderCommand#execute
is called, and it will check whether the orderToEdit
is completed; if it is, it
will throw a CommandException
with MESSAGE_ORDER_ALREADY_COMPLETED
. Otherwise, the method continues to run.
Step 3. The EditOrderCommand#createEditedOrder
creates an edited order using the information in the
EditOrderDescriptor
. When the user inputs an InventoryItem
and Quantity
, it checks whether:
-
the
InventoryItem
exists in theInventoryList
.- If it does not exist, the method will throw a
CommandException
withMESSAGE_NONEXISTENT_ITEM
. This is because customers cannot order things that are not in stock. - If it exists, the method will keep running.
- If it does not exist, the method will throw a
-
the
InventoryItem
exists in theOrder
’s list of ordered items, which is stored as aList<ItemQuantityPair>
. This is done byInventoryItem#isSameItem
, which returns true if both the newly inputtedInventoryItem
and theInventoryItem
referenced inItemQuantityPair
share the sameItemName
(case-insensitive).- If it does not exist, then the
InventoryItem
andQuantity
will form a new instance ofItemQuantityPair
which will be added to theList<ItemQuantityPair>
. - If it exists, it will check whether:
- The
Quantity
is0
. If it is, then:- If the order’s list of ordered items has more than one
ItemQuantityPair
will be removed from theList<ItemQuantityPair>
. - If the order’s list of ordered items has only one
ItemQuantityPair
, then aCommandException
withMESSAGE_ONE_ORDERED_ITEM
will be thrown. This is because an order cannot have zero ordered items.
- If the order’s list of ordered items has more than one
- The newly inputted
Quantity
is different from the existingQuantity
. If it is, then it will update to the newly inputtedQuantity
.- Otherwise, a
CommandException
withMESSAGE_NO_CHANGE_IN_QUANTITY
will be thrown. This is to warn users that the newly inputtedQuantity
is the same as the existingQuantity
and does not update theQuantity
field at all.
- Otherwise, a
- The
- If it does not exist, then the
Step 4. The Order
at the target index is then replaced by the newly created Order
using Model#setOrder()
,
successfully executing the edit order command in the Model
. Model#refreshData
is called to refresh the GUI, and
Model#updateFilteredOrderList(PREDICATE_SHOW_ALL_ORDERS)
is called to update the list to show all orders.
EditOrderCommand#execute()
returns a CommandResult
to the LogicManager
.
The sequence diagram below illustrates this process.
EditOrderCommandParser
and EditOrderCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Design Considerations
Aspect: Whether to implement the edit order feature
-
Alternative 1 (current choice): The command is implemented and edits the order based on the prefixes
inputted by the user.
- Pros: The user can edit only the fields that they want to edit.
- Cons: The user may have to input long commands.
-
Alternative 2: No edit command, users have to delete and re-add orders should there be any change.
- Pros: Less bug-prone, more convenient for the developers to implement.
- Cons: Not user-friendly and makes things more difficult for the user.
Sort Orders Feature
The sort orders feature allows the user to sort all the displayed order list based on their time of creation.
Implementation
The sort orders feature is supported by the SortOrdersCommand
. It extends Command
. This command is implemented by
wrapping a SortedList
around the FilteredList
in ModelManager
. The command must be used with at least 1 of the
2 different keywords: new
or old
.
Given below is an example usage scenario and how the SortOrdersCommand
mechanism behaves at each step.
Step 1. The user inputs the command sorto new
. This calls:
LogicManager#execute()
-
TrackOParser#parseCommand()
. This parses the command as anSortOrdersCommandParser
and returns aSortOrdersCommandParser
object. -
SortOrdersCommandParser#parse()
parses the arguments and creates anOrderDateTimeComparator
based on the input keywordnew
. ASortOrdersCommand
object with theOrderDateTimeComparator
is returned.
The OrderDateTimeComparator
determines the order in which the SortedList
should be sorted and is created based on the
keywords new
or old
.
Step 2. SortOrdersCommand#execute()
is called and the SortOrdersCommand
calls Model#updateSortedOrderList
which
updates the comparator used for the sortedList
in ModelManager
.
The sequence diagram below illustrates this process.
SortOrdersCommandParser
and SortOrdersCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline
reaches the end of diagram.
Design Considerations
Aspect: Sorting criteria for sorto
command
-
Alternative 1 (current choice): The command sorts all the orders in the order list by time created.
- Pros: Easier to implement.
- Cons: User can only sort by order’s time of creation.
-
Alternative 2: The command allows the user to sort by different criteria based on order details.
- Pros: User has more flexibility while sorting orders.
- Cons: Harder to implement.
Documentation, logging, testing, configuration, dev-ops
Appendix A: Product scope
Target user profile:
- home-based small business owners who want to manage orders and inventory information efficiently
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value proposition: offers a CLI-based application for home-based small business owners who prefer to type more/are more efficient at typing to allow them to save time on managing orders and logistics instead of traditional GUI applications such as Excel, or even pen and paper.
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… |
---|---|---|---|
* * * |
business owner | add orders easily | keep track of ongoing orders |
* * * |
business owner | delete entire orders | |
* * * |
business owner | list all orders | see all my ongoing orders in one place and keep track of them |
* * * |
business owner | add items to my inventory | keep track of additions to my inventory |
* * * |
business owner | delete items from my inventory | have an updated list of inventory items |
* * * |
business owner | list all items in my inventory | see all items in my inventory in one place |
* * * |
business owner | tag inventory items | keep an organised inventory of items |
* * |
business owner | find orders | locate an order without manually searching through the entire list |
* * |
business owner | find items in my inventory | locate an item in my inventory without manually searching through the entire list |
* * |
business owner | edit order details | update changes to orders |
* * |
business owner | edit inventory item details | update changes to inventory |
* * |
business owner | see which orders have been paid for | press customers for payment |
* * |
business owner | mark orders as completed | not get mixed up with ones that have not been completed yet |
* * |
business owner | sort orders by expected delivery time | know which orders are due first |
* * |
business owner | sort orders by delivery address | optimise delivery routes |
* * |
business owner | sort orders by urgency (e.g. by deadline, or days outstanding) | know which orders I have to prepare first |
* * |
business owner | look at my total earnings | better optimise my earnings |
* |
business owner | export all business data | save the data elsewhere if needed |
* |
business owner who is new to the application | import my current database of order and inventory information to TrackO | seamlessly transfer from other applications to TrackO |
* |
business owner who is new to the application | use more verbose commands to complete my tasks | get more used to the syntax of the commands in the application |
* |
tired business owner working at night | view the application’s GUI in dark mode | my eyes don’t get strained |
Appendix C: Use cases
(For all use cases below, the System is the TrackO
and the Actor is the user
, unless specified otherwise)
Use case: UC01 - Add an order
MSS
- User requests to add an order.
-
System adds the order.
Use case ends.
Extensions
- 1a. User inputs incomplete order data.
-
1a1. System informs user of the incomplete data.
Use case resumes at 1.
-
Use case: UC02 - Delete an order
MSS
- User requests to delete an order.
-
System deletes the order.
Use case ends.
Extensions
-
1a. The order the user wishes to delete does not exist.
-
1a1. System informs the user of the non-existent order.
Use case ends.
-
-
2a. The list has no orders.
-
2a1. System informs the user of the empty order list.
Use case ends.
-
Use case: UC03 - List orders
MSS
- User requests to list all orders.
-
System lists all orders.
Use case ends.
Extensions
- 2a. The list of orders is empty.
-
2a1. System informs the user that the list is empty.
Use case ends.
-
Use case: UC04 - Find orders
MSS
- User requests to find an order.
-
System finds the order and informs the user of its details.
Use case ends.
Extensions
- 1a. The order the user is trying to find does not exist.
-
1a1. System informs the user that the order does not exist.
Use case ends.
-
Use case: UC05 - Sort orders based on the time they are created
- User requests to sort orders based on the time they are created.
-
System sorts the orders.
Use case ends.
Use case: UC06 - Edit an order
- User requests to edit an item.
-
System edits the order.
Use case ends.
Extensions
- 1a. User inputs incomplete order data.
-
1a1. System informs user of the incomplete order data.
Use case resumes at 1.
-
Use case: UC07 - Add an inventory item
MSS
- User requests to add an inventory item.
-
System adds the inventory item.
Use case ends.
Extensions
- 1a. User inputs incomplete details of the item.
-
1a1. System informs user of the incomplete details.
Use case resumes at 1.
-
Use case: UC08 - Delete an inventory item
MSS
- User requests to delete an inventory item.
-
System deletes the inventory item.
Use case ends.
Extensions
- 1a. The item that the user requests to delete does not exist.
-
1a1. System informs user of the non-existent item.
Use case ends.
-
- 2a. The list of inventory items is empty.
-
2a1. System informs user that the list of items is empty.
Use case ends.
-
Use case: UC09 - List all inventory items
MSS
- User requests to list all inventory items.
-
System lists all inventory items.
Use case ends.
Extensions
- 2a. The list of inventory items is empty.
-
2a1. System informs user of the empty list.
Use case ends.
-
Use case: UC10 - Find an inventory item
MSS
- User requests to find an inventory item.
-
System finds the item and informs the user of its details.
Use case ends.
Extensions
- 1a. The inventory item that the user requests to find does not exist.
-
1a1. System informs the user of the non-existent item.
Use case ends.
-
Use case: UC11 - Edit an inventory item
- User requests to edit an inventory item.
-
System edits the inventory item.
Use case ends.
Extensions
- 1a. User inputs incomplete item data.
-
1a1. System informs user of the incomplete item data.
Use case resumes at 1.
-
Appendix D: Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11
or above installed. - The software should be portable. Moving from one device to another should not create any problems as long as it is on a mainstream OS with Java
11
or above installed. - Each command should be executed within 1 second.
- Should be able to hold up to 10000 orders without a noticeable sluggishness in performance for typical usage.
- Should be able to hold up to 100 items 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.
Appendix E: Glossary
- Mainstream OS (Operating System): Windows, Linux, Unix, OS-X
- CLI: Command Line Interface, receives commands from user in the form of lines of text
- GUI: Graphical User Interface, a system of interactive user components for computer software
- Inventory: Any item that the business needs to operate
- Order: Any sales promise that needs to be fulfilled
- Command: An instruction for the application to execute
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 orders and items. The window automatically expands to occupy the entire screen.
Starting up with missing/corrupted data files
- Data file is corrupted
Expected: The system will start with an empty application. - Data file is missing from the application
Expected: The system will start with sample data.
Adding an inventory item
- Adding an inventory item
- Prerequisites: None
- Test case:
addi i/Chair q/100 d/Wooden Chair sp/50 cp/10 t/Fragile
Expected: Inventory item is added to the inventory list. Details of the added inventory item shown in the status message. - Test case:
addi i/Chair d/Wooden Chair sp/50 cp/10 t/Fragile
Expected: No inventory item is added. Error details shown in the status message. - Other incorrect addi commands to try:
addi
,addi x
,...
(where x is a string containing the inventory item details but is missing a required parameter)
Expected: similar to previous.
Listing all inventory items
- Display all inventory items of a populated inventory
- Prerequisites: Have an inventory containing 1 or more inventory items
- Test case:
listi
Expected: All inventory items are displayed.
- Display all inventory items of an empty inventory
- Prerequisites: Have an inventory containing 0 inventory items
- Test case:
listi
Expected: No inventory items are displayed.
Finding an inventory item
- Finding an inventory item that exists in the inventory list
- Prerequisites: Have an inventory list containing only inventory items with the item names
Chair
,Table
,Bed
. - Test case:
findi Chair
Expected: Only the inventory item with the item nameChair
is displayed. Number of inventory items found shown in the status message. - Test case:
findi
Expected: No inventory item is found, no change to current displayed inventory item list. Error details shown in the status message.
- Prerequisites: Have an inventory list containing only inventory items with the item names
- Finding an inventory item that does not exist in the inventory list
- Prerequisites: Have an inventory list containing only inventory items with the item names
Chair
,Table
,Bed
. - Test case:
findi pen
Expected: No inventory item is displayed in the inventory list. 0 inventory items found shown in the status message.
- Prerequisites: Have an inventory list containing only inventory items with the item names
Deleting an inventory item
- Deleting an inventory item while all inventory item(s) are being shown
- Prerequisites: List all inventory items using the
listi
command. Multiple inventory items in the inventory list. First inventory item in the displayed inventory list is not involved in any uncompleted orders. Third inventory item in the displayed inventory list is involved in uncompleted order(s). For example, with the sample data loaded in TrackO, the commandlisti
will list all inventory items, where the first inventory itemChair
is not involved in any uncompleted orders, whereas the third itemBolster
is. - Test case:
deletei 1
Expected: First inventory item is deleted from the inventory list. Details of the deleted inventory item shown in the status message. - Test case:
deletei 3
Expected: No inventory item is deleted from the inventory list. Error details shown in the status message (involved in uncompleted orders). - Test case:
deletei 0
Expected: No inventory item is deleted. Error details shown in the status message. - Other incorrect delete commands to try
deletei
,deletei x
, … (where x is larger than the size of the displayed inventory list)
Expected: Similar to previous.
- Prerequisites: List all inventory items using the
- Deleting an inventory item while only some inventory item(s) are being shown
- Prerequisites: Find inventory item(s) using the
findi
command. First inventory item in the displayed inventory list is not involved in any uncompleted orders. Second inventory item in the displayed inventory list is involved in uncompleted order(s). For example, with the sample data loaded in TrackO, the commandfindi Chair Mattress
will find and display only the items with the nameChair
andMattress
in the inventory list, where first itemChair
is not involved in any uncompleted orders, whereas second itemMattress
is involved. - Test case:
deletei 1
Expected: First inventory item is deleted from the displayed inventory list. Details of the deleted inventory item shown in the status message. - Test case:
deletei 2
, where n is the index of an inventory item which is involved in uncompleted order(s). For example,deletei 2
afterfindi Chair Pillow
with the sample data.
Expected: No inventory item is deleted. Error details shown in the status message. - Test case:
deletei 0
Expected: No inventory item is deleted. Error details shown in the status message. - Other incorrect delete commands to try:
deletei
,deletei x
, … (where x is larger than the size of the displayed inventory list)
Expected: Similar to previous.
- Prerequisites: Find inventory item(s) using the
Editing an inventory item
- Editing an inventory item while all inventory item(s) are being shown
- Prerequisites: List all inventory items using the
listi
command. Multiple inventory items in the inventory list. First inventory item in the displayed inventory list is not involved in any uncompleted orders. Third inventory item in the displayed inventory list is involved in uncompleted order(s). For example, with the sample data loaded in TrackO, the commandlisti
will list all inventory items, where the first inventory itemChair
is not involved in any uncompleted orders, whereas the third itemBolster
is. - Test case:
editi 1 i/Red Chair q/20 sp/10 cp/2
Expected: First inventory item is edited. Name, quantity, sell price and cost price is updated toRed Chair
,20
,$10.00
,$2.00
respectively. - Test case:
editi 3 i/Test Item Name
Expected: No inventory item is edited. Error details shown in the status message (involved in uncompleted orders). - Test case:
editi 0
Expected: No inventory item is edited. Error details shown in the status message. - Other incorrect edit commands to try:
editi
,editi x
, … (where x is larger than the size of the displayed inventory list)
Expected: Similar to previous.
- Prerequisites: List all inventory items using the
- Editing an inventory item while only some inventory item(s) are being shown
- Prerequisites: Find inventory item(s) using the
findi
command. First inventory item in the displayed inventory list is not involved in any uncompleted orders. Second inventory item in the displayed inventory list is involved in uncompleted order(s). For example, with the sample data loaded in TrackO, the commandfindi Chair Mattress
will find and display only the items with the nameChair
andMattress
in the inventory list, where first itemChair
is not involved in any uncompleted orders, whereas second itemMattress
is involved. - Test case:
editi 1 i/Red Chair q/20 sp/10 cp/2
Expected: First inventory item is edited. Name, quantity, sell price and cost price is updated toRed Chair
,20
,$10.00
,$2.00
respectively. - Test case:
editi 2 i/Test Item Name
Expected: No inventory item is edited. Error details shown in the status message (involved in uncompleted orders). - Test case:
editi 0
Expected: No inventory item is edited. Error details shown in the status message. - Other incorrect edit commands to try:
editi
,editi x
, … (where x is larger than the sie of the displayed inventory list)
Expected: Similar to previous.
- Prerequisites: Find inventory item(s) using the
Adding an order
- Adding an order, attempt to add existing and non-existent inventory items in order’s item list.
- Prerequisites: Multiple inventory items exist in the inventory list. One of them with the item name
Chair
, and none of them with the nameApple
- Test Case: Execute the following commands below in sequence and check the response by the system.
- Step 1:
addo n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25
Expected: Add order command initiated. System prompts for further item and quantity input - Step 2:
i/Chair q/10
Expected: System accepts the item and quantity input, prompts for further input. - Step 3:
i/Apple q/20
Expected: System notifies that inventory item with nameApple
does not exist, prompts for further input. - Step 4:
done
Expected: Order is added to the order list. Order details shown in the status message.
- Step 1:
- Prerequisites: Multiple inventory items exist in the inventory list. One of them with the item name
- Initiating the command, attempt to add an order with an empty item list
- Prerequisites: None
- Test case: Execute the following commands below in sequence and check the response by the system.
- Step 1:
addo n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25
Expected: Add order command initiated. System prompts for further item and quantity input - Step 2:
done
Expected: System notifies that order’s item list cannot be empty and exits the command sequence.
- Step 1:
- Initiating the command, aborting the command.
- Prerequisites: None
- Test case: Execute the following commands below in sequence and check the response by the system.
- Step 1:
addo n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25
Expected: Add order command initiated. System prompts for further item and quantity input. - Step 2:
cancel
Expected: System notifies that the command has been aborted and exits the command sequence.
- Step 1:
Listing all orders
- Listing all orders after calling
findo
- Prerequisites: List all orders using the
listo
command. There are already multiple existing orders. Of these orders, there exist 2 orders made by customers withChan
in their names. Before testing, enterfindo n/Chan
Expected: Order list displays 2 orders by customers withChan
in their name. - Test case: Enter
listo
into the command box.
Expected: All orders listed in the order list. - Other incorrect
listo
commands to try: EnterlistO
into the command box.
Expected: Result display showsUnknown command
.
- Prerequisites: List all orders using the
Finding order(s)
- Finding an order while all orders are being shown
- Prerequisites: List all orders using the
listo
command. Multiple orders in the list. - Test case: Enter
findo -d
into the command box.
Expected: Orders which have been delivered are displayed. The number of orders which correspond to the search parameters is displayed in the result display. - Test case: Enter
findo n/Alex a/Geylang
into the command box.
Expected: Orders which have a customer nameAlex
and address containing the wordGeylang
will be displayed. The number of orders which correspond to the search parameters is displayed in the result display. - Test case: Enter
findo Alex
into the command box.
Expected: Result display displays an invalid command format message with the specifications of the correctfindo
command format. - Other incorrect
findo
commands to try:findo
,findo -e
.
Expected: Similar to previous.
- Prerequisites: List all orders using the
Sorting orders by time created
- Sorting orders by time created while all orders are being shown
- Prerequisites: List all orders using the
listo
command. Multiple orders in the order list. - Test case: Enter
sorto old
into the command box.
Expected: Orders in the order card will be displayed from oldest to newest. - Test case: Enter
sorto new
into the command box.
Expected: Orders in the order card will be displayed from newest to oldest. - Test case: Enter
sorto hello
into the command box.
Expected: Result display displays an invalid command format message with the specifications of the correctsorto
command format.
- Prerequisites: List all orders using the
Deleting an order
- Deleting an order while all orders are being shown
- Prerequisites: List all orders using the
listo
command. Multiple orders in the orders list. - Test case:
deleteo 1
Expected: First order is deleted from the list. Details of the deleted order shown in the status message. - Test case:
deleteo 0
Expected: No order is deleted. 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.
- Prerequisites: List all orders using the
- Deleting an order while only some orders are being shown
- Prerequisites: Find orders using the
findo
keyword. For example, with the sample data loaded in TrackO, the commandfindo i/pillow
can be used. A number of orders (less than total orders) in the orders list. - Test case:
deleteo 1
Expected: First order in the current list is deleted from the list. Details of the deleted order shown in the status message. - Test case:
deleteo 0
Expected: No order is deleted. Error details shown in the status message. - Other incorrect delete commands to try:
deleteo
,deleteo x
,...
(where x is larger than the current list size)
Expected: Similar to previous.
- Prerequisites: Find orders using the
Editing an order
- Editing an order while all orders are being shown
- Prerequisites: List all orders using the
listo
command. Multiple orders in the orders list. - Test case with sample data:
edito 4 p/91234567
(Note: the order at the index must not be labelled as paid / delivered / completed)
Expected: Phone number of the fourth order in the list is updated to91234567
. Updated details of the edited order shown in the status message. - Test case:
edito 0
Expected: No order is edited. Error details shown in the status message. - Other incorrect edit commands to try:
edito
,edito x
,...
(where x is the index of a completed order)
Expected: Similar to previous.
- Prerequisites: List all orders using the
Marking an order
- Marking an order while all orders are being shown
- Prerequisites: List all orders using the
listo
command. Multiple orders in the orders list. - Test case with sample data:
marko 3 -p
(Note: the order at the index must not already be paid)
Expected: First order in the list is marked as paid. Details of the marked order shown in the status message. - Test case:
marko 0 -p
Expected: No order is marked. Error details shown in the status message. - Other incorrect mark commands to try:
marko
,marko x
,...
(where x is less than the size of the list)
Expected: Similar to previous.
- Prerequisites: List all orders using the
- Marking an order while only some orders are being shown
- Prerequisites: Find orders using the
findo
keyword. For example, with the sample data loaded in TrackO, the commandfindo i/mattress
can be used. A number of orders (less than total orders) in the orders list. - Test case:
marko 1 -d
Expected: First order in the current list is marked as delivered. Details of the marked order shown in the status message. - Test case:
marko 0 -d
Expected: No order is marked. Error details shown in the status message. - Other incorrect mark commands to try:
marko
,marko x -p
,...
(where x is the index of an order already paid)
Expected: Similar to previous.
- Prerequisites: Find orders using the
Getting help
- Opening the help window
- Prerequisites: Help window is not opened, or not in focus.
- Test case:
help
Expected: Help window is opened. - Test case:
help 123
,help x
,help #$%
,...
(where there can be any input after the wordhelp
, as long as it is followed by a whitespace)
Expected: Help window is opened. - Test case:
help###
,Help
,helpxx
,...
(where there are characters not separated by a whitespace afterhelp
)
Expected: The help window is not opened and an error message is shown by the system. - Test case:
Help
,HELP
,...
(wherehelp
is not in all lower cases)
Expected: The help window is not opened and an error message is shown by the system.
Clearing data in TrackO
- Clearing data in TrackO.
- Test case:
clear
, followed byconfirm
Expected: All data in theOrderList
andInventoryList
is cleared. - Test case:
clear
, followed bycancel
Expected: All data in theOrderList
andInventoryList
should remain intact. - Test case:
Clear
,CLEAR
,...
(whereclear
is not in all lower cases)
Expected: The command does not proceed to the next stage and an error message is shown by the system. - Test case:
clear
, followed byx
,123
,abc
,...
(any input that is notconfirm
orcancel
)
Expected: An error message showing the proper ways to proceed or abort the command is shown by the system.
- Test case:
Exiting TrackO
- Exiting via CLI
- Test case:
exit
Expected: Window closes.
- Test case:
Editing the data file
- Data is edited according to the right format
Expected: The system will detect the change, and the edited data will load into the application successfully. - Data is edited following an incorrect format
Expected: The system will start with an empty application.