Skip to content

Commit

Permalink
Merge branch 'master' into dg-draft
Browse files Browse the repository at this point in the history
  • Loading branch information
evanpy authored Mar 23, 2023
2 parents e3e4604 + 4a39cc2 commit 389396f
Show file tree
Hide file tree
Showing 30 changed files with 526 additions and 35 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ task coverage(type: JacocoReport) {
}
}

run {
enableAssertions = true
}

dependencies {
String jUnitVersion = '5.4.0'
String javaFxVersion = '11'
Expand Down
48 changes: 48 additions & 0 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,26 @@ The following activity diagram summarizes what happens when a user executes a so

![SortActivityDiagram](images/SortActivityDiagram.png)

### Lead Status feature

The Lead Status feature aims to provide information about the contact based on when the status was last set.
It is represented by the `LeadStatus status` attribute in a `Person`, which contains a `LeadStatusName` and
`LocalDateTime` timestamp.

Because we would like to limit the types of statuses a contact should have, for consistency's sake, each
type of lead status is represented by an enum in `LeadStatusName`. `LeadStatusName` also contains mappings for
abbreviations of each status type.

![](images/PersonLeadStatusDiagram.png)

The default lead status of a new contact added is `UNCONTACTED`, and the timestamp is the time of adding the contact.
The user is able to change the lead status of a contact to any other lead status. The timestamp is updated to the
`LocalDateTime.now()` of when the command is executed. If the lead status to change to is the same as the preexisting
one, the command returns and does not alter the previous lead status (and timestamp).

![](images/StatusSequenceDiagram.png)
(to update seq diagram to reflect timestamp implementation)

### \[Proposed\] Undo/redo feature

#### Proposed Implementation
Expand Down Expand Up @@ -260,6 +280,33 @@ _{more aspects and alternatives to be added}_

_{Explain here how the data archiving feature will be implemented}_

### Add transaction feature

#### Proposed Implementation

The proposed add transaction mechanism is facilitated by `UniqueTransactionList`. It is similar to `UniquePersonList` which stores a list of unique transaction records.

Given below is an example scenario and how to add transaction mechanism behaves at each step.

Step 1. The user launches the application for the first time. The `Storage` will check if there are existing transaction records in local storage. If transaction records are found, a `UniqueTransactionList` is created with existing transaction records. Else, an empty `UniqueTransactionList` is created in `AddressBook`.

Step 2. The user excutes `addtxn td/1 Venti Cold Brew …​` to add a new transaction record. the `addtxn` command will be parsed by `AddTxnCommandParser` and a `AddTxnCommand` will be created. `AddTxnCommand#exexute()` add the input transaction record if it has a valid owner and it's not a duplicate of existing record, then it creates a `CommandResult` to provide feedback to the user.

![AddTxnCommandSequenceDiagram](images/AddTxnCommandSequenceDiagram.png)

#### Design considerations:

**Aspect: How add transaction executes:**

* **Alternative 1 (current choice):** Saves all transaction records in a separate list, each transaction has a non-null owner attribute indicates the other party involved in this transaction.
* Pros: Easy to implement, easy to search through all transaction records.
* Cons: May need long time to list down all transaction records under the save name.

* **Alternative 2:** Each Person object has a transaction list attribute, to store transactions belong to him or her.
* Pros: Less time taken to identify transactions with the same person as no need to search through the whole transaction list.
* Cons: Difficult to carry out operations on all transactions.



--------------------------------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -303,6 +350,7 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli
| `* *` | frantic salesperson | be warned when I make certain actions in my application | won’t jeopardise my work through carelessness |
| `*` | user with many persons in the address book | sort persons by name | locate a person easily |
| `*` | new user | import my current database | |
| `*` | salesperson | record down all transactions with clients | |


### Use cases
Expand Down
56 changes: 35 additions & 21 deletions docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ prioritise sales tasks

* `list` : Lists all contacts.

* `add n/John Doe p/98765432 e/johnd@example.com c/company X` : Adds a contact named `John Doe` to the Address Book.
* `add n/Charlotte Oliveiro g/female p/93210283 e/charlotte@example.com c/Mac King i/food and beverage o/entrepreneur j/CEO a/Blk 11 Ang Mo Kio Street 74, #11-04` : Adds a contact named `Charlotte Oliveiro` to the Address Book.

* `delete 3` : Deletes the 3rd contact shown in the current list.

Expand Down Expand Up @@ -92,15 +92,28 @@ Format: `help`

Adds a person to the address book.

Format: `add [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [c/COMPANY] [t/TAG]`
Format: `add [n/NAME] [g/GENDER] [p/PHONE_NUMBER] [e/EMAIL] [c/COMPANY] [i/INDUSTRY] [o/OCCUPATION] [j/JOBTITLE] [a/ADDRESS] [t/TAG]`

<div markdown="span" class="alert alert-primary">:bulb: **Tip:**
A contact must include name and phone number.
A contact must include all fields except tag.
</div>

Examples:
* `add n/John Doe p/98765432 e/johnd@example.com c/company X`
* `add n/Betsy Crowe p/62353535 t/friend`
* `add n/Charlotte Oliveiro g/female p/93210283 e/charlotte@example.com c/Mac King i/food and beverage o/entrepreneur j/CEO a/Blk 11 Ang Mo Kio Street 74, #11-04`
* `add n/Amy Bee g/female p/85355255 e/amy@gmail.com c/Tesleh i/automobile o/engineer j/industrial engineer a/123, Jurong West Ave 6, #08-111 t/friend`

### Sorting all persons : `sort`

Sorts all persons in the address book based on an attribute.

Format: `sort [name] [gender] [phone number] [email] [company] [industry] [occupation] [job title] [address] [remark] [status]`

* At least one of the optional fields must be provided.
* The address book will be sorted based on the specified attribute by their value.

Examples:
* `sort name` Sorts all persons alphabetically by name.
* `sort occupation` Sorts all persons alphabetically by occupation.

### Listing all persons : `list`

Expand All @@ -112,7 +125,7 @@ Format: `list`

Edits an existing person in the address book.

Format: `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [c/COMPANY] [t/TAG] …​`
Format: `edit INDEX [n/NAME] [g/GENDER] [p/PHONE_NUMBER] [e/EMAIL] [c/COMPANY] [i/INDUSTRY] [o/OCCUPATION] [j/JOBTITLE] [a/ADDRESS] [t/TAG] …​`

* 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.
Expand Down Expand Up @@ -282,18 +295,19 @@ _Details coming soon ..._

*italic* - optional

| Action | Format, Examples |
|----------------|------------------------------------------------------------------------------------------------------------------------------------------|
| **Add** | `add [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [c/COMPANY] ...​` <br> e.g., `add n/John Doe p/98765432 c/company X` |
| **Add Txn** | `addtxn [td/DESCRIPTION] [tv/VALUE] [ts/STATUS] [to/OWNER] ` <br> e.g., `addtxn [td/DESCRIPTION] [tv/VALUE] [ts/STATUS] [to/OWNER]` |
| **Clear** | `clear` |
| **Delete** | `delete INDEX`<br> e.g., `delete 3` | |
| **Delete Txn** | `deletetxn INDEX`<br> e.g., `deletetxn 3` |
| **Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [c/COMPANY] [t/TAG] …​`<br> e.g.,`edit 2 n/James Lee e/jameslee@example.com` |
| **Edit Txn** | `edittxn INDEX [td/DESCRIPTION] [tv/VALUE] [ts/STATUS] [to/OWNER]` <br> e.g., `edittxn 1 ts/closed` |
| **Status** | `status INDEX_NUMBER` *`[STATUS …]`*<br> `status NAME` *`[STATUS …]`*<br> e.g., `status 1, status David closed-won` |
| **List** | `list` |
| **List Txn** | `listtxn` |
| **Help** | `help` |

``

| Action | Format, Examples |
|----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **Add** | `add [n/NAME] [g/GENDER] [p/PHONE_NUMBER] [e/EMAIL] [c/COMPANY] [i/INDUSTRY] [o/OCCUPATION] [j/JOBTITLE] [a/ADDRESS] [t/TAG] ...​` <br> e.g., `add n/Amy Bee g/female p/85355255 e/amy@gmail.com c/Tesleh i/automobile o/engineer j/industrial engineer a/123, Jurong West Ave 6, #08-111` |
| **Sort** | `sort [name] [gender] [phone number] [email] [company] [industry] [occupation] [job title] [address] [remark] [status]` <br> e.g., `sort name` |
| **Add Txn** | `addtxn [td/DESCRIPTION] [tv/VALUE] [ts/STATUS] [to/OWNER] ` <br> e.g., `addtxn [td/DESCRIPTION] [tv/VALUE] [ts/STATUS] [to/OWNER]` |
| **Clear** | `clear` |
| **Delete** | `delete INDEX`<br> e.g., `delete 3` | |
| **Delete Txn** | `deletetxn INDEX`<br> e.g., `deletetxn 3` |
| **Edit** | `edit INDEX [n/NAME] [g/GENDER] [p/PHONE_NUMBER] [e/EMAIL] [c/COMPANY] [i/INDUSTRY] [o/OCCUPATION] [j/JOBTITLE] [a/ADDRESS] [t/TAG] …​`<br> e.g.,`edit 2 n/James Lee e/jameslee@example.com` |
| **Edit Txn** | `edittxn INDEX [td/DESCRIPTION] [tv/VALUE] [ts/STATUS] [to/OWNER]` <br> e.g., `edittxn 1 ts/closed` |
| **Status** | `status INDEX_NUMBER` *`[STATUS …]`*<br> `status NAME` *`[STATUS …]`*<br> e.g., `status 1, status David closed-won` |
| **List** | `list` |
| **List Txn** | `listtxn` |
| **Help** | `help` |

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

box Logic LOGIC_COLOR_T1
participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant "AddTxnCommandParser" as AddTxnCommandParser LOGIC_COLOR
participant "a:AddTxnCommand" as AddTxnCommand 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("addtxn td/...")
activate LogicManager

LogicManager -> AddressBookParser : parseCommand("addtxn td/...")
activate AddressBookParser

AddressBookParser -> AddTxnCommandParser
activate AddTxnCommandParser
AddTxnCommandParser --> AddressBookParser
deactivate AddTxnCommandParser

AddressBookParser -> AddTxnCommandParser: parse("td/...")
activate AddTxnCommandParser

create AddTxnCommand
AddressBookParser -> AddTxnCommand
activate AddTxnCommand

AddTxnCommand --> AddressBookParser: a
deactivate AddTxnCommand

AddTxnCommandParser --> AddressBookParser: a
deactivate AddTxnCommandParser

AddTxnCommandParser -[hidden]-> AddressBookParser
deactivate AddTxnCommandParser

AddressBookParser --> LogicManager: a
deactivate AddressBookParser

AddTxnCommand -> AddTxnCommandParser : execute()
activate AddTxnCommand

AddTxnCommand -> Model: addTransaction("td/...")
activate Model

Model --> AddTxnCommand
deactivate Model

create CommandResult
AddTxnCommand -> CommandResult
activate CommandResult

CommandResult --> AddTxnCommand
deactivate CommandResult

AddTxnCommand --> LogicManager : result
deactivate AddTxnCommand

[<--LogicManager
deactivate LogicManager
@enduml
35 changes: 35 additions & 0 deletions docs/diagrams/PersonLeadStatusDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@startuml
skinparam classAttributeIconSize 0
hide circle

class Person
class LeadStatus
enum "<<enumeration>>\nLeadStatusName" as LeadStatusName

LeadStatusName <-- LeadStatus
LeadStatus <-- Person

class Person {
}

class LeadStatus {
-lastUpdateTime:LocalDateTime

+update(LeadStatusName newStatus)
+getTimestamp()
}

enum LeadStatusName {
UNCONTACTED
WORKING
QUALIFIED
UNQUALIFIED

+SYMBOL_LEAD_STATUS_MAP:HashMap
+STRING_LEAD_STATUS_MAP:HashMap

+isValidStatusName(String)
+get(String)
}

@enduml
36 changes: 36 additions & 0 deletions docs/diagrams/StatusSequenceDiagram.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@startuml
'https://plantuml.com/sequence-diagram
!include style.puml


participant ":StatusCommand" as StatusCommand LOGIC_COLOR
participant ":Model" as Model LOGIC_COLOR



-> StatusCommand: execute()

StatusCommand -> Model: getFilteredPersonList()
Model --> StatusCommand: List<person> lastShownList

alt index exceeds lastShownList.size()
<--- StatusCommand: CommandException
end

StatusCommand -> Model: getZeroBased(index)
StatusCommand <-- Model: toBeUpdated:Person

alt lead status is the same as\nlead status of toBeUpdated
<-- StatusCommand: CommandException
end

StatusCommand -> StatusCommand : createPersonWithNewStatus()\n return:updatedPerson

StatusCommand -> Model : setPerson(updatedPerson)
Model --> StatusCommand

StatusCommand -> Model : updateFilteredPersonList()
Model --> StatusCommand

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

participant ":LogicManager" as LogicManager LOGIC_COLOR
participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
participant ":AddTxnTransaction" as AddTxnCommandParser LOGIC_COLOR
participant "a:AddTxnCommand" as AddTxnCommand LOGIC_COLOR
participant ":CommandResult" as CommandResult LOGIC_COLOR

LogicManager -> AddressBookParser : execute("addtxn")


@enduml
2 changes: 1 addition & 1 deletion docs/diagrams/UndoRedoState2.puml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ package States <<rectangle>> {
State1 -[hidden]right-> State2
State2 -[hidden]right-> State3

class Pointer as "Current State" #FFFFF
class Pointer as "Current State" #FFFFFF

Pointer -up-> State3
@end
Binary file added docs/images/AddTxnCommandSequenceDiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/PersonLeadStatusDiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/StatusSequenceDiagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 3 additions & 2 deletions src/main/java/seedu/address/commons/core/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ public class Messages {

public static final String MESSAGE_UNKNOWN_COMMAND = "Unknown command";
public static final String MESSAGE_INVALID_COMMAND_FORMAT = "Invalid command format! \n%1$s";
public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The person index provided is invalid";
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_INVALID_PERSON_DISPLAYED_INDEX = "The lead's index provided is invalid";
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d leads listed!";
public static final String MESSAGE_PERSONS_SORTED_OVERVIEW = "Leads sorted by %1$s";

public static final String MESSAGE_INVALID_TXN_DISPLAYED_INDEX = "The transaction index provided is invalid";

Expand Down
43 changes: 43 additions & 0 deletions src/main/java/seedu/address/logic/commands/SortCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;

import seedu.address.commons.core.Messages;
import seedu.address.model.Model;

/**
* Sorts address book based on lead attribute.
*/
public class SortCommand extends Command {
public static final String COMMAND_WORD = "sort";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Sorts all persons based on a specific attribute "
+ "the specified attribute (case-insensitive) and displays them as a list with index numbers.\n"
+ "Parameters: ATTRIBUTE \n"
+ "Example: " + COMMAND_WORD + " name";
private final String attribute;

public SortCommand(String attribute) {
this.attribute = attribute;
}

@Override
public CommandResult execute(Model model) {
requireNonNull(model);
try {
model.sortPersonList(attribute);
return new CommandResult(
String.format(
Messages.MESSAGE_PERSONS_SORTED_OVERVIEW, attribute));
} catch (RuntimeException e) {
return new CommandResult(e.getMessage());
}
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof SortCommand // instanceof handles nulls
&& attribute.equals(((SortCommand) other).attribute)); // state check
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ public EditTxnDescriptor() {}
* Copy constructor.
* A defensive copy of {@code tags} is used internally.
*/

public EditTxnDescriptor(EditTxnDescriptor toCopy) {
setDescription(toCopy.description);
setOwner(toCopy.owner);
Expand Down
Loading

0 comments on commit 389396f

Please sign in to comment.