diff --git a/README.md b/README.md index 13f5c77403f..526b9f6efdb 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,24 @@ -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) +[![CI Status](https://github.com/AY2122S1-CS2103-T14-3/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2122S1-CS2103-T14-3/tp/actions) ![Ui](docs/images/Ui.png) -* This is **a sample project for Software Engineering (SE) students**.
- Example usages: - * as a starting point of a course project (as opposed to writing everything from scratch) - * as a case study -* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details. - * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big. - * It comes with a **reasonable level of user and developer documentation**. -* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...). -* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**. -* This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info. +## MyCRM +MyCRM, short for _"My Customer Relationship Manager"_, is a desktop application for managing client contacts, repair job +statuses, and product information.
+ +* It is targeted at computer repair shop technician. Specifically, it can help he/she to + * Centralize on-going jobs and client information in a single application. + * Integrate a job status tracking system. + * Integrate a client notification system. + * Generate monthly reports and statistics automatically.
+* It has been optimised for use via a Command Line Interface (CLI) while maintaining the benefits of a Graphical User + Interface (GUI). + +### About our project +* It is an ongoing software project with regular updates and constantly improving features. +* It is written in OOP fashion and provides a reasonably well-written code base with around 6k LoC. +* It comes with a reasonable level of user and developer documentation. +* For the detailed documentation of this project, see the **[MyCRM Product Website](https://ay2122s1-cs2103-t14-3.github.io/tp/)**. + +### Acknowledgment +This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org). diff --git a/build.gradle b/build.gradle index be2d2905dde..df333c84a4c 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { id 'jacoco' } -mainClassName = 'seedu.address.Main' +mainClassName = 'seedu.mycrm.Main' sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 @@ -66,7 +66,16 @@ dependencies { } shadowJar { - archiveName = 'addressbook.jar' + archiveName = 'MyCrm.jar' +} + +run { + enableAssertions = true; +} + +tasks.withType(JavaCompile) { + options.fork = true + options.forkOptions.jvmArgs += ["-Duser.language=en"] } defaultTasks 'clean', 'test' diff --git a/copyright.txt b/copyright.txt index 93aa2a39ce2..6a552c80f09 100644 --- a/copyright.txt +++ b/copyright.txt @@ -1,8 +1,8 @@ Some code adapted from http://code.makery.ch/library/javafx-8-tutorial/ by Marco Jakob -Copyright by Susumu Yoshida - http://www.mcdodesign.com/ -- address_book_32.png -- AddressApp.ico +Copyright Free Icons Library - hhttps://icon-library.com/icon/crm-icon-3.html +- myCrm_icon.png +- MyCrmApp.ico Copyright by Jan Jan Kovařík - http://glyphicons.com/ - calendar.png diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 1c9514e966a..58faa79614b 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -7,53 +7,70 @@ We are a team based in the [School of Computing, National University of Singapor You can reach us at the email `seer[at]comp.nus.edu.sg` -## Project team +## Project Team -### John Doe +### Timothy Chua - + -[[homepage](http://www.comp.nus.edu.sg/~damithch)] -[[github](https://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](https://github.com/ooawagaeri)] +[[portfolio](team/ooawagaeri.md)] -* Role: Project Advisor +* Role: Team Lead, Scheduling and Tracking +* Responsibilities: + * Focus on issues. + * Defining, assigning, and tracking project tasks. + * Ensuring everyone has manageable task. -### Jane Doe +### Hang Zelin - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](https://github.com/hangzelin)] +[[portfolio](team/hangzelin.md)] -* Role: Team Lead -* Responsibilities: UI +* Role: Code Quality / Integration handler +* Responsibilities: + * Pull request reviewer. + * Merging of pull requests. + * Ensure adherence to coding standards. -### Johnny Doe +

+### Zhang Yubin - + -[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)] +[[github](https://github.com/Kimowarui)] +[[portfolio](team/kimowarui.md)] -* Role: Developer -* Responsibilities: Data +* Role: Deliverables and Deadlines +* Responsibilities: + * Focus on milestones page. + * Update milestones according to CS2103 website. + * Ensure project deliverables are done on time and in the right format. + * Chase people if need be. -### Jean Doe +### Fan Tianhao - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](https://github.com/TTraveller7)] +[[portfolio](team/ttraveller7.md)] -* Role: Developer -* Responsibilities: Dev Ops + Threading +* Role: Documents +* Responsibilities: + * Ensure quality of various project documents + * UI mockup and design -### James Doe +### Dhruv Shah - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](https://github.com/dhshah1)] +[[portfolio](team/dhshah1.md)] -* Role: Developer -* Responsibilities: UI +* Role: Tester +* Responsibilities: + * Ensure proper tests are written for all modules + * Ensure new features/modules don't introduce bugs + * Ensure application works as expected diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 46eae8ee565..5328581a669 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,6 +2,7 @@ layout: page title: Developer Guide --- + * Table of Contents {:toc} @@ -9,7 +10,8 @@ title: Developer Guide ## **Acknowledgements** -* {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +* Project template and structure, AddressBook Level 3 from [SE-EDU](https://github.com/se-edu/addressbook-level3). +* Reuse of code: URL encoding from [2ality](https://2ality.com/2010/12/simple-way-of-sending-emails-in-java.html). -------------------------------------------------------------------------------------------------------------------- @@ -23,12 +25,18 @@ Refer to the guide [_Setting up and getting started_](SettingUp.md).
-:bulb: **Tip:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/se-edu/addressbook-level3/tree/master/docs/diagrams/) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams. +:bulb: **Tip 1:** The `.puml` files used to create diagrams in this document can be found in the [diagrams](https://github.com/se-edu/addressbook-level3/tree/master/docs/diagrams/) folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams. + +:bulb: **Tip 2:** Each of the following class, sequence and activity diagram can be enlarged by CLICKING on the respective +images! +
### Architecture + + The ***Architecture Diagram*** given above explains the high-level design of the App. @@ -36,7 +44,7 @@ Given below is a quick overview of main components and how they interact with ea **Main components of the architecture** -**`Main`** has two classes called [`Main`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java). It is responsible for, +**`Main`** has two classes called [`Main`](https://github.com/AY2122S1-CS2103-T14-3/tp/blob/master/src/main/java/seedu/mycrm/Main.java) and [`MainApp`](https://github.com/AY2122S1-CS2103-T14-3/tp/blob/master/src/main/java/seedu/mycrm/MainApp.java). 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. @@ -52,9 +60,11 @@ The rest of the App consists of four components. **How the architecture components interact with each other** -The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete 1`. +The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `deleteContact 1`. + + Each of the four main components (also shown in the diagram above), @@ -63,90 +73,131 @@ Each of the four main components (also shown in the diagram above), 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`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java) +The **API** of this component is specified in [`Ui.java`](https://github.com/AY2122S1-CS2103-T14-3/tp/blob/master/src/main/java/seedu/mycrm/ui/Ui.java) + +[![](images/UiClassDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/UiClassDiagram.png) -![Structure of the UI Component](images/UiClassDiagram.png) +
-The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `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 consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `MainDisplay`, +`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`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/resources/view/MainWindow.fxml) +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`](https://github.com/AY2122S1-CS2103-T14-3/tp/blob/master/src/main/java/seedu/mycrm/ui/MainWindow.java) +is specified in [`MainWindow.fxml`](https://github.com/AY2122S1-CS2103-T14-3/tp/blob/master/src/main/resources/view/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 the `UI` relies on the `Logic` to execute commands. -* depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model`. +* depends on some classes in the `Model` component, as it displays `Job`, `Mail`, `Contact`, `Product`, `Template`, `History` + objects residing in the `Model`. ### Logic component -**API** : [`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java) +**API** : [`Logic.java`](https://github.com/AY2122S1-CS2103-T14-3/tp/blob/master/src/main/java/seedu/mycrm/logic/Logic.java) Here's a (partial) class diagram of the `Logic` component: - +[![](images/LogicClassDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/LogicClassDiagram.png) How the `Logic` component works: -1. When `Logic` is called upon to execute a command, it uses the `AddressBookParser` class to parse the user command. -1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `AddCommand`) which is executed by the `LogicManager`. -1. The command can communicate with the `Model` when it is executed (e.g. to add a person). -1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`. +1. When `Logic` is called upon to execute a command, it uses the `MyCRMParser` class to parse the user command. +2. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `AddCommand`) which is executed by the `LogicManager`. +3. `StateManager` checks to see whether the parsed command can currently be executed depending on the current state of the application. + If it can the `Command` object is executed by the `LogicManager`. +4. The command can communicate with the `Model` when it is executed (e.g. to add a person). +5. The result of the command execution is encapsulated as a `CommandResult` object. +6. For certain commands `StateManager` intercepts this `CommandResult` object. It communicates with model to perform extra operations and modifies the + `CommandResult` accordingly. +7. The `CommandResult` object is returned from `Logic`. -The Sequence Diagram below illustrates the interactions within the `Logic` component for the `execute("delete 1")` API call. +The Sequence Diagram below illustrates the interactions within the `Logic` component for the `execute("addJob c/1 p/1 d/Fix...")` API call. -![Interactions Inside the Logic Component for the `delete 1` Command](images/DeleteSequenceDiagram.png) +[![Interactions Inside the Logic Component for the `addJob c/1 p/1 d/Fix...` Command](images/job/AddJobSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/AddJobSequenceDiagram.png) -
:information_source: **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. -
+Please refer to [StateManager](#statemanager) for a more detailed explanation on its motivation and implementation. 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 an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as a `Command` object. +* When called upon to parse a user command, the `MyCrmParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `MyCrmParser` returns back as a `Command` object. * All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing. ### Model component **API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java) - + + + + + + -The `Model` component, + + + -* stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object). -* stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` 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 a `ReadOnlyUserPref` 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) + + + -
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique tag, instead of each `Person` needing their own `Tag` objects.
+ + + - + + + -
+The `Model` component, + +* stores the MyCrm data i.e: + * all `Contact` objects (which are contained in a `UniqueContactList` object). + * all `Product` objects (which are contained in a `UniqueProductList` object). + * all `Template` objects (which are contained in a `UniqueTemplateList` object). + * all `Job` objects (which are contained in a `UniqueJobList` object). + * all `Mail` objects (which are contained in a `UniqueMailList` object). +* stores the currently 'selected' `Contact`, `Product`, `Template`,`Job`and `Mail` objects (e.g., results of a + search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable + `ObservableList` 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 a `ReadOnlyUserPref` 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) ### Storage component **API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/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` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed). +* can save both MyCrm data and user preference data in json format, and read them back into corresponding objects. +* inherits from both `MyCrmStorage` and `UserPrefStorage`, 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 the `Storage` component's job is to save/retrieve objects that belong to the `Model`) ### Common classes -Classes used by multiple components are in the `seedu.addressbook.commons` package. +Classes used by multiple components are in the `seedu.mycrm.commons` package. -------------------------------------------------------------------------------------------------------------------- @@ -154,90 +205,614 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa This section describes some noteworthy details on how certain features are implemented. -### \[Proposed\] Undo/redo feature +* [Adding a contact](#adding-a-contact) +* [Editing a contact](#editing-a-contact) +* [Deleting a contact](#deleting-a-contact) +* [Finding a contact](#finding-a-contact) +* [Hiding a contact](#hiding-a-contact) +* [Undoing Hiding a contact](#undoing-hiding-a-contact) +* [Listing contacts](#listing-contacts) +* [Adding a template](#adding-a-template) +* [Editing a template](#editing-a-template) +* [Deleting a template](#deleting-a-template) +* [Finding a template](#finding-a-template) +* [Constructing an email](#constructing-an-email) +* [Adding a product](#adding-a-product) +* [Editing a product](#editing-a-product) +* [StateManager](#statemanager) +* [Adding a job](#adding-a-job) +* [Editing a job](#editing-a-job) +* [Printing a monthly job report](#printing-a-monthly-job-report) -#### Proposed Implementation +### Adding a Contact -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: +#### Implementation -* `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. +The **Adding a Contact** mechanism is facilitated by `MyCRM`. This Contact created is stored internally using +`UniqueContactList` inside the `MyCrm` object. +Additionally, `addContact` allows to have only partially info of a client with consideration of privacy. Commands +such as `AddContact n/xxx e/xxx` `addContact n/xxx c/xxx` are all acceptable. -These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. +#### Usage -Given below is an example usage scenario and how the undo/redo mechanism behaves at each step. +The activity diagram below illustrates how the events of `addContact` command behave when executed by a user: -Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state. +[![](images/contact/AddContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/AddContactActivityDiagram.png) -![UndoRedoState0](images/UndoRedoState0.png) +Given below is an example usage scenario and how the **Adding a Contact** mechanism behaves at each step. -Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state. +[![](images/contact/AddContactParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/AddContactParseSequenceDiagram.png) -![UndoRedoState1](images/UndoRedoState1.png) +Within `AddContactCommandParser#parse`, `ParserUtil#parseName` will be called to create a name using +"Sans", `ParserUtil#parsePhone` to create a phone using "83921823", `ParserUtil#parseEmail` to +create an email using "Sans@gmail.com", `ParserUtil#parseAddress` to create an address using "Maxwell...". +Then create a contact using the new name, phone, email and address. -Step 3. The user executes `add n/David …​` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`. +Note that `Phone`, `Email`, `Address`, are optional, but at least one of these 3 fields +must exist. -![UndoRedoState2](images/UndoRedoState2.png) +[![](images/contact/AddContactSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/AddContactSequenceDiagram.png) -
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`. +Note: Please refer to [StateManager](#statemanager) for more details on why the command result of the AddContactCommand is intercepted. -
+### Editing a Contact -Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state. +#### Implementation -![UndoRedoState3](images/UndoRedoState3.png) +The **Editing a Contact** mechanism is facilitated by `MyCRM`. This mechanism reads and modifies a target contact +object from `UniqueContactList` inside the `MyCRM` object. -
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#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. +#### Usage -
+The activity diagram below illustrates how the events of `editContact` command behave when executed by a user: -The following sequence diagram shows how the undo operation works: +[![](images/contact/EditContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/EditContactActivityDiagram.png) -![UndoSequenceDiagram](images/UndoSequenceDiagram.png) +Given below is an example usage scenario and how the **Editing a Contact** mechanism behaves at each step. -
:information_source: **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. +[![](images/contact/EditContactParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/EditContactParseSequenceDiagram.png) -
+Within `EditContactCommandParser#parse`, +- `Index` must be is valid (within the range of contactList). +- `EditContactDescriptor` will only get the values of `Name`, `Phone`, `Email`, `Address`, and `Tags` +if their respective prefixes are present. +- `isHidden` is will not be handled by `EditContactDescrptior`, it will be updated in `createEditedContact`. -The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state. +`EditContactCommandParser#parse` will call `ArgumentMultimap#getPreamble` to get the target contact's index and +`ArgumentMultimap#getValue` to extract `Name`, `Phone`, `Email`, `Address`: "Frisks", "88888888", "Frisks@gmail.com" +and "Jurong West" from the command string respectively. -
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#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. +[![](images/contact/EditContactSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/EditContactSequenceDiagram.png) -
+### Deleting a Contact + +#### Implementation + +The **Deleting a Contact** mechanism is facilitated by `MyCRM`. This mechanism reads and deletes a target contact +object from `UniqueContactList` inside the `MyCRM` object. + +#### Usage + +The activity diagram below illustrates how the events of `deleteContact` command behave when executed by a user: + +[![](images/contact/DeleteContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/DeleteContactActivityDiagram.png) + +Given below is an example usage scenario and how the **Deleting a Contact** mechanism behaves at each step. + +[![](images/contact/DeleteContactParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/DeleteContactParseSequenceDiagram.png) + +Within `DeleteContactCommandParser#parse`, +- `Index` must be is valid (within the range of contactList). +- The contact specified to be deleted must have no jobs linked, otherwise error message will be displayed in UI panel. + +`DeleteContactCommandParser#parse` will call `ParserUtil#parseIndex` to get the target contact's index to delete it. + +[![](images/contact/DeleteContactSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/DeleteContactSequenceDiagram.png) + +### Finding a Contact + +#### Implementation + +The **Finding a Contact** mechanism is facilitated by `MyCRM`. This mechanism finds specific list of contact +object from `UniqueContactList` inside the `MyCRM` object with certain keywords provided. + +#### Usage + +The activity diagram below illustrates how the events of `findContact` command behave when executed by a user: + +[![](images/contact/FindContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/FindContactActivityDiagram.png) + +Given below is an example usage scenario and how the **Finding a Contact** mechanism behaves at each step. + +[![](images/contact/FindContactParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/FindContactParseSequenceDiagram.png) + + +Within `FindContactCommandParser#parse`, +- `Keywords` must be presented. (At least one trim of String) + +`FindContactCommandParser#parse` will call `String#trim` and `String#split` to get list of keywords +in order for MyCRM to find corresponding contacts with these keywords as predicate. + +[![](images/contact/FindContactSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/FindContactSequenceDiagram.png) + +### Hiding a Contact + +#### Implementation + +The **Hiding a Contact** mechanism is facilitated by the `MyCRM`. It hides a specific contact +which is visible only when user types the command `listContact -a`. Hidden contact will be tagged as `Hidden`. + +#### Usage + +The activity diagram below illustrates how the events of `hideContact` command behave when executed by a user: + +[![](images/contact/HideContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/HideContactActivityDiagram.png) + +Given below is an example usage scenario and how the **Hiding a Contact** mechanism behaves at each step. + +[![](images/contact/HideContactParserSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/HideContactParseSequenceDiagram.png) + +Within `HideContactCommandParser#parse`, +- `Index` must be is valid (within the range of contactList). + +`HideContactCommandParser#parse` will call `ParserUtil#parseIndex` to get the target contact's index to hide it. + +[![](images/contact/HideContactSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/HideContactSequenceDiagram.png) + +### Undoing Hiding a Contact + +#### Implementation + +The **Undoing Hiding a Contact** mechanism is facilitated by the `MyCRM`. It will unhide a hidden contact in list. Users are +required to type in command `listContact -a` in order to see **hidden** contacts. + +Implementation and usage details for **Undoing Hiding a Contact** are similar to [Hiding a Contact](#hiding-a-contact) design +pattern. Can refer to `hideContact` command implementation details. +#### Usage + +The activity diagram below illustrates how the events of `undoHideContact` command behave when executed by a user: + +[![](images/contact/UndoHideContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/UndoHideContactActivityDiagram.png) + +Given below is an example usage scenario and how the **Undoing Hiding a Contact** mechanism behaves at each step. + +[![](images/contact/UndoHideContactParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/UndoHideContactParseSequenceDiagram.png) + +Within `UndoHideContactCommandParser#parse`, +- `listContact -a` must first be typed in to see hidden contacts. +- `Index` must be is valid (within the range of contactList). + +`UndoHideContactCommandParser#parse` will call `ParserUtil#parseIndex` + +[![](images/contact/UndoHideContactSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/UndoHideContactSequenceDiagram.png) + +### Listing Contacts + +#### Implementation + +The **Listing a Contact** mechanism is facilitated by `MyCRM`. This mechanism lists all unhidden Contact +object from `UniqueContactList` inside the `MyCRM` object by default. If `listContact -a` is invoked, +`MyCRM` will list all contacts including not hidden ones. + +#### Usage + +The activity diagram below illustrates how the events of `listContact` command behave when executed by a user: + +[![](images/contact/ListContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/ListContactActivityDiagram.png) + +Given below is an example usage scenario and how the **Listing a Contact** mechanism behaves at each step. + +[![](images/contact/ListContactParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/ListContactParseSequenceDiagram.png) + +Within `ListContactCommandParser#parse`, +- `Keywords` is optional but if provided, it can only be **"-a"**. +- If correct keyword is presented, contact list will show all contacts including hidden contacts. +If not, by default `listContact` will only show not hidden contacts in contact list. + +`ListcontactCommandParser#parse` will call `String#trim` to get specific keyword. + +[![](images/contact/ListContactSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/contact/ListContactSequenceDiagram.png) + +### Adding a Template + +#### Implementation + +The **Adding a Template** mechanism is facilitated by `MyCRM`. This template created is stored internally using +`UniqueTemplateList` inside the `MyCRM` object. + +#### Usage + +The activity diagram below illustrates how the events of `addTemplate` command behave when executed by user: + +[![](images/mail/AddTemplateActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/AddTemplateActivityDiagram.png) + +Given below is an example usage scenario and how the Adding a Template mechanism behaves at each step. + +[![](images/mail/AddTemplateParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/AddTemplateParseSequenceDiagram.png) + +**Parse user input** + +Within `AddTemplateCommandParser#parse`, `ParserUtil#parseSubject` will be called to create a subject using +"Completed", `ParserUtil#parseBody` to create a body using "Dear customer..." and create a template using the new +subject and body. + +[![](images/mail/AddTemplateSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/AddTemplateSequenceDiagram.png) + +Additionally, before adding the new template into `Model`, `Template t` will be checked if a similar copy exist +within `Model`. The conditions required is: + +* If both templates have the DO NOT same `Subject` content i.e. there is an existing template with subject "Completed". + +#### Design Considerations + +**Aspect: Unique Template** + +* Current choice: Unique by Subject + * Pros: Easy to understand and differentiate templates + * Cons: Does not allow for different variations of general / common email headers i.e. "Completed" subject header + cannot be reused with different body content based on scenario +* Alternative: Unique by Subject and Body + * Pros: Enables different variations of general / common email headers + * Cons: May not be user-friendly as it may be hard to differentiate templates as some may be too similar at first + glance. Such as, minor typos, copy and paste with a couple of different words. Higher risk of confusion. + +### Editing a Template + +#### Implementation + +The **Editing a Template** mechanism is facilitated by `MyCRM`. This mechanism reads and modifies a target template +object from `UniqueTemplateList` inside the `MyCRM` object. + +#### Usage + +The activity diagram below illustrates how the events of `editTemplate` command behave when executed by user: + +[![](images/mail/EditTemplateActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/EditTemplateActivityDiagram.png) + +Given below is an example usage scenario and how the Editing a Template mechanism behaves at each step. + +[![](images/mail/EditTemplateParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/EditTemplateParseSequenceDiagram.png) + +**Parse user input** + +Within `EditTemplateCommandParser#parse`, +- `Index` must be is valid (within the range of templates). +- `EditTemplateDescriptor` will only get the values of `Subject` and `Body` if their respective prefixes are present. + +`EditTemplateCommandParser#parse` will call `ArgumentMultimap#getPreamble` to get the specified template index and +`ArgumentMultimap#getValue` to extract both `Subject` and `Body`: "Completed" and "Order Completed!" from the +command string respectively. + +[![](images/mail/EditTemplateSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/EditTemplateSequenceDiagram.png) + +### Deleting a Template + +#### Implementation + +The **Deleting a Template** mechanism is facilitated by `MyCRM`. This template removes a target template object from +`UniqueTemplateList` inside the `MyCRM` object. + +#### Usage + +The activity diagram below illustrates how the events of `deleteTemplate` command behave when executed by user: + +[![](images/mail/DeleteTemplateActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/DeleteTemplateActivityDiagram.png) + +Given below is an example usage scenario and how the Deleting a Template mechanism behaves at each step. + +[![](images/mail/DeleteTemplateParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/DeleteTemplateParseSequenceDiagram.png) + +**Parse user input** + +Within `DeleteTemplateCommandParser#parse`, +- `Index` must be is valid (within the range of templates) and at least one field to be edited, for the mechanism to + execute successfully. +- `ParserUtil#parseIndex` will be called to extract the index of the specified template to delete. + +[![](images/mail/DeleteTemplateSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/DeleteTemplateSequenceDiagram.png) + +### Finding a Template + +#### Implementation + +The **Finding a Template** mechanism is facilitated by `MyCRM`. This mechanism finds specific list of template object +from `UniqueTemplateList` inside the `MyCRM` object with certain keywords provided. + +#### Usage + +The activity diagram below illustrates how the events of `findTemplate` command behave when executed by a user: + +[![](images/mail/FindTemplateActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/FindTemplateActivityDiagram.png) + +Given below is an example usage scenario and how the Finding a Template mechanism behaves at each step. + +[![](images/mail/FindTemplateParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/FindTemplateParseSequenceDiagram.png) + +**Parse user input** + +Within `FindTemplateCommandParser#parse`, +- At least one keyword must be presented. +- Keyword specified must be whole word. + +`FindTemplateCommandParser#parse` will call `String#trim` and `String#split` to get list of keywords +in order for MyCRM to find corresponding templates with these keywords as predicate. + +[![](images/mail/FindTemplateSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/FindTemplateSequenceDiagram.png) + +### Constructing an Email + +#### Implementation + +The **Constructing an Email** mechanism is facilitated by `MyCRM`. This email is constructed based of the information +from a specified job and template from `UniqueJobList` and `UniqueTemplateList` inside the `MyCRM` object. A +mailto URL will be generated, sending users to their default mailing application with details of the job and +template. + +#### Usage + +The activity diagram below illustrates how the events of `mail` command behave when executed by user: -Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged. +[![](images/mail/MailActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/MailActivityDiagram.png) -![UndoRedoState4](images/UndoRedoState4.png) +Given below is an example usage scenario and how the Constructing an Email mechanism behaves at each step. -Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …​` command. This is the behavior that most modern desktop applications follow. +[![](images/mail/MailParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/MailParseSequenceDiagram.png) -![UndoRedoState5](images/UndoRedoState5.png) +**Parse user input** -The following activity diagram summarizes what happens when a user executes a new command: +Within `MailCommandParser#parse`, +- `JobIndex` must be is valid (within the range of job). +- `TemplateIndex` must be is valid (within the range of templates). +- `ParserUtil#parseIndex` will be called to extract both the index of the specified job and template to mail. - +[![](images/mail/MailSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/MailSequenceDiagram.png) -#### Design considerations: +An additional feature of constructing an email is the generation of a mailto URL, allowing for users to transfer +their job and template details to the user's default mailing application. -**Aspect: How undo & redo executes:** +Given below is an example of the **generation of a mailto URL**: -* **Alternative 1 (current choice):** Saves the entire address book. - * Pros: Easy to implement. - * Cons: May have performance issues in terms of memory usage. +[![](images/mail/MailUrlSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/mail/MailUrlSequenceDiagram.png) -* **Alternative 2:** Individual command knows how to undo/redo by - itself. - * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). - * Cons: We must ensure that the implementation of each individual command are correct. +After the URL is generated, the URL string is passed to a JavaFX Hyperlink object that when clicked, will +execute the URL path. -_{more aspects and alternatives to be added}_ +#### Design Considerations -### \[Proposed\] Data archiving +**Aspect: Mailing Extension** -_{Explain here how the data archiving feature will be implemented}_ +* Current choice: mailto URL + * Pros: Easy to implement, is not limited to any specific email application, does not require user's email account. + * Cons: Does not allow for direct (immediate) sending of mail to client email addresses. +* Alternative: Embedding Oauth with email service + * Pros: Enables direct and quick sending of email directly from MyCRM application + * Cons: Higher complexity in implementation with JavaFX, requires internet access to save drafts of emails, + requires the storage and security assurance of user sensitive data (email account information), and limited + management number of email accounts i.e. swapping different email services like Gmail and Outlook +### Adding a Product + +#### Implementation + +The **Adding a Product** mechanism is facilitated by `MyCRM`. This product created is stored internally using +`UniqueProductList` inside the `MyCRM` object. + +#### Usage + +The activity diagram below illustrates how the events of `addProduct` command behave when executed by user: + +[![](images/product/AddProductActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/product/AddProductActivityDiagram.png) + +Given below is an example usage scenario and how the mechanism behaves at each step. + +[![](images/product/AddProductSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/product/AddProductSequenceDiagram.png) + +Note: Please refer to [StateManager](#statemanager) for more details on why the command result of the AddProductCommand is intercepted. + +**Parse user input** + +Within `AddProductCommandParser#parse`, the **factory methods** of product components (`getProductName` and +`getEmptyProductName` for product name, `getType` and `getEmptyType` for type, ...) will be invoked to create product +component objects: name, type, manufacturer, description. + +**Note**: Name is *compulsory* for creating a product, whereas type, manufacturer and description are *optional* fields. + +[![](images/product/AddProductSequenceDiagram_Parse.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/product/AddProductSequenceDiagram_Parse.png) + +### Editing a Product + +#### Implementation + +The **Editing a Product** mechanism is facilitated by `MyCRM`. This mechanism first reads the target product object from +`UniqueProductList`, then creates a new product object with user input fields and unchanged fields of target +product. Lastly, it replaces the target product with the new one, updates its references in jobs, and updates UI. + +#### Usage + +The activity diagram below illustrates how the events of `editProduct` command behave when executed by user: + +[![](images/product/EditProductActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/product/EditProductActivityDiagram.png) + +Given below is an example usage scenario and how the mechanism behaves at each step. + +[![](images/product/EditProductSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/product/EditProductSequenceDiagram.png) + +**Parse user input** + +Within `EditProductCommandParser#parse`, +* EditProductCommandParser will only get the values of fields(`name`, `manufacturer`, `type`, `description`) if their + respective prefixes are present. + +`EditTemplateCommandParser#parse` will call `ArgumentMultimap#getPreamble` to get the specified product index and +`ArgumentMultimap#getValue` to extract product name “Asus” and description “DisplayPort, HDMI” from user input +respectively. + +[![](images/product/EditProductSequenceDiagram_Parse.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/product/EditProductSequenceDiagram_Parse.png) + +**Updates product references in jobs** + +After target product is replaced with new product, `EditProductCommand#execute()` will traverse job list and replace +references to target product with references to new product. + +To get the full job list, `EditProductCommand#execute()` will store the *lastest predicate* of job list and set the +predicate to "show all jobs". After traversing the job list and updating the references, the *latest predicate* is +restored. + +Design Consideration: An alternative way to get full job list is to retrieve the underlying `UniqueJobList` through +`Model`. `EditProductCommand` is implemented in the other way as directly accessing and modifying `UniqueJobList` leads to an +association between `EditProductCommand` and `UniqueJobList`, which increases coupling. + +[![](images/product/EditProductSequenceDiagram_Sync.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/product/EditProductSequenceDiagram_Sync.png) + +### StateManager + +#### Motivation + +As seen from the description of the [Model Component](#model-component) the job entity holds a reference to exactly one contact and product entity. +As such, one key consideration behind job related commands was providing an easy and flexible way for users to choose to assign either +existing or new contact and/or products to jobs. As an example, when a user is adding a new job, the product or contact information needed might already exist in MyCRM, +if there have been prior repairs on the same product or if it is a repeat client. In such cases the user will want to assign an existing contact and/or product to the new job. +In other cases a new job will require creation of new contact and product entities not already present in MyCRM and subsequent assignment of these new contact and/or product entities +to the job. The goal of `StateManager` is to handle these various scenarios amd make the process of assigning contacts and products to jobs easy for the user. + +#### Implementation + +The description of the [Logic Component](#logic-component) describes at a high level how `StateManager` controls which commands can be executed by `LogicManager` +and how `StateManager` intercepts results of a `Command` to perform additional operations (if needed) by communicating with the `Model`. + +Here is a more detailed look at how `StateManager` works: +1. Internally it has a list of possible states of the application. Based on the commands executed it remembers the current state of the application. + e.g. If a `addJob` command is issued without a contact index, that job will not be added to `MyCRM` immediately. + Instead, StateManager` will remember that a job is being added, and needs a contact assigned to it. +2. Each state has a corresponding list of allowed commands that are permitted in that state. It prevents `LogicManager` from executing commands not permitted for the + current state. e.g When a contact is being assigned to a job, some commands that are allowed (non-exhaustive) are `addContact`, `listContact`, `findContact` etc... +3. When a command is executed, the state manager might intercept its `CommandResult`, to perform additional operations and update its internal state. + e.g After an `addContact` command, `StateManager` will check the current state to see if a job is currently being added. If so state manager will link it to that job. + If the job is complete (does not require assignment of a product), it will be added to `MyCRM` and the job creation will be complete. Otherwise, `StateManager` will update + its internal state to remember that a job is being added, and needs a product assigned to it. +4. The `CommandResult` is modified suitably based on additional operations performed before being returned to `LogicManager`. This is so that the user is able to see + appropriate feedback on what operations were completed. + +While the above examples were in the context of `addJob` commands, `StateManager` plays a identical role in helping with the reassignment of contact and/or product for existing jobs, via the +`editJob` command. + +The two activity diagrams below illustrates the events that might occur when MyCRM prompts the user to assign a contact and/or product to a job. This can happen after the user +has issued an `addJob` or `editJob` command without a contact or product index. + +[![Activity diagram of assigning contact to job](images/job/AssigningContactActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/AssigningContactActivityDiagram.png) + +[![Activity diagram of assigning product to job](images/job/AssigningProductActivtyDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/AssigningProductActivtyDiagram.png) + +Notice that the user can still choose to select an existing contact and/or product even if their index wasnt provided in the `addJob` or `editJob` command itself. +This is made possible using a `select` command. + +Also notice that the user can call an `abort` command to exit from the current operation. +`StateManager` will clear its state, and the adding or editing of the job will not go through. + +### Adding a Job + +#### Implementation + +The **Adding a Job** mechanism is facilitated by `MyCRM`. Similar to other entities like products or contacts, jobs created +are stored internally using`UniqueJobList` inside the `MyCrm` object. + +#### Usage + +The activity diagram below illustrates the possible workflows when the `addJob` command is being executed by the user. + +[![Activity diagram of add job](images/job/AddJobActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/AddJobActivityDiagram.png) + +Notice that in the case the contact and/or product index are not provided `StateManager` will prompt for the two entities sequentially. +First it checks if the contact has been assigned, and then it checks if the product is assigned. +If only one of contact or product index is missing, `StateManager` will only ask for assignment of the missing entity. + +In the [Logic Component](#logic-component) a high level sequence diagram is shown for when both the contact or product index are provided, and the job is added to MyCRM. + +The below sequence diagram shows an example usage scenario where the product index is missing. +Notice how the job is passed to the `StateManager` but not added to the model, because the job does not have a product assigned. + +[![Sequence diagram of add job](images/job/AddJobSequenceDiagramShort.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/AddJobSequenceDiagramShort.png) + +**Parsing of user input** + +As seen from the description of the [Model Component](#model-component) the job entity has many subcomponents such as `JobDescription`, `JobFee`, +`JobDate`, etc... Within `AddJobCommandParser#parse`, methods from `ParserUtil` are used to create these job subcomponents, before creating the job to be added to `MyCRM`. + +[![Sequence diagram of parsing user input](images/job/AddJobParseSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/AddJobParseSequenceDiagram.png) + +### Editing a job + +#### Implementation +The **Editing a Job** mechanism is facilitated by `MyCRM`. Similar to the other entities, this mechanism first reads the target job object from +`UniqueJobList`, and then creates a new job object with the user input fields in the `editJob` command and unchanged fields of target +job. Lastly, it replaces the target job with the new one and is reflected in the updated UI. + +#### Usage + +The activity diagram below illustrates the possible workflows when the `editJob` command is being executed by the user. + +Notice one difference between the workflow between `addJob` and `editJob`. Even though the user doesn't have to provide the contact or product index in the command itself, +the user still has to indicate an intention to reassign the contact and/or product of the existing job. This is done by providing the contact or product prefixes in the command +without their index, e.g `editJob INDEX c/ p/` + +[![Activity diagram of edit job](images/job/EditJobActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/EditJobActivityDiagram.png) + +The below sequence diagram shows an example usage scenario where both the contact and product indexes are present. + +[![Sequence diagram of edit job](images/job/EditJobSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/job/EditJobSequenceDiagram.png) + +The parsing for `editJob` is similar to `addJob` where methods from `ParserUtil` are used to create the sub-components, +before creating the edited version of the job. + +### Printing a monthly job report + +#### Implementation + +The **Printing a monthly job report** mechanism is facilitated by `MyCRM`. This job report is generated based of the information from +jobs completed in this month and received in this month from `UniqueJobList` inside `MyCRM` object. A report window +will be created with details of completed jobs, in-progress jobs, top three popular products, and a bar graph showing monthly revenue. + +#### Usage + +The activity diagram below illustrates how the events of `printReport` command behave when executed by user: + +[![Activity diagram of print report](images/report/PrintReportActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/report/PrintReportActivityDiagram.png) + +Given below is an example usage scenario and how the mechanism behaves at each step. + +[![Sequence diagram of print report parser](images/report/PrintReportParserSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/report/PrintReportParserSequenceDiagram.png) + +Within `PrintReportCommandParser#parse`, +- `CommandFlag` is optional but if provided, it can only be either **"-i"** or **"-p"**. +- If **"-i"** is presented, report window will show all in-progress jobs received in this month. +- If **"-i"** is presented, report window will show the top three popular products in this month. +- if no flag is presented, report windwo will shou all jobs completed in this month by default. + +`PrintReportCommandParser#parse` will call `String#trim` to get specific command flag. + +[![Sequence diagram of print report](images/report/PrintReportSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/report/PrintReportSequenceDiagram.png) + +### Exporting a monthly job report + +#### Implementation + +The **Exporting a monthly job report** mechanism is facilitated by `MyCRM`. This job report is generated based of the information from +jobs completed in this month and received in this month from `UniqueJobList` inside `MyCRM` object. Then `MyCRM` will export +the job report by printer or as PDF format. + +#### Usage + +The activity diagram below illustrates how the events of `printReport` command behave when executed by user: + +[![Activity diagram of export report](images/report/ExportReportActivityDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/report/ExportReportActivityDiagram.png) + +Given below is an example usage scenario and how the mechanism behaves at each step. + +[![Sequence diagram of export report parser](images/report/ExportReportParserSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/report/ExportReportParserSequenceDiagram.png) + +[![Sequence diagram of export report](images/report/ExportReportSequenceDiagram.png)](https://ay2122s1-cs2103-t14-3.github.io/tp/images/report/ExportReportSequenceDiagram.png) + +The implementation detail of `fillInnerParts` method call is similar to `printReport`. -------------------------------------------------------------------------------------------------------------------- @@ -257,121 +832,1632 @@ _{Explain here how the data archiving feature will be implemented}_ **Target user profile**: -* has a need to manage a significant number of contacts +* is a tech-savvy computer repair shop technician. +* owns a business repairing computers and laptops, actively servicing multiple clients and answering their queries. +* has a need to manage a wide range of models and deals with both hardware and software issues. +* has multiple repair-phases which have to be updated to clients. * prefer desktop apps over other types * can type fast * prefers typing to mouse interactions * is reasonably comfortable using CLI apps -**Value proposition**: manage contacts faster than a typical mouse/GUI driven app +**Value proposition**: +* manages clients and jobs faster than a typical mouse/GUI driven app +* centralizes jobs and client information +* integrates both status tracking and client notification/mailing +* automates monthly reports and statistics generation ### User stories Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*` -| Priority | As a …​ | I want to …​ | So that I can…​ | -| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- | -| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App | -| `* * *` | user | add a new person | | -| `* * *` | user | delete a person | remove entries that I no longer need | -| `* * *` | user | find a person by name | locate details of persons without having to go through the entire list | -| `* *` | user | hide private contact details | minimize chance of someone else seeing them by accident | -| `*` | user with many persons in the address book | sort persons by name | locate a person easily | - -*{More to be added}* +| Priority | As a …​ | I want to …​ | So that I can…​ | +| -------- | ---------------------- | --------------------------------------------------------- | --------------------------------------------------------------------- | +| `*` | potential user | see the app populated with sample data | easily see how the app will look like when it is in use | +| `*` | user ready to start | purge all current data | Get rid of sample data and begin tinkering / exploring the app | +| `* *` | new user | view a guide | familiarize with the text-input commands | +| `* * *` | user | send out emails | easily notify clients that their repair job has been completed | +| `* * *` | user | create new jobs | begin tracking a new repair job | +| `* * *` | user | edit existing jobs | amend details pertaining to a job | +| `* * *` | user | create new contacts | notify a client of his/her job status (like completion, etc.) | +| `* * *` | user | edit existing contacts | change information about a client | +| `* * *` | user | link an existing contact to a job | reuse the contact information of a returning client for a new job | +| `* * *` | user | create new products | refer to the relevant details of how to repair a specific device | +| `* * *` | user | edit existing products | change repair details or method about a product | +| `* * *` | user | link an existing product to a job | reuse the product information of a previous for a new job | +| `* * *` | user | search for jobs using job status, service tag, client name or product name | find the jobs that match the specification | +| `* *` | regular user | print out monthly job records and statistics | learn about the month’s performance and analyze how to improve | +| `* *` | regular user | print out next month’s scheduled / on-going job | plan ahead resources for the coming month | +| `*` | regular user | hide unused job fields | not be distracted by empty / irrelevant fields. | +| `*` | regular user | hide unused contacts | not be distracted by irrelevant clients. | +| `*` | regular user | customize the app’s user interface (like font and colour) | make the interface look more stylish and pleasant for the eyes | +| `* *` | regular user | export my monthly records and statistics | store my record externally for future reference | ### Use cases -(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise) +(For all use cases below, the **System** is the `MyCRM` and the **Actor** is the `user`, unless specified otherwise) -**Use case: Delete a person** +**Use case: UC01 - Adding a repair job** **MSS** -1. User requests to list persons -2. AddressBook shows a list of persons -3. User requests to delete a specific person in the list -4. AddressBook deletes the person +1. User provides details to add a repair job. +2. MyCRM creates a new repair job with the provided job description and associates a repair job with + a product and contact. - Use case ends. + Use case ends. **Extensions** -* 2a. The list is empty. +* 1a. User does not provide all the necessary details needed for the creation of a job. + + * 1a1. MyCRM shows an error message and requests for the missing details. + * 1a2. User enters the missing details. + + Steps 1a1-1a2 are repeated until the user enters the details. Use case resumes at step 2. + +**Use case: UC02 - Editing a repair job** + +**MSS** + +1. User requests to edit a repair job. +2. MyCRM shows the list of repair jobs. +3. User selects a repair job from the list. +4. User provides details about fields they want to update. +5. MyCRM updates the fields of the repair job with the information provided. + + Use case ends. + +**Extensions** + +* 2a. The list of repair jobs is empty. Use case ends. -* 3a. The given index is invalid. +* 3a. User selects invalid repair job not in the list. - * 3a1. AddressBook shows an error message. + * 3a1. MyCRM shows an error message and asks user to re-select a repair job. + * 3a2. User re-selects a repair job. - Use case resumes at step 2. + Steps 3a1-3a2 are repeated until the user selects a valid repair job. Use case resumes at step 4. -*{More to be added}* +* 4a. The given fields provided by the User are invalid. -### Non-Functional Requirements + * 4a1. MyCRM shows an error message and asks user for the details they want to update again. + * 4a2. User provides the details they want to update. -1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. -2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. -3. 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. + Steps 4a1-4a2 are repeated until the user provided valid details. Use case resumes at step 5. -*{More to be added}* +**Use case: UC03 - Deleting a repair job** -### Glossary +**MSS** -* **Mainstream OS**: Windows, Linux, Unix, OS-X -* **Private contact detail**: A contact detail that is not meant to be shared with others +1. User requests to delete a repair job. +2. MyCRM shows a list of repair jobs. +3. User selects a repair job from the list which they want to delete. +4. MyCRM deletes the repair job. --------------------------------------------------------------------------------------------------------------------- + Use case ends. -## **Appendix: Instructions for manual testing** +**Extensions** -Given below are instructions to test the app manually. +* 2a. The list is empty. -
:information_source: **Note:** These instructions only provide a starting point for testers to work on; -testers are expected to do more *exploratory* testing. + Use case ends. -
+* 3a. User selects invalid repair job not in the list. -### Launch and shutdown + * 3a1. MyCRM shows an error message and asks user to re-select a repair job. + * 3a2. User re-selects a repair job they want to delete. -1. Initial launch + Steps 3a1-3a2 are repeated until the user selects a valid repair job. Use case resumes at step 4. - 1. Download the jar file and copy into an empty folder +**Use case: UC04 - Mark a repair job as completed** - 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum. +**MSS** -1. Saving window preferences +1. User requests to mark a repair job as completed. +2. MyCRM shows a list of repair jobs. +3. User selects a repair job from the list which they want to mark as completed. +4. MyCRM marks the repair job as complete, and hides the repair job from the job list. - 1. Resize the window to an optimum size. Move the window to a different location. Close the window. + Use case ends. - 1. Re-launch the app by double-clicking the jar file.
- Expected: The most recent window size and location is retained. +**Extensions** -1. _{ more test cases …​ }_ +* 2a. The list is empty. -### Deleting a person + Use case ends. -1. Deleting a person while all persons are being shown +* 3a. User selects invalid repair job not in the list. - 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list. + * 3a1. MyCRM shows an error message and asks user to re-select a repair job. + * 3a2. User re-selects a repair job they want to hide. - 1. Test case: `delete 1`
- Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. + Steps 3a1-3a2 are repeated until the user selects a valid repair job. Use case resumes at step 4. - 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. +* 3b. User selects a job that is already marked as completed. + * 3b1. MyCRM shows an error message telling the user the job has + already been marked as completed. - 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
- Expected: Similar to previous. + Use case ends. -1. _{ more test cases …​ }_ +**Use case: UC05 - List repair jobs** -### Saving data +**MSS** + +1. User requests to list all repair jobs. +2. MyCRM shows a list of repair jobs. + + Use case ends. + +**Extensions** + +* 2a. The list is empty. -1. Dealing with missing/corrupted data files + Use case ends. - 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_ +**Use case: UC06 - Find a repair job** + +**MSS** + +1. User wants to find a repair job and provides keywords they want to search by. +2. MyCRM shows a list of filtered repair jobs for which the keywords + appear in the job's description, contact or product. + + Use case ends. + +**Extensions** + +* 2a. No repair job matches any of the keywords provided by the user. + + Use case ends. + +**Use case: UC07 - Adding a client contact** + +**MSS** + +1. User requests to add a contact with specific info of name, contact number, address, and email. +2. MyCRM stores the new contact in the contact list. + + Use case ends. + +**Extensions** + +* 1a. The given contact name is empty. + + * 1a1. MyCRM shows an error message. + + Use case resumes at step 1. + +* 1b. Either the given contact number, address or email is empty. + + * 1b1. MyCRM shows an error message. + + Use case resumes at step 1. + +* 1c. The given contact name already exists. + + * 1c1. MyCRM shows an error message. + + Use case resumes at step 1. + +**Use case: UC08 - Editing a client contact** + +**MSS** + +1. User requests to edit a contact. +2. MyCRM shows a list of contacts. +3. User requests to edit a specific contact's info with specific index and type of the field in contact. +4. MyCRM updates this specific contact's info. + + Use case ends. + +**Extensions** + +* 2a. The list is empty. + + Use case ends. + +* 3a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + +* 3b. The given edit field type is invalid. + + * 3b1. MyCRM shows an error message. + + Use case resumes at step 2. + +**Use case: UC09 - Deleting a client contact** + +**MSS** + +1. User requests to delete a contact. +2. MyCRM shows a list of contacts. +3. User requests to delete a specific contact +4. MyCRM deletes the contact. + + Use case ends. + +**Extensions** + +* 2a. The list is empty. + + Use case ends. + +* 3a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + + +**Use case: UC10 - Hiding a client contact** + +**MSS** + +1. User requests to hide a contact. +2. MyCRM shows a list of contacts. +3. User requests to hide a specific contact in the list. +4. MyCRM tags the contact as hidden. + + Use case ends. + +**Extensions** + +* 2a. The list is empty. + + Use case ends. + +* 3a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + +**Use case: UC11 - Undo hiding a client contact** + +**MSS** + +1. User requests to undo hiding a hidden contact. +2. MyCRM shows a list of contacts. +3. User requests to undo hiding the specific contact in the list. +4. MyCRM undo the hidden tag for this contact. + + Use case ends. + +**Extensions** + +* 2a. The list is empty. + + Use case ends. + +* 3a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + +**Use case: UC12 - Sending an email** + +**Precondition:** Operating system has a default email application + +**MSS** + +1. User requests to send an email. +2. MyCRM shows a list of jobs. +3. User requests to email a specific job in the list. +4. MyCRM shows a list of email templates. +5. User requests to copy a specific email template. +6. MyCRM generates mailto link of the job and template + + Use case ends. + +**Extensions** + +* 2a. The list of jobs is empty. + + Use case ends. + +* 3a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + +* 3b. The job at given index does not have an email. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + +* 4a. The list of templates is empty. + + Use case ends. + +* 5a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 4. + +**Use case: UC13 - Adding an email template** + +**MSS** + +1. User requests to add an email template with specific subject and body. +2. MyCRM creates email template. + + Use case ends. + +**Extensions** + +* 1a. The given subject is empty. + + * 1a1. MyCRM shows an error message. + + Use case resumes at step 1. + +* 1b. The given subject is invalid format. + + * 1b1. MyCRM shows an error message. + + Use case resumes at step 1. + +* 1c. The given body is empty. + + * 1c1. MyCRM shows an error message. + + Use case resumes at step 1. + +**Use case: UC14 - Listing all email template** + +**MSS** + +1. User requests to view all email template. +2. MyCRM shows a list of email template. + + Use case ends. + +**Use case: UC15 - Listing all email template** + +**MSS** + +1. User request to find a template of specified subject keyword(s). +2. MyCRM shows a list of filtered template for which the keywords appear in the template's subject. + product. + + Use case ends. + + +**Use case: UC16 - Editing an email template** + +**MSS** + +1. User request to edit an email template. +2. MyCRM shows a list of email template. +3. User requests to edit a specific template's subject or body (or both) in the list. +4. MyCRM modifies the template with new subject or body (or both). + + Use case ends. + +**Extensions** + +* 2a. The list is empty. + + Use case ends. + +* 3a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + +* 3b. The given subject is empty + + * 3b1. MyCRM shows an error message. + + Use case resumes at step 2. + +* 3c. The given subject is invalid format. + + * 3c1. MyCRM shows an error message. + + Use case resumes at step 2. + +* 3d. The given body is empty. + + * 3d1. MyCRM shows an error message. + + Use case resumes at step 2. + +**Use case: UC17 - Deleting an email template** + +**MSS** + +1. User requests to delete an email template. +2. MyCRM shows a list of email template. +3. User requests to delete a specific template in the list. +4. MyCRM shows deletes the template. + + Use case ends. + +**Extensions** + +* 2a. The list is empty. + + Use case ends. + +* 3a. The given index is invalid. + + * 3a1. MyCRM shows an error message. + + Use case resumes at step 2. + +**Use case: UC18 - Finding an email template** + +**MSS** + +1. User wants to find an email template job and provides keywords they want to search by. +2. MyCRM shows a list of filtered templates for which the keywords appear in the template's subject. + + Use case ends. + +**Use case: UC19 - Viewing user guide** + +**MSS** + +1. User requests to view the user guide. +2. MyCRM shows a popup with the GitHub user guide URL. + + Use case ends. + +**Use case: UC20 - Exiting the program** + +**Postcondition:** MyCRM application closes. + +**MSS** + +1. User requests to exit MyCRM. +2. MyCRM shows a goodbye message. + + Use case ends. + +**Use case: UC21 - Clearing MyCRM data** + +**Postcondition:** MyCRM data of contacts, products, and templates are empty. + +**MSS** + +1. User request to clear data. +2. MyCRM removes data from job, contact, product list. + + Use case ends. + +**Use case: UC22 - Add Product** + +**MSS** + +1. User requests to add a new product. +2. MyCRM creates a new product and shows a message with info of the product. + + Use case ends. + +**Extensions** + +* 2a. The product name already exists. + * MyCRM shows an error message. + + Use case ends. + + +* 2b. The product name is empty. + * MyCRM shows an error message. + + Use case ends. + +**Use case: UC23 - List Products** + +**MSS** + +1. User requests to view the list of products. +2. MyCRM shows the list of products. + + Use case ends. + +**Extensions** +* 2a. The list of products is empty. + + Use case ends. + +**Use case: UC24: Delete a product** + +**MSS** + +1. User requests to delete a specific product in the list. +2. MyCRM deletes the product. + + Use case ends. + +**Extensions** + +* 1a. The given index is invalid. + * 1a1. MyCRM shows an error message. + + Use case ends. + +* 1b. The specified product is linked to one or more jobs. + * 1b1. MyCRM shows an error message. + + Use case ends. + +**Use case: UC25: Edit a product.** + +**MSS** + +1. User requests to edit a specific product in the list. +2. MyCRM edits the product and shows a success message with info of edited product. + + Use case ends. + +**Extensions** + +* 1a. The given index is invalid. + * 1a1. MyCRM shows an error message. + + Use case ends. + +* 1b. User requests to edit the name of the product. + * 1b1. The product name already exists + * 1b2. MyCRM shows an error message. + + Use case ends. + +* 1c. All fields that user provides are empty. + * 1c1. MyCRM shows an error message. + + Use case ends. + +**Use case: UC26 - Retrieve Previous Command** + +**MSS** + +1. User requests to retrieve previously entered command. +2. MyCRM shows the previous command. + + Use case ends. + +**Extensions** +* 2a. MyCRM show the most recent command. + + Use case ends. + +* 2b. MyCRM list all history commands. + + Use case ends. + +**Use case: UC27 - Change the theme of user interface(UI)** + +**MSS** + +1. User requests to change the theme of UI. +2. MyCRM changes the theme of Ui. + + Use case ends. + +**Extensions** +* 1a. User enters a theme name that does not exist in MyCRM. + * 1a1. MyCRM shows an error message. + + Use case ends. + +* 1b. User enters the name of current theme. + * 1a1. MyCRM keeps the current theme. + + Use case ends. + +**Use case: UC28 - Print out monthly job records and statistics** + +**MSS** + +1. User requests to print out monthly job report. +2. MyCRM shows the monthly job report in a new window. + + Use case ends. + +**Extensions** +* 1a. User requests to print out monthly job report when report window is not shown. + * 1a1. MyCRM shows the report window. + + Use case ends. + +* 1b. User requests to print out monthly job report when report window is shown. + * 1b1. MyCRM focuses on the report window. + + Use case ends. + +**Use case: UC29 - Export monthly job records and statistics** + +**MSS** + +1. User requests to export monthly job report. +2. MyCRM show the page setup dialog and print dialog. + + +### Non-Functional Requirements + +1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. +2. Should be able to hold up to 100 _entries_ without a noticeable sluggishness in performance for typical usage. +3. Should be designed for a single-user. +4. Should work without an internet connection. +5. Should be accessible via the downloaded JAR file without any other installations needed. +6. Should take up less than 50 MB computer storage. +7. Should work on both 32-bit and 64-bit environments. +8. 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. + +### Glossary + +* **Mainstream OS**: Windows, Linux, Unix, OS-X. +* **Private contact detail**: A contact detail that is not meant to be shared with others. +* **Repair Job**: A customer request to restore machinery, equipment, or other products to working order. +* **Job Status**: A progress bar showing the customer's job's degree of completion. +* **JSON**: Javascript Standard Object Notation, which is a form of syntax used for storing data. +* **mailto**: A Uniform Resource Identifier scheme for email addresses, produces hyperlinks on websites that allow + users to send an email. +* **URL**: A Uniform Resource Locators is a unique identifier commonly used to access a resource on the Internet. +* **Entry**: Contact/job/product. + +-------------------------------------------------------------------------------------------------------------------- + +## **Appendix: Instructions for manual testing** + +Given below are instructions to test the app manually. + +
:information_source: **Note:** These instructions only provide a starting point for testers to work on; +testers are expected to do more *exploratory* testing. + +
+ +### Launch + +1. Initial launch + + 1. Download the jar file and copy into an empty folder + + 2. Double-click the jar file. +
Expected: Shows the GUI with a set of sample contacts, products, templates and job. The window size may + not be optimum. + +2. Saving window preferences + + 1. Resize the window to an optimum size. Move the window to a different location. Close the window. + + 2. Re-launch the app by double-clicking the jar file. +
Expected: The most recent window size and location is retained. + +1. Saving theme preferences + + 1. [Choose a theme](UserGuide.md#changing-the-theme-of-user-interface-theme) of GUI. Close the window. + + 1. Re-launch the app by double-clicking the jar file.
+ Expected: The most recent theme is retained. + +### Shutdown + +1. Exiting application + + 1. Test case: `exit` +
Expected: GUI closes and application is shutdown. + + 2. Test case: Click the exit 'x' (cross) +
Expected: Similar to previous + +### Requesting help + +1. Opening help page + + 1. Test case: `help` +
Expected: Shows the help GUI with user guide details. + + 2. Test case: Press F1 +
Expected: Similar to previous + + 3. Test case: Click "Help" > "Help F1" +
Expected: Similar to previous + +### Adding contact + +1. Inserting a contact while all contacts are being shown. + + 1. Prerequisites: List contacts using the `listContact` command. Shows list of contacts in side panel. + + 2. Test case: `addContact n/Jack Ryan c/94678954 a/Blk 65 Tampines Ave 1 e/jryan@gmail.com` +
Expected: + - New contact is added to the list. + - Details of contact shown in status message. + + 3. Test case: `addContact n/Sans c/85230240 a/Clementi Ave 1 e/Sans@gmail.com` +
Expected: + - New contact is added to the list. + - Details of contact shown in status message. + + 4. Test case: `addContact n/Jack Ryan c/94678954 a/Blk 65 Tampines Ave 1 e/jryan@gmail.com` +
Expected: + - No new contact is added + - Command error for duplicate contact is shown in status message. + + 5. Test case: `addContact n/Jay` +
Expected: + - Similar to previous. + - Command error for at least one field of phone, email and address required is shown in status message. + + 6. Test case: `addContact n/Jay&sda c/83336233` +
Expected: + - Similar to previous. + - Command error for name format details is shown in status message. + + 7. Test case: `addContact n/Jay c/abcd` +
Expected: + - Similar to previous. + - Command error for phone format details is shown in status message. + + 8. Test case: `addContact n/Jay e/abcd` +
Expected: + - Similar to previous. + - Command error for email format details is shown in status message. + + 9. Test case: `addContact n/Jay a/` +
Expected: + - Similar to previous. + - Command error for address format details is shown in status message. + +2. Inserting a contact while all contacts are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all contacts. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel remains at current list. No new contacts are added. + +### Editing a contact + +1. Editing a contact while all contacts are being shown. + + 1. Prerequisites: List contacts using the `listContact` command. Shows list of contacts in side panel. + + 2. Test case: `editContact 1 n/Jacky e/Jacky@gmail.com` +
Expected: + - Contact index 1 is updated in the list. + - Details of contact shown in status message. + + 3. Test case: `editContact 2 n/Jacky` +
Expected: + - No contact is edited. + - Command error for duplicate contact is shown in status message. + + 4. Test case: `editContact 1` +
Expected: + - Similar to previous. + - Command error for at least one field of name, phone, email, address or tag required is shown in status message. + + 5. Test case: `editContact 1 n/Jay&sda` +
Expected: + - Similar to previous. + - Command error for name format details is shown in status message. + + 6. Test case: `editContact 1 c/abcd` +
Expected: + - Similar to previous. + - Command error for phone format details is shown in status message. + + 7. Test case: `editContact 1 e/abcd` +
Expected: + - Similar to previous. + - Command error for email format details is shown in status message. + + 8. Test case: `editContact 1 a/` +
Expected: + - Similar to previous. + - Command error for address format details is shown in status message. + +2. Editing a contact while all contacts are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all contacts. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel remains at current list. No new contacts are edited. + + +### Deleting a contact + +1. Deleting a contact while all contacts are being shown. + + 1. Prerequisites: List contacts using the `listContact` command. Shows list of contacts in side panel. + + 2. Prerequisites: No contacts are linked to a job. + + 3. Test case: `deleteContact 1` +
Expected: + - Contact index 1 is deleted in the list. + - Details of contact shown in status message. + + 4. Test case: `deleteContact -1` +
Expected: + - Similar to previous. + - Command error for invalid index is shown in status message. + +2. Deleting a contact while all contacts are being shown. + + 1. Prerequisites: List contacts using the `listContact` command. Shows list of contacts in side panel. + + 2. Prerequisites: All contacts are linked to a job. + + 3. Test case: `deleteContact 1` +
Expected: + - No contacts are deleted. + - Command error for invalid contact deletion requirement is shown in status message. + + 4. Test case: `deleteContact -1` +
Expected: + - Similar to previous. + - Command error for invalid index is shown in status message. + +3. Deleting a contact while all contacts are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Prerequisites: No contacts are linked to a job. + + 3. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list updated contact list. + + 4. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel remains at current list. No contacts are deleted. + + +### Finding contacts + +1. Finding contacts while all contacts are being shown. + + 1. Prerequisites: List contacts using the `listContact` command. Shows list of contacts in side panel. + + 2. Test case: `findContact Jacky` +
Expected: + - Matching contacts are shown on list. + - Number of contacts found shown in status message. + + 3. Test case: `findContact abcd` +
Expected: + - No matching contacts are shown on list. + - Zero contacts found shown in status message. + +2. Finding contacts while all contacts are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list matching all contacts. + +### Hiding contacts + +1. Hiding a contact while all contacts are being shown. + + 1. Prerequisites: List contacts using the `listContact` command. Shows unhidden list of contacts in side panel. + + 2. Test case: `hideContact 1` +
Expected: + - Contact 1 is hidden on list. + - Side panel will update list of all not hidden contacts. + + 3. Test case: `hideContact -1` +
Expected: + - No contact is hidden on list. + - Side panel will remain the current contact list. + +2. Hiding a contact while all contacts are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will update contact list. + + 3. Incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will remain current contact list. + +### Undoing hiding contacts + +1. Undo hiding a contact while all contacts are being shown. + + 1. Prerequisites: List contacts using the `listContact -a` command. Shows unhidden list of contacts in side panel. + + 2. Test case: `undoHideContact 1` +
Expected: + - Contact 1 is hidden on list. + - Side panel will update list of all not hidden contacts. + + 3. Test case: `undoHideContact -1` +
Expected: + - No contact is hidden on list. + - Side panel will remain the current contact list. + +### Listing contacts + +1. Test case: `listContact` +
Expected: + - Side panel will list all not hidden contacts. + +2. Test case: `listContact -a` +
Expected: + - Side panel will list all contacts. + +3. Test case: `listContact abcd` +
Expected: + - Side panel will remain current list. + - Command error for invalid listContact format is shown in status message. + + +### Constructing mail + +1. Constructing a mail when there is at least one job and mail. + + 1. Prerequisites: There must be at least one job and mail in MyCRM. `addJob`, `addTemplate` + + 2. Test case: `mail j/1 t/1` +
Expected: + - New mail is added to MyCRM with first job and template. + - Details of mail shown in status message. + - Details of mail shown in main panel with mailtoURL. + + 3. Test case: `mail j/1` +
Expected: + - No mail is constructed. + - Format error details is shown in status message. + + 4. Test case: `mail t/1` +
Expected: + - Similar to previous + + 5. Test case: `mail j/0 t/0` +
Expected: + - Similar to previous + - Index error details is shown in status message. + + 6. Test case: `mail j/1 t/-1` +
Expected: + - Similar to previous + +### Adding template + +1. Inserting a template while all templates are being shown. + + 1. Prerequisites: List all templates using the `listTemplate` command. Shows list of templates in side panel. + + 2. Test case: `addTemplate s/ANewTemplate b/This is a new template!` +
Expected: + - New template is added to the list. + - Details of template shown in status message. + + 3. Test case: `addTemplate s/A New Template b/This is a new template!\nRegards` +
Expected: + - Similar to previous + - New template body will represent '\n' as a newline. + + 4. Test case: `addTemplate s/Completed b/Your order has been completed` +
Expected: + - No template is added. + - Duplicate error details is shown in status message. + + 5. Test case: `addTemplate s/!Inv@lid b/Your order has been completed` +
Expected: + - Similar to previous + - Subject error details is shown in status message. + + 6. Test case: `addTemplate s/Valid subject b/` +
Expected: + - Similar to previous + - Body error details is shown in status message. + +2. Inserting a template while all templates are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listProduct` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all templates. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will NOT list all templates. Remains at current list. + +### Editing template + +1. Editing a template while all templates are being shown. + + 1. Prerequisites: List all templates using the `listTemplate` command. Shows list of templates in side panel. + + 2. Test case: `editTemplate 1 s/New Completed` +
Expected: + - First template is updated to the list. + - Details of template shown in status message. + + 3. Test case: `editTemplate 1 b/New Body` +
Expected: + - Similar to previous. + + 4. Test case: `editTemplate 1 s/Brand New Completed b/Brand New Body` +
Expected: + - Similar to previous. + + 5. Test case: `editTemplate 1 s/!Inv@lid` +
Expected: + - No template is edited. + - Subject error details is shown in status message. + + 6. Test case: `editTemplate 1 b/ ` +
Expected: + - Similar to previous + - Body error details is shown in status message. + + 7. Test case: `editTemplate 0 s/3rd New Completed b/3rd New Body` +
Expected: + - Similar to previous + - Format error details is shown in status message. + +2. Editing a template while all templates are not shown. + + 1. Prerequisites: List other data types i.e. `listProduct` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all templates. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will NOT list all templates. Remains at current list. + +### Deleting template + +1. Deleting a template while all templates are being shown. + + 1. Prerequisites: List all templates using the `listTemplate` command. Shows list of templates in side panel. + + 2. Test case: `deleteTemplate 1` +
Expected: + - First template is deleted to the list. + - Details of template shown in status message. + + 3. Test case: `deleteTemplate 0` +
Expected: + - Similar to previous + - Format error details is shown in status message. + +2. Deleting a template while all templates are not shown. + + 1. Prerequisites: List other data types i.e. `listProduct` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all templates. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will NOT list all templates. Remains at current list. + +### Finding template + +1. Finding a template while all templates are being shown. + + 1. Prerequisites: List all templates using the `listTemplate` command. Shows list of templates in side panel. + + 2. Test case: `findTemplate Done` +
Expected: + - Matching templates are shown on list. + - Number of template found shown in status message. + + 3. Test case: `findTemplate Done New Template` +
Expected: + - Similar to previous + + 3. Test case: `findTemplate $` +
Expected: + - No matching templates are shown on list. + - Zero templates found shown in status message. + +2. Finding a template while all templates are not shown. + + 1. Prerequisites: List other data types i.e. `listProduct` command. Shows list of other data in side panel. + + 2. Test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all templates. + +### Saving data + +1. Dealing with missing data files + + 1. To simulate a missing file, delete the myCrm.json file from the data directory. + 2. Re-launch the app by double-clicking the jar file. +
Expected: The application will generate a new myCrm.json with sample data. + +2. Dealing with corrupted data files + + 1. To simulate a corrupted file, open the myCrm.json file from data directory. + 2. Delete line 2 from the file. + 3. Re-launch the app by double-clicking the jar file. +
Expected: The application will not load any data, empty content. + +3. Customising with JSON data file + + 1. Test case: Customising contact + 1. Open the myCrm.json file from data directory. + 2. Modify first contact name i.e.'Damith Rajapakse' + 3. Re-launch the app by double-clicking the jar file. +
Expected: The application will load data, first contact name is modified. + + 2. Test case: Customising template + 1. Similar to previous + 2. Modify first subject i.e.'Welcome newcomer' +
Expected: The application will load data, first subject is modified. + + 3. Test case: Customising product + 1. Similar to previous + 2. Modify first product type i.e.'Computer Unit' +
Expected: The application will load data, first product type is modified. + + 4. Test case: Customising job + 1. Similar to previous + 2. Modify first job fee i.e.'$100.00' +
Expected: The application will load data, first job fee is modified. + + 5. Other correct test cases: Customising contact, template, product, job + 1. Similar to adding correct contact, template, product, job test case +
Expected: The application will load data, data is modified. + + 6. Other incorrect test cases: Customising contact, template, product, job + 1. Similar to adding incorrect contact, template, product, job test case +
Expected: The application will not load any data, empty content. + +### Adding product + +1. Inserting a product while all products are being shown + + 1. Prerequisites: List all products using the `listProduct` command. Shows list of products in side panel. + + 2. Test case: `addProduct n/new product one t/GPU m/Asus` +
Expected: + - New product is added to the list. + - Details of product shown in status message. + + 3. Test case: `addProduct n/new product two` +
Expected: + - Similar to previous. + + 4. Test case: `addProduct n/ t/CPU m/Intel` +
Expected: + - No product is added. + - Format error details is show in status message. + + 5. Test case: `addProduct n/duplicate_product_name t/Motherboard m/Asus` +
Expected: + - No product is added. + - Duplicate error details is shown in status message. + +2. Inserting a product while all products are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all products. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will NOT list all products. Remains at current list. + +### Editing product + +1. Editing a product while all products are being shown + + 1. Prerequisites: List all products using the `listProduct` command. Shows list of products in side panel. + + 2. Test case: `editProduct 2 d/Video output interface: DisplayPort, HDMI` +
Expected: + - Second product is updated to the list. + - Details of product shown in status message. + + 3. Test case: `editProduct 2 m/GIGABYTE` +
Expected: + - Similar to previous. + + 4. Test case: `editProduct 2 n/duplicate product name` +
Expected: + - No product is edited. + - Duplicate error details is shown in status message. + + 5. Test case: `editProduct 0 m/GIGABYTE` +
Expected: + - No product is edited. + - Format error details is show in status message. + +2. Editing a product while all products are NOT being shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all products. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will NOT list all products. Remains at current list. + +### Deleting Product + +1. Deleting a product while all products are being shown. + + 1. Prerequisites: List all products using the `listProduct` command. Shows list of products in side panel. + + 2. Test case: `deleteProduct 1` +
Expected: + - First product is deleted to the list. + - Details of product shown in status message. + + 3. Test case: `deleteProduct 0` +
Expected: + - No product is deleted. + - Format error details is shown in status message. + +2. Deleting a product while all products are not shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Correct test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all products. + + 3. Other incorrect test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will NOT list all products. Remains at current list. + +### Finding product + +1. Finding a product while all products are being shown. + + 1. Prerequisites: List all products using the `listProduct` command. Shows list of products in side panel. + + 2. Test case: `findProduct Asus` +
Expected: + - Matching products are shown on list. + - Number of product found shown in status message. + + 3. Test case: `findProduct Asus gpu` +
Expected: + - Similar to previous + + 3. Test case: `findProduct @` +
Expected: + - No matching products are shown on list. + - Zero products found shown in status message. + +2. Finding a product while all products are not shown. + + 1. Prerequisites: List other data types i.e. `listTemplate` command. Shows list of other data in side panel. + + 2. Test cases similar to (1) +
Expected: + - Similar to (1) + - Side panel will list all products. + +### Adding job + +1. Inserting a new job while all in-progress jobs are being shown. + + 1. Prerequisites: List all in-progress jobs using the `listJob` command. Shows list of in-progress jobs in the main panel. + At least 1 contact and product must be present for below test cases. + + 3. Test case: `addJob d/CPU replacement needed fee/$30.00 recv/08/11/2021 by/03/01/2022 c/1 p/1` +
Expected: + - New job is added to the job list. Job should be linked to first contact displayed currently in the + contact list and first product currently displayed in the product list. + - Details of job added shown in status message. + + 4. Test case: `addJob d/CPU fix needed fee/$30.00 by/03/01/2022 c/1 p/1` +
Expected: + - New job is added to the job list. Job should be linked to first contact currently displayed in the + contact list and first product currently displayed in the product list. + - Details of job added shown in status message. + - Since received date wasn't provided it should be automatically set to the current date. + + 5. Test case: `addJob d/CPU fix needed fee/$30.00 by/03/01/2022 c/1 p/1` +
Expected: + - No new job is added (provided the previous test case was run first) + - Error for duplicate job is shown in status message. + + 6. Test case: `addJob d/CPU replacement fee/$30.00` +
Expected: + - No new job is added + - Invalid command format error shown + + 7. Test case: `addJob d/CPU replacement by/03/01/2021` +
Expected: + - No new job is added + - Invalid command format error shown + + 8. Test case: `addJob fee/$30.00 by/03/01/2022` +
Expected: + - No new job is added + - Invalid command format error shown + + 9. Test case: + Input these 3 commands one after another: + - `addJob d/Upgrade CPU fee/$100.00 by/05/01/2022` + - `select 1` + - `select 1` +
Expected: + - New job is added to the job list. Job should be linked to first contact currently displayed in the + contact list and first product currently displayed in the product list. + - Details of job added shown in status message. + +2. Inserting a job while all completed jobs are being shown. + + 1. Prerequisites: List all completed jobs using the `listJob -c` command. Shows list of completed jobs in the main panel. + + 2. Test Case : `addJob d/CPU not working fee/$30.00 recv/08/11/2021 by/03/01/2022 c/1 p/1` +
Expected: + - Main panel will switch to show all in-progress jobs. + - New in-progress job is added to the job list. Job should be linked to first contact currently displayed in the + contact list and first product currently displayed in the product list. + - Details of job added shown in status message + +### Editing a job + +1. Editing an in-progress job. + + 1. Prerequisites: List all in-progress jobs using the `listJob` command. Shows list of in-progress jobs in the main panel. + Must have at least 1 in-progress job in the list for below test cases to work. + + 2. Test case: `editJob 1 fee/$1000.00` +
Expected: + - Job at index 1 in the currently displayed job list, should have its fee updated accordingly. + - Details of job edited shown in status message. + + 3. Test case: `editJob 1 d/CPU Slow` +
Expected: + - Job at index 1 in the currently displayed job list, should have its description updated accordingly. + - Details of job edited shown in status message. + + 4. Test case: `editJob 1` +
Expected: + - Job at index 1 in the currently displayed job list, should not be edited. + - Error shown saying at least one field to edit must be provided. + +2. Editing a completed job + + 1. Prerequisites: List all completed jobs using the `listJob -c` command. Shows list of completed jobs in the main panel. + Must have at least 1 completed job in the list for below test cases to work. + + 2. Test case: `editJob 1 d/Completed repair for CPU` +
Expected: + - Job at index 1 in the currently displayed job list, should have its description updated accordingly. + - Details of job edited shown in status message. + +### Deleting a job + +1. Deleting an in-progress job + + 1. Prerequisites: List all in-progress jobs using the `listJob` command. Shows list of in-progress jobs in the main panel. + Must have at least 1 in-progress job in the list for below test cases to work. + + 2. Test case: `deleteJob 1` +
Expected: + - Job at index 1 in the currently displayed job list is deleted. + - Details of deleted job shown in status message. + + 3. Test case: `deleteJob -1` +
Expected: + - No jobs are deleted. + - Invalid command format error shown. + +2. Deleting a completed job. + + 1. Prerequisites: List all completed jobs using the `listJob -c` command. Shows list of completed jobs in the main panel. + Must have at least 1 completed job in the list for below test cases to work. + + 2. Test case: `deleteJob 1` +
Expected: + - Job at index 1 in the currently displayed job list is deleted. + - Details of deleted job shown in status message. + - Job list should continue to show list of all completed jobs. (Or an empty list if the only completed job was deleted) + +### Finding jobs + +1. Test case: `findJob CPU` +
Expected: + - Matching jobs (both in-progress and completed) are shown on list. + - Number of jobs found shown in status message. + +### Marking job as complete + +1. Marking an in-progress job as complete. + + 1. Prerequisites: Prerequisites: List all in-progress jobs using the `listJob` command. Shows list of in-progress jobs in the main panel. + Must have at least 1 in-progress job in the list for below test cases to work. + + 2. Test case: `completeJob 1 10/01/2022` +
Expected: + - Job at index 1 in the currently displayed job list will be marked as complete, and will disappear from the current job + list displaying all in-progress jobs. + - Details of completed job shown in status message. + +2. Marking a completed job as complete. + + 1. Prerequisites: List all completed jobs using the `listJob -c` command. Shows list of completed jobs in the main panel. + Must have at least 1 completed job in the list for below test cases to work. + + 2. Test case: `completeJob 1` +
Expected: + - Job at index 1 in the currently displayed job list remains unchanged. + - Error message informing user that the job has already been completed is shown. + +### Revert completion status of a previously complete job + +1. Revert completion status of an in-progress job. + + 1. Prerequisites: Prerequisites: List all in-progress jobs using the `listJob` command. Shows list of in-progress jobs in the main panel. + Must have at least 1 in-progress job in the list for below test cases to work. + + 2. Test case: `undoCompleteJob 1` +
Expected: + - Job at index 1 in the currently displayed job list remains unchanged. + - Error message informing user that the job has not been completed yet is shown. + +2. Revert completion status of a completed job. + + 1. Prerequisites: List all completed jobs using the `listJob -c` command. Shows list of completed jobs in the main panel. + Must have at least 1 completed job in the list for below test cases to work. + + 2. Test case: `undoCompleteJob 1` +
Expected: + - Completion status of Job at index 1 in the currently displayed job list reverted. + - Details of job whose completion status was reverted is shown. + + +### Listing jobs + +1. Test case: `listJob` +
Expected: + - Main panel will list all in-progress jobs. + +2. Test case: `listJob -a` +
Expected: + - Main panel will list all jobs (completed and in-progress). + +3. Test case: `listJob -c` +
Expected: + - Main panel will list all completed jobs. + +### Retrieving history command + +1. Retrieving all history commands in a list. + + 1. Test case: `history` +
Expected: + - All previously entered commands are shown in side panel. + +2. Retrieving the most recent history command. + + 1. Prerequisites: At least two commands are entered i.e. `listProduct`, `anything`, etc. + + 2. Test case: "Press up arrow key" +
Expected: + - The most recent history command will appear in command box. + + 3. Test case: "Press up arrow key twice" +
Expected: + - The command before the last one will appear in command box. + + 4. Test case: "Press up arrow key twice and then press down arrow key" +
Expected: + - The last entered command will appear in command box. + +### Printing out monthly job report + +1. Printing out monthly job report while report window is not shown. + + 1. Prerequisites: At least one contact is added to MyCRM +
i.e. `addContact n/Sans c/83921823 e/Sans@gmail.com a/Maxwell Chambers 32 Maxwell Rd` +
two jobs are added to MyCRM +
i.e. `addJob d/Change CPU fee/$50 by/10/11/2021 c/1 p/2`, `addJob d/Change GPU fee/$55 by/11/11/2021 c/1 p/1` +
and two products are added to MyCRM. +
i.e. `addProduct n/Asus DUAL-GTX1060-O6G t/GPU m/Asus`, `addProduct n/Intel i5-10400F t/CPU m/Intel d/2.90GHz` +
Then marking one job as completed +
i.e. `completeJob 1` + + 2. Test case: `printReport` +
Expected: + - The report window will pop up. + - The report window will show the monthly completed jobs in a list and a bar graph indicating the monthly revenue for last four months of this year and last year. + + 3. Test case: `printReport -i` +
Expected; + - The report window will pop up. + - The report window will show the incompleted jobs received in this month and a bar graph similar to last test case. + + 4. Test case: `printReport -p` +
Expected: + - The report window will pop up. + - The report window will show the top three popular product received in this month and a bar graph similar to last test case. + +2. Printing out monthly job report while report window is shown but minimized. + + 1.Prerequisites: Similar to (1) but minimize the report window. + + 2. Test case similar to (1) +
Expected: + - Similar to (1) + - The report window is focused. + +### Exporting monthly job report + +1. Exporting monthly job report while report window is opened. + + 1. Prerequisites: Open report window i.e. `printReport`. + + 2. Test case: "Click on the Print button" +
Expected: + - MyCRM will show a page setup page and print page (on WindowsOS). + - MyCRM will show a print page (on MacOS). + +2. Exporting monthly job report while report window is not opened. + + 1. Prerequisites: Not open report window beforehand. + + 1. Test case: `exportReport` +
Expected: + - Similar to (1), + +
:information_source: **Note:** *Print* button might not always work for MacOS users. + +
-1. _{ more test cases …​ }_ diff --git a/docs/SettingUp.md b/docs/SettingUp.md index 275445bd551..3d62bbe3982 100644 --- a/docs/SettingUp.md +++ b/docs/SettingUp.md @@ -23,7 +23,7 @@ If you plan to use Intellij IDEA (highly recommended): 1. **Import the project as a Gradle project**: Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html) to import the project into IDEA.
:exclamation: Note: Importing a Gradle project is slightly different from importing a normal Java project. 1. **Verify the setup**: - 1. Run the `seedu.address.Main` and try a few commands. + 1. Run the `seedu.mycrm.Main` and try a few commands. 1. [Run the tests](Testing.md) to ensure they all pass. -------------------------------------------------------------------------------------------------------------------- diff --git a/docs/Testing.md b/docs/Testing.md index 8a99e82438a..961ddf9cd33 100644 --- a/docs/Testing.md +++ b/docs/Testing.md @@ -29,8 +29,8 @@ There are two ways to run tests. This project has three types of tests: 1. *Unit tests* targeting the lowest level methods/classes.
- e.g. `seedu.address.commons.StringUtilTest` + e.g. `seedu.mycrm.commons.StringUtilTest` 1. *Integration tests* that are checking the integration of multiple code units (those code units are assumed to be working).
- e.g. `seedu.address.storage.StorageManagerTest` + e.g. `seedu.mycrm.storage.StorageManagerTest` 1. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together.
- e.g. `seedu.address.logic.LogicManagerTest` + e.g. `seedu.mycrm.logic.LogicManagerTest` diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3716f3ca8a4..14071e18e17 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -3,41 +3,51 @@ layout: page title: User Guide --- -AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps. +MyCRM is a **desktop application for managing client contacts, repair job statuses, and product information that has +been optimised for use via a Command Line Interface (CLI)** while maintaining the benefits of a Graphical User Interface +(GUI). If you type quickly, MyCRM can complete customer relationship management tasks faster than traditional GUI +applications. + +**Target Audience:** Tech savvy computer repair shop technician. Owns a business repairing computers and laptops, +actively servicing multiple clients and answering their queries. Services a wide range of models and deals with both +hardware and software issues. Also has multiple repair-phases which have to be updated to clients. + * Table of Contents {:toc} -------------------------------------------------------------------------------------------------------------------- - +
## Quick start 1. Ensure you have Java `11` or above installed in your Computer. -1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases). +2. Download the latest `MyCRM.jar` from [here](https://github.com/AY2122S1-CS2103-T14-3/tp/releases). -1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. +3. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. -1. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
+4. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the + app contains some sample data.
![Ui](images/Ui.png) -1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
+5. Type the command in the command box and press Enter to execute it.
Some example commands you can try: - * **`list`** : Lists all contacts. + * **`listContact `** : Lists all contacts. - * **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book. + * **`addContact `**`n/John Doe c/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact + named `John Doe` to the CRM. - * **`delete`**`3` : Deletes the 3rd contact shown in the current list. + * **`deleteContact `**`1` : Deletes the 1st contact shown in the current list. - * **`clear`** : Deletes all contacts. + * **`clear`** : Deletes all contacts, jobs and products in MyCRM. * **`exit`** : Exits the app. -1. Refer to the [Features](#features) below for details of each command. +6. Refer to the [Features](#features) below for details of each command. -------------------------------------------------------------------------------------------------------------------- - +
## Features
@@ -54,139 +64,636 @@ AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized fo e.g. `[t/TAG]…​` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. * Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. + e.g. if the command specifies `n/NAME c/PHONE_NUMBER`, `c/PHONE_NUMBER n/NAME` is also acceptable. -* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence of the parameter will be taken.
- e.g. if you specify `p/12341234 p/56785678`, only `p/56785678` will be taken. +* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence + of the parameter will be taken.
+ e.g. if you specify `c/12341234 c/56785678`, only `c/56785678` will be taken. -* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`. +* Extraneous parameters for commands that do not take in parameters (such as `listJob`, `listProduct`, and `exit` + ) will be ignored.
+ e.g. if the command specifies `listJob 123`, it will be interpreted as `listJob`.
-### Viewing help : `help` +### Adding a job: `addJob` + +Adds a new repair job to the CRM. + +Format: `addJob d/DESCRIPTION by/EXPECTED_COMPLETION_DATE fee/FEE [recv/RECIEVED_DATE] [c/CONTACT_INDEX] [p/PRODUCT_INDEX]` +Format of special subcommands: `select INDEX` and `abort` (details on subcommand usage below) + +* Creates a new repair job. +* Links the contact and product that correspond to `CONTACT_INDEX` and `PRODUCT_INDEX` (in the respective contact + and product list) to the job. +* `EXPECTED_COMPLETION_DATE` refers to the date by which the repair expected to be completed. +* `FEE` refers to the repair fee charged to the client. +* `RECIEVED_DATE` refers to the date the repair job request was received from the client. If not provided, it is by default, + set to the date the job is created in MyCRM. +* Both product and contact are compulsory attributes of job. If they are not provided + in the form of an index in the above command, the job is not immediately added. + * Instead, in such a case, the user will be asked for info on the missing contact or product (or both). + * User can choose to create a new contact/product and immediately assign it to the job currently being created + via the `addContact` and `addProduct` commands. + * Or the user can issue a command `select INDEX` to select an item from its displayed list. + * While the user is being asked for a contact/product only selected commands will be allowed + (namely the list, find and add commands for either product or contact). + * The user can choose to stop this operation and not add any new job by issuing a `abort` command. + * Note: The user is asked for the contact and product one after the other. i.e If asked for the contact first + user cannot select or create a product instead. + * Note: If the operation is stopped via the `abort` command, the job will not be added but any new products/contacts + created through the `addContact` and `addProduct` commands will still be added. -Shows a message explaning how to access the help page. +Examples: -![help message](images/helpMessage.png) +* To add a job with a pre-existing contact and product +* Either the command `addJob d/Change CPU fee/$50 by/10/11/2021 c/1 p/1` can be issued OR +* The following sequence of commands can be issued: + * `addJob d/Change CPU fee/$50 by/10/11/2021` + * `select 1` (to select contact) + * `select 1` (to select product) + + + +* To add a job with a new contact and product +* Issue the following sequence of commands: + * `addJob d/Change CPU fee/$50 by/10/11/2021` + * `addContact n/Jack Ryan c/94678954 a/Blk 65 Tampines Ave 1 e/jryan@gmail.com` + * `addProduct n/Asus DUAL-GTX1060-O6G t/GPU m/Asus d/DisplayPort, HDMI` + + + +### Editing a job: `editJob` + +Edits an existing repair job to the CRM. + +Format: `editJob INDEX [d/DESCRIPTION] [by/EXPECTED_COMPLETION_DATE] [fee/FEE] [recv/RECIEVED_DATE] [c/CONTACT_INDEX] [p/PRODUCT_INDEX]` +Format of special subcommands: `select INDEX` and `abort` (details on subcommand usage below) + +* Edits the repair job at the specified `INDEX` +* `INDEX` refers to the index of the repair job as shown in the repair job listing +* `INDEX` must be a positive integer(1,2,3…) +* It is possible to not indicate the `CONTACT_INDEX` or `PRODUCT_INDEX`. i.e A command like `editJob INDEX c/ p/` is valid. + * In such a case the user will be asked for info which product or contact (or both) + they now want to assign to the job. + * User can choose to create new contact/product and immediately assign it via + the `addContact` and `addProduct` commands. + * Or the user can issue a command `select INDEX` to select an item from the displayed list. + * While the user is being asked for a contact/product only selected commands will be allowed + (namely the list, find and add commands for either product or contact). + * The user can choose to stop this operation and not edit the job by issuing a `abort` command. + * Note: The user is asked for the contact and product one after the other. i.e If asked for the contact first + user cannot select or create a product instead. + * Note: If the operation is stopped via the `abort` command, the job will not be edited at all. + However, any new products/contacts created through the `addContact` and `addProduct` commands will still be added. -Format: `help` +Examples: +* To edit a job and reassign to it other pre-existing contact and product +* Either the command `editJob 1 c/1 p/2` can be issued OR +* The following sequence of commands can be issued: + * `editJob 1 c/ p/` + * `select 1` (to select contact) + * `select 2` (to select product) -### Adding a person: `add` + -Adds a person to the address book. +* To add a job with new a contact and product +* Issue the following sequence of commands: + * `editJob 1 c/ p/` + * `addContact n/James Bond c/94678007 a/Blk 61 Yishun Ave 1 e/bond@gmail.com` + * `addProduct n/SAMSUNG 980 PRO 1TB SSD t/Hard disk m/SAMSUNG d/SATA` -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` + + +### Listing all jobs: `listJob` -
:bulb: **Tip:** -A person can have any number of tags (including 0) -
+Shows a list of all in-progress repair jobs in the CRM. + +Format: `listJob [-a] [-c]` + +* To show a list of all jobs, regardless of completion status the command `listJob -a` can be issued +* To show a list of all completed jobs the command `listJob -c` can be issued Examples: -* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` -* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` -### Listing all persons : `list` +* `listJob` + + + +* `listJob -c` + + + +* `listJob -a` + + + +### Find Job: `findJob` + +Find jobs whose description, contact or product contain certain keywords. + +Format: `findJob [MORE_KEYWORDS]...` + +* The search is case-insensitive. e.g. `intel` will match `Intel`. +* Only full words will be matched. e.g. `Inte` will not match `Intel`. +* Jobs matching at least one keyword will be returned. + +Example: + +* `findJob charlotte intel` + + + +### Marking job as complete: `completeJob` -Shows a list of all persons in the address book. +Marks a repair job as complete -Format: `list` +Format: `completeJob INDEX [COMPLETION_DATE]` -### Editing a person : `edit` +* Marks the repair job at the specified `INDEX` as complete +* By default `listJob` only shows jobs that are yet to be completed. As such marking the job as complete will cause + it to disappear from the current job list. User can issue the command `listJob -c` to view the list of completed jobs. +* `INDEX` refers to the index of the repair job as shown in the repair job listing +* `INDEX` must be a positive integer(1,2,3…) +* `COMPLETION_DATE` is set to the current date if it is not provided -Edits an existing person in the address book. +Example: -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` +* Given one in-progress job + + + +* `completeJob 1` - causes the job to disappear from the current job list + + + +* If `listJob -c` is called, it can be seen that the job was successfully completed + + + +### Revert the completion status of a previously complete job: `undoCompleteJob` + +Reverts the status of a previously completed job back to in-progress. + +Format: `undoCompleteJob INDEX` + +* Marks the repair job at the specified `INDEX` as complete +* User should call `listJob -c` to view all completed jobs before calling this command +* `INDEX` must refer to a completed job. It will not work on a currently in-progress job +* `INDEX` refers to the index of the repair job as shown in the repair job listing +* `INDEX` must be a positive integer(1,2,3…) + +Example: + +* Given one completed job + + + +* If `undoCompleteJob 1` is called, it can be seen that the job's status was reverted to in-progress + + + +### Deleting a job: `deleteJob` + +Delete the specified repair job from the CRM + +Format: `deleteJob INDEX` + +* Deletes the repair job at the specified `INDEX` +* `INDEX` refers to the index of the repair job as shown in the repair job listing +* `INDEX` must be a positive integer(1,2,3…) + +### Adding a contact: `addContact` + +Add a new contact info of a client into the CRM. + +Format: `addContact n/CLIENT_NAME [c/CONTACT_NUMBER] [e/EMAIL] [a/ADDRESS] [t/tags]` + +* Creates a new contact info of a client. +* At least one field of `c/CONTACT_NUMBER` `e/EMAIL` `a/ADDRESS`should exist even though they are considered optional fields. + + i.e. `addContact n/CLIENT_NAME` is not allowed. + + `addContact n/CLIENT_NAME e/EMAIL`, `addContact n/CLIENT_NAME c/CONTACT_NUMBER` commands like these are valid. -* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …​ -* At least one of the optional fields must be provided. -* Existing values will be updated to the input values. -* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. -* You can remove all the person’s tags by typing `t/` without - specifying any tags after it. Examples: -* `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. -* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. -### Locating persons by name: `find` +* `addContact n/Frisk c/93487234 e/Frisk@gmail.com a/Laptop Factory Outlet Bugis Junction` +* `addContact n/Sans c/83921823 e/Sans@gmail.com a/Maxwell Chambers 32 Maxwell Rd` + + + +### Deleting a contact: `deleteContact` + +Deletes the specified contact from the CRM + +Format: `deleteContact INDEX` -Finds persons whose names contain any of the given keywords. +* Deletes the contact at the specified `INDEX` +* `INDEX` refers to the index of the contact as shown in the contact listing +* `INDEX` must be a positive integer(1,2,3…) +* If this contact is link to a job, it can not be deleted unless the linked job is deleted. -Format: `find KEYWORD [MORE_KEYWORDS]` +Example: -* The search is case-insensitive. e.g `hans` will match `Hans` -* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` -* Only the name is searched. -* Only full words will be matched e.g. `Han` will not match `Hans` -* Persons matching at least one keyword will be returned (i.e. `OR` search). - e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +`deleteContact 3` + + + +### Editing a contact: `editContact` + +Edits the specified contact from the CRM + +Format: `editContact INDEX [n/NAME] [c/PHONE] [e/EMAIL] [a/ADDRESS]` + +* At least one field of name, phone, email or address has to provide in order to + change a contact's info. +* After invoking `editContact ...` command, the job linked to this contact will also + update. + + +Example: + +`editContact 1 a/Jurong West Street 42` + + + +### Finding a contact: `findContact ` + +Find certain contact with keyword specified. + +Format: `findContact [MORE_KEYWORDS]... ` + +* User must provide at least one keyword of a contact. + +Example: + +`findContact Frisk Sans` + + + + +### Hiding a contact: `hideContact` + +Hide certain contact with INDEX specified. + +Format: `hideContact INDEX` + +* `hideContact` will add a tag `hidden` to those being hidden. +* Cannot invoke `hideContact` **again** to those being hidden. +* Contacts hidden does not display in MyCRM unless `listContact -a` is invoked. +* So far hiding a specific contact will not affect job card. + +Example: + +`hideContact 1` + + + +### Undoing hiding a contact: `undoHideContact` + +Undo a previous `hideContact` command to certain contact with INDEX specified. + +Format: `undoHideContact INDEX` + +* `listContact -a` must be called in order to see hidden contacts. +* `undoHideContact` will delete `hidden` tag to the hidden contact. +* Cannot invoke `undoHideContact` to visible contacts. + +Example: + +`undoHideContact 1` + + + + +### Listing all contacts: `listContact` + +Show a list of all contact info in the CRM. + +Format: `listContact` or `listContact -a` + +* Normally, `listContact` will only list contacts not being hidden. +* If `listContact -a` is invoked, all contacts including hidden ones will be listed. Examples: -* `find John` returns `john` and `John Doe` -* `find alex david` returns `Alex Yeoh`, `David Li`
- ![result for 'find alex david'](images/findAlexDavidResult.png) -### Deleting a person : `delete` +* `listContact` + + + +* `listContact -a` + + + -Deletes the specified person from the address book. +### Adding a product: `addProduct` -Format: `delete INDEX` +Adds a new product to the CRM. -* Deletes the person at the specified `INDEX`. -* The index refers to the index number shown in the displayed person list. -* The index **must be a positive integer** 1, 2, 3, …​ +Format: `addProduct n/NAME [t/TYPE] [m/MANUFACTURER] [d/DESCRIPTION]` + +* `NAME` is a compulsory field. It must be non-empty. Examples: -* `list` followed by `delete 2` deletes the 2nd person in the address book. -* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command. -### Clearing all entries : `clear` +* `addProduct n/Asus DUAL-GTX1060-O6G t/GPU m/Asus` +* `addProduct n/Intel i5-10400F t/CPU m/Intel d/2.90GHz` -Clears all entries from the address book. + -Format: `clear` +### Listing all products: `listProduct` + +Shows a list of all products in the CRM. + +Format: `listProduct` + +### Deleting a product: `deleteProduct` + +Deletes the specified product from the CRM. + +Format: `deleteProduct INDEX` + +* Deletes the product at the specified `INDEX`. +* `INDEX` refers to the index of the product as shown in the product listing. +* `INDEX` must be a positive integer(1,2,3…). +* A product cannot be deleted if it is linked to one or more jobs. + +### Editing a product: `editProduct` + +Edits an existing product in the CRM. + +Format: `editProduct INDEX [n/NAME] [t/TYPE] [m/MANUFACTURER] [d/DESCRIPTION]` + +* Edits the product at the specified `INDEX`. +* The index refers to the index number shown in the displayed product list. +* `INDEX` must be a positive integer(1,2,3…). +* At least one of the optional fields must be provided. +* No change is made if a field is empty. e.g. + `editProduct 1 m/Asus t/` will not change the product's `Type` field. +* Changes in product fields will be updated in job list *automatically*. + +Example: + +* `editProduct 3 d/Video output interface: DisplayPort, HDMI` edits the description of the 3rd product to be + `Video output interface: DisplayPort, HDMI`. + + + +### Locating products by name: `findProduct` + +Finds products whose names contain certain keywords. + +Format: `findProduct [MORE_KEYWORDS]...` + +* The search is case-insensitive. e.g. `asus` will match `Asus`. +* Only full words will be matched. e.g. `Asu` will not match `Asus`. +* Products matching at least one keyword will be returned. + +Example: + +* `findProduct asus` + + + +### Send mail: `mail` + +Constructs an email to send to a customer of a specified job. This command also generates a `mailto:` hyperlink to +mail the email to a customer of a specified job. + +Format: `mail j/JOB_INDEX t/TEMPLATE_INDEX` + +* Constructs a new email with template content and contact details of the job at the specified `JOB_INDEX` and + `TEMPLATE_INDEX`. +* `JOB_INDEX` refers to the index of the job shown in the repair job listing. +* `JOB_INDEX` must be a positive integer (1,2,3…). +* `TEMPLATE_INDEX` refers to the index of the template as shown in the template listing. +* `TEMPLATE_INDEX` must be a positive integer (1,2,3…). +* `Job` selected must have an email address, non-empty. + +Examples: + +* `listJob` and `listTemplate` followed by` mail j/1 t/1` constructs an email to the 2nd job’s customer with the 2nd + email template and `mailto:` hyperlink. + + + + + +### Adding mail template: `addTemplate` + +Adds a new email template into the CRM. + +Format: `addTemplate s/SUBJECT b/BODY` + +* `SUBJECT` and `BODY` field must be non-empty. +* `SUBJECT` only accepts alphanumeric values and spaces in between. + * i.e. Special characters are not allowed. + * Such as `s/He@der 3!` are not allowed. +* `BODY` accepts any string value (alphanumeric and special characters). +* `BODY` processes special string `\n` as newline for constructing email. + * This is only displayed on `mail` command + +Examples: + +* `addTemplate s/Issue Has Occurred b/Attention:\nYour product has encountered an issue` adds a new Template with + subject "Issue Has Occurred" and body "Attention:\nYour product has encountered an issue". +* `addTemplate s/Your order is confirmed b/Your order is confirmed! Thank you for ordering from XXX` adds a new + Template with subject "our order is confirmed" and body "Your order is confirmed! Thank you for ordering from XXX". + + + +### Listing all templates: `listTemplate` + +Shows a list of all templates in the CRM. + +Format: `listTemplate` + + + +### Editing mail template: `editTemplate` + +Edits the specified template from the CRM. + +Format: `editTemplate INDEX [s/SUBJECT] [b/BODY]` + +* At least one optional edit field must be provided +* `SUBJECT` only accepts alphanumeric values and spaces in between. +* `BODY` accepts any string value (alphanumeric and special characters). + +Edits the template at the specified `INDEX` + +* `INDEX` refers to the index of the template as shown in the template listing +* `INDEX` must be a positive integer(1,2,3…). + +Examples: + +* `listTemplate` followed by `editTemplate 4 b/We’re excited for you to receive your order` edits the 4th email + template in the CRM, overriding the 4th email template's body with the new input. + + + +### Finding mail template: `findTemplate` + +Find certain template(s) with keyword specified. + +Format: `findTemplate [MORE_KEYWORDS]... ` + +* User must provide at least one keyword of a template. +* `MORE_KEYWORDS` searches for `Subject` title +* `MORE_KEYWORDS` are case-insensitive +* `MORE_KEYWORDS` searched are whole words + +Example: + +* `findTemplate Order` + + + +### Deleting mail template: `deleteTemplate` + +Deletes the specified template from the CRM. + +Format: `deleteTemplate INDEX` + +Deletes the template at the specified `INDEX` +* `INDEX` refers to the index of the template as shown in the template listing. +* `INDEX` must be a positive integer(1,2,3…). + +Examples: + +* `listTemplate` followed by `deleteTemplate 4` deletes the 4th email template in the CRM. + + + +### Retrieve previous command: `history` + +Retrieves the previously entered command + +Format: Press "Up arrow key" / `history` + +* ‘Press Up arrow key’ on the keyboard to gain the most recent command in the CRM. +* `history` will list all history commands in the CRM + +Examples: + +* `history`(Assume that `listJob` and `listContact` have been entered before running `history`): + + + +### Clear history command data: `clearHistory` + +Clears all historical data of user input + +Format: `clearHistory` + +### Viewing user guide: `help` + +Shows a message explaining how to access the help page and a hyperlink to it. + +Format: `help` + + ### Exiting the program : `exit` -Exits the program. +Ends MyCRM and exits the programme. Format: `exit` -### Saving the data +### Clearing data: `clear` -AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. +Clears current data in the CRM. Empties CRM data. -### Editing the data file +Format: `clear` -AddressBook data are saved as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file. + -
:exclamation: **Caution:** -If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. -
+### Changing the theme of user interface `theme` + +Changes the theme of user interface. + +Format: `theme THEME_NAME` -### Archiving data files `[coming in v2.0]` +* There are 2 available Ui themes of the CRM. Their names are `dark` and `light`. +* `THEME_NAME` is case-insensitive. -_Details coming soon ..._ +Example: `theme light` + + + +### Printing monthly report `printReport` + +Prints a report of all jobs within current month. + +Format: `printReport [-i] [-p]` + +* To show a report window with monthly in-progress jobs list, the command `printReport -i` can be issued +* To show a report window with monthly top-three products list, the command `printReport -p` can be issued +* MyCRM will show a report window with monthly completed job list by default + + + +### Export monthly report + +Exports a report of all jobs within current month to printer. + +Format: Click on "Print" / `exportReport` + + + + + (for Windows OS) +

+ + + (for Mac OS) -------------------------------------------------------------------------------------------------------------------- ## FAQ **Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder. +**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that +contains the data of your previous MyCRM home folder. -------------------------------------------------------------------------------------------------------------------- - +
## Command summary -Action | Format, Examples ---------|------------------ -**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​`
e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` -**Clear** | `clear` -**Delete** | `delete INDEX`
e.g., `delete 3` -**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g.,`edit 2 n/James Lee e/jameslee@example.com` -**Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` -**List** | `list` -**Help** | `help` +Action | Format, Examples +--------------------|------------------ +**Add Job** | `addJob d/DESCRIPTION by/EXPECTED_COMPLETION_DATE fee/FEE [recv/RECIEVED_DATE] [c/CONTACT_INDEX] [p/PRODUCT_INDEX]`
e.g.,`addJob d/CPU replacement needed c/1 p/1 by/15/09/2021 fee/30.00` +**Edit Job** | `editJob INDEX [d/DESCRIPTION] [by/EXPECTED_COMPLETION_DATE] [fee/FEE] [recv/RECIEVED_DATE] [c/CONTACT_INDEX] [p/PRODUCT_INDEX]`
e.g., `editJob 1 fee/50.00 c/2 p/3` +**List Job** | `listJob` +**Find Job** | `findJob [MORE_KEYWORDS]... `
e.g., `findJob charlotte intel` +**Complete Job** | `completeJob INDEX [COMPLETION_DATE]`
e.g., `completeJob 1` +**Undo Complete Job** | `undoCompleteJob INDEX`
e.g., `undoCompleteJob 1` +**Delete Job** | `deleteJob INDEX`
e.g., `deleteJob 2` +**Select** | `select INDEX`
e.g.,`select 1` +**Abort** | `abort` +**Add Contact** | `addContact n/CLIENT_NAME [c/CONTACT_NUMBER] [e/EMAIL] [a/ADDRESS] [t/tag]`
e.g., `addContact n/Frisk c/93487234 e/Frisk@gmail.com a/Laptop Factory Outlet Bugis Junction` +**Edit Contact** |`editContact INDEX [n/NAME] [c/PHONE] [e/EMAIL] [a/ADDRESS] `
e.g., `EditContact 1 n/Dante` +**List Contact** | `listContact` `listContact -a` +**Find Contact** |`findContact [MORE_KEYWORDS]... `
e.g., `findContact Sans` +**Hide Contact** |`hideContact INDEX `
e.g., `hideContact 1` +**Undo Hide Contact** |`undoHideContact INDEX... `
e.g., `undoHideContact 1` +**Delete Contact** | `deleteContact INDEX`
e.g., `deleteContact 4` +**Add Product** | `addProduct n/NAME [t/TYPE] [m/MANUFACTURER] [d/DESCRIPTION]`
e.g., `addProduct n/Asus DUAL-GTX1060-O6G t/GPU m/Asus` +**List Product** | `listProduct` +**Delete Product** | `deleteProduct INDEX`
e.g., `deleteProduct 4` +**Edit Product** | `editProduct INDEX [n/NAME] [t/TYPE] [m/MANUFACTURER] [d/DESCRIPTION]`
e.g., `editProduct 2 d/Video output interface: DisplayPort, HDMI` +**Find Product** | `findProduct [MORE_KEYWORDS]...`
e.g., `findProduct asus` +**Mail** | `mail j/JOB_INDEX t/TEMPLATE_INDEX`
e.g., `mail j/3 t/1` +**Add Template** | `addTemplate s/SUBJECT b/BODY`
e.g., `addTemplate s/Repair In Progress b/Your product is current;y being repaired` +**List Templates** | `listTemplate` +**Find Templates** |`findTemplate [MORE_KEYWORDS]... `
e.g., `findTemplates complete` +**Edit Templates** | `editTemplate INDEX [s/SUBJECT] [b/SUBJECT]`
e.g., `editTemplate 2 s/Your immediate attention` +**Delete Template** | `deleteTemplate INDEX`
e.g., `deleteTemplate 4` +**Retrieve Previous Command** | `history`, "Press Up arrow key" +**Exit** | `exit` +**Change Theme** | `theme THEME_NAME`
e.g., `theme light` +**Print Monthly Report** | `printReport` +**Export Monthly Report** | `exportReport` diff --git a/docs/_config.yml b/docs/_config.yml index 6bd245d8f4e..3e0714c029f 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,5 +1,5 @@ -title: "AB-3" -theme: minima +title: "MyCRM" +theme: jekyll-theme-cayman header_pages: - UserGuide.md @@ -8,7 +8,7 @@ header_pages: markdown: kramdown -repository: "se-edu/addressbook-level3" +repository: "AY2122S1-CS2103-T14-3/tp" github_icon: "images/github-icon.png" plugins: diff --git a/docs/_sass/minima/_base.scss b/docs/_sass/minima/_base.scss index 0d3f6e80ced..a305363b02e 100644 --- a/docs/_sass/minima/_base.scss +++ b/docs/_sass/minima/_base.scss @@ -288,7 +288,7 @@ table { text-align: center; } .site-header:before { - content: "AB-3"; + content: "MyCRM"; font-size: 32px; } } diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index ef81d18c337..a5901d151ae 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -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 : "deleteContact 1" activate ui UI_COLOR -ui -[UI_COLOR]> logic : execute("delete 1") +ui -[UI_COLOR]> logic : execute("deleteContact 1") activate logic LOGIC_COLOR -logic -[LOGIC_COLOR]> model : deletePerson(p) +logic -[LOGIC_COLOR]> model : deleteContact(contact) activate model MODEL_COLOR model -[MODEL_COLOR]-> logic deactivate model -logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook) +logic -[LOGIC_COLOR]> storage : saveMyCrm(myCrm) activate storage STORAGE_COLOR storage -[STORAGE_COLOR]> storage : Save to file diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml index 5731f9cbaa1..4f2f0e361ba 100644 --- a/docs/diagrams/BetterModelClassDiagram.puml +++ b/docs/diagrams/BetterModelClassDiagram.puml @@ -4,18 +4,20 @@ 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 +MyCrm *-right-> "1" UniqueContactList +MyCrm *-right-> "1" UniqueTagList +UniqueTagList -[hidden]down- UniqueContactList +UniqueTagList -[hidden]down- UniqueContactList UniqueTagList *-right-> "*" Tag -UniquePersonList -right-> Person +UniqueContactList -right-> Contact + +Contact -up-> "*" Tag + +Contact *--> Name +Contact *--> Phone +Contact *--> Email +Contact *--> Address -Person -up-> "*" Tag -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address @enduml diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml index 1dc2311b245..b9a29238e8c 100644 --- a/docs/diagrams/DeleteSequenceDiagram.puml +++ b/docs/diagrams/DeleteSequenceDiagram.puml @@ -3,7 +3,7 @@ box Logic LOGIC_COLOR_T1 participant ":LogicManager" as LogicManager LOGIC_COLOR -participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR participant ":CommandResult" as CommandResult LOGIC_COLOR @@ -16,17 +16,17 @@ end box [-> LogicManager : execute("delete 1") activate LogicManager -LogicManager -> AddressBookParser : parseCommand("delete 1") -activate AddressBookParser +LogicManager -> MyCrmParser : parseCommand("delete 1") +activate MyCrmParser create DeleteCommandParser -AddressBookParser -> DeleteCommandParser +MyCrmParser -> DeleteCommandParser activate DeleteCommandParser -DeleteCommandParser --> AddressBookParser +DeleteCommandParser --> MyCrmParser deactivate DeleteCommandParser -AddressBookParser -> DeleteCommandParser : parse("1") +MyCrmParser -> DeleteCommandParser : parse("1") activate DeleteCommandParser create DeleteCommand @@ -36,14 +36,14 @@ activate DeleteCommand DeleteCommand --> DeleteCommandParser : d deactivate DeleteCommand -DeleteCommandParser --> AddressBookParser : d +DeleteCommandParser --> MyCrmParser : d deactivate DeleteCommandParser 'Hidden arrow to position the destroy marker below the end of the activation bar. -DeleteCommandParser -[hidden]-> AddressBookParser +DeleteCommandParser -[hidden]-> MyCrmParser destroy DeleteCommandParser -AddressBookParser --> LogicManager : d -deactivate AddressBookParser +MyCrmParser --> LogicManager : d +deactivate MyCrmParser LogicManager -> DeleteCommand : execute() activate DeleteCommand diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml index 6d14b17b361..a823fa8b4fb 100644 --- a/docs/diagrams/LogicClassDiagram.puml +++ b/docs/diagrams/LogicClassDiagram.puml @@ -6,11 +6,11 @@ skinparam classBackgroundColor LOGIC_COLOR package Logic { -Class AddressBookParser +Class MyCrmParser Class XYZCommand Class CommandResult Class "{abstract}\nCommand" as Command - +Class StateManager Interface Logic <> Class LogicManager @@ -27,12 +27,17 @@ Class HiddenOutside #FFFFFF HiddenOutside ..> Logic LogicManager .right.|> Logic -LogicManager -right->"1" AddressBookParser -AddressBookParser ..> XYZCommand : creates > +LogicManager -right->"1" MyCrmParser +MyCrmParser ..> XYZCommand : creates > XYZCommand -up-|> Command LogicManager .left.> Command : executes > +StateManager .up.> CommandResult : produces > +LogicManager --> StateManager +Command .up.> StateManager : intercepts < +StateManager .right.> Model + LogicManager --> Model LogicManager --> Storage Storage --[hidden] Model @@ -43,4 +48,5 @@ note right of XYZCommand: XYZCommand = AddCommand, \nFindCommand, etc Logic ..> CommandResult LogicManager .down.> CommandResult Command .up.> CommandResult : produces > + @enduml diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index 1122257bd9a..1ea2e1d94bd 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -5,50 +5,47 @@ skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR Package Model <>{ -Interface ReadOnlyAddressBook <> +Interface ReadOnlyMyCrm <> Interface ReadOnlyUserPrefs <> Interface Model <> -Class AddressBook -Class ReadOnlyAddressBook +Class MyCrm +Class ReadOnlyMyCrm Class Model Class ModelManager Class UserPrefs Class ReadOnlyUserPrefs - -Class UniquePersonList -Class Person -Class Address -Class Email -Class Name -Class Phone -Class Tag - +package Entities { +package Contact #F4F6F6{} +package Product #F4F6F6{} +package Template #F4F6F6{} +package Job #F4F6F6{} +package Mail #F4F6F6{} +} } Class HiddenOutside #FFFFFF HiddenOutside ..> Model -AddressBook .up.|> ReadOnlyAddressBook +MyCrm .up.|> ReadOnlyMyCrm ModelManager .up.|> Model Model .right.> ReadOnlyUserPrefs -Model .left.> ReadOnlyAddressBook -ModelManager -left-> "1" AddressBook +Model .left.> ReadOnlyMyCrm +ModelManager -left-> "1" MyCrm ModelManager -right-> "1" UserPrefs UserPrefs .up.|> ReadOnlyUserPrefs -AddressBook *--> "1" UniquePersonList -UniquePersonList --> "~* all" Person -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address -Person *--> "*" Tag +MyCrm *--> Entities +ModelManager -[hidden]-> Entities +ModelManager --> Entities +note top of Entities: Every package within\nEntities is associated with\nMyCrm and ModelManager + + +Job --> "1" Product +Job --> "1" Contact -Name -[hidden]right-> Phone -Phone -[hidden]right-> Address -Address -[hidden]right-> Email +Mail--> "1" Template +Mail --> "1" Job -ModelManager -->"~* filtered" Person @enduml diff --git a/docs/diagrams/ModelContactClassDiagram.puml b/docs/diagrams/ModelContactClassDiagram.puml new file mode 100644 index 00000000000..a97aa1a2849 --- /dev/null +++ b/docs/diagrams/ModelContactClassDiagram.puml @@ -0,0 +1,33 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Package Contact { +Class UniqueContactList +Class Contact +Class Address +Class Email +Class Name +Class Phone +Class Tag +} + + +MyCrm *-left-> "1" UniqueContactList +UniqueContactList --> "~* all" Contact +Contact *--> "1" Name +Contact *--> "0..1" Phone +Contact *--> "0..1" Email +Contact *--> "0..1" Address +Contact *--> "*" Tag + +Name -[hidden]right- Address + +Contact -[hidden]right- ModelManager +ModelManager -->"~* filtered" Contact + +Contact "1" <-up- Job + +@enduml diff --git a/docs/diagrams/ModelJobClassDiagram.puml b/docs/diagrams/ModelJobClassDiagram.puml new file mode 100644 index 00000000000..83cb2908bd4 --- /dev/null +++ b/docs/diagrams/ModelJobClassDiagram.puml @@ -0,0 +1,36 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Package Job { +Class UniqueJobList +Class Job +Class JobDate +Class JobStatus +Class JobDescription +Class Hidden #FFF +} + + +MyCrm *-left-> "1" UniqueJobList +UniqueJobList --> "~* all" Job +Job *--> JobDate +Job *--> JobDate +Job *-->"1 received\n1 expected\n 0..1 completed" JobDate +Hidden -[hidden]left- JobDate + +Job *--> "1" JobStatus +Job *--> "1" JobDescription +Job --> " 1 client" Contact +Job --> " 1 fix" Product + + +'Class ModelManager #FFFFFF +Job -[hidden]right- ModelManager +ModelManager -->"~* filtered" Job + +Job "1" <-up- Mail + +@enduml diff --git a/docs/diagrams/ModelMailClassDiagram.puml b/docs/diagrams/ModelMailClassDiagram.puml new file mode 100644 index 00000000000..f434870e34a --- /dev/null +++ b/docs/diagrams/ModelMailClassDiagram.puml @@ -0,0 +1,23 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Package Mail { +Class UniqueMailList +Class Mail +} + + +MyCrm *-left-> "1" UniqueMailList +UniqueMailList --> "~* all" Mail + +'Class ModelManager #FFFFFF +Mail -[hidden]right- ModelManager +ModelManager -->" ~* filtered" Mail + +Mail --> "1" Job +Mail --> "1" Template + +@enduml diff --git a/docs/diagrams/ModelProductClassDiagram.puml b/docs/diagrams/ModelProductClassDiagram.puml new file mode 100644 index 00000000000..4cc6ee16bb4 --- /dev/null +++ b/docs/diagrams/ModelProductClassDiagram.puml @@ -0,0 +1,29 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Package Product { +Class UniqueProductList +Class Product +Class ProductName +Class Type +Class Manufacturer +Class Description +} + + +MyCrm *-left-> "1" UniqueProductList +UniqueProductList --> "~* all" Product +Product *--> "1" ProductName +Product *--> "1" Type +Product *--> "1" Description +Product *--> "1" Manufacturer + +Product -[hidden]right- ModelManager +ModelManager -->"~* filtered" Product + +Product "1" <-up- Job + +@enduml diff --git a/docs/diagrams/ModelTemplateClassDiagram.puml b/docs/diagrams/ModelTemplateClassDiagram.puml new file mode 100644 index 00000000000..87450115136 --- /dev/null +++ b/docs/diagrams/ModelTemplateClassDiagram.puml @@ -0,0 +1,27 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Package Template { +Class UniqueTemplateList +Class Template +Class Subject +Class Body +} + + +MyCrm *-left-> "1" UniqueTemplateList +UniqueTemplateList --> "~* all" Template +Template *--> "1" Subject +Template *--> "1" Body + + +'Class ModelManager #FFFFFF +Template -[hidden]right- ModelManager +ModelManager -->"~* filtered" Template + +Template "1" <-up- Mail + +@enduml diff --git a/docs/diagrams/ParserClasses.puml b/docs/diagrams/ParserClasses.puml index 6ba585cba01..003485b88b3 100644 --- a/docs/diagrams/ParserClasses.puml +++ b/docs/diagrams/ParserClasses.puml @@ -9,7 +9,7 @@ Class XYZCommand package "Parser classes"{ Interface Parser <> -Class AddressBookParser +Class MyCrmParser Class XYZCommandParser Class CliSyntax Class ParserUtil @@ -19,12 +19,12 @@ Class Prefix } Class HiddenOutside #FFFFFF -HiddenOutside ..> AddressBookParser +HiddenOutside ..> MyCrmParser -AddressBookParser .down.> XYZCommandParser: creates > +MyCrmParser .down.> XYZCommandParser: creates > XYZCommandParser ..> XYZCommand : creates > -AddressBookParser ..> Command : returns > +MyCrmParser ..> Command : returns > XYZCommandParser .up.|> Parser XYZCommandParser ..> ArgumentMultimap XYZCommandParser ..> ArgumentTokenizer diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index 85ac3ea2dee..95640df2c02 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -14,12 +14,15 @@ Class JsonUserPrefsStorage Interface Storage <> Class StorageManager -package "AddressBook Storage" #F4F6F6{ -Interface AddressBookStorage <> -Class JsonAddressBookStorage -Class JsonSerializableAddressBook -Class JsonAdaptedPerson +package "MyCrm Storage" #F4F6F6{ +Interface MyCrmStorage <> +Class JsonMyCrmStorage +Class JsonSerializableMyCrm +Class JsonAdaptedContact Class JsonAdaptedTag +Class JsonAdaptedJob +Class JsonAdaptedProduct +Class JsonAdaptedTemplate } } @@ -29,15 +32,17 @@ HiddenOutside ..> Storage StorageManager .up.|> Storage StorageManager -up-> "1" UserPrefsStorage -StorageManager -up-> "1" AddressBookStorage +StorageManager -up-> "1" MyCrmStorage Storage -left-|> UserPrefsStorage -Storage -right-|> AddressBookStorage +Storage -right-|> MyCrmStorage JsonUserPrefsStorage .up.|> UserPrefsStorage -JsonAddressBookStorage .up.|> AddressBookStorage -JsonAddressBookStorage ..> JsonSerializableAddressBook -JsonSerializableAddressBook --> "*" JsonAdaptedPerson -JsonAdaptedPerson --> "*" JsonAdaptedTag - +JsonMyCrmStorage .up.|> MyCrmStorage +JsonMyCrmStorage ..> JsonSerializableMyCrm +JsonSerializableMyCrm --> "*" JsonAdaptedContact +JsonAdaptedContact --> "*" JsonAdaptedTag +JsonSerializableMyCrm --> "*" JsonAdaptedJob +JsonSerializableMyCrm --> "*" JsonAdaptedProduct +JsonSerializableMyCrm --> "*" JsonAdaptedTemplate @enduml diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml index ecae4876432..3cd926bda26 100644 --- a/docs/diagrams/UiClassDiagram.puml +++ b/docs/diagrams/UiClassDiagram.puml @@ -9,18 +9,59 @@ Interface Ui <> Class "{abstract}\nUiPart" as UiPart Class UiManager Class MainWindow -Class HelpWindow + +Class ThemeManager + +Class CommandBox Class ResultDisplay -Class PersonListPanel -Class PersonCard + +package "MainDisplay Section" #F4F6F6{ +Class MainDisplay +Class JobListPanel +Class JobCard +Class MailListPanel +Class MailCard +} + +package "SideDisplay Section" #F4F6F6{ +Class SideDisplay +Class ContactListPanel +Class ContactCard + +Class ProductListPanel +Class ProductCard + +Class TemplateListPanel +Class TemplateCard + +Class HistoryListPanel +Class HistoryCard +} + +package "ReportWindow Section" #F4F6F6{ +Class ReportWindow +Class GraphDisplay +Class JobDisplay +} + Class StatusBarFooter -Class CommandBox +Class HelpWindow + + +note "All classes in these sections\ninherit from **UiPart** class." as N1 +N1 .. "SideDisplay Section" +N1 .. "MainDisplay Section" +N1 .. "ReportWindow Section" } + + package Model <> { Class HiddenModel #FFFFFF } +Model -[hidden]up- "MainDisplay" + package Logic <> { Class HiddenLogic #FFFFFF } @@ -30,31 +71,55 @@ HiddenOutside ..> Ui UiManager .left.|> Ui UiManager -down-> "1" MainWindow +MainWindow -left-> "1" ThemeManager MainWindow *-down-> "1" CommandBox MainWindow *-down-> "1" ResultDisplay -MainWindow *-down-> "1" PersonListPanel +MainWindow *-down-> "1" MainDisplay +MainWindow *-down-> "1" SideDisplay MainWindow *-down-> "1" StatusBarFooter MainWindow --> "0..1" HelpWindow - -PersonListPanel -down-> "*" PersonCard +MainWindow --> "0..1" ReportWindow +HelpWindow -[hidden]- CommandBox +StatusBarFooter -[hidden]- ResultDisplay MainWindow -left-|> UiPart -ResultDisplay --|> UiPart +UiManager -right-> Logic +MainWindow -right-> Logic + +' Main display package +MainDisplay *-down-> "1" JobListPanel +MainDisplay *-down-> "1" MailListPanel +JobListPanel -down-> "*" JobCard +MailListPanel -down-> "*" MailCard +JobCard .down.> Model +MailCard .down.> Model + +' Side display package +SideDisplay *-down-> "1" ContactListPanel +SideDisplay *-down-> "1" ProductListPanel +SideDisplay *-down-> "1" TemplateListPanel +SideDisplay *-down-> "1" HistoryListPanel +ContactListPanel -down-> "*" ContactCard +ProductListPanel -down-> "*" ProductCard +TemplateListPanel -down-> "*" TemplateCard +HistoryListPanel -down-> "*" HistoryCard +ContactCard .down.> Model +ProductCard .down.> Model +TemplateCard .down.> Model +HistoryCard .down.> Model + +' Report window package +ReportWindow *-down-> "1" GraphDisplay +GraphDisplay -[hidden]down- JobDisplay +ReportWindow *-down-> "1" JobDisplay +JobDisplay .down.> Model + +' Inherit UiPart CommandBox --|> UiPart -PersonListPanel --|> UiPart -PersonCard --|> UiPart +ResultDisplay --|> UiPart StatusBarFooter --|> UiPart HelpWindow --|> UiPart -PersonCard ..> Model -UiManager -right-> Logic -MainWindow -left-> Logic - -PersonListPanel -[hidden]left- HelpWindow -HelpWindow -[hidden]left- CommandBox -CommandBox -[hidden]left- ResultDisplay -ResultDisplay -[hidden]left- StatusBarFooter - MainWindow -[hidden]-|> UiPart @enduml diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/UndoRedoState2.puml index bccc230a5d1..b6b64bd0831 100644 --- a/docs/diagrams/UndoRedoState2.puml +++ b/docs/diagrams/UndoRedoState2.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "add n/David" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__mc0:MyCrm__" + class State2 as "__mc1:MyCrm__" + class State3 as "__mc2:MyCrm__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/contact/AddContactActivityDiagram.puml b/docs/diagrams/contact/AddContactActivityDiagram.puml new file mode 100644 index 00000000000..36231d881ff --- /dev/null +++ b/docs/diagrams/contact/AddContactActivityDiagram.puml @@ -0,0 +1,31 @@ +@startuml +start +:User executes add contact command; +:MyCRM parses user inputs; +if() then ([InValid Input]) + :Throws ParseException; + :Displays unsuccessful adding contact message on UI; +else ([Valid Input]) + fork + :Creates new **Name**; + fork again + :(Optional) + Creates new **Phone**; + fork again + : (Optional) + Creates new **Email**; + fork again + : (Optional) + Creates new **Address**; + end fork + :Creates new contact; + if () then ([Duplicate contact]) + :Throws CommandException; + :Displays unsuccessful adding contact message on UI; + else ([Else]) + :Stores contact into MyCRM; + :Displays successful adding contact message on UI; + endif +endif; +stop +@enduml diff --git a/docs/diagrams/contact/AddContactParseSequenceDiagram.puml b/docs/diagrams/contact/AddContactParseSequenceDiagram.puml new file mode 100644 index 00000000000..a0e266b29ab --- /dev/null +++ b/docs/diagrams/contact/AddContactParseSequenceDiagram.puml @@ -0,0 +1,82 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":AddContactCommandParser" as AddContactCommandParser LOGIC_COLOR +participant "contactToAdd:AddContactCommand" as AddContactCommand LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant "n:Name" as Name MODEL_COLOR +participant "c:Phone" as Phone MODEL_COLOR +participant "e:Email" as Email MODEL_COLOR +participant "a:Address" as Address MODEL_COLOR +participant "contact:Contact" as Contact MODEL_COLOR +end box +[-> LogicManager : execute("addContact n/Sans c/83921823 e/Sans@gmail.com a/Maxwell...") +activate LogicManager + +group sd parse add contact +LogicManager -> MyCrmParser : parseCommand("addContact n/Sans c/83921823 e/Sans@gmail.com a/Maxwell...") +activate MyCrmParser + +create AddContactCommandParser +MyCrmParser -> AddContactCommandParser +activate AddContactCommandParser + +AddContactCommandParser --> MyCrmParser +deactivate AddContactCommandParser + +MyCrmParser -> AddContactCommandParser : parse("addContact n/Sans c/83921823 e/Sans@gmail.com a/Maxwell...") +activate AddContactCommandParser + +create Name +AddContactCommandParser -> Name : "Sans" +activate Name +Name --> AddContactCommandParser : n +deactivate Name + +create Phone +AddContactCommandParser -> Phone : "83921823" +activate Phone +Phone --> AddContactCommandParser : c +deactivate Phone + +create Email +AddContactCommandParser -> Email : "Sans@gmail.com" +activate Email +Email --> AddContactCommandParser : e +deactivate Email + +create Address +AddContactCommandParser -> Address : "Maxwell..." +activate Address +Address --> AddContactCommandParser : a +deactivate Address + +create Contact +AddContactCommandParser -> Contact : n, c, e, a +activate Contact +Contact --> AddContactCommandParser : contact +deactivate Contact + +create AddContactCommand +AddContactCommandParser -> AddContactCommand : contact +activate AddContactCommand +AddContactCommand --> AddContactCommandParser : contactToAdd +deactivate AddContactCommand + +AddContactCommandParser --> MyCrmParser : contactToAdd +deactivate AddContactCommandParser +'Hidden arrow to position destroy marker below the end of the activation bar. +AddContactCommandParser -[hidden]-> MyCrmParser +destroy AddContactCommandParser + +MyCrmParser --> LogicManager : contactToAdd +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/AddContactSequenceDiagram.puml b/docs/diagrams/contact/AddContactSequenceDiagram.puml new file mode 100644 index 00000000000..c4148e2add2 --- /dev/null +++ b/docs/diagrams/contact/AddContactSequenceDiagram.puml @@ -0,0 +1,57 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "contactToAdd:AddContactCommand" as AddContactCommand LOGIC_COLOR +participant "c:CommandResult" as CommandResult LOGIC_COLOR +participant ":StateManager" as StateManager LOGIC_COLOR +participant "modifiedResult:CommandResult" as CommandResult2 LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box +[-> LogicManager : execute("addContact n/Sans c/83921823 e/Sans@gmail.com a/MaxWell...") +activate LogicManager + +ref over LogicManager, AddContactCommand : parse add contact + +LogicManager -> AddContactCommand : execute() +activate AddContactCommand + +AddContactCommand -> Model : addContact(contactToAdd) +activate Model + +Model --> AddContactCommand +deactivate Model + +create CommandResult +AddContactCommand -> CommandResult +activate CommandResult + +CommandResult --> AddContactCommand : c +deactivate CommandResult + +AddContactCommand -> StateManager : handleContact(contactToAdd, c) +activate StateManager + +create CommandResult2 +StateManager -> CommandResult2 +activate CommandResult2 + +CommandResult2 --> StateManager : modifiedResult +deactivate CommandResult2 + +StateManager --> AddContactCommand : modifiedResult +deactivate StateManager + +AddContactCommand --> LogicManager : modifiedResult +deactivate AddContactCommand + +AddContactCommand -[hidden]-> LogicManager +destroy AddContactCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/DeleteContactActivityDiagram.puml b/docs/diagrams/contact/DeleteContactActivityDiagram.puml new file mode 100644 index 00000000000..df87eafa672 --- /dev/null +++ b/docs/diagrams/contact/DeleteContactActivityDiagram.puml @@ -0,0 +1,24 @@ +@startuml +start +:User executes delete contact command; +:MyCRM parses user inputs; +if () then ([InValid Input]) + :Throws ParseException; + :Displays unsuccessful deleting contact message on UI; +else ([Valid Input]) +if () then ([Invalid Index]) + :Throws CommandException; + :Displays unsuccessful deleting contact message on UI; +else ([Else]) + :Gets contact to be deleted with index provided; + if () then ([Contact not linked to any jobs]) + :Delete the specific contact from MyCRM; + :Displays successful deleting contact message on UI; + else ([Contact linked to a job])) + :Throws CommandException; + :Displays unsuccessful deleting contact message on UI; +endif +endif +endif +stop +@enduml diff --git a/docs/diagrams/contact/DeleteContactParseSequenceDiagram.puml b/docs/diagrams/contact/DeleteContactParseSequenceDiagram.puml new file mode 100644 index 00000000000..cb7b8f8672c --- /dev/null +++ b/docs/diagrams/contact/DeleteContactParseSequenceDiagram.puml @@ -0,0 +1,47 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":DeleteContactCommandParser" as DeleteContactCommandParser LOGIC_COLOR +participant "contactToDelete:DeleteContactCommand" as DeleteContactCommand LOGIC_COLOR +end box + +[-> LogicManager : execute("deleteContact 1") +activate LogicManager + +group sd parse delete contact +LogicManager -> MyCrmParser : parseCommand("deleteContact 1") +activate MyCrmParser + +create DeleteContactCommandParser +MyCrmParser -> DeleteContactCommandParser +activate DeleteContactCommandParser + +DeleteContactCommandParser --> MyCrmParser +deactivate DeleteContactCommandParser + +MyCrmParser -> DeleteContactCommandParser : parse("1") +activate DeleteContactCommandParser + +create DeleteContactCommand +DeleteContactCommandParser -> DeleteContactCommand : 1 +activate DeleteContactCommand + +DeleteContactCommand --> DeleteContactCommandParser : contactToDelete +deactivate DeleteContactCommand + +DeleteContactCommandParser --> MyCrmParser : contactToDelete +deactivate DeleteContactCommandParser + +'Hidden arrow to position destroy marker below the end of the activation bar. +DeleteContactCommandParser -[hidden]-> MyCrmParser +destroy DeleteContactCommandParser + +MyCrmParser --> LogicManager : contactToDelete +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/DeleteContactSequenceDiagram.puml b/docs/diagrams/contact/DeleteContactSequenceDiagram.puml new file mode 100644 index 00000000000..90627cb4c05 --- /dev/null +++ b/docs/diagrams/contact/DeleteContactSequenceDiagram.puml @@ -0,0 +1,59 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "contactToDelete:DeleteContactCommand" as DeleteContactCommand LOGIC_COLOR +participant "lastShownList: List" as ListContact 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("deleteContact 1") +activate LogicManager + +ref over LogicManager, DeleteContactCommand : parse delete contact + +LogicManager -> DeleteContactCommand : execute() + +activate DeleteContactCommand + +DeleteContactCommand -> Model : getFilteredContactList() +activate Model +Model --> DeleteContactCommand : lastShownList +deactivate Model + +DeleteContactCommand -> ListContact : get(index) +activate ListContact +ListContact --> DeleteContactCommand : contactToDelete +deactivate ListContact + +DeleteContactCommand -> Model : deleteContact(contactToDelete) +activate Model +Model --> DeleteContactCommand +deactivate Model + +DeleteContactCommand -> Model : updateFilteredContactList(PREDICATE_SHOW_NOT_HIDDEN_CONTACTS) +activate Model +Model --> DeleteContactCommand +deactivate Model + +create CommandResult +DeleteContactCommand -> CommandResult +activate CommandResult + +CommandResult --> DeleteContactCommand +deactivate CommandResult + +DeleteContactCommand --> LogicManager : result +deactivate DeleteContactCommand + +DeleteContactCommand -[hidden]-> LogicManager +destroy DeleteContactCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/EditContactActivityDiagram.puml b/docs/diagrams/contact/EditContactActivityDiagram.puml new file mode 100644 index 00000000000..df1230fa496 --- /dev/null +++ b/docs/diagrams/contact/EditContactActivityDiagram.puml @@ -0,0 +1,25 @@ +@startuml +start +:User executes edit contact command; +:MyCRM parses user inputs; +if () then ([InValid Input]) + :Throws ParseException; + :Displays unsuccessful editing contact message on UI; +else ([Valid Input]) +if () then ([Invalid Index]) + :Throws CommandException; + :Displays unsuccessful editing contact on UI; +else ([Else]) +:Gets contact to be edited with index provided; +:Creates edited contact; +if () then ([Duplicate Contact]) + :Throws CommandException; + :Displays unsuccessful editing contact on UI; +else ([Else]) +:Replaces specific contact with edited contact; +:Displays successful editing contact message on UI; +endif +endif +endif +stop +@enduml diff --git a/docs/diagrams/contact/EditContactParseSequenceDiagram.puml b/docs/diagrams/contact/EditContactParseSequenceDiagram.puml new file mode 100644 index 00000000000..75e793f0c87 --- /dev/null +++ b/docs/diagrams/contact/EditContactParseSequenceDiagram.puml @@ -0,0 +1,65 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":EditContactCommandParser" as EditContactCommandParser LOGIC_COLOR +participant "contactToEdit:EditContactCommand" as EditContactCommand LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant "editContactDescriptor:EditContactDescriptor" as EditContactDescriptor MODEL_COLOR +end box +[-> LogicManager : execute("editContact 1 n/Frisks c/88888888 e/Frisks@gmail.com a/Jurong West") +activate LogicManager + +group sd parse edit contact +LogicManager -> MyCrmParser : parseCommand("editContact 1 n/Frisks c/88888888 e/Frisks@gmail.com a/Jurong West") +activate MyCrmParser + +create EditContactCommandParser +MyCrmParser -> EditContactCommandParser +activate EditContactCommandParser + +EditContactCommandParser --> MyCrmParser +deactivate EditContactCommandParser + +MyCrmParser -> EditContactCommandParser : parse("1 n/Frisks c/88888888 e/Frisks@gmail.com a/Jurong West") +activate EditContactCommandParser + +create EditContactDescriptor +EditContactCommandParser -> EditContactDescriptor +activate EditContactDescriptor +EditContactDescriptor --> EditContactCommandParser : editContactDescriptor +deactivate EditContactDescriptor + +EditContactCommandParser -> EditContactDescriptor : setName("Frisks") + +EditContactCommandParser -> EditContactDescriptor : setPhone("88888888") + +EditContactCommandParser -> EditContactDescriptor : setEmail("Frisks@gmail.com") + +EditContactCommandParser -> EditContactDescriptor : setAddress("Jurong West") + + +create EditContactCommand +EditContactCommandParser -> EditContactCommand : 1, editContactDescriptor +activate EditContactCommand + +EditContactCommand --> EditContactCommandParser : contactToEdit +deactivate EditContactCommand + +EditContactCommandParser --> MyCrmParser : contactToEdit +deactivate EditContactCommandParser + +'Hidden arrow to position destroy marker below the end of the activation bar. +EditContactCommandParser -[hidden]-> MyCrmParser +destroy EditContactCommandParser + +MyCrmParser --> LogicManager : contactToEdit +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/EditContactSequenceDiagram.puml b/docs/diagrams/contact/EditContactSequenceDiagram.puml new file mode 100644 index 00000000000..d0d0222627c --- /dev/null +++ b/docs/diagrams/contact/EditContactSequenceDiagram.puml @@ -0,0 +1,75 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "contactToEdit:EditContactCommand" as EditContactCommand LOGIC_COLOR +participant "lastShownList: List" as ListContact LOGIC_COLOR +participant "**<>**\nContact" as Contact 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("editContact 1 n/Frisks c/88888888 e/Frisks@gmail.com a/Jurong West") +activate LogicManager + +ref over LogicManager, EditContactCommand : parse edit contact + +LogicManager -> EditContactCommand : execute() + +activate EditContactCommand + +EditContactCommand -> Model : getFilteredContactList() +activate Model +Model --> EditContactCommand : lastShownList +deactivate Model + +EditContactCommand -> ListContact : get(index) +activate ListContact +ListContact --> EditContactCommand : contactToEdit +deactivate ListContact + +EditContactCommand -> Contact : createEditedContact(contactToEdit, editContactDescriptor) +activate Contact +Contact --> EditContactCommand : editedContact +deactivate Contact + +EditContactCommand -> Model : setContact(contactToEdit, editedContact) +activate Model +Model --> EditContactCommand +deactivate Model + +EditContactCommand -> Model : updateFilteredContactList(PREDICATE_SHOW_NOT_HIDDEN_CONTACTS) +activate Model +Model --> EditContactCommand +deactivate Model + +EditContactCommand -> Model : getLatestJobPredicate() +activate Model +Model --> EditContactCommand : latestJobPredicate +deactivate Model + +EditContactCommand -> Model : updateFilteredJobList(latestJobPredicate) +activate Model +Model --> EditContactCommand +deactivate Model + +create CommandResult +EditContactCommand -> CommandResult +activate CommandResult + +CommandResult --> EditContactCommand +deactivate CommandResult + +EditContactCommand --> LogicManager : result +deactivate EditContactCommand + +EditContactCommand -[hidden]-> LogicManager +destroy EditContactCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/FindContactActivityDiagram.puml b/docs/diagrams/contact/FindContactActivityDiagram.puml new file mode 100644 index 00000000000..e1d0efdaecf --- /dev/null +++ b/docs/diagrams/contact/FindContactActivityDiagram.puml @@ -0,0 +1,15 @@ +@startuml +start +:User executes find contact command; +:MyCRM parses user inputs; +if () then ([InValid Input]) + :Throws ParseException; + :Displays unsuccessful finding contact message on UI; +else ([Valid Input]) +:Gets contact names predicate with keywords provided; +:Update contact list with new predicate: +showing contacts whose names contain keywords; +:Displays successful finding contact message on UI; +endif +stop +@enduml diff --git a/docs/diagrams/contact/FindContactParseSequenceDiagram.puml b/docs/diagrams/contact/FindContactParseSequenceDiagram.puml new file mode 100644 index 00000000000..50bd066285a --- /dev/null +++ b/docs/diagrams/contact/FindContactParseSequenceDiagram.puml @@ -0,0 +1,55 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":FindContactCommandParser" as FindContactCommandParser LOGIC_COLOR +participant ":FindContactCommand" as FindContactCommand LOGIC_COLOR +participant "keywordsPredicate:NameContainsKeywordsPredicate" as NameContainsKeywordsPredicate LOGIC_COLOR +end box + +[-> LogicManager : execute("findContact Frisks") +activate LogicManager + +group sd parse find contact +LogicManager -> MyCrmParser : parseCommand("findContact Frisks") +activate MyCrmParser + +create FindContactCommandParser +MyCrmParser -> FindContactCommandParser +activate FindContactCommandParser + +FindContactCommandParser --> MyCrmParser +deactivate FindContactCommandParser + +MyCrmParser -> FindContactCommandParser : parse("Frisks") +activate FindContactCommandParser + +create NameContainsKeywordsPredicate +FindContactCommandParser -> NameContainsKeywordsPredicate: "Frisks" +activate NameContainsKeywordsPredicate +NameContainsKeywordsPredicate --> FindContactCommandParser : keywordsPredicate +deactivate NameContainsKeywordsPredicate + +create FindContactCommand +FindContactCommandParser -> FindContactCommand : keywordsPredicate +activate FindContactCommand + +FindContactCommand --> FindContactCommandParser +deactivate FindContactCommand + +FindContactCommandParser --> MyCrmParser +deactivate FindContactCommandParser + +'Hidden arrow to position destroy marker below the end of the activation bar. +FindContactCommandParser -[hidden]-> MyCrmParser +destroy FindContactCommandParser + + +MyCrmParser --> LogicManager : +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/FindContactSequenceDiagram.puml b/docs/diagrams/contact/FindContactSequenceDiagram.puml new file mode 100644 index 00000000000..9275baa51b8 --- /dev/null +++ b/docs/diagrams/contact/FindContactSequenceDiagram.puml @@ -0,0 +1,43 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":FindContactCommand" as FindContactCommand 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("findContact Frisks") +activate LogicManager + +ref over LogicManager, FindContactCommand : parse find contact + +LogicManager -> FindContactCommand : execute() + +activate FindContactCommand + +FindContactCommand -> Model : updateFilteredContactList(keywordsPredicate) +activate Model +Model --> FindContactCommand +deactivate Model + +create CommandResult +FindContactCommand -> CommandResult +activate CommandResult + +CommandResult --> FindContactCommand +deactivate CommandResult + +FindContactCommand --> LogicManager : result +deactivate FindContactCommand + +FindContactCommand -[hidden]-> LogicManager +destroy FindContactCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/HideContactActivityDiagram.puml b/docs/diagrams/contact/HideContactActivityDiagram.puml new file mode 100644 index 00000000000..e4eab2adcf3 --- /dev/null +++ b/docs/diagrams/contact/HideContactActivityDiagram.puml @@ -0,0 +1,24 @@ +@startuml +start +:User executes hide contact command; +:MyCRM parses user inputs; +if () then ([InValid Input]) + :Throws ParseException; + :Displays unsuccessful hiding contact message on UI; +else ([Valid Input]) +if () then ([Invalid Index]) + :Throws CommandException; + :Displays unsuccessful hiding contact on UI; +else ([Else]) +:Gets contact to be hidden with index provided; +if () then ([Contact is not hidden]) +:Hide the specific contact from MyCRM; +:Displays successful hiding contact message on UI; +else ([Contact is hidden]) +:Throws CommandException; +:Displays unsuccessful hiding contact message on UI; +endif +endif +endif +stop +@enduml diff --git a/docs/diagrams/contact/HideContactParserSequenceDiagram.puml b/docs/diagrams/contact/HideContactParserSequenceDiagram.puml new file mode 100644 index 00000000000..d46cd5eb7e7 --- /dev/null +++ b/docs/diagrams/contact/HideContactParserSequenceDiagram.puml @@ -0,0 +1,47 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":HideContactCommandParser" as HideContactCommandParser LOGIC_COLOR +participant "contactToHide:HideContactCommand" as HideContactCommand LOGIC_COLOR +end box + +[-> LogicManager : execute("hideContact 1") +activate LogicManager + +group sd parse hide contact +LogicManager -> MyCrmParser : parseCommand("hideContact 1") +activate MyCrmParser + +create HideContactCommandParser +MyCrmParser -> HideContactCommandParser +activate HideContactCommandParser + +HideContactCommandParser --> MyCrmParser +deactivate HideContactCommandParser + +MyCrmParser -> HideContactCommandParser : parse("1") +activate HideContactCommandParser + +create HideContactCommand +HideContactCommandParser -> HideContactCommand : 1 +activate HideContactCommand + +HideContactCommand --> HideContactCommandParser : contactToHide +deactivate HideContactCommand + +HideContactCommandParser --> MyCrmParser : contactToHide +deactivate HideContactCommandParser + +'Hidden arrow to position destroy marker below the end of the activation bar. +HideContactCommandParser -[hidden]-> MyCrmParser +destroy HideContactCommandParser + +MyCrmParser --> LogicManager : contactToHide +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/HideContactSequenceDiagram.puml b/docs/diagrams/contact/HideContactSequenceDiagram.puml new file mode 100644 index 00000000000..318815d4287 --- /dev/null +++ b/docs/diagrams/contact/HideContactSequenceDiagram.puml @@ -0,0 +1,59 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "contactToHide:HideContactCommand" as HideContactCommand LOGIC_COLOR +participant "lastShownList: List" as ListContact 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("hideContact 1") +activate LogicManager + +ref over LogicManager, HideContactCommand : parse hide contact + +LogicManager -> HideContactCommand : execute() + +activate HideContactCommand + +HideContactCommand -> Model : getFilteredContactList() +activate Model +Model --> HideContactCommand : lastShownList +deactivate Model + +HideContactCommand -> ListContact : get(index) +activate ListContact +ListContact --> HideContactCommand : contactToHide +deactivate ListContact + +HideContactCommand -> Model : hideContact(contactToHide) +activate Model +Model --> HideContactCommand +deactivate Model + +HideContactCommand -> Model : updateFilteredContactList(PREDICATE_SHOW_NOT_HIDDEN_CONTACTS) +activate Model +Model --> HideContactCommand +deactivate Model + +create CommandResult +HideContactCommand -> CommandResult +activate CommandResult + +CommandResult --> HideContactCommand +deactivate CommandResult + +HideContactCommand --> LogicManager : result +deactivate HideContactCommand + +HideContactCommand -[hidden]-> LogicManager +destroy HideContactCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/ListContactActivityDiagram.puml b/docs/diagrams/contact/ListContactActivityDiagram.puml new file mode 100644 index 00000000000..e97a1af9e03 --- /dev/null +++ b/docs/diagrams/contact/ListContactActivityDiagram.puml @@ -0,0 +1,18 @@ +@startuml +start +:User executes list contact command; +:MyCRM parses user inputs; +if () then ([InValid Input]) + :Throws ParseException; + :Displays unsuccessful listing contact message on UI; +else ([Valid Input]) +:Gets keyword for predicate of listContact; +if () then ([predicate "-a"]) +:Shows all contacts in the list including hidden ones ; +else ([no predicate]) +:Shows not hidden contacts in the list; +endif; +:Displays successful listing contact message on UI; +endif +stop +@enduml diff --git a/docs/diagrams/contact/ListContactParseSequenceDiagram.puml b/docs/diagrams/contact/ListContactParseSequenceDiagram.puml new file mode 100644 index 00000000000..2e1d86400b9 --- /dev/null +++ b/docs/diagrams/contact/ListContactParseSequenceDiagram.puml @@ -0,0 +1,55 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":ListContactCommandParser" as ListContactCommandParser LOGIC_COLOR +participant ":ListContactCommand" as ListContactCommand LOGIC_COLOR +participant "listPredicate:Predicate" as PredicateContact LOGIC_COLOR +end box + +[-> LogicManager : execute("listContact -a") +activate LogicManager + +group sd parse list contact +LogicManager -> MyCrmParser : parseCommand("listContact -a") +activate MyCrmParser + +create ListContactCommandParser +MyCrmParser -> ListContactCommandParser +activate ListContactCommandParser + +ListContactCommandParser --> MyCrmParser +deactivate ListContactCommandParser + +MyCrmParser -> ListContactCommandParser : parse("listContact -a") +activate ListContactCommandParser + +create PredicateContact +ListContactCommandParser -> PredicateContact : "-a" +activate PredicateContact +PredicateContact --> ListContactCommandParser : listPredicate +deactivate PredicateContact + +create ListContactCommand +ListContactCommandParser -> ListContactCommand : listPredicate +activate ListContactCommand + +ListContactCommand --> ListContactCommandParser +deactivate ListContactCommand + +ListContactCommandParser --> MyCrmParser +deactivate ListContactCommandParser + +'Hidden arrow to position destroy marker below the end of the activation bar. +ListContactCommandParser -[hidden]-> MyCrmParser +destroy ListContactCommandParser + + +MyCrmParser --> LogicManager : +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/ListContactSequenceDiagram.puml b/docs/diagrams/contact/ListContactSequenceDiagram.puml new file mode 100644 index 00000000000..0c5cb1143db --- /dev/null +++ b/docs/diagrams/contact/ListContactSequenceDiagram.puml @@ -0,0 +1,43 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":ListContactCommand" as ListContactCommand 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("listContact -a") +activate LogicManager + +ref over LogicManager, ListContactCommand : parse list contact + +LogicManager -> ListContactCommand : execute() + +activate ListContactCommand + +ListContactCommand -> Model : updateFilteredContactList(listPredicate) +activate Model +Model --> ListContactCommand +deactivate Model + +create CommandResult +ListContactCommand -> CommandResult +activate CommandResult + +CommandResult --> ListContactCommand +deactivate CommandResult + +ListContactCommand --> LogicManager : result +deactivate ListContactCommand + +ListContactCommand -[hidden]-> LogicManager +destroy ListContactCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/UndoHideContactActivityDiagram.puml b/docs/diagrams/contact/UndoHideContactActivityDiagram.puml new file mode 100644 index 00000000000..559dd24861a --- /dev/null +++ b/docs/diagrams/contact/UndoHideContactActivityDiagram.puml @@ -0,0 +1,24 @@ +@startuml +start +:User executes undo hide contact command; +:MyCRM parses user inputs; +if () then ([InValid Input]) + :Throws ParseException; + :Displays unsuccessful undoing hiding contact message on UI; +else ([Valid Input]) +if () then ([Invalid Index]) + :Throws CommandException; + :Displays unsuccessful undoing hiding contact on UI; +else ([Else]) +:Gets contact to undo hiding with index provided; +if () then ([Contact is hidden]) +:Undo Hiding the specific contact from MyCRM; +:Displays successful undoing hiding contact message on UI; +else ([Contact is not hidden]) +:Throws CommandException; +:Displays unsuccessful undoing hiding contact message on UI; +endif +endif +endif +stop +@enduml diff --git a/docs/diagrams/contact/UndoHideContactParseSequenceDiagram.puml b/docs/diagrams/contact/UndoHideContactParseSequenceDiagram.puml new file mode 100644 index 00000000000..a45ff2e298b --- /dev/null +++ b/docs/diagrams/contact/UndoHideContactParseSequenceDiagram.puml @@ -0,0 +1,47 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":UndoHideContactCommandParser" as UndoHideContactCommandParser LOGIC_COLOR +participant "contactToUndoHide:UndoHideContactCommand" as UndoHideContactCommand LOGIC_COLOR +end box + +[-> LogicManager : execute("undoHideContact 1") +activate LogicManager + +group sd parse undo hide contact +LogicManager -> MyCrmParser : parseCommand("undoHideContact 1") +activate MyCrmParser + +create UndoHideContactCommandParser +MyCrmParser -> UndoHideContactCommandParser +activate UndoHideContactCommandParser + +UndoHideContactCommandParser --> MyCrmParser +deactivate UndoHideContactCommandParser + +MyCrmParser -> UndoHideContactCommandParser : parse("1") +activate UndoHideContactCommandParser + +create UndoHideContactCommand +UndoHideContactCommandParser -> UndoHideContactCommand : 1 +activate UndoHideContactCommand + +UndoHideContactCommand --> UndoHideContactCommandParser : contactToUndoHide +deactivate UndoHideContactCommand + +UndoHideContactCommandParser --> MyCrmParser : contactToUndoHide +deactivate UndoHideContactCommandParser + +'Hidden arrow to position destroy marker below the end of the activation bar. +UndoHideContactCommandParser -[hidden]-> MyCrmParser +destroy UndoHideContactCommandParser + +MyCrmParser --> LogicManager : contactToUndoHide +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/contact/UndoHideContactSequenceDiagram.puml b/docs/diagrams/contact/UndoHideContactSequenceDiagram.puml new file mode 100644 index 00000000000..6bcdb7f7440 --- /dev/null +++ b/docs/diagrams/contact/UndoHideContactSequenceDiagram.puml @@ -0,0 +1,59 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "contactToUndoHide:UndoHideContactCommand" as UndoHideContactCommand LOGIC_COLOR +participant "lastShownList: List" as ListContact 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("undoHideContact 1") +activate LogicManager + +ref over LogicManager, UndoHideContactCommand : parse undo hide contact + +LogicManager -> UndoHideContactCommand : execute() + +activate UndoHideContactCommand + +UndoHideContactCommand -> Model : getFilteredContactList() +activate Model +Model --> UndoHideContactCommand : lastShownList +deactivate Model + +UndoHideContactCommand -> ListContact : get(index) +activate ListContact +ListContact --> UndoHideContactCommand : contactToUndoHide +deactivate ListContact + +UndoHideContactCommand -> Model : UndoHideContact(contactToUndoHide) +activate Model +Model --> UndoHideContactCommand +deactivate Model + +UndoHideContactCommand -> Model : updateFilteredContactList(PREDICATE_SHOW_NOT_HIDDEN_CONTACTS) +activate Model +Model --> UndoHideContactCommand +deactivate Model + +create CommandResult +UndoHideContactCommand -> CommandResult +activate CommandResult + +CommandResult --> UndoHideContactCommand +deactivate CommandResult + +UndoHideContactCommand --> LogicManager : result +deactivate UndoHideContactCommand + +UndoHideContactCommand -[hidden]-> LogicManager +destroy UndoHideContactCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/job/AddJobActivityDiagram.puml b/docs/diagrams/job/AddJobActivityDiagram.puml new file mode 100644 index 00000000000..9968d010f02 --- /dev/null +++ b/docs/diagrams/job/AddJobActivityDiagram.puml @@ -0,0 +1,49 @@ +@startuml +sprite $rake [16x16/8] { +0000000000000000 +0000000jj0000000 +0000000jj0000000 +0005555jj5555000 +000jjeejjeejj000 +000jj00jj00jj000 +000jj00jj00jj000 +0000000000000000 +} + +start +:User executes add job command; +:MyCRM parses user inputs; +if () then ([Valid inputs]) + if () then ([Contact Index was provided]) + else ([else]) + :Assign contact to job <$rake>; + if () then([operation aborted]) + stop; + else ([else]) + endif + endif + +if () then ([Product Index was provided]) + else ([else]) + :Assign product to job <$rake>; + if () then([operation aborted]) + stop; + else ([else]) + endif + endif + + :Creates new job; + if () then ([Duplicate contact]) + :Throws CommandException; + :Displays unsuccessful adding of job on UI; + else ([Else]) + :Stores job into MyCRM; + :Displays successful add job on UI; + endif + +else ([Invalid inputs]) + :Throws ParseException; + :Displays unsuccessful add job on UI; +endif +stop +@enduml diff --git a/docs/diagrams/job/AddJobParseSequenceDiagram.puml b/docs/diagrams/job/AddJobParseSequenceDiagram.puml new file mode 100644 index 00000000000..ce05f7e9c64 --- /dev/null +++ b/docs/diagrams/job/AddJobParseSequenceDiagram.puml @@ -0,0 +1,82 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":AddJobCommandParser" as AddJobCommandParser LOGIC_COLOR +participant "ToAdd:AddJobCommand" as AddJobCommand LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant "desc:JobDescription" as JobDescription MODEL_COLOR +participant "fee:JobFee" as JobFee MODEL_COLOR +participant "recv:JobDate" as RECEIVED_DATE MODEL_COLOR +participant "by:JobDate" as EXPECTED_COMPLETION MODEL_COLOR +participant "job:Job" as Job MODEL_COLOR +end box +[-> LogicManager :execute("addJob d/Fix CPU fee/30.00 recv/29/10/2021 by/30/10/2021 c/1") +activate LogicManager + +group sd parse add contact +LogicManager -> MyCrmParser : parseCommand("addJob d/Fix CPU fee/30.00 recv/29/10/2021 by/30/10/2021 c/1") +activate MyCrmParser + +create AddJobCommandParser +MyCrmParser -> AddJobCommandParser +activate AddJobCommandParser + +AddJobCommandParser --> MyCrmParser +deactivate AddJobCommandParser + +MyCrmParser -> AddJobCommandParser : parse("addJob d/Fix CPU fee/30.00 recv/29/10/2021 by/30/10/2021 c/1") +activate AddJobCommandParser + +create JobDescription +AddJobCommandParser -> JobDescription : "Fix CPU" +activate JobDescription +JobDescription --> AddJobCommandParser : desc +deactivate JobDescription + +create JobFee +AddJobCommandParser -> JobFee : "30.00" +activate JobFee +JobFee --> AddJobCommandParser : fee +deactivate JobFee + +create RECEIVED_DATE +AddJobCommandParser -> RECEIVED_DATE : "29/10/2021" +activate RECEIVED_DATE +RECEIVED_DATE --> AddJobCommandParser : recv +deactivate RECEIVED_DATE + +create EXPECTED_COMPLETION +AddJobCommandParser -> EXPECTED_COMPLETION : "30/10/2021" +activate EXPECTED_COMPLETION +EXPECTED_COMPLETION --> AddJobCommandParser : by +deactivate EXPECTED_COMPLETION + +create Job +AddJobCommandParser -> Job : desc, fee, recv, by +activate Job +Job --> AddJobCommandParser : job +deactivate Job + +create AddJobCommand +AddJobCommandParser -> AddJobCommand : job, contactIndex +activate AddJobCommand +AddJobCommand --> AddJobCommandParser : ToAdd +deactivate AddJobCommand + +AddJobCommandParser --> MyCrmParser : ToAdd +deactivate AddJobCommandParser +'Hidden arrow to position destroy marker below the end of the activation bar. +AddJobCommandParser -[hidden]-> MyCrmParser +destroy AddJobCommandParser + +MyCrmParser --> LogicManager : jobToAdd +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/job/AddJobSequenceDiagram.puml b/docs/diagrams/job/AddJobSequenceDiagram.puml new file mode 100644 index 00000000000..c8df510f044 --- /dev/null +++ b/docs/diagrams/job/AddJobSequenceDiagram.puml @@ -0,0 +1,86 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":AddJobCommandParser" as AddJobCommandParser LOGIC_COLOR +participant "a:AddJobCommand" as AddJobCommand LOGIC_COLOR +participant ":StateManager" as StateManager 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("addJob c/1 p/1 d/Fix...") +activate LogicManager + +LogicManager -> MyCrmParser : parseCommandWord("addJob c/1 p/1 d/Fix...") +activate MyCrmParser +MyCrmParser --> LogicManager +deactivate MyCrmParser + +LogicManager -> StateManager : isCommandAllowed("addJob") +activate StateManager +StateManager --> LogicManager +deactivate StateManager + +LogicManager -> MyCrmParser : parseCommand("addJob c/1 p/1 d/Fix...") +activate MyCrmParser + +create AddJobCommandParser +MyCrmParser -> AddJobCommandParser +activate AddJobCommandParser + +AddJobCommandParser --> MyCrmParser +deactivate AddJobCommandParser + +MyCrmParser -> AddJobCommandParser : parse("c/1 p/1 d/Fix...") +activate AddJobCommandParser + +create AddJobCommand +AddJobCommandParser -> AddJobCommand +activate AddJobCommand + +AddJobCommand --> AddJobCommandParser : a +deactivate AddJobCommand + +AddJobCommandParser --> MyCrmParser : a +deactivate AddJobCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +AddJobCommandParser -[hidden]-> MyCrmParser +destroy AddJobCommandParser + +MyCrmParser --> LogicManager : a +deactivate MyCrmParser + +LogicManager -> AddJobCommand : execute() +activate AddJobCommand + +AddJobCommand -> StateManager : handleAddJob(jobToAdd) +activate StateManager + +StateManager -> Model : addJob(jobToAdd) +activate Model + +Model --> StateManager +deactivate Model + +create CommandResult +StateManager -> CommandResult +activate CommandResult + +CommandResult --> StateManager +deactivate CommandResult + +StateManager --> AddJobCommand +deactivate StateManager + +AddJobCommand --> LogicManager : result +deactivate AddJobCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/job/AddJobSequenceDiagramShort.puml b/docs/diagrams/job/AddJobSequenceDiagramShort.puml new file mode 100644 index 00000000000..95f6222aba8 --- /dev/null +++ b/docs/diagrams/job/AddJobSequenceDiagramShort.puml @@ -0,0 +1,54 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "toAdd:AddJobCommand" as AddJobCommand LOGIC_COLOR +participant "lastShownList: List" as ListContact LOGIC_COLOR +participant ":StateManager" as StateManager 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("addJob d/Fix CPU fee/30.00 by/30/10/2021 c/1") +activate LogicManager + +ref over LogicManager, AddJobCommand : parse add job + +LogicManager -> AddJobCommand : execute() +activate AddJobCommand + +AddJobCommand -> Model : getFilteredContactList() +activate Model +Model --> AddJobCommand : lastShownList +deactivate Model + +AddJobCommand -> ListContact : get(contactIndex) +activate ListContact +ListContact --> AddJobCommand : contact +deactivate ListContact + +AddJobCommand -> StateManager : handleAddJob(jobToAdd) +activate StateManager + +create CommandResult +StateManager -> CommandResult +activate CommandResult + +CommandResult --> StateManager +deactivate CommandResult + +StateManager --> AddJobCommand +deactivate StateManager + +AddJobCommand --> LogicManager : result +deactivate AddJobCommand + +AddJobCommand -[hidden]-> LogicManager +destroy AddJobCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/job/AssigningContactActivityDiagram.puml b/docs/diagrams/job/AssigningContactActivityDiagram.puml new file mode 100644 index 00000000000..d282cf91786 --- /dev/null +++ b/docs/diagrams/job/AssigningContactActivityDiagram.puml @@ -0,0 +1,32 @@ +@startuml +title :Assign contact to job + +start +repeat :MyCRM asks user to provide contact for the job; +:User issues command; +:MyCRM parses user input; +if () then([invalid input]) + :Throws Parse Exception; + :Displays unsuccessful command execution in UI; +else ([valid input]) + :MyCRM executes user command; + if () then([abort command]) + :Operation will be aborted; + :Displays abortion of current operation in UI; + stop; + else ([else]) + if () then( [existing contact selected]) + :Existing contact will be linked to job; + else ([else]) + if () then([new contact created]) + :Newly created contact will be linked to job; + else ([else]) + endif + endif + endif +endif +repeat while () is ([contact not assigned to job]) +->[else]; +:Displays successful linking of contact to job in UI; +stop +@enduml diff --git a/docs/diagrams/job/AssigningProductActivtyDiagram.puml b/docs/diagrams/job/AssigningProductActivtyDiagram.puml new file mode 100644 index 00000000000..0d4e7f52e8b --- /dev/null +++ b/docs/diagrams/job/AssigningProductActivtyDiagram.puml @@ -0,0 +1,32 @@ +@startuml +title :Assign product to job + +start +repeat :MyCRM asks user to provide product for the job; +:User issues command; +:MyCRM parses user input; +if () then([invalid input]) + :Throws Parse Exception; + :Displays unsuccessful command execution in UI; +else ([valid input]) + :MyCRM executes user command; + if () then([abort command]) + :Operation will be aborted; + :Displays abortion of current operation in UI; + stop; + else ([else]) + if () then( [existing product selected]) + :Existing product will be linked to job; + else ([else]) + if () then([new product created]) + :Newly created product will be linked to job; + else ([else]) + endif + endif + endif +endif +repeat while () is ([product not assigned to job]) +->[else]; +:Displays successful linking of product to job in UI; +stop +@enduml diff --git a/docs/diagrams/job/EditJobActivityDiagram.puml b/docs/diagrams/job/EditJobActivityDiagram.puml new file mode 100644 index 00000000000..7475aa70432 --- /dev/null +++ b/docs/diagrams/job/EditJobActivityDiagram.puml @@ -0,0 +1,60 @@ +@startuml +sprite $rake [16x16/8] { +0000000000000000 +0000000jj0000000 +0000000jj0000000 +0005555jj5555000 +000jjeejjeejj000 +000jj00jj00jj000 +000jj00jj00jj000 +0000000000000000 +} + +start +:User executes edit job command; +:MyCRM parses user inputs; +if () then ([Valid inputs]) + if () then ([Invalid index]) + :Throws ParseException; + :Displays unsuccessful edit job on UI; + else ([else]) + :Gets job to be edited with index provided; + if () then ([Contact should be reassigned)]) + if () then ([else]) + else ([Contact index not provided]) + :MyCRM asks user to assign contact <$rake>; + if () then([operation aborted]) + stop; + else ([else]) + endif + endif + else ([else]) + endif + if () then ([Product should be reassigned)]) + if () then ([else]) + else ([Product index not provided]) + :MyCRM asks user to assign product <$rake>; + if () then([operation aborted]) + stop; + else ([else]) + endif + endif + else ([else]) + endif + + :Creates edited job; + if () then ([Duplicate job]) + :Throws CommandException; + :Displays unsuccessful adding of job on UI; + else ([Else]) + :Stores job into MyCRM; + :Replaces job being edited with edited job; + :Displays successful editing contact message on UI; + endif + endif +else ([Invalid inputs]) + :Throws ParseException; + :Displays unsuccessful edit job on UI; +endif +stop +@enduml diff --git a/docs/diagrams/job/EditJobSequenceDiagram.puml b/docs/diagrams/job/EditJobSequenceDiagram.puml new file mode 100644 index 00000000000..5faa4a3cc2e --- /dev/null +++ b/docs/diagrams/job/EditJobSequenceDiagram.puml @@ -0,0 +1,79 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "jobToEdit:EditJobCommand" as EditJobCommand LOGIC_COLOR +participant "lastShownJobList: List" as ListJob LOGIC_COLOR +participant "**<>**\nJob" as Job LOGIC_COLOR +participant ":StateManager" as StateManager 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("editJob 1 c/2 p/3") +activate LogicManager + +ref over LogicManager, EditJobCommand : parse edit job + +LogicManager -> EditJobCommand : execute() + +activate EditJobCommand + +EditJobCommand -> Model : getFilteredJobList() +activate Model +Model --> EditJobCommand : lastShownJobList +deactivate Model + +EditJobCommand -> Model : getFilteredContactList() +activate Model +Model --> EditJobCommand : lastShownContactList +deactivate Model + +EditJobCommand -> Model : getFilteredProductList() +activate Model +Model --> EditJobCommand : lastShownProductList +deactivate Model + +EditJobCommand -> ListJob : get(jobIndex) +activate ListJob +ListJob --> EditJobCommand : jobToEdit +deactivate ListJob + +EditJobCommand -> Job : createEditedJob(jobToEdit, editJobDescriptor, "lastShownContactList, lastShownProductList) +activate Job +Job --> EditJobCommand : editedJob +deactivate Job + +EditJobCommand -> StateManager : handleEditJob(jobToEdit, editedJob, shouldEditContact, shouldEditProduct) +activate StateManager + +StateManager -> Model : setJob(jobToEdit, editedJob) +activate Model + +Model --> StateManager +deactivate Model + +create CommandResult +StateManager -> CommandResult +activate CommandResult + +CommandResult --> StateManager +deactivate CommandResult + +StateManager --> EditJobCommand +deactivate StateManager + +EditJobCommand --> LogicManager : result +deactivate EditJobCommand + +EditJobCommand -[hidden]-> LogicManager +destroy EditJobCommand + +[<--LogicManager +deactivate LogicManager +@enduml + diff --git a/docs/diagrams/mail/AddTemplateActivityDiagram.puml b/docs/diagrams/mail/AddTemplateActivityDiagram.puml new file mode 100644 index 00000000000..a7ccc0ee873 --- /dev/null +++ b/docs/diagrams/mail/AddTemplateActivityDiagram.puml @@ -0,0 +1,20 @@ +@startuml +start +:User executes add template command; +:MyCRM parses user inputs; +if () then ([Invalid inputs]) + :Throws ParseException; + :Displays unsuccessful add template on UI; +else ([Valid inputs]) + :Creates new template; + if () then ([Duplicate template]) + :Throws CommandException; + :Displays unsuccessful add template on UI; + else ([Else]) + :Stores template into MyCRM; + :Displays successful add template on UI; + endif +endif +stop + +@enduml diff --git a/docs/diagrams/mail/AddTemplateParseSequenceDiagram.puml b/docs/diagrams/mail/AddTemplateParseSequenceDiagram.puml new file mode 100644 index 00000000000..209a747590e --- /dev/null +++ b/docs/diagrams/mail/AddTemplateParseSequenceDiagram.puml @@ -0,0 +1,68 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":AddTemplateCommandParser" as AddTemplateCommandParser LOGIC_COLOR +participant "toAdd:AddTemplateCommand" as AddTemplateCommand LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant "s:Subject" as Subject MODEL_COLOR +participant "b:Body" as Body MODEL_COLOR +participant "t:Template" as Template MODEL_COLOR +end box +[-> LogicManager : execute("addTemplate s/Completed b/Dear...") +activate LogicManager + +group sd parse add template +LogicManager -> MyCrmParser : parseCommand("addTemplate s/Completed b/Dear...") +activate MyCrmParser + +create AddTemplateCommandParser +MyCrmParser -> AddTemplateCommandParser +activate AddTemplateCommandParser + +AddTemplateCommandParser --> MyCrmParser +deactivate AddTemplateCommandParser + +MyCrmParser -> AddTemplateCommandParser : parse("s/Completed b/Dear...") +activate AddTemplateCommandParser + +create Subject +AddTemplateCommandParser -> Subject : "Completed" +activate Subject +Subject --> AddTemplateCommandParser : s +deactivate Subject + +create Body +AddTemplateCommandParser -> Body : "Dear..." +activate Body +Body --> AddTemplateCommandParser : b +deactivate Body + +create Template +AddTemplateCommandParser -> Template : s, b +activate Template +Template --> AddTemplateCommandParser : t +deactivate Template + +create AddTemplateCommand +AddTemplateCommandParser -> AddTemplateCommand : t +activate AddTemplateCommand +AddTemplateCommand --> AddTemplateCommandParser : toAdd +deactivate AddTemplateCommand + +AddTemplateCommandParser --> MyCrmParser : toAdd +deactivate AddTemplateCommandParser +'Hidden arrow to position destroy marker below the end of the activation bar. +AddTemplateCommandParser -[hidden]-> MyCrmParser +destroy AddTemplateCommandParser + +MyCrmParser --> LogicManager : toAdd +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/mail/AddTemplateSequenceDiagram.puml b/docs/diagrams/mail/AddTemplateSequenceDiagram.puml new file mode 100644 index 00000000000..2a118072ecf --- /dev/null +++ b/docs/diagrams/mail/AddTemplateSequenceDiagram.puml @@ -0,0 +1,42 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "toAdd:AddTemplateCommand" as AddTemplateCommand 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("addTemplate s/Completed b/Dear...") +activate LogicManager + +ref over LogicManager, AddTemplateCommand : parse add template + +LogicManager -> AddTemplateCommand : execute() +activate AddTemplateCommand + +AddTemplateCommand -> Model : addTemplate(toAdd) +activate Model + +Model --> AddTemplateCommand +deactivate Model + +create CommandResult +AddTemplateCommand -> CommandResult +activate CommandResult + +CommandResult --> AddTemplateCommand +deactivate CommandResult + +AddTemplateCommand --> LogicManager : result +deactivate AddTemplateCommand + +AddTemplateCommand -[hidden]-> LogicManager +destroy AddTemplateCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/mail/DeleteTemplateActivityDiagram.puml b/docs/diagrams/mail/DeleteTemplateActivityDiagram.puml new file mode 100644 index 00000000000..c490a795f48 --- /dev/null +++ b/docs/diagrams/mail/DeleteTemplateActivityDiagram.puml @@ -0,0 +1,20 @@ +@startuml +start +:User executes delete template command; +:MyCRM parses user inputs; +if () then ([Invalid inputs]) + :Throws ParseException; + :Displays unsuccessful delete template on UI; +else ([Valid inputs]) + if () then ([Index out of range]) + :Throws CommandException; + :Displays unsuccessful delete template on UI; + else ([Else]) + :Retrieves template to be deleted; + :Deletes template from MyCRM; + :Displays successful delete template on UI; + endif +endif +stop + +@enduml diff --git a/docs/diagrams/mail/DeleteTemplateParseSequenceDiagram.puml b/docs/diagrams/mail/DeleteTemplateParseSequenceDiagram.puml new file mode 100644 index 00000000000..59ca4e4f8b2 --- /dev/null +++ b/docs/diagrams/mail/DeleteTemplateParseSequenceDiagram.puml @@ -0,0 +1,47 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":MyCrmParser" as MyCrmParser LOGIC_COLOR +participant ":DeleteTemplateCommandParser" as DeleteTemplateCommandParser LOGIC_COLOR +participant "toDelete:DeleteTemplateCommand" as DeleteTemplateCommand LOGIC_COLOR +end box + +[-> LogicManager : execute("deleteTemplate 1") +activate LogicManager + +group sd parse delete template +LogicManager -> MyCrmParser : parseCommand("deleteTemplate 1") +activate MyCrmParser + +create DeleteTemplateCommandParser +MyCrmParser -> DeleteTemplateCommandParser +activate DeleteTemplateCommandParser + +DeleteTemplateCommandParser --> MyCrmParser +deactivate DeleteTemplateCommandParser + +MyCrmParser -> DeleteTemplateCommandParser : parse("1") +activate DeleteTemplateCommandParser + +create DeleteTemplateCommand +DeleteTemplateCommandParser -> DeleteTemplateCommand : 1 +activate DeleteTemplateCommand + +DeleteTemplateCommand --> DeleteTemplateCommandParser : toDelete +deactivate DeleteTemplateCommand + +DeleteTemplateCommandParser --> MyCrmParser : toDelete +deactivate DeleteTemplateCommandParser + +'Hidden arrow to position destroy marker below the end of the activation bar. +DeleteTemplateCommandParser -[hidden]-> MyCrmParser +destroy DeleteTemplateCommandParser + +MyCrmParser --> LogicManager : toDelete +deactivate MyCrmParser +end + +deactivate LogicManager +@enduml diff --git a/docs/diagrams/mail/DeleteTemplateSequenceDiagram.puml b/docs/diagrams/mail/DeleteTemplateSequenceDiagram.puml new file mode 100644 index 00000000000..30ba0d6d403 --- /dev/null +++ b/docs/diagrams/mail/DeleteTemplateSequenceDiagram.puml @@ -0,0 +1,54 @@ +@startuml +!include ../style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant "toDelete:DeleteTemplateCommand" as DeleteTemplateCommand LOGIC_COLOR +participant "lastShownList: List