diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 233ae234981..233376accec 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -219,17 +219,17 @@ The following activity diagram summarizes what happens when a user executes a ad Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*` -| Priority | As a …​ | I want to …​ | So that I can…​ | -|----------|---------------------|---------------------------------------------------------------------------|-----------------------------------------------| -| `* * *` | financial advisor | add a new client’s contact details | easily manage my client base | -| `* * *` | financial advisor | view all of a client’s details on one screen | have all necessary information in one place. | -| `* * *` | financial advisor | delete outdated client contact information | keep my database clean and relevant | -| `* *` | financial advisor | search for a client by name or company | ensure that I always have the latest details | -| `* *` | financial advisor | categorize my clients (e.g., VIP, standard) | prioritize my communication with them | -| `*` | financial advisor | update a client’s contact information | ensure that I always have the latest details | -| `*` | financial advisor | tag clients with specific keywords (e.g., investor, retiree) | segment them for different services | -| `*` | financial advisor | add notes to a client’s profile | track important interactions or discussions | -| `*` | financial advisor | assign tasks related to each client (e.g., "Review investment portfolio") | stay organized and focused | +| Priority | As a …​ | I want to …​ | So that I can…​ | +|----------|---------------------|---------------------------------------------------------------------------------|-----------------------------------------------| +| `* * *` | financial advisor | add a new client’s contact details | easily manage my client base | +| `* * *` | financial advisor | view all of a client’s details on one screen | have all necessary information in one place. | +| `* * *` | financial advisor | delete outdated client contact information | keep my database clean and relevant | +| `* *` | financial advisor | search for a client by their personal information, such as name or phone number | ensure that I always have the latest details | +| `* *` | financial advisor | sort all clients in alphabetical order based on their names | prioritize my communication with them | +| `*` | financial advisor | update a client’s contact information | ensure that I always have the latest details | +| `*` | financial advisor | tag clients with specific client types (e.g., investor, retiree) | segment them for different services | +| `*` | financial advisor | add description to a client’s profile | track important interactions or discussions | +| `*` | financial advisor | assign reminders to each client (e.g., "Review investment portfolio") | stay organized and focused | *{More to be added}* @@ -237,10 +237,10 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli (For all use cases below, the **System** is the `ClientHub` and the **Actor** is the `user`, unless specified otherwise) -**Use case: Add a new contact** +**Use case: Add a new client** **MSS** -1. User requests to add a client's contact +1. User inputs the command to add a client's contact 2. ClientHub adds the contact to the list of contacts 3. ClientHub shows successful output message @@ -262,16 +262,17 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli * 1c. ClientHub detects a duplicate contact - * 1c1. ClientHub informs user that there is more than one contact with the same name and prompts for confirmation - * 1c2. User confirms the addition of contact + * 1c1. ClientHub informs user that there is more than one contact with the same name and prompt the user to input a + different name. + + Step 1 is repeated until user inputs a unique name. + - Use case resumes at step 2. - -**Use case: Delete a contact** +**Use case: Delete a client** **MSS** -1. User requests to delete a contact +1. User keys in the command to delete a client 2. ClientHub deletes the person 3. ClientHub shows successful output message @@ -305,13 +306,147 @@ Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unli **Extensions** +* 1a. ClientHub detects unknown command + * 1a1. ClientHub shows an error message that the command is not recognized + + Use case ends. + +**Use case: Search for a contact** + +**MSS** +1. User inputs the command to search for a contact +2. ClientHub searches for the contact +3. ClientHub shows the contact details + + Use case ends. + +**Extensions** + * 1a. ClientHub detects invalid input format + * 1a1. ClientHub shows an error message that the input is in the wrong format + + Step 1 is repeated until user inputs the correct format. +* 1b. ClientHub detects that the given name is not in the list + * 1b1. ClientHub shows an error message that the name is not in the list + + Use case ends. +* 1c. ClientHub detects multiple clients that matches the same name + * 1c1. ClientHub informs the user that multiple clients matches the same name and requests the user to input the full name of the client - * 1a1. ClientHub shows an error message + Step 1 is repeated until user inputs full name of the contact. - Step 1 is repeated until user inputs the correct format. +**Use case: Edit a client** -*{More to be added}* +**MSS** +1. User inputs the command to edit a client's contact +2. ClientHub edits the contact details +3. ClientHub shows successful output message + + Use case ends. + +**Extensions** + +* 1a. ClientHub detects invalid input format + * 1a1. ClientHub shows an error message that the input is in the wrong format + + Step 1 is repeated until user inputs the correct format. +* 1b. ClientHub detects that the given name is not in the list + * 1b1. ClientHub shows an error message that the name is not in the list + + Use case ends. +* 1c. ClientHub detects multiple contacts of the same name + * 1c1. ClientHub informs the user that there are multiple contacts with the same name and requests the user to input the full name of the contact + + Step 1 is repeated until user inputs full name of the contact. + +**Use case: Sort clients** + +**MSS** + +1. User inputs the command to sort clients +2. ClientHub sorts the clients in alphabetical order based on their names +3. ClientHub shows the sorted list of clients + + Use case ends. + +**Extensions** + +* 1a. ClientHub detects unknown command + * 1a1. ClientHub shows an error message that the command is not recognized + + Use case ends. +* 1b. ClientHub detects invalid input format + * 1b1. ClientHub shows an error message that the input is in the wrong format + + Step 1 is repeated until user inputs the correct format. + +**Use case: Add reminder** + +**MSS** + +1. User inputs the command to add a reminder +2. ClientHub adds the reminder to the client +3. ClientHub shows successful output message + Use case ends. + +**Extensions** + +* 1a. ClientHub detects invalid input format + * 1a1. ClientHub shows an error message that the input is in the wrong format + + Step 1 is repeated until user inputs the correct format. +* 1b. ClientHub detects that the given name is not in the list + * 1b1. ClientHub shows an error message that the name is not in the list + + Use case ends. +* 1c. ClientHub detects multiple contacts of the same name + * 1c1. ClientHub informs the user that there are multiple contacts with the same name and requests the user to input the full name of the contact + + Step 1 is repeated until user inputs full name of the contact. +* 1d. ClientHub detects that the reminder is already added + * 1d1. ClientHub shows an error message that the reminder is already added + + Use case ends. + +**Use case: Delete reminder** + +**MSS** + +1. User inputs the command to delete a reminder +2. ClientHub deletes the reminder from the client +3. ClientHub shows successful output message + Use case ends. + +**Extensions** + +* 1a. ClientHub detects invalid input format + * 1a1. ClientHub shows an error message that the input is in the wrong format + + Step 1 is repeated until user inputs the correct format. +* 2a. ClientHub detects the given index is out of range + * 2a1. ClientHub shows an error message that the index is out of range + + Step 1 is repeated until user inputs the correct format. + + +**Use case: Edit reminder** + +**MSS** +1. User inputs the command to edit a reminder +2. ClientHub edits the reminder +3. ClientHub shows successful output message + Use case ends. + +**Extensions** + +* 1a. ClientHub detects invalid input format + * 1a1. ClientHub shows an error message that the input is in the wrong format + + Step 1 is repeated until user inputs the correct format. +* 2a. ClientHub detects the given index is out of range + * 2a1. ClientHub shows an error message that the index is out of range + + Step 1 is repeated until user inputs the correct format. ### Non-Functional Requirements diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index c513d5c6e8d..3673f216aad 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -22,7 +22,7 @@ public class Messages { public static final String MESSAGE_PERSON_NOT_FOUND = "The client cannot be found in the clientHub \n" + "Please use the list command to see all clients!"; public static final String MESSAGE_VAGUE_DELETE = "Please be more specific in the name \n" - + "or use / to indicate the end of an EXACT name"; + + "or use $ to indicate the end of an EXACT name"; public static final String MESSAGE_PERSON_LISTED_OVERVIEW_FOR_VIEW = "%1$d client found for viewing!"; public static final String MESSAGE_NO_PERSON_FOUND_FOR_VIEW = "No clients found please use the list command to see all clients"; diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index 7e06be0de4f..f58bf158f6f 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -44,8 +44,8 @@ public class AddCommand extends Command { public static final String MESSAGE_SUCCESS = "New client added: %1$s"; public static final String MESSAGE_DUPLICATE_PERSON = "This name already exists in Client Hub. If the " - + "newly added client has the same name, Please add use () to add more information after the name " - + "to differentiate the names."; + + "newly added client has the same name, please use parenthesis to add more information after the name " + + "to differentiate the clients."; private final Person toAdd; diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/seedu/address/logic/commands/DeleteCommand.java index a12548a0c18..a92618150f6 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/seedu/address/logic/commands/DeleteCommand.java @@ -26,7 +26,7 @@ public class DeleteCommand extends Command { + SHORT_COMMAND_WORD + " John Doe \n" + "Additional Info: \n" + "- To delete a client with a common name, please provide fullname or\n" - + "use / to indicate the end of the name eg Jon snow/"; + + "use $ to indicate the end of the name eg Jon snow$"; public static final String MESSAGE_DELETE_PERSON_SUCCESS = "Deleted Client: %1$s"; diff --git a/src/main/java/seedu/address/logic/commands/reminder/DeleteReminderCommand.java b/src/main/java/seedu/address/logic/commands/reminder/DeleteReminderCommand.java index 14377cca9f7..10b1828accd 100644 --- a/src/main/java/seedu/address/logic/commands/reminder/DeleteReminderCommand.java +++ b/src/main/java/seedu/address/logic/commands/reminder/DeleteReminderCommand.java @@ -68,7 +68,7 @@ public CommandResult execute(Model model) throws CommandException { model.deleteReminder(reminderToDelete); // Parse input using the NameContainsKeywordsPredicate - String fullName = reminderToDelete.getPersonName() + "/"; + String fullName = reminderToDelete.getPersonName() + "$"; String[] nameKeywords = fullName.split("\\s+"); NameContainsKeywordsDeletePredicate predicate = new NameContainsKeywordsDeletePredicate( List.of(nameKeywords)); diff --git a/src/main/java/seedu/address/logic/commands/reminder/EditReminderCommand.java b/src/main/java/seedu/address/logic/commands/reminder/EditReminderCommand.java index cfaa5b8aaab..77244154ee8 100644 --- a/src/main/java/seedu/address/logic/commands/reminder/EditReminderCommand.java +++ b/src/main/java/seedu/address/logic/commands/reminder/EditReminderCommand.java @@ -79,7 +79,7 @@ public CommandResult execute(Model model) throws CommandException { } // Parse input using the NameContainsKeywordsPredicate - String fullName = reminderToEdit.getPersonName() + "/"; + String fullName = reminderToEdit.getPersonName() + "$"; String[] nameKeywords = fullName.split("\\s+"); NameContainsKeywordsDeletePredicate predicate = new NameContainsKeywordsDeletePredicate( List.of(nameKeywords)); diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java index 62900f4da96..95f007e43c2 100644 --- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java @@ -21,7 +21,7 @@ public class DeleteCommandParser implements Parser { */ public DeleteCommand parse(String args) throws ParseException { String personNames = args.trim(); - if (!Name.isValidName(personNames) && !personNames.endsWith("/")) { + if (!Name.isValidName(personNames) && !personNames.endsWith("$")) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); } diff --git a/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java b/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java index c8fe4c269e9..4b3daab8c07 100644 --- a/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindNameCommandParser.java @@ -24,7 +24,7 @@ public FindNameCommand parse(String args) throws ParseException { throw new ParseException( String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindNameCommand.MESSAGE_USAGE)); } - if (!trimmedArgs.matches("^[a-zA-Z()\\s]+$")) { + if (!trimmedArgs.matches("^[a-zA-Z()/$\\s]+$")) { throw new ParseException( String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindNameCommand.MESSAGE_USAGE)); } diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/seedu/address/model/person/Name.java index 2c8e16da48c..16688871eaf 100644 --- a/src/main/java/seedu/address/model/person/Name.java +++ b/src/main/java/seedu/address/model/person/Name.java @@ -10,13 +10,15 @@ public class Name { public static final String MESSAGE_CONSTRAINTS = - "Names should only contain letters, space, parenthesis and slash, and it should not be blank"; + "Names should only contain letters, space, parenthesis and slash, and it should not be blank. Names should " + + "start with a letter and end with a letter or closing bracket."; /* * The first character of the address must not be a whitespace, * otherwise " " (a blank string) becomes a valid input. */ - public static final String VALIDATION_REGEX = "^[a-zA-Z()/]+[a-zA-Z()/\\s]*$"; + public static final String VALIDATION_REGEX = "^[a-zA-Z]+[a-zA-Z()/\\s]*[a-zA-Z)]$"; + public final String fullName; diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsDeletePredicate.java b/src/main/java/seedu/address/model/person/NameContainsKeywordsDeletePredicate.java index 02becb41cfb..a2353bebd7e 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsDeletePredicate.java +++ b/src/main/java/seedu/address/model/person/NameContainsKeywordsDeletePredicate.java @@ -33,7 +33,7 @@ public NameContainsKeywordsDeletePredicate(List keywords) { public boolean test(Person person) { if (keywords.isEmpty()) { return false; - } else if (keywords.get(keywords.size() - 1).contains("/")) { + } else if (keywords.get(keywords.size() - 1).contains("$")) { return isExact(person); } else { return keywords.stream() @@ -50,7 +50,7 @@ public boolean test(Person person) { * @return {@code true} if the concatenated keywords, without the trailing "/", match the person's full name. */ public boolean isExact(Person person) { - String fullname = String.join("", keywords).toLowerCase().split("/")[0].trim(); + String fullname = String.join("", keywords).toLowerCase().split("\\$")[0].trim(); String personName = person.getName().fullName.trim().toLowerCase().replace(" ", ""); return fullname.equals(personName); } diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java index c3a9fa25e37..ca12efc802b 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java @@ -20,7 +20,7 @@ public NameContainsKeywordsPredicate(List keywords) { public boolean test(Person person) { if (keywords.isEmpty()) { return false; - } else if (keywords.get(keywords.size() - 1).contains("/")) { + } else if (keywords.get(keywords.size() - 1).contains("$")) { return isExact(person); } else { return keywords.stream() @@ -38,7 +38,7 @@ public boolean test(Person person) { * @return {@code true} if the concatenated keywords, match the person's full name. */ public boolean isExact(Person person) { - String fullname = String.join("", keywords).toLowerCase().split("/")[0].trim(); + String fullname = String.join("", keywords).toLowerCase().split("\\$")[0].trim(); String personName = person.getName().fullName.trim().toLowerCase().replace(" ", ""); return fullname.equals(personName); } diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java index fac8b068595..e6d8d433ba3 100644 --- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java +++ b/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java @@ -110,7 +110,7 @@ public void test_isExact() { assertFalse(predicate.isExact(new PersonBuilder().withName("Alice Bob").build())); // Slash character ignored in matching - predicate = new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob/")); + predicate = new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob$")); assertTrue(predicate.isExact(new PersonBuilder().withName("Alice Bob").build())); // No match due to leading or trailing spaces @@ -130,7 +130,7 @@ public void test_isExact() { assertTrue(predicate.isExact(new PersonBuilder().withName("Alice Bob").build())); // Multiple keywords without space between words - predicate = new NameContainsKeywordsPredicate(Arrays.asList("AliceBob/")); + predicate = new NameContainsKeywordsPredicate(Arrays.asList("AliceBob$")); assertTrue(predicate.isExact(new PersonBuilder().withName("Alice Bob").build())); // Different casing in keywords and person name