Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edit UG/DG + delete schedulecard/schedulelistpanel #150

Merged
merged 8 commits into from Oct 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
91 changes: 79 additions & 12 deletions docs/DeveloperGuide.adoc
Expand Up @@ -44,14 +44,15 @@ The following class plays an important role at the architecture level:

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

The rest of the App consists of four components.
The rest of the App consists of five components.

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

Each of the four components
Each of the five components

* Defines its _API_ in an `interface` with the same name as the Component.
* Exposes its functionality using a `{Component Name}Manager` class.
Expand All @@ -66,7 +67,7 @@ image::LogicClassDiagram.png[]

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

.Component interactions for `delete 1` command
.Component interactions for `delete-c 1` command
image::ArchitectureSequenceDiagram.png[]

The sections below give more details of each component.
Expand Down Expand Up @@ -101,15 +102,15 @@ link:{repoURL}/src/main/java/seedu/address/logic/Logic.java[`Logic.java`]
. `Logic` uses the `SellerManagerParser` class to parse the user command.
. This results in a `Command` object which is executed by the `LogicManager`.
. The command execution can affect the `Model` (e.g. adding a customer/phone/order/schedule).
. The result of the command execution is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
. In addition, the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying help to the user.
. The result of the command execution, a `String` message and `UiChange` enum is encapsulated as a `CommandResult` object which is passed back to the `Ui`.
. In addition, the `UiChange` enum in the `CommandResult` object can also instruct the `Ui` to perform certain actions, such as displaying the respective panels or help/statistics window.

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

.Interactions Inside the Logic Component for the `delete 1` Command
.Interactions Inside the Logic Component for the `delete-c 1` Command
image::DeleteSequenceDiagram.png[]

NOTE: The lifeline for `DeleteCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
NOTE: The lifeline for `DeleteCustomerCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

[[Design-Model]]
=== Model component
Expand All @@ -122,12 +123,15 @@ image::ModelClassDiagram.png[]
The `Model`,

* stores a `UserPref` object that represents the user's preferences.
* stores the Address Book data.
* exposes an unmodifiable `ObservableList<Person>` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
* does not depend on any of the other three components.
* stores a `CalendarDate` object that stores date shown on the calendar panel.
* stores the Seller Manager data.
* exposes 4 unmodifiable `ObservableList<Identifiable>` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
* does not depend on any of the other four components.

[NOTE]
As a more OOP model, we can store a `Tag` list in `Address Book`, which `Person` can reference. This would allow `Address Book` to only require one `Tag` object per unique `Tag`, instead of each `Person` needing their own `Tag` object. An example of how such a model may look like is given below. +
As a more OOP model, we can store a `UniqueList<Tag>` in `Seller Manager`, which `Customer` / `Phone` / `Order` / `Schedule` can reference.
This would allow `Seller Manager` to only require one `Tag` object per unique `Tag`, instead of each object needing their own `Tag`.
An example of how such `UniqueList<Tag>` and `UniqueList<Customer>` interacts is given below. +
+
image:BetterModelClassDiagram.png[]

Expand Down Expand Up @@ -290,6 +294,69 @@ form or string form. With this the feature has finished executing! Attached belo

image::StatisticsCalculationUI.png[]

=== Calendar / Schedule feature
==== Implementation

We decided to incorporate a third party library, `JFXtras's Agenda`, to represent our schedules on a calendar for easy viewing by our users.

`CalendarPanel` keeps `UniqueList<Schedule>` and `UniqueList<Order>` objects as class variables. On instantiation, all the schedules in `UniqueList<Schedule>` will be converted to `Appointments` and then added to `Agenda`.
To set the display information of the `Schedule` object, we will find its `Order` in the `UniqueList<Order>` and retrieve its index.
`CalendarPanel` also keeps `CalendarDate` as a variable to set the date shown by `Agenda`.

Schedule supports a few basic commands:

* Add -- adds a new schedule into SML, command will be in this format: `add-s ORDER_INDEX cd/DATE ct/TIME v/VENUE [t/TAGS]`
* Edit -- edits an existing schedule in SML, command will be in this format: `edit-s ORDER_INDEX [cd/DATE] [ct/TIME] [v/VENUE] [t/TAGS]`
* Delete -- delete an existing schedule in SML, command will be in this format: `delete-s ORDER_INDEX`
* Schedule -- switches the week on the panel to the week containing the date entered, command will be in this format: `schedule cd/DATE`

The schedules and date the calendar panel shows is automatically updated depending on the commands executed by the users.
For example:

* If the user adds/edits/deletes a schedule -- calendar panel will display the week with the date of the schedule.
* If the user uses the switch-s command -- calendar panel will display the week with today's date.
* If the user uses the schedule command -- calendar will display the week with the date resquested by the user.

Changes to the schedules are made in the model by editing the `UniqueList<Schedule>` object.
`CalendarPanel` adds a listener to its `UniqueList<Schedule>` variable.
`CalendarPanel` listen to the changes and generates the updated list of `Schedules` into `Appointments` to add to `Agenda`.

The current date shown on the calendar panel is encapsulated in a `CalendarDate` object.
The `CalendarDate` class uses `SimpleObjectProperty` to keep track of the Calendar (date).
When any of the schedule commands are executed, the model will edit the `CalendarDate` object with the updated Calendar (date).
`CalendarPanel` adds a listener to its `CalendarDate` variable.
`CalendarPanel` listen to the changes and sets the agenda view to the new `Calendar` in `CalendarDate`.

Here is a sample of what happens when a schedule command is entered by the user:

image::ScheduleCommandSequenceDiagram.png[]

Basically, after the setCalendarDate(calendar) method in `Model` is executed, `CalendarPanel` listens to it and make the necessary changes to the agenda view by calling its setAgendaView(calendar) method.

Adding on, we will be adding an additional feature to check for clashing schedules.
In the case of a clash, users will be given a choice to allow clashing schedules, or to just change to timing to avoid the clashes.

===== Design Considerations / Alternative designs considered

We do not keep a list of `Appointment` in `CalendarPanel` as `Appointment` is only used for `Agenda` while the rest of our system uses `Schedule`.
Instead, we have decided to only convert `Schedule` into `Appointment` when needed - during the instantiation of `CalendarPanel` or when there are changes made to the `UniqueList<Schedule>`.
Not keeping a list of `Appointment` ensures that we do not keep duplicate information.

The changes to `CalendarDate` was initially done in the `CalendarPanel` itself.
So, `CommandResult` was made to have one more variable `Optional<Calendar>`.
In that case, every time a schedule command was executed, a specific `Calendar` (if any) will be placed inside the constructor while creating the `CommandResult` object.
Else, Optional.Empty() will be placed inside.

When the `MainWindow` executes the method performUiChanges(CommandResult), it will call the handleSchedule method with Calendar (from CommandResult) as an argument.
If `Optional<Calendar>` in `CommandResult` is empty, today's date and time will be used instead.
Then, `CalendarPanel` will be called in the handleSchedule method to set the agenda view.

This implementation was however changed because we thought that the date shown on the panel should be changed automatically.
Hence, we decided to use a listener instead.
`CalendarDate` is then placed in `Model` so that it can be edited right away when `Model` executes any schedule related commands.
Also, this ensures that `CommandResult` remains unchanged and kept as simple as possible.

=======
=== Find Customer/Phone feature

The find feature allows the user to find the order according to its data field or without any data field.
Expand Down
63 changes: 32 additions & 31 deletions docs/UserGuide.adoc
Expand Up @@ -226,66 +226,67 @@ Export any of the data in SML to PDF format.

== Command Summary
* *Add* +
** customer : `add -c n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
** phone : `add -p n/NAME q/QUANTITY [p/PRICE] [t/TAG]…`
** order : `add -o p/PHONE_NUMBER i/ITEM...`
** customer : `add-c n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…`
** phone : `add-p n/NAME q/QUANTITY [p/PRICE] [t/TAG]…`
** order : `add-o p/PHONE_NUMBER i/ITEM...`
** schedule : `add-s ORDER_INDEX cd/DATE ct/TIME v/VENUE [t/TAG]…`

* *Cancel* +
** order : `cancel -o INDEX`

* *Check* +
** stock : `check -p <threshold>`
** order : `cancel INDEX`

* *Clear* : `clear`

* *Complete* +
** order : `complete -o INDEX`
** order : `complete INDEX`

* *Copy* +
** customer : `copy -c <field>`
** phone : `copy -p <field>`
** order : `copy -o <field>`
** customer : `copy-c <field>`
** phone : `copy-p <field>`
** order : `copy-o <field>`

* *Delete* +
** customer : `delete -c INDEX`
** phone : `delete -p INDEX`
** customer : `delete-c INDEX`
** phone : `delete-p INDEX`
** schedule : `delete-s ORDER_INDEX`

* *Duplicate* +
** order : `duplicate -o INDEX`
** order : `duplicate-o INDEX`

* *Edit* +
** customer : `edit-c INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
** phone : `edit-p INDEX n/NAME [p/PRICE] [q/QUANTITY] [t/TAG]...`
** order : `edit-o INDEX ...`
** schedule : `edit-s ORDER_INDEX [cd/DATE] [ct/TIME] [v/VENUE] [t/TAG]…`

* *Exit* : `exit`

* *Export* +
** customer : `export -c`
** phone : `export -p`
** order : `export -o`
** customer : `export-c`
** phone : `export-p`
** order : `export-o`

* *Find* +
** customer : `find -c KEYWORD [MORE_KEYWORDS]`
** phone : `find -p p/PHONE`
** order : `find -o INDEX`
** customer : `find-c KEYWORD [MORE_KEYWORDS]`
** phone : `find-p p/PHONE`
** order : `find-o INDEX`

* *Generate* : `generate -s s/STAT -d d/ -t t/TYPE`

* *Import* +
** customer : `import -c`
** phone : `import -p`
** order : `import -o`
** customer : `import-c`
** phone : `import-p`
** order : `import-o`

* *List* +
** customer : `list -c`
** phone : `list -p`
** order : `list -o`
** customer : `list-c`
** phone : `list-p`
** order : `list-o`

* *Help* : `help`

* *Redo* : `redo`

* *Schedule* +
** order : `schedule -o INDEX DD/MM/YY HHMM`
* *Schedule* : `schedule cd/DATE`

* *Undo* : `undo`

