Skip to content

Commit

Permalink
Merge ad79632 into 74ca564
Browse files Browse the repository at this point in the history
  • Loading branch information
junnbang committed Nov 8, 2019
2 parents 74ca564 + ad79632 commit 6aa5979
Show file tree
Hide file tree
Showing 33 changed files with 474 additions and 217 deletions.
133 changes: 95 additions & 38 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,101 @@ Similarly, calling `free` command will:
// end::task-scheduling[]


// tag::task-feature[]
=== Task Feature (E.g. Add Delivery Task)
==== Implementation
The *Add Delivery Task* feature adds a new task into a task list. +
It uses the `AddTaskCommand`, which extends `Command`, to add a `Task` into the `TaskManager`.
`AddTaskCommandParser` is also utilised to parse and validate the user inputs before sending it to `AddTaskCommand` to execute.
'AddTaskCommand' requires the following fields: `Task`, `customerId`.
The attributes of Task is as follows:

.Class Diagram of Task class.
image::Task.png[]

As seen in the above class diagram, `driver` and `eventTime` are optional fields that are not mandatory when adding a task.
They will be assigned subsequently using `assign` command. (Refer to Assign feature)
The mandatory fields for users are: 'description', 'date' and 'Customer'.
After the validation is completed, `AddTaskCommand` will fetch `Customer` using the `customerId` through the `CustomerManager`.
A unique id will also be allocated to the task for differentiation.

The following sequence diagrams show how the add task operation works:

.Sequence Diagram of adding a task.
image::AddTaskCommand.png[]
.Sequence Diagram of Model interaction with the CustomerManager and TaskManager for adding a task.
image::ModelInteractWithManagers.png[]

[NOTE]
The flow of how the task is being accessed and managed as shown above is the same for other task related command
such as edit task command (`editT`) and delete task command (`del`).

==== Design Considerations

===== Aspect: Coupling of Task and other entities (Driver and Customer)

* **Alternative 1 (current choice):** Task class contains Driver and Customer classes as attributes.
** Pros: Centralised Task class that encapsulates all the information, which makes it easy to manage task.
** Cons: Task will have to depend on Driver and Customer. Decreases testability.
* **Alternative 2:** Driver and Customer classes have Task class as attribute.
** Pros: Easy to access tasks through the respective classes. (Driver and Customer classes)
** Cons: Having 2 classes depend on Task class. Decreases testability.
// end::task-feature[]



// tag:generate-pdf[]
=== Generate PDF Task Summary Feature
==== Implementation
The *generate PDF Task Summary* feature creates a task summary in a user-friendly layout in PDF format for *user reference* and *archive* usage.
`PdfCreator` class creates and saves the PDF document as well as formatting its layout.
It is implemented with the help of an external library, https://github.com/itext/itext7[iText7].

[NOTE]
Regarding iText's license, it can be used for free in situations where you distribute your software for free.
It is a Affero General Public License (AGPL) library. +
Information updated as of 6 November 2019.
For more information, please visit the https://itextpdf.com/en[iText official website].

The following sequence diagram shows how the user command `savepdf` is being executed and handled.

.Sequence Diagram of how PDF task summary is saved.
image::SavePdfCommand.png[]

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

Notice that only the `filepath` and the `date of delivery` is needed when calling `saveDriverTaskPdf`.
This is because only the saving location of the PDF file and the date, where the task summary will be based on, are the only fields needed for the `PdfCreator`.
The rest of the components, such as fetching of the tasks, will be handled by the `Model` while the formatting will be handled by `PdfCreator`.

The following sequence diagram shows how the model interact with `PdfCreator` to generate the PDF task summary.

.Sequence Diagram of how the model generates the PDF task summary.
image::GeneratePdfSequenceDiagram.png[]

The `PdfWrapperLayout` provides a outer canvas to encapsulates all the layouts.
The following layouts are mainly what makes up the task summary:

* `PdfDriverLayout` class - wraps driver details.
* `PdfCustomerLayout` class - wraps customer details.
* `PdfTaskLayout` class - wraps task details.

The following activity diagram shows what happens when a user executes the `savepdf` command:

.Activity Diagram of how a PDF task summary is generated.
image::GeneratePdfActivityDiagram.png[]

==== Design Considerations

===== Aspect:

* **Alternative 1 (current choice)**: Abstract the layout of each part of the task summary.
** Pros: Encourages reuse and easier to manage and add on.
** Cons: Harder to implement.
* **Alternative 2**: Do the whole task summary layout in 1 class.
** Pros: Easy to implement.
** Cons: Harder to manage.
// end::generate-pdf[]



Expand Down Expand Up @@ -313,44 +408,6 @@ We are using `java.util.logging` package for logging. The `LogsCenter` class is

Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: `config.json`).

=== Task Feature (E.g. Add Delivery Task)
==== Implementation
The *Add Delivery Task* feature adds a new task into a task list. +
It uses the `AddTaskCommand`, which extends `Command`, to add a `Task` into the `TaskManager`.
`AddTaskCommandParser` is also utilised to parse and validate the user inputs before sending it to `AddTaskCommand` to execute.
'AddTaskCommand' requires the following fields: `Task`, `customerId`.
The attributes of Task is as follows:

.Class Diagram of Task class.
image::Task.png[]

As seen in the above class diagram, `driver` and `eventTime` are optional fields that are not mandatory when adding a task.
They will be assigned subsequently using `assign` command. (Refer to Assign feature)
The mandatory fields for users are: 'description', 'date' and 'Customer'.
After the validation is completed, `AddTaskCommand` will fetch `Customer` using the `customerId` through the `CustomerManager`.
A unique id will also be allocated to the task for differentiation.

The following sequence diagrams show how the add task operation works:

.Sequence Diagram of adding a task.
image::AddTaskCommand.png[]
.Sequence Diagram of Model interaction with the CustomerManager and TaskManager for adding a task.
image::ModelInteractWithManagers.png[]

[NOTE]
The flow of how the task is being accessed and managed as shown above is the same for other task related command such as Edit and Delete.

==== Design Considerations

===== Aspect: Couping of Task and other entities (Driver and Customer)

* **Alternative 1 (current choice):** Task class contains Driver and Customer classes as attributes.
** Pros: Centralised Task class that encapsulates all the information, which makes it easy to manage task.
** Cons: Task will have to depend on Driver and Customer. Decreases testability.
* **Alternative 2:** Driver and Customer classes have Task class as attribute.
** Pros: Easy to access tasks through the respective classes. (Driver and Customer classes)
** Cons: Having 2 classes depend on Task class. Decreases testability.

=== Customer Feature (E.g. Add Customer)
==== Implementation
The *Add Customer* feature adds a new Customer into a Customer list. +
Expand Down
11 changes: 8 additions & 3 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -195,15 +195,17 @@ Deletes task (Task ID: 1) from the task manager.
* `del d/2` +
Deletes driver (Driver ID: 2) from the driver manager.

==== Saves assigned delivery tasks into PDF document: `savepdf`
The PDF document is arranged in a table format to allow easy reference of the delivery tasks that is assigned to each drivers for the date. +
==== Saves assigned delivery tasks for a specific date into PDF document: `savepdf`
The PDF document is arranged in a table format to allow easy reference of the delivery tasks that is assigned to each drivers for the date.
Its purpose is for user reference and archive. +
Refer to <<PdfLayout>> for sample. +
Format: `savepdf [DATE]`

****
* `DATE` format is dd/mm/yyy.
* `DATE` field is OPTIONAL. If date field is not declared, it will take the date of today.
* PDF document will be saved under `data` folder which is the same directory as where you put the deliveria.jar.
* Name of the PDF document will be DeliveryTasks (DATE).pdf .
* Name of the PDF document will be DeliveryTasks [DATE].pdf .
****

Examples:
Expand Down Expand Up @@ -263,3 +265,6 @@ There is no need to save manually.
*Q*: How do I know the list of commands? +
*A*: The `help` command will give a list of available commands.

== Appendix
.PDF Document generated by `savepdf` command
image::/images/DeliveryTasks_Pdf_Layout.png[id="PdfLayout", Delivery Tasks PDF]
28 changes: 28 additions & 0 deletions docs/diagrams/GeneratePdfActivityDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
@startuml
start
:User executes `savepdf` command;

:Checks if there is tasks
assigned for the day;

'Since the beta syntax does not support placing the condition outside the
'diamond we place it as the true branch instead.

if () then ([has tasks assigned for the day])
if () then ([file path does
not exists])
:Create file path;
else ([else])
endif
:Generates a task summary
in PDF format;
:Save PDF document
in the file path;
else ([else])
:Notify user that no tasks
are assigned for the day;
stop
endif

stop
@enduml
67 changes: 67 additions & 0 deletions docs/diagrams/GeneratePdfSequenceDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
@startuml
!include style.puml

box Model MODEL_COLOR_T1
participant ":Model" as Model MODEL_COLOR
participant ":PdfCreator" as PdfCreator MODEL_COLOR
participant ":TaskManager" as TaskManager MODEL_COLOR
participant ":PdfWrapperLayout" as PdfWrapperLayout MODEL_COLOR
end box