* *Update* +
** customer : `update -c INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
** phone : `update -p n/NAME [p/PRICE] [q/QUANTITY] [t/TAG]...`
8 changes: 4 additions & 4 deletions docs/diagrams/ArchitectureSequenceDiagram.puml
Expand Up @@ -7,19 +7,19 @@ Participant ":Logic" as logic LOGIC_COLOR
Participant ":Model" as model MODEL_COLOR
Participant ":Storage" as storage STORAGE_COLOR

user -[USER_COLOR]> ui : "delete 1"
user -[USER_COLOR]> ui : "delete-c 1"
activate ui UI_COLOR

ui -[UI_COLOR]> logic : execute("delete 1")
ui -[UI_COLOR]> logic : execute("delete-c 1")
activate logic LOGIC_COLOR

logic -[LOGIC_COLOR]> model : deletePerson(p)
logic -[LOGIC_COLOR]> model : deleteCustomer(c)
activate model MODEL_COLOR

model -[MODEL_COLOR]-> logic
deactivate model

logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook)
logic -[LOGIC_COLOR]> storage : saveCustomerBook(customerBook)
activate storage STORAGE_COLOR

storage -[STORAGE_COLOR]> storage : Save to file
Expand Down
21 changes: 10 additions & 11 deletions docs/diagrams/BetterModelClassDiagram.puml
Expand Up @@ -4,18 +4,17 @@ skinparam arrowThickness 1.1
skinparam arrowColor MODEL_COLOR
skinparam classBackgroundColor MODEL_COLOR

AddressBook *-right-> "1" UniquePersonList
AddressBook *-right-> "1" UniqueTagList
UniqueTagList -[hidden]down- UniquePersonList
UniqueTagList -[hidden]down- UniquePersonList
SellerManager *-right-> "1" "UniqueList<Customer>"
SellerManager *-right-> "1" "UniqueList<Tag>"
"UniqueList<Tag>" -[hidden]down- "UniqueList<Customer>"
"UniqueList<Tag>" -[hidden]down- "UniqueList<Customer>"

UniqueTagList *-right-> "*" Tag
UniquePersonList o-right-> Person
"UniqueList<Tag>" *-right-> "*" Tag
"UniqueList<Customer>" o-right-> Customer

Person o-up-> "*" Tag
Customer o-up-> "*" Tag

Person *--> Name
Person *--> Phone
Person *--> Email
Person *--> Address
Customer *--> CustomerName
Customer *--> ContactNumber
Customer *--> Email
@enduml
65 changes: 32 additions & 33 deletions docs/diagrams/DeleteSequenceDiagram.puml
Expand Up @@ -3,66 +3,65 @@

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR
participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR
participant ":SellerManagerParser" as SellerManagerParser LOGIC_COLOR
participant ":DeleteCustomerCommandParser" as DeleteCustomerCommandParser LOGIC_COLOR
participant "command:DeleteCustomerCommand" as DeleteCustomerCommand LOGIC_COLOR
participant ":CommandResult" as CommandResult LOGIC_COLOR
end box

box Model MODEL_COLOR_T1
participant ":Model" as Model MODEL_COLOR
end box

[-> LogicManager : execute("delete 1")
[-> LogicManager : execute("delete-c 1")
activate LogicManager

LogicManager -> AddressBookParser : parseCommand("delete 1")
activate AddressBookParser
LogicManager -> SellerManagerParser : parseCommand("delete-c 1")
activate SellerManagerParser

create DeleteCommandParser
AddressBookParser -> DeleteCommandParser
activate DeleteCommandParser
create DeleteCustomerCommandParser
SellerManagerParser -> DeleteCustomerCommandParser
activate DeleteCustomerCommandParser

DeleteCommandParser --> AddressBookParser
deactivate DeleteCommandParser
DeleteCustomerCommandParser --> SellerManagerParser
deactivate DeleteCustomerCommandParser

AddressBookParser -> DeleteCommandParser : parse("1")
activate DeleteCommandParser
SellerManagerParser -> DeleteCustomerCommandParser : parse("delete-c 1")
activate DeleteCustomerCommandParser

create DeleteCommand
DeleteCommandParser -> DeleteCommand
activate DeleteCommand
create DeleteCustomerCommand
DeleteCustomerCommandParser -> DeleteCustomerCommand : targetIndex
activate DeleteCustomerCommand

DeleteCommand --> DeleteCommandParser : d
deactivate DeleteCommand
DeleteCustomerCommand --> DeleteCustomerCommandParser : command
deactivate DeleteCustomerCommand

DeleteCommandParser --> AddressBookParser : d
deactivate DeleteCommandParser
DeleteCustomerCommandParser --> SellerManagerParser : command
deactivate DeleteCustomerCommandParser
'Hidden arrow to position the destroy marker below the end of the activation bar.
DeleteCommandParser -[hidden]-> AddressBookParser
destroy DeleteCommandParser
DeleteCustomerCommandParser -[hidden]-> SellerManagerParser
destroy DeleteCustomerCommandParser

AddressBookParser --> LogicManager : d
deactivate AddressBookParser
SellerManagerParser --> LogicManager : command
deactivate SellerManagerParser

LogicManager -> DeleteCommand : execute()
activate DeleteCommand
LogicManager -> DeleteCustomerCommand : execute()
activate DeleteCustomerCommand

DeleteCommand -> Model : deletePerson(1)
DeleteCustomerCommand -> Model : deleteCustomer(customerToDelete)
activate Model

Model --> DeleteCommand
Model --> DeleteCustomerCommand
deactivate Model

create CommandResult
DeleteCommand -> CommandResult
DeleteCustomerCommand -> CommandResult : message, UiChange
activate CommandResult

CommandResult --> DeleteCommand
CommandResult --> DeleteCustomerCommand : commandResult
deactivate CommandResult

DeleteCommand --> LogicManager : result
deactivate DeleteCommand
DeleteCustomerCommand --> LogicManager : commandResult
deactivate DeleteCustomerCommand

[<--LogicManager
deactivate LogicManager
Expand Down