[-> Model : saveDriverTaskPdf( \n FILEPATH*, 5/11/2019)
note right: FILEPATH*: "./data/DeliveryTasks 2019-11-5".pdf"
activate Model

create PdfCreator
Model -> PdfCreator : new PdfCreator(FILEPATH*)
activate PdfCreator

PdfCreator --> Model
deactivate PdfCreator

Model -> TaskManager : getList()
activate TaskManager

TaskManager --> Model: tasks
deactivate TaskManager

Model -> TaskManager : getDriversFromTasks()
activate TaskManager

TaskManager --> Model: drivers
deactivate TaskManager

Model -> PdfCreator : saveDriverTaskPdf(tasks, drivers, 5/11/2019)
activate PdfCreator

PdfCreator -> PdfCreator ++: createDocument()
PdfCreator --> PdfCreator --: document

PdfCreator -> PdfCreator ++: insertCoverPage(document, 5/11/2019)
PdfCreator --> PdfCreator --

PdfCreator -> PdfCreator ++: insertDriverTask(document, 5/11/2019)

create PdfWrapperLayout
PdfCreator -> PdfWrapperLayout : new PdfWrapperLayout(document)
activate PdfWrapperLayout

PdfWrapperLayout --> PdfCreator
deactivate PdfWrapperLayout

PdfCreator -> PdfWrapperLayout : populateDocumentWithTasks(tasks, 5/11/2019);
activate PdfWrapperLayout

PdfWrapperLayout --> PdfCreator
deactivate PdfWrapperLayout

PdfCreator --> PdfCreator --

PdfCreator --> Model
deactivate PdfCreator

[<-- Model
deactivate Model

@enduml
73 changes: 73 additions & 0 deletions docs/diagrams/SavePdfCommand.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
@startuml
!include style.puml

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant ":SavePdfCommandParser" as SavePdfCommandParser LOGIC_COLOR
participant "p:SavePdfCommand" as SavePdfCommand 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(\n"savepdf 5/11/2019")
activate LogicManager

LogicManager -> AddressBookParser : parseCommand(\n"savepdf 5/11/2019")
activate AddressBookParser

create SavePdfCommandParser
AddressBookParser -> SavePdfCommandParser : SavePdfCommandParser()
activate SavePdfCommandParser

SavePdfCommandParser --> AddressBookParser
deactivate SavePdfCommandParser

AddressBookParser -> SavePdfCommandParser : parse("savepdf 5/11/2019")
activate SavePdfCommandParser

create SavePdfCommand
SavePdfCommandParser -> SavePdfCommand : SavePdfCommand(5/11/2019)
activate SavePdfCommand

SavePdfCommand --> SavePdfCommandParser : p
deactivate SavePdfCommand

SavePdfCommandParser --> AddressBookParser : p
deactivate SavePdfCommandParser

'Hidden arrow to position the destroy marker below the end of the activation bar.
SavePdfCommandParser -[hidden]-> AddressBookParser
destroy SavePdfCommandParser

AddressBookParser --> LogicManager : p
deactivate AddressBookParser

LogicManager -> SavePdfCommand : execute()
activate SavePdfCommand


note right : FILEPATH*: "./data/DeliveryTasks 2019-11-05.pdf"
SavePdfCommand -> Model : saveDriverTaskPdf(FILEPATH*, 5/11/2019)
activate Model

Model --> SavePdfCommand
deactivate Model

create CommandResult
SavePdfCommand -> CommandResult
activate CommandResult

CommandResult --> SavePdfCommand
deactivate CommandResult

SavePdfCommand --> LogicManager : result
deactivate SavePdfCommand

[<--LogicManager
deactivate LogicManager

@enduml
Binary file added docs/images/DeliveryTasks_Pdf_Layout.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/GeneratePdfActivityDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/GeneratePdfSequenceDiagram.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/SavePdfCommand.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions src/main/java/seedu/address/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ private Model initModelManager(Storage storage, ReadOnlyUserPrefs userPrefs) {
try {
centralManagerOptional = storage.readManager();
if (!centralManagerOptional.isPresent()) {
logger.info("Data file not found. Will be starting with a sample AddressBook");
logger.info("Data file not found. Will be starting with a sample Central Manager");
}

initialManagerData = centralManagerOptional.orElseGet(SampleDataUtil::getSampleCentralManager);
} catch (DataConversionException e) {
logger.warning("Data file not in the correct format. Will be starting with an empty AddressBook");
logger.warning("Data file not in the correct format. Will be starting with an empty Central Manager");
initialManagerData = new CentralManager();
} catch (IOException e) {
logger.warning("Problem while reading from the file. Will be starting with an empty AddressBook");
logger.warning("Problem while reading from the file. Will be starting with an empty Central Manager");
initialManagerData = new CentralManager();
}

Expand Down
4 changes: 4 additions & 0 deletions src/main/java/seedu/address/commons/core/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ public class Messages {
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_CUSTOMERS_LISTED_OVERVIEW = "%1$d customers listed!";
public static final String MESSAGE_DRIVERS_LISTED_OVERVIEW = "%1$d drivers listed!";

public static final String MESSAGE_DATA_START_NEW = "Starting with a empty manager. \n"
+ "If you had data previously, this means that your data file is corrupted";

public static final String MESSAGE_ASSIGN_SUCCESS = "Assigned #%1$d to %2$s at %3$s";
public static final String MESSAGE_ALREADY_ASSIGNED = "This task is already scheduled. ";
public static final String MESSAGE_ALREADY_COMPLETED = "This task is completed. ";
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/seedu/address/logic/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ public interface Logic {
/** Returns an unmodifiable view of the filtered list of customers */
ObservableList<Customer> getFilteredCustomerList();

boolean isStartAfresh();

/**
* Returns a list of incomplete tasks from previous days
*/
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ public ObservableList<Customer> getFilteredCustomerList() {
return model.getFilteredCustomerList();
}

@Override
public boolean isStartAfresh() {
return model.isStartAfresh();
}

@Override
public Path getAddressBookFilePath() {
return model.getAddressBookFilePath();
Expand Down

0 comments on commit 6aa5979

Please sign in to comment